This is an automated email from the ASF dual-hosted git repository.

thenatog pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new ef60e7e  NIFI-6714 Corrected OSUtils to use Process.pid interface 
method
ef60e7e is described below

commit ef60e7e404e111852b0fa7f4059ef6aea421f7f8
Author: exceptionfactory <[email protected]>
AuthorDate: Sat Apr 3 23:48:07 2021 -0500

    NIFI-6714 Corrected OSUtils to use Process.pid interface method
    
    Signed-off-by: Nathan Gough <[email protected]>
    
    This closes #4970.
---
 .../org/apache/nifi/bootstrap/util/OSUtils.java    | 155 +++++++++------------
 .../apache/nifi/bootstrap/util/OSUtilsTest.groovy  |  87 ------------
 .../apache/nifi/bootstrap/http/OSUtilsTest.java    |  56 ++++++++
 3 files changed, 124 insertions(+), 174 deletions(-)

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 95df4b3..cde0baf 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
@@ -36,62 +36,6 @@ public final class OSUtils {
      * @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
-     * @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 or 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.
@@ -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 <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;
+    }
 }
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 7facaa9..0000000
--- 
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 0000000..89a9dbc
--- /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));
+        }
+    }
+}

Reply via email to