Remove the deprecated org.springframework.data.gemfire.ForkUtil class.
Resolves gh-296.
This commit is contained in:
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2021 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.springframework.data.gemfire;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.springframework.data.gemfire.fork.CqCacheServerProcess;
|
||||
import org.springframework.data.gemfire.fork.FunctionCacheServerProcess;
|
||||
import org.springframework.data.gemfire.tests.process.ProcessExecutor;
|
||||
import org.springframework.data.gemfire.tests.util.IOUtils;
|
||||
import org.springframework.data.gemfire.tests.util.ThreadUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Utility class used to fork Java, JVM processes.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author John Blum
|
||||
* @deprecated {@link ForkUtil} has serious design flaws; please use {@link ProcessExecutor} from STDG instead
|
||||
*/
|
||||
@Deprecated
|
||||
public class ForkUtil {
|
||||
|
||||
private static final long TIMEOUT = 30000L;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ForkUtil.class);
|
||||
|
||||
private static OutputStream processStandardInStream;
|
||||
|
||||
private static final String JAVA_CLASSPATH = System.getProperty("java.class.path");
|
||||
private static final String JAVA_HOME = System.getProperty("java.home");
|
||||
private static final String JAVA_EXE = JAVA_HOME.concat(File.separator).concat("bin").concat(File.separator).concat("java");
|
||||
private static final String TEMP_DIRECTORY = System.getProperty("java.io.tmpdir");
|
||||
|
||||
private static List<String> buildJavaCommand(String arguments) {
|
||||
return buildJavaCommand(arguments.split("\\s+"));
|
||||
}
|
||||
|
||||
private static List<String> buildJavaCommand(String[] args) {
|
||||
List<String> command = new ArrayList<>(args.length + 5);
|
||||
|
||||
command.add(JAVA_EXE);
|
||||
command.add("-server");
|
||||
command.add("-ea");
|
||||
command.add("-classpath");
|
||||
command.add(JAVA_CLASSPATH);
|
||||
command.addAll(Arrays.asList(args));
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
private static OutputStream cloneJVM(String arguments) {
|
||||
AtomicBoolean runCondition = new AtomicBoolean(true);
|
||||
|
||||
List<String> command = buildJavaCommand(arguments);
|
||||
|
||||
Process javaProcess;
|
||||
|
||||
try {
|
||||
javaProcess = Runtime.getRuntime().exec(command.toArray(new String[command.size()]));
|
||||
|
||||
logger.debug("Started fork from command: {}",
|
||||
StringUtils.arrayToDelimitedString(command.toArray()," "));
|
||||
|
||||
captureProcessStreams(runCondition, javaProcess);
|
||||
registerShutdownHook(runCondition, javaProcess);
|
||||
|
||||
processStandardInStream = javaProcess.getOutputStream();
|
||||
|
||||
return processStandardInStream;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(String.format("Failed to fork JVM process using command [%s]",
|
||||
StringUtils.arrayToDelimitedString(command.toArray(), " ")), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void captureProcessStreams(AtomicBoolean runCondition, Process javaProcess) {
|
||||
startNewThread(newProcessStreamReader(runCondition, javaProcess.getErrorStream(), "[FORK-ERR]"));
|
||||
startNewThread(newProcessStreamReader(runCondition, javaProcess.getInputStream(), "[FORK-OUT]"));
|
||||
}
|
||||
|
||||
private static Thread startNewThread(Runnable runnable) {
|
||||
Thread runnableThread = new Thread(runnable);
|
||||
runnableThread.setDaemon(true);
|
||||
runnableThread.setPriority(Thread.NORM_PRIORITY);
|
||||
runnableThread.start();
|
||||
return runnableThread;
|
||||
}
|
||||
|
||||
private static Runnable newProcessStreamReader(AtomicBoolean runCondition, InputStream processStream, String label) {
|
||||
return () -> {
|
||||
BufferedReader processStreamReader = null;
|
||||
|
||||
try {
|
||||
processStreamReader = new BufferedReader(new InputStreamReader(processStream));
|
||||
|
||||
for (String line = "Reading..."; runCondition.get() && line != null;
|
||||
line = processStreamReader.readLine()) {
|
||||
|
||||
logger.debug("{} {}", label, line);
|
||||
}
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
}
|
||||
finally {
|
||||
IOUtils.close(processStreamReader);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void registerShutdownHook(AtomicBoolean runCondition, Process javaProcess) {
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
|
||||
runCondition.set(false);
|
||||
processStandardInStream = null;
|
||||
|
||||
try {
|
||||
javaProcess.destroyForcibly();
|
||||
javaProcess.waitFor();
|
||||
}
|
||||
catch (InterruptedException ignore) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static OutputStream cacheServer(Class<?> type) {
|
||||
return startCacheServer(type.getName());
|
||||
}
|
||||
|
||||
public static OutputStream cqCacheServer() {
|
||||
return cacheServer(CqCacheServerProcess.class);
|
||||
}
|
||||
|
||||
public static OutputStream functionCacheServer() {
|
||||
return cacheServer(FunctionCacheServerProcess.class);
|
||||
}
|
||||
|
||||
public static OutputStream startCacheServer(String args) {
|
||||
return startGemFireProcess(args, "cache server");
|
||||
}
|
||||
|
||||
protected static OutputStream startGemFireProcess(String args, String processName) {
|
||||
|
||||
String className = args.split(" ")[0];
|
||||
|
||||
if (controlFileExists(className)) {
|
||||
deleteControlFile(className);
|
||||
}
|
||||
|
||||
OutputStream outputStream = cloneJVM(args);
|
||||
|
||||
long timeout = (System.currentTimeMillis() + TIMEOUT);
|
||||
|
||||
while (!controlFileExists(className) && System.currentTimeMillis() < timeout) {
|
||||
ThreadUtils.sleep(500L);
|
||||
}
|
||||
|
||||
if (!controlFileExists(className)) {
|
||||
throw new RuntimeException(String.format("Failed to fork %s", processName));
|
||||
}
|
||||
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
public static void sendSignal() {
|
||||
|
||||
try {
|
||||
processStandardInStream.write("\n".getBytes());
|
||||
processStandardInStream.flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.info("Cannot communicate with forked VM", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean createControlFile( String name) throws IOException {
|
||||
return new File(TEMP_DIRECTORY + File.separator + name).createNewFile();
|
||||
}
|
||||
|
||||
public static boolean controlFileExists(String name) {
|
||||
return new File(TEMP_DIRECTORY + File.separator + name).isFile();
|
||||
}
|
||||
|
||||
public static boolean deleteControlFile(String name) {
|
||||
return new File(TEMP_DIRECTORY + File.separator + name).delete();
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import org.apache.geode.cache.RegionFactory;
|
||||
import org.apache.geode.cache.RegionShortcut;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
|
||||
import org.springframework.data.gemfire.ForkUtil;
|
||||
import org.springframework.data.gemfire.util.SpringUtils;
|
||||
|
||||
/**
|
||||
@@ -85,10 +84,8 @@ public class CqCacheServerProcess {
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "deprecation", "unused" })
|
||||
private static void waitForShutdown(Cache gemfireCache) throws IOException {
|
||||
|
||||
ForkUtil.createControlFile(CqCacheServerProcess.class.getName());
|
||||
@SuppressWarnings({ "unused" })
|
||||
private static void waitForShutdown(Cache gemfireCache) {
|
||||
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.fork;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -31,8 +30,6 @@ import org.apache.geode.cache.execute.FunctionContext;
|
||||
import org.apache.geode.cache.execute.FunctionService;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
|
||||
import org.springframework.data.gemfire.ForkUtil;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
* @author David Turanski
|
||||
@@ -107,15 +104,13 @@ public class FunctionCacheServerProcess {
|
||||
return gemfireCache;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "deprecation", "unused" })
|
||||
private static void waitForShutdown(Cache gemfireCache) throws IOException {
|
||||
ForkUtil.createControlFile(FunctionCacheServerProcess.class.getName());
|
||||
@SuppressWarnings({ "unused" })
|
||||
private static void waitForShutdown(Cache gemfireCache) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
scanner.nextLine();
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
static class EchoFunction implements Function {
|
||||
static class EchoFunction implements Function<Object> {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
@@ -123,7 +118,9 @@ public class FunctionCacheServerProcess {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute(FunctionContext functionContext) {
|
||||
|
||||
Object[] arguments = (Object[]) functionContext.getArguments();
|
||||
|
||||
for (int index = 0; index < arguments.length; index++) {
|
||||
@@ -137,8 +134,8 @@ public class FunctionCacheServerProcess {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
static class ServerFunction implements Function {
|
||||
@SuppressWarnings("unchecked")
|
||||
static class ServerFunction implements Function<Object> {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
||||
@@ -10,15 +10,12 @@
|
||||
* 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.springframework.data.gemfire.fork;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.gemfire.ForkUtil;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -63,9 +60,8 @@ public class SpringContainerProcess {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "deprecation", "unused" })
|
||||
private static void waitForShutdown(ConfigurableApplicationContext applicationContext) throws IOException {
|
||||
ForkUtil.createControlFile(SpringContainerProcess.class.getName());
|
||||
@SuppressWarnings({ "unused" })
|
||||
private static void waitForShutdown(ConfigurableApplicationContext applicationContext) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
scanner.nextLine();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user