diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/util/OSUtils.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/util/OSUtils.java
index 95df4b3bc8..cde0bafe23 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/util/OSUtils.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/util/OSUtils.java
@@ -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 pid
- * 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 pid
- * 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());
- }
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- logger.debug("Could not find PID for child process due to {}", e);
+ try {
+ // 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 (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());
}
- } 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")) {
- pid = getWindowsProcessId(process, logger);
}
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 pid
+ * 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 pid
+ * 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;
+ }
}
diff --git a/nifi-bootstrap/src/test/groovy/org/apache/nifi/bootstrap/util/OSUtilsTest.groovy b/nifi-bootstrap/src/test/groovy/org/apache/nifi/bootstrap/util/OSUtilsTest.groovy
deleted file mode 100644
index 7facaa9b0e..0000000000
--- a/nifi-bootstrap/src/test/groovy/org/apache/nifi/bootstrap/util/OSUtilsTest.groovy
+++ /dev/null
@@ -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 }
- }
-}
diff --git a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/OSUtilsTest.java b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/OSUtilsTest.java
new file mode 100644
index 0000000000..89a9dbc6ba
--- /dev/null
+++ b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/OSUtilsTest.java
@@ -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));
+ }
+ }
+}