mirror of
https://github.com/apache/nifi.git
synced 2025-03-06 17:39:36 +00:00
NIFI-6714 Corrected OSUtils to use Process.pid interface method
Signed-off-by: Nathan Gough <thenatog@gmail.com> This closes #4970.
This commit is contained in:
parent
fa3da2aa1c
commit
ef60e7e404
@ -31,62 +31,6 @@ import org.slf4j.Logger;
|
||||
* OS specific utilities with generic method interfaces
|
||||
*/
|
||||
public final class OSUtils {
|
||||
/**
|
||||
* @param process NiFi Process Reference
|
||||
* @param logger Logger Reference for Debug
|
||||
* @return Returns pid or null in-case pid could not be determined
|
||||
* This method takes {@link Process} and {@link Logger} and returns
|
||||
* the platform specific ProcessId for Unix like systems, a.k.a <b>pid</b>
|
||||
* In-case it fails to determine the pid, it will return Null.
|
||||
* Purpose for the Logger is to log any interaction for debugging.
|
||||
*/
|
||||
private static Long getUnicesPid(final Process process, final Logger logger) {
|
||||
try {
|
||||
final Class<?> procClass = process.getClass();
|
||||
final Field pidField = procClass.getDeclaredField("pid");
|
||||
pidField.setAccessible(true);
|
||||
final Object pidObject = pidField.get(process);
|
||||
|
||||
logger.debug("PID Object = {}", pidObject);
|
||||
|
||||
if (pidObject instanceof Number) {
|
||||
return ((Number) pidObject).longValue();
|
||||
}
|
||||
return null;
|
||||
} catch (final IllegalAccessException | NoSuchFieldException nsfe) {
|
||||
logger.debug("Could not find PID for child process due to {}", nsfe);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param process NiFi Process Reference
|
||||
* @param logger Logger Reference for Debug
|
||||
* @return Returns pid or null in-case pid could not be determined
|
||||
* This method takes {@link Process} and {@link Logger} and returns
|
||||
* the platform specific Handle for Win32 Systems, a.k.a <b>pid</b>
|
||||
* In-case it fails to determine the pid, it will return Null.
|
||||
* Purpose for the Logger is to log any interaction for debugging.
|
||||
*/
|
||||
private static Long getWindowsProcessId(final Process process, final Logger logger) {
|
||||
/* determine the pid on windows plattforms */
|
||||
try {
|
||||
Field f = process.getClass().getDeclaredField("handle");
|
||||
f.setAccessible(true);
|
||||
long handl = f.getLong(process);
|
||||
|
||||
Kernel32 kernel = Kernel32.INSTANCE;
|
||||
WinNT.HANDLE handle = new WinNT.HANDLE();
|
||||
handle.setPointer(Pointer.createConstant(handl));
|
||||
int ret = kernel.GetProcessId(handle);
|
||||
logger.debug("Detected pid: {}", ret);
|
||||
return Long.valueOf(ret);
|
||||
} catch (final IllegalAccessException | NoSuchFieldException nsfe) {
|
||||
logger.debug("Could not find PID for child process due to {}", nsfe);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param process NiFi Process Reference
|
||||
* @param logger Logger Reference for Debug
|
||||
@ -109,49 +53,35 @@ public final class OSUtils {
|
||||
* of the pid method to the Process API.
|
||||
*/
|
||||
Long pid = null;
|
||||
if (!System.getProperty("java.version").startsWith("1.")) {
|
||||
try {
|
||||
Method pidMethod = process.getClass().getMethod("pid");
|
||||
pidMethod.setAccessible(true);
|
||||
Object pidMethodResult = pidMethod.invoke(process);
|
||||
if (Long.class.isAssignableFrom(pidMethodResult.getClass())) {
|
||||
pid = (Long) pidMethodResult;
|
||||
} else {
|
||||
logger.debug("Could not determine PID for child process because returned PID was not " +
|
||||
"assignable to type " + Long.class.getName());
|
||||
// Get Process.pid() interface method to avoid illegal reflective access
|
||||
final Method pidMethod = Process.class.getDeclaredMethod("pid");
|
||||
final Object pidNumber = pidMethod.invoke(process);
|
||||
if (pidNumber instanceof Long) {
|
||||
pid = (Long) pidNumber;
|
||||
}
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
logger.debug("Could not find PID for child process due to {}", e);
|
||||
}
|
||||
} else if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
|
||||
pid = getUnicesPid(process, logger);
|
||||
} else if (process.getClass().getName().equals("java.lang.Win32Process")
|
||||
|| process.getClass().getName().equals("java.lang.ProcessImpl")) {
|
||||
} catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
final String processClassName = process.getClass().getName();
|
||||
if (processClassName.equals("java.lang.UNIXProcess")) {
|
||||
pid = getUnixPid(process, logger);
|
||||
} else if (processClassName.equals("java.lang.Win32Process")
|
||||
|| processClassName.equals("java.lang.ProcessImpl")) {
|
||||
pid = getWindowsProcessId(process, logger);
|
||||
} else {
|
||||
logger.debug("Failed to determine Process ID from [{}]: {}", processClassName, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
// The two Java version methods are copied from CertificateUtils in nifi-commons/nifi-security-utils
|
||||
|
||||
/**
|
||||
* Returns the JVM Java major version based on the System properties (e.g. {@code JVM 1.8.0.231} -> {code 8}).
|
||||
*
|
||||
* @return the Java major version
|
||||
*/
|
||||
public static int getJavaVersion() {
|
||||
String version = System.getProperty("java.version");
|
||||
return parseJavaVersion(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the major version parsed from the provided Java version string (e.g. {@code "1.8.0.231"} -> {@code 8}).
|
||||
*
|
||||
* @param version the Java version string
|
||||
* @return the major version as an int
|
||||
*/
|
||||
public static int parseJavaVersion(String version) {
|
||||
public static int parseJavaVersion(final String version) {
|
||||
String majorVersion;
|
||||
if (version.startsWith("1.")) {
|
||||
majorVersion = version.substring(2, 3);
|
||||
@ -167,4 +97,55 @@ public final class OSUtils {
|
||||
return Integer.parseInt(majorVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param process NiFi Process Reference
|
||||
* @param logger Logger Reference for Debug
|
||||
* @return Returns pid or null in-case pid could not be determined
|
||||
* This method takes {@link Process} and {@link Logger} and returns
|
||||
* the platform specific ProcessId for Unix like systems, a.k.a <b>pid</b>
|
||||
* In-case it fails to determine the pid, it will return Null.
|
||||
* Purpose for the Logger is to log any interaction for debugging.
|
||||
*/
|
||||
private static Long getUnixPid(final Process process, final Logger logger) {
|
||||
try {
|
||||
final Class<?> procClass = process.getClass();
|
||||
final Field pidField = procClass.getDeclaredField("pid");
|
||||
pidField.setAccessible(true);
|
||||
final Object pidObject = pidField.get(process);
|
||||
|
||||
if (pidObject instanceof Number) {
|
||||
return ((Number) pidObject).longValue();
|
||||
}
|
||||
return null;
|
||||
} catch (final IllegalAccessException | NoSuchFieldException e) {
|
||||
logger.debug("Could not find Unix PID", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param process NiFi Process Reference
|
||||
* @param logger Logger Reference for Debug
|
||||
* @return Returns pid or null in-case pid could not be determined
|
||||
* This method takes {@link Process} and {@link Logger} and returns
|
||||
* the platform specific Handle for Win32 Systems, a.k.a <b>pid</b>
|
||||
* In-case it fails to determine the pid, it will return Null.
|
||||
* Purpose for the Logger is to log any interaction for debugging.
|
||||
*/
|
||||
private static Long getWindowsProcessId(final Process process, final Logger logger) {
|
||||
Long pid = null;
|
||||
try {
|
||||
final Field handleField = process.getClass().getDeclaredField("handle");
|
||||
handleField.setAccessible(true);
|
||||
long peer = handleField.getLong(process);
|
||||
|
||||
final Kernel32 kernel = Kernel32.INSTANCE;
|
||||
final WinNT.HANDLE handle = new WinNT.HANDLE();
|
||||
handle.setPointer(Pointer.createConstant(peer));
|
||||
pid = Long.valueOf(kernel.GetProcessId(handle));
|
||||
} catch (final IllegalAccessException | NoSuchFieldException e) {
|
||||
logger.debug("Could not find Windows PID", e);
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +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.nifi.bootstrap.util
|
||||
|
||||
|
||||
import org.junit.After
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
class OSUtilsTest extends GroovyTestCase {
|
||||
private static final Logger logger = LoggerFactory.getLogger(OSUtilsTest.class)
|
||||
|
||||
@BeforeClass
|
||||
static void setUpOnce() throws Exception {
|
||||
logger.metaClass.methodMissing = { String name, args ->
|
||||
logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
static void tearDownOnce() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
void setUp() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
void tearDown() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldParseJavaMajorVersion8Below() {
|
||||
// Arrange
|
||||
def possibleVersionStrings = ["1.8", "1.8.0.0", "1.8.0_262"]
|
||||
|
||||
// Act
|
||||
def results = possibleVersionStrings.collect {
|
||||
OSUtils.parseJavaVersion(it)
|
||||
}
|
||||
logger.info("Parsed Java versions: ${results}")
|
||||
|
||||
// Assert
|
||||
assert results.every { it == 8 }
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShouldParseJavaMajorVersion9Plus() {
|
||||
// Arrange
|
||||
def possibleVersionStrings = [
|
||||
"11.0.6", "11.0.0", "11.12.13", "11"
|
||||
]
|
||||
|
||||
// Act
|
||||
def results = possibleVersionStrings.collect {
|
||||
OSUtils.parseJavaVersion(it)
|
||||
}
|
||||
logger.info("Parsed Java versions: ${results}")
|
||||
|
||||
// Assert
|
||||
assert results.every { it == 11 }
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.nifi.bootstrap.http;
|
||||
|
||||
import org.apache.nifi.bootstrap.util.OSUtils;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class OSUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testGetPid() throws IOException {
|
||||
final ProcessBuilder builder = new ProcessBuilder();
|
||||
final Process process = builder.command("java").start();
|
||||
final Logger logger = LoggerFactory.getLogger("testing");
|
||||
final Long pid = OSUtils.getProcessId(process, logger);
|
||||
process.destroy();
|
||||
assertNotNull("Process ID not found", pid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseJavaVersion8() {
|
||||
final String[] versions = new String[] { "1.8", "1.8.0", "1.8.0_100" };
|
||||
for (final String version : versions) {
|
||||
assertEquals(8, OSUtils.parseJavaVersion(version));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseJavaVersion11() {
|
||||
final String[] versions = new String[] { "11", "11.0", "11.0.11" };
|
||||
for (final String version : versions) {
|
||||
assertEquals(11, OSUtils.parseJavaVersion(version));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user