# HG changeset patch # User aeriksso # Date 1412864453 -7200 # Node ID d0f1aec5c8b480656917bf512b14b9f1f5e5fdd2 # Parent 5e38c7e9b978437f6cdcfdb5692a7c83a3d618d1 6461635: [TESTBUG] BasicTests.sh test fails intermittently Summary: Transform dummy class instead of BigInteger to avoid complication by -Xshare. Ported from script to java. Reviewed-by: sla, alanb Contributed-by: mattias.tobiasson@oracle.com diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/ProblemList.txt --- a/test/ProblemList.txt Fri Oct 10 20:14:42 2014 +0400 +++ b/test/ProblemList.txt Thu Oct 09 16:20:53 2014 +0200 @@ -384,9 +384,6 @@ # jdk_tools -# 6461635 -com/sun/tools/attach/BasicTests.sh generic-all - # Filed 6986875 sun/tools/jps/jps-Vvml.sh generic-all diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/AgentSetup.sh --- a/test/com/sun/tools/attach/AgentSetup.sh Fri Oct 10 20:14:42 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code 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 General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - - -# -# -# Agent set - creates Agent.jar, BadAgent.jar and RedefineAgent.jar in ${TESTCLASSES} - -$JAVAC -d "${TESTCLASSES}" "${TESTSRC}"/Agent.java "${TESTSRC}"/BadAgent.java "${TESTSRC}"/RedefineAgent.java - -$JAR -cfm "${TESTCLASSES}"/Agent.jar "${TESTSRC}"/agent.mf \ - -C "${TESTCLASSES}" Agent.class - -$JAR -cfm "${TESTCLASSES}"/BadAgent.jar "${TESTSRC}"/badagent.mf \ - -C "${TESTCLASSES}" BadAgent.class - -$JAR -cfm "${TESTCLASSES}"/RedefineAgent.jar "${TESTSRC}"/redefineagent.mf \ - -C "${TESTCLASSES}" RedefineAgent.class - -agent="${TESTCLASSES}${FS}Agent.jar" -badagent="${TESTCLASSES}${FS}BadAgent.jar" -redefineagent="${TESTCLASSES}${FS}RedefineAgent.jar" - diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/Application.java --- a/test/com/sun/tools/attach/Application.java Fri Oct 10 20:14:42 2014 +0400 +++ b/test/com/sun/tools/attach/Application.java Thu Oct 09 16:20:53 2014 +0200 @@ -22,25 +22,39 @@ */ /* - * - * * A simple "Application" used by the Attach API unit tests. This application is * launched by the test. It binds to a random port and shuts down when somebody * connects to that port. + * Used port and pid are written both to stdout and to a specified file. */ import java.net.Socket; import java.net.ServerSocket; +import java.io.PrintWriter; +import jdk.testlibrary.ProcessTools; public class Application { public static void main(String args[]) throws Exception { // bind to a random port + if (args.length < 1) { + System.err.println("First argument should be path to output file."); + } + String outFileName = args[0]; + ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort(); + int pid = ProcessTools.getProcessId(); - // signal test that we are started - do not remove this line!! - System.out.println(port); + System.out.println("shutdownPort=" + port); + System.out.println("pid=" + pid); System.out.flush(); + try (PrintWriter writer = new PrintWriter(outFileName)) { + writer.println("shutdownPort=" + port); + writer.println("pid=" + pid); + writer.println("done"); + writer.flush(); + } + // wait for test harness to connect Socket s = ss.accept(); s.close(); diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/ApplicationSetup.sh --- a/test/com/sun/tools/attach/ApplicationSetup.sh Fri Oct 10 20:14:42 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code 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 General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - - -# -# -# Application Setup - creates ${TESTCLASSES}/Application.jar and the following -# procedures: -# startApplication - starts target application -# stopApplication $1 - stops application via TCP shutdown port $1 - -$JAVAC -d "${TESTCLASSES}" "${TESTSRC}"/Application.java "${TESTSRC}"/Shutdown.java -$JAR -cfm "${TESTCLASSES}"/Application.jar "${TESTSRC}"/application.mf \ - -C "${TESTCLASSES}" Application.class - -OUTPUTFILE=${TESTCLASSES}/Application.out -rm -f ${OUTPUTFILE} - -startApplication() -{ - # put all output from the app into ${OUTPUTFILE} - ${JAVA} $1 $2 $3 -jar "${TESTCLASSES}"/Application.jar > ${OUTPUTFILE} 2>&1 & - pid="$!" - - # MKS creates an intermediate shell to launch ${JAVA} so - # ${pid} is not the actual pid. We have put in a small sleep - # to give the intermediate shell process time to launch the - # "java" process. - if [ "$OS" = "Windows" ]; then - sleep 2 - if [ "${isCygwin}" = "true" ] ; then - realpid=`ps -p ${pid} | tail -1 | awk '{print $4;}'` - else - realpid=`ps -o pid,ppid,comm|grep ${pid}|grep "java"|cut -c1-6` - fi - pid=${realpid} - fi - - echo "Waiting for Application to initialize..." - attempts=0 - while true; do - sleep 1 - port=`tail -1 ${OUTPUTFILE} | sed -e 's@\\r@@g' ` - if [ ! -z "$port" ]; then - # In case of errors wait time for output to be flushed - sleep 1 - cat ${OUTPUTFILE} - break - fi - attempts=`expr $attempts + 1` - echo "Waiting $attempts second(s) ..." - done - echo "Application is process $pid, shutdown port is $port" - return $port -} - -stopApplication() -{ - $JAVA -classpath "${TESTCLASSES}" Shutdown $1 -} - diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/BasicTests.java --- a/test/com/sun/tools/attach/BasicTests.java Fri Oct 10 20:14:42 2014 +0400 +++ b/test/com/sun/tools/attach/BasicTests.java Thu Oct 09 16:20:53 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 2013 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,160 +21,257 @@ * questions. */ -/* - * - * - * Unit test for Attach API. Attaches to the given VM and performs a number - * unit tests. - */ import com.sun.tools.attach.*; import java.net.ServerSocket; import java.net.Socket; import java.io.IOException; import java.util.Properties; import java.util.List; +import java.io.File; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.JDKToolLauncher; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.ProcessThread; +/* + * @test + * @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757 + * @summary Basic unit tests for the VM attach mechanism. + * @library /lib/testlibrary + * @run build Agent BadAgent RedefineAgent Application Shutdown RedefineDummy + * @run main BasicTests + * + * This test will perform a number of basic attach tests. + */ public class BasicTests { - public static void main(String args[]) throws Exception { - String pid = args[0]; - String agent = args[1]; - String badagent = args[2]; - String redefineagent = args[3]; - System.out.println(" - Attaching to application ..."); - VirtualMachine vm = VirtualMachine.attach(pid); + /* + * The actual test is in the nested class TestMain. + * The responsibility of this class is to: + * 1. Build all needed jars. + * 2. Start the Application class in a separate process. + * 3. Find the pid and shutdown port of the running Application. + * 4. Launches the tests in nested class TestMain that will attach to the Application. + * 5. Shut down the Application. + */ + public static void main(String args[]) throws Throwable { + final String pidFile = "TestsBasic.Application.pid"; + ProcessThread processThread = null; + RunnerUtil.ProcessInfo info = null; + try { + buildJars(); + processThread = RunnerUtil.startApplication(pidFile); + info = RunnerUtil.readProcessInfo(pidFile); + runTests(info.pid); + } catch (Throwable t) { + System.out.println("TestBasic got unexpected exception: " + t); + t.printStackTrace(); + throw t; + } finally { + // Make sure the Application process is stopped. + RunnerUtil.stopApplication(info.shutdownPort, processThread); + } + } - // Test 1 - read the system properties from the target VM and - // check that property is set - System.out.println(" - Test: system properties in target VM"); - Properties props = vm.getSystemProperties(); - String value = props.getProperty("attach.test"); - if (value == null || !value.equals("true")) { - throw new RuntimeException("attach.test property not set"); - } - System.out.println(" - attach.test property set as expected"); + /** + * Runs the actual tests in nested class TestMain. + * The reason for running the tests in a separate process + * is that we need to modify the class path. + */ + private static void runTests(int pid) throws Throwable { + final String sep = File.separator; - // Test 1a - read the agent properties from the target VM. - // By default, the agent property contains "sun.java.command", - // "sun.jvm.flags", and "sun.jvm.args". - // Just sanity check - make sure not empty. - System.out.println(" - Test: agent properties in target VM"); - props = vm.getAgentProperties(); - if (props == null || props.size() == 0) { - throw new RuntimeException("Agent properties is empty"); - } - System.out.println(" - agent properties non-empty as expected"); + // Need to add jdk/lib/tools.jar to classpath. + String classpath = + System.getProperty("test.class.path", "") + File.pathSeparator + + System.getProperty("test.jdk", ".") + sep + "lib" + sep + "tools.jar"; + String testClassDir = System.getProperty("test.classes", "") + sep; + + // Argumenta : -classpath cp BasicTests$TestMain pid agent badagent redefineagent + String[] args = { + "-classpath", + classpath, + "BasicTests$TestMain", + Integer.toString(pid), + testClassDir + "Agent.jar", + testClassDir + "BadAgent.jar", + testClassDir + "RedefineAgent.jar" }; + OutputAnalyzer output = ProcessTools.executeTestJvm(args); + output.shouldHaveExitValue(0); + } - // Test 2 - attempt to load an agent that does not exist - System.out.println(" - Test: Load an agent that does not exist"); - try { - vm.loadAgent("SilverBullet.jar"); - } catch (AgentLoadException x) { - System.out.println(" - AgentLoadException thrown as expected!"); + /** + * Will build all jars needed by the tests. + */ + private static void buildJars() throws Throwable { + String[] jars = {"Agent", "BadAgent", "RedefineAgent", "Application" }; + for (String jar : jars) { + buildJar(jar); } + } - // Test 3 - load an "bad" agent (agentmain throws an exception) - System.out.println(" - Test: Load a bad agent"); - System.out.println("INFO: This test will cause error messages " - + "to appear in the application log about SilverBullet.jar " - + "not being found and an agent failing to start."); - try { - vm.loadAgent(badagent); - throw new RuntimeException( - "AgentInitializationException not thrown as expected!"); - } catch (AgentInitializationException x) { - System.out.println( - " - AgentInitializationException thrown as expected!"); - } + /** + * Will build a jar with the given name. + * Class file and manifest must already exist. + * @param jarName Name of the jar. + */ + private static void buildJar(String jarName) throws Throwable { + String testClasses = System.getProperty("test.classes", "?"); + String testSrc = System.getProperty("test.src", "?"); + String jar = String.format("%s/%s.jar", testClasses, jarName); + String manifest = String.format("%s/%s.mf", testSrc, jarName.toLowerCase()); + String clazz = String.format("%s.class", jarName); + + // Arguments to the jar command has this format: + // "-cfm TESTCLASSES/Agent.jar TESTSRC/agent.mf -C TESTCLASSES Agent.class" + RunnerUtil.createJar("-cfm", jar, manifest, "-C", testClasses, clazz); + } + + /** + * This is the actual test. It will attach to the running Application + * and perform a number of basic attach tests. + */ + public static class TestMain { + public static void main(String args[]) throws Exception { + String pid = args[0]; + String agent = args[1]; + String badagent = args[2]; + String redefineagent = args[3]; - // Test 4 - detach from the VM and attempt a load (should throw IOE) - System.out.println(" - Test: Detach from VM"); - System.out.println("INFO: This test will cause error messages " - + "to appear in the application log about a BadAgent including " - + "a RuntimeException and an InvocationTargetException."); - vm.detach(); - try { - vm.loadAgent(agent); - throw new RuntimeException("loadAgent did not throw an exception!!"); - } catch (IOException ioe) { - System.out.println(" - IOException as expected"); - } + System.out.println(" - Attaching to application ..."); + VirtualMachine vm = VirtualMachine.attach(pid); + + // Test 1 - read the system properties from the target VM and + // check that property is set + System.out.println(" - Test: system properties in target VM"); + Properties props = vm.getSystemProperties(); + String value = props.getProperty("attach.test"); + if (value == null || !value.equals("true")) { + throw new RuntimeException("attach.test property not set"); + } + System.out.println(" - attach.test property set as expected"); - // Test 5 - functional "end-to-end" test. - // Create a listener socket. Load Agent.jar into the target VM passing - // it the port number of our listener. When agent loads it should connect - // back to the tool. - - System.out.println(" - Re-attaching to application ..."); - vm = VirtualMachine.attach(pid); + // Test 1a - read the agent properties from the target VM. + // By default, the agent property contains "sun.java.command", + // "sun.jvm.flags", and "sun.jvm.args". + // Just sanity check - make sure not empty. + System.out.println(" - Test: agent properties in target VM"); + props = vm.getAgentProperties(); + if (props == null || props.size() == 0) { + throw new RuntimeException("Agent properties is empty"); + } + System.out.println(" - agent properties non-empty as expected"); - System.out.println(" - Test: End-to-end connection with agent"); + // Test 2 - attempt to load an agent that does not exist + System.out.println(" - Test: Load an agent that does not exist"); + try { + vm.loadAgent("SilverBullet.jar"); + } catch (AgentLoadException x) { + System.out.println(" - AgentLoadException thrown as expected!"); + } - ServerSocket ss = new ServerSocket(0); - int port = ss.getLocalPort(); - - System.out.println(" - Loading Agent.jar into target VM ..."); - vm.loadAgent(agent, Integer.toString(port)); + // Test 3 - load an "bad" agent (agentmain throws an exception) + System.out.println(" - Test: Load a bad agent"); + System.out.println("INFO: This test will cause error messages " + + "to appear in the application log about SilverBullet.jar " + + "not being found and an agent failing to start."); + try { + vm.loadAgent(badagent); + throw new RuntimeException( + "AgentInitializationException not thrown as expected!"); + } catch (AgentInitializationException x) { + System.out.println( + " - AgentInitializationException thrown as expected!"); + } - System.out.println(" - Waiting for agent to connect back to tool ..."); - Socket s = ss.accept(); - System.out.println(" - Connected to agent."); - - // Test 5b - functional "end-to-end" test. - // Now with an agent that does redefine. + // Test 4 - detach from the VM and attempt a load (should throw IOE) + System.out.println(" - Test: Detach from VM"); + System.out.println("INFO: This test will cause error messages " + + "to appear in the application log about a BadAgent including " + + "a RuntimeException and an InvocationTargetException."); + vm.detach(); + try { + vm.loadAgent(agent); + throw new RuntimeException("loadAgent did not throw an exception!!"); + } catch (IOException ioe) { + System.out.println(" - IOException as expected"); + } - System.out.println(" - Re-attaching to application ..."); - vm = VirtualMachine.attach(pid); + // Test 5 - functional "end-to-end" test. + // Create a listener socket. Load Agent.jar into the target VM passing + // it the port number of our listener. When agent loads it should connect + // back to the tool. + + System.out.println(" - Re-attaching to application ..."); + vm = VirtualMachine.attach(pid); + + System.out.println(" - Test: End-to-end connection with agent"); - System.out.println(" - Test: End-to-end connection with RedefineAgent"); + ServerSocket ss = new ServerSocket(0); + int port = ss.getLocalPort(); - ServerSocket ss2 = new ServerSocket(0); - int port2 = ss2.getLocalPort(); + System.out.println(" - Loading Agent.jar into target VM ..."); + vm.loadAgent(agent, Integer.toString(port)); + + System.out.println(" - Waiting for agent to connect back to tool ..."); + Socket s = ss.accept(); + System.out.println(" - Connected to agent."); - System.out.println(" - Loading RedefineAgent.jar into target VM ..."); - vm.loadAgent(redefineagent, Integer.toString(port2)); + // Test 5b - functional "end-to-end" test. + // Now with an agent that does redefine. + + System.out.println(" - Re-attaching to application ..."); + vm = VirtualMachine.attach(pid); - System.out.println(" - Waiting for RedefineAgent to connect back to tool ..."); - Socket s2 = ss2.accept(); - System.out.println(" - Connected to RedefineAgent."); + System.out.println(" - Test: End-to-end connection with RedefineAgent"); + + ServerSocket ss2 = new ServerSocket(0); + int port2 = ss2.getLocalPort(); + + System.out.println(" - Loading RedefineAgent.jar into target VM ..."); + vm.loadAgent(redefineagent, Integer.toString(port2)); - // Test 6 - list method should list the target VM - System.out.println(" - Test: VirtualMachine.list"); - List l = VirtualMachine.list(); - if (!l.isEmpty()) { - boolean found = false; - for (VirtualMachineDescriptor vmd: l) { - if (vmd.id().equals(pid)) { - found = true; - break; + System.out.println(" - Waiting for RedefineAgent to connect back to tool ..."); + Socket s2 = ss2.accept(); + System.out.println(" - Connected to RedefineAgent."); + + // Test 6 - list method should list the target VM + System.out.println(" - Test: VirtualMachine.list"); + List l = VirtualMachine.list(); + if (!l.isEmpty()) { + boolean found = false; + for (VirtualMachineDescriptor vmd: l) { + if (vmd.id().equals(pid)) { + found = true; + break; + } + } + if (found) { + System.out.println(" - " + pid + " found."); + } else { + throw new RuntimeException(pid + " not found in VM list"); } } - if (found) { - System.out.println(" - " + pid + " found."); - } else { - throw new RuntimeException(pid + " not found in VM list"); - } - } - // test 7 - basic hashCode/equals tests - System.out.println(" - Test: hashCode/equals"); + // test 7 - basic hashCode/equals tests + System.out.println(" - Test: hashCode/equals"); - VirtualMachine vm1 = VirtualMachine.attach(pid); - VirtualMachine vm2 = VirtualMachine.attach(pid); - if (!vm1.equals(vm2)) { - throw new RuntimeException("virtual machines are not equal"); - } - if (vm.hashCode() != vm.hashCode()) { - throw new RuntimeException("virtual machine hashCodes not equal"); + VirtualMachine vm1 = VirtualMachine.attach(pid); + VirtualMachine vm2 = VirtualMachine.attach(pid); + if (!vm1.equals(vm2)) { + throw new RuntimeException("virtual machines are not equal"); + } + if (vm.hashCode() != vm.hashCode()) { + throw new RuntimeException("virtual machine hashCodes not equal"); + } + System.out.println(" - hashCode/equals okay"); + + // --- + System.out.println(" - Cleaning up..."); + s.close(); + ss.close(); + s2.close(); + ss2.close(); } - System.out.println(" - hashCode/equals okay"); - - - // --- - System.out.println(" - Cleaning up..."); - s.close(); - ss.close(); - s2.close(); - ss2.close(); } } diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/BasicTests.sh --- a/test/com/sun/tools/attach/BasicTests.sh Fri Oct 10 20:14:42 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code 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 General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - - -# @test -# @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757 -# @summary Basic unit tests for the VM attach mechanism. -# -# @build BasicTests -# @run shell BasicTests.sh - -if [ "${TESTSRC}" = "" ] -then - echo "TESTSRC not set. Test cannot execute. Failed." - exit 1 -fi - -# Windows 2000 is a problem here, so we skip it, see 6962615 -osrev=`uname -a` -if [ "`echo ${osrev} | grep 'CYGWIN[^ ]*-5\.0'`" != "" ] ; then - echo "Treating as a pass, not testing Windows 2000" - exit 0 -fi -if [ "`echo ${osrev} | grep 'Windows'`" != "" ] ; then - if [ "`echo ${osrev} | grep '5 00'`" != "" ] ; then - echo "Treating as a pass, not testing Windows 2000" - exit 0 - fi -fi - -. ${TESTSRC}/CommonSetup.sh -. ${TESTSRC}/ApplicationSetup.sh -. ${TESTSRC}/AgentSetup.sh - -startApplication -Dattach.test=true -# pid = process-id, port = shutdown port - -failures=0 - -echo "Running tests ..." - -$JAVA -classpath "${TESTCLASSES}${PS}${TESTJAVA}/lib/tools.jar" \ - BasicTests $pid $agent $badagent $redefineagent 2>&1 -if [ $? != 0 ]; then failures=`expr $failures + 1`; fi - -stopApplication $port - -# Add these info messages to $OUTPUTFILE just in case someone -# looks at it and wonders about the failures. We have to do -# this after the application is stopped because it is writing -# to $OUTPUTFILE. -( -echo "" -echo "INFO: Test 2 will cause error messages about SilverBullet.jar" \ - "and an agent failing to start." -echo "INFO: Test 3 will cause error messages about BadAgent" \ - "including a RuntimeException and an InvocationTargetException." -) >> ${OUTPUTFILE} - -if [ $failures = 0 ]; - then echo "All tests passed."; - else echo "$failures test(s) failed:"; cat ${OUTPUTFILE}; -fi -exit $failures diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/CommonSetup.sh --- a/test/com/sun/tools/attach/CommonSetup.sh Fri Oct 10 20:14:42 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code 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 General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - - -# -# -# Common setup for the Attach API unit tests. Setups up the following variables: -# -# PS - path sep. -# FS - file sep. -# JAVA - java cmd. -# JAVAC - javac cmd. -# JAR - jar cmd. - -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin ) - PS=":" - FS="/" - ;; - Windows* ) - PS=";" - OS="Windows" - FS="\\" - ;; - CYGWIN* ) - PS=";" - OS="Windows" - FS="\\" - isCygwin=true - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -if [ "${TESTJAVA}" = "" ] -then - echo "TESTJAVA not set. Test cannot execute. Failed." - exit 1 -fi - -if [ "${TESTSRC}" = "" ] -then - echo "TESTSRC not set. Test cannot execute. Failed." - exit 1 -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi - -JAVA="${TESTJAVA}/bin/java" -JAVAC="${TESTJAVA}/bin/javac" -JAR="${TESTJAVA}/bin/jar" - diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/PermissionTest.java --- a/test/com/sun/tools/attach/PermissionTest.java Fri Oct 10 20:14:42 2014 +0400 +++ b/test/com/sun/tools/attach/PermissionTest.java Thu Oct 09 16:20:53 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,39 +21,119 @@ * questions. */ -/* - * - * - * Unit test for Attach API - this checks that a SecurityException is thrown as - * expected. - */ import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.AttachNotSupportedException; import java.util.Properties; +import java.io.File; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.ProcessThread; +/* + * @test + * @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757 + * @summary Basic unit tests for the VM attach mechanism. + * @library /lib/testlibrary + * @run build Application Shutdown + * @run main PermissionTest + * + * Unit test for Attach API - + * this checks that a SecurityException is thrown as expected. + */ public class PermissionTest { - public static void main(String args[]) throws Exception { - SecurityManager sm = System.getSecurityManager(); - if (sm == null) { - throw new RuntimeException("Test configuration error - no security manager set"); - } - String pid = args[0]; - boolean shouldFail = Boolean.parseBoolean(args[1]); - + /* + * The actual test is in the nested class TestMain. + * The responsibility of this class is to: + * 1. Start the Application class in a separate process. + * 2. Find the pid and shutdown port of the running Application. + * 3. Run the tests in TstMain that will attach to the Application. + * 4. Shut down the Application. + */ + public static void main(String args[]) throws Throwable { + final String pidFile ="TestPermission.Application.pid"; + ProcessThread processThread = null; + RunnerUtil.ProcessInfo info = null; try { - VirtualMachine.attach(pid).detach(); - if (shouldFail) { - throw new RuntimeException("SecurityException should be thrown"); + processThread = RunnerUtil.startApplication(pidFile); + info = RunnerUtil.readProcessInfo(pidFile); + runTests(info.pid); + } catch (Throwable t) { + System.out.println("TestPermission got unexpected exception: " + t); + t.printStackTrace(); + throw t; + } finally { + // Make sure the Application process is stopped. + RunnerUtil.stopApplication(info.shutdownPort, processThread); + } + } + + /** + * Runs the actual test the nested class TestMain. + * The test is run in a separate process because we need to add to the classpath. + */ + private static void runTests(int pid) throws Throwable { + final String sep = File.separator; + + // Need to add jdk/lib/tools.jar to classpath. + String classpath = + System.getProperty("test.class.path", "") + File.pathSeparator + + System.getProperty("test.jdk", ".") + sep + "lib" + sep + "tools.jar"; + String testSrc = System.getProperty("test.src", "") + sep; + + // Use a policy that will NOT allow attach. Test will verify exception. + String[] args = { + "-classpath", + classpath, + "-Djava.security.manager", + String.format("-Djava.security.policy=%sjava.policy.deny", testSrc), + "PermissionTest$TestMain", + Integer.toString(pid), + "true" }; + OutputAnalyzer output = ProcessTools.executeTestJvm(args); + output.shouldHaveExitValue(0); + + // Use a policy that will allow attach. + args = new String[] { + "-classpath", + classpath, + "-Djava.security.manager", + String.format("-Djava.security.policy=%sjava.policy.allow", testSrc), + "PermissionTest$TestMain", + Integer.toString(pid), + "false" }; + output = ProcessTools.executeTestJvm(args); + output.shouldHaveExitValue(0); + } + + /** + * This is the actual test code. It will attach to the Application and verify + * that we get a SecurityException when that is expected. + */ + public static class TestMain { + public static void main(String args[]) throws Exception { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + throw new RuntimeException("Test configuration error - no security manager set"); } - System.out.println(" - attached to target VM as expected."); - } catch (Exception x) { - // AttachNotSupportedException thrown when no providers can be loaded - if (shouldFail && ((x instanceof AttachNotSupportedException) || - (x instanceof SecurityException))) { - System.out.println(" - exception thrown as expected."); - } else { - throw x; + + String pid = args[0]; + boolean shouldFail = Boolean.parseBoolean(args[1]); + + try { + VirtualMachine.attach(pid).detach(); + if (shouldFail) { + throw new RuntimeException("SecurityException should be thrown"); + } + System.out.println(" - attached to target VM as expected."); + } catch (Exception x) { + // AttachNotSupportedException thrown when no providers can be loaded + if (shouldFail && ((x instanceof AttachNotSupportedException) || + (x instanceof SecurityException))) { + System.out.println(" - exception thrown as expected."); + } else { + throw x; + } } } } diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/PermissionTests.sh --- a/test/com/sun/tools/attach/PermissionTests.sh Fri Oct 10 20:14:42 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code 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 General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - - -# @test -# @bug 6173612 -# @summary Security manager and permission tests for Attach API -# -# @build PermissionTest -# @run shell PermissionTests.sh - -if [ "${TESTSRC}" = "" ] -then - echo "TESTSRC not set. Test cannot execute. Failed." - exit 1 -fi - -. ${TESTSRC}/CommonSetup.sh -. ${TESTSRC}/ApplicationSetup.sh - -failures=0 - -# Start target VM -startApplication -# pid = process-id, port = shutdown port - -echo "Deny test" -# deny -$JAVA -classpath "${TESTCLASSES}${PS}${TESTJAVA}/lib/tools.jar" \ - -Djava.security.manager \ - -Djava.security.policy=${TESTSRC}/java.policy.deny \ - PermissionTest $pid true 2>&1 -if [ $? != 0 ]; then failures=`expr $failures + 1`; fi - -# allow -echo "Allow test" -$JAVA -classpath "${TESTCLASSES}${PS}${TESTJAVA}/lib/tools.jar" \ - -Djava.security.manager \ - -Djava.security.policy=${TESTSRC}/java.policy.allow \ - PermissionTest $pid false 2>&1 -if [ $? != 0 ]; then failures=`expr $failures + 1`; fi - -# Stop target VM -stopApplication $port - -if [ $failures = 0 ]; - then echo "All tests passed."; - else echo "$failures test(s) failed:"; cat ${OUTPUTFILE}; -fi -exit $failures diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/ProviderTest.java --- a/test/com/sun/tools/attach/ProviderTest.java Fri Oct 10 20:14:42 2014 +0400 +++ b/test/com/sun/tools/attach/ProviderTest.java Thu Oct 09 16:20:53 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,24 +21,98 @@ * questions. */ -/* - * - * - * Unit test for Attach API. Attaches to the given VM and performs a number - * unit tests. - */ +import java.io.File; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.JDKToolLauncher; +import jdk.testlibrary.ProcessTools; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.spi.AttachProvider; +/* + * @test + * @bug 6173612 6273707 6277253 6335921 6348630 6342019 6381757 + * @summary Basic unit tests for the VM attach mechanism. + * @library /lib/testlibrary + * @run build SimpleProvider + * @run main ProviderTest + * + * The test will attach and detach to/from the running Application. + */ public class ProviderTest { - public static void main(String args[]) throws Exception { - // deal with internal builds where classes are loaded from the - // 'classes' directory rather than rt.jar - ClassLoader cl = AttachProvider.class.getClassLoader(); - if (cl != ClassLoader.getSystemClassLoader()) { - System.out.println("Attach API not loaded by system class loader - test skipped"); - return; + + /* + * The actual tests are in the nested class TestMain below. + * The responsibility of this class is to: + * 1. Build the needed jar. + * 2. Run tests in ProviderTest.TestMain. + */ + public static void main(String args[]) throws Throwable { + try { + buildJar(); + runTests(); + } catch (Throwable t) { + System.out.println("TestProvider got unexpected exception: " + t); + t.printStackTrace(); + throw t; } - VirtualMachine.attach("simple:1234").detach(); + } + + /** + * Runs the actual tests in the nested class TestMain. + * We need to run the tests in a separate process, + * because we need to add to the classpath. + */ + private static void runTests() throws Throwable { + final String sep = File.separator; + String testClassPath = System.getProperty("test.class.path", ""); + String testClasses = System.getProperty("test.classes", "") + sep; + String jdkLib = System.getProperty("test.jdk", ".") + sep + "lib" + sep; + + // Need to add SimpleProvider.jar and tools.jar to classpath. + String classpath = + testClassPath + File.pathSeparator + + testClasses + "SimpleProvider.jar" + File.pathSeparator + + jdkLib + "tools.jar"; + + String[] args = { + "-classpath", + classpath, + "ProviderTest$TestMain" }; + OutputAnalyzer output = ProcessTools.executeTestJvm(args); + output.shouldHaveExitValue(0); + } + + /** + * Will build the SimpleProvider.jar. + */ + private static void buildJar() throws Throwable { + final String sep = File.separator; + String testClasses = System.getProperty("test.classes", "?") + sep; + String testSrc = System.getProperty("test.src", "?") + sep; + String serviceDir = "META-INF" + sep + "services" + sep; + + RunnerUtil.createJar( + "-cf", testClasses + "SimpleProvider.jar", + "-C", testClasses, "SimpleProvider.class", + "-C", testClasses, "SimpleVirtualMachine.class", + "-C", testSrc, + serviceDir + "com.sun.tools.attach.spi.AttachProvider"); + } + + /** + * This is the actual test code that attaches to the running Application. + * This class is run in a separate process. + */ + public static class TestMain { + public static void main(String args[]) throws Exception { + // deal with internal builds where classes are loaded from the + // 'classes' directory rather than rt.jar + ClassLoader cl = AttachProvider.class.getClassLoader(); + if (cl != ClassLoader.getSystemClassLoader()) { + System.out.println("Attach API not loaded by system class loader - test skipped"); + return; + } + VirtualMachine.attach("simple:1234").detach(); + } } } diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/ProviderTests.sh --- a/test/com/sun/tools/attach/ProviderTests.sh Fri Oct 10 20:14:42 2014 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -# -# Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code 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 General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @bug 6173612 -# @summary AttachProvider unit tests -# -# @build ProviderTest SimpleProvider -# @run shell ProviderTests.sh - -if [ "${TESTSRC}" = "" ] -then - echo "TESTSRC not set. Test cannot execute. Failed." - exit 1 -fi - -. ${TESTSRC}/CommonSetup.sh - -echo "Creating JAR file ..." - -$JAR -cf ${TESTCLASSES}/SimpleProvider.jar \ - -C ${TESTCLASSES} SimpleProvider.class \ - -C ${TESTCLASSES} SimpleVirtualMachine.class \ - -C "${TESTSRC}" META-INF/services/com.sun.tools.attach.spi.AttachProvider - -echo "Running test ..." - -$JAVA -classpath \ - "${TESTCLASSES}${PS}${TESTCLASSES}/SimpleProvider.jar${PS}${TESTJAVA}/lib/tools.jar" \ - ProviderTest - diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/RedefineAgent.java --- a/test/com/sun/tools/attach/RedefineAgent.java Fri Oct 10 20:14:42 2014 +0400 +++ b/test/com/sun/tools/attach/RedefineAgent.java Thu Oct 09 16:20:53 2014 +0200 @@ -43,15 +43,15 @@ public class RedefineAgent implements ClassFileTransformer { static byte[] classfilebytes; - static final String targetName = "java.math.BigInteger"; - static final String targetNameSlashes = "java/math/BigInteger"; + static final String targetName = "RedefineDummy"; + static final String targetNameSlashes = "RedefineDummy"; static boolean gotRedefineTransform = false; // test transform and capture class bytes for redefine public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, - ProtectionDomain protectionDomain, + ProtectionDomain protectionDomain, byte[] classfileBuffer) { if (className.equals(targetNameSlashes)) { if (classBeingRedefined == null) { diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/RedefineDummy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/tools/attach/RedefineDummy.java Thu Oct 09 16:20:53 2014 +0200 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Simple dummy class used to test class retransform. + */ +public class RedefineDummy { + public String toString() { + return "RedefineDummy"; + } +} diff -r 5e38c7e9b978 -r d0f1aec5c8b4 test/com/sun/tools/attach/RunnerUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/tools/attach/RunnerUtil.java Thu Oct 09 16:20:53 2014 +0200 @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.JDKToolLauncher; +import jdk.testlibrary.ProcessTools; +import jdk.testlibrary.Utils; +import jdk.testlibrary.ProcessThread; + +/* + * Utility functions for test runners. + * (Test runner = class that launch a test) + */ +public class RunnerUtil { + /** + * The Application process must be run concurrently with our tests since + * the tests will attach to the Application. + * We will run the Application process in a separate thread. + * + * The Application must be started with flag "-Xshare:off" for the Retransform + * test in TestBasics to pass on all platforms. + * + * The Application will write its pid and shutdownPort in the given outFile. + */ + public static ProcessThread startApplication(String outFile) throws Throwable { + String classpath = System.getProperty("test.class.path", "."); + String[] args = Utils.addTestJavaOpts( + "-Dattach.test=true", "-classpath", classpath, "Application", outFile); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); + ProcessThread pt = new ProcessThread("runApplication", pb); + pt.start(); + return pt; + } + + /** + * Will stop the running Application. + * First tries to shutdown nicely by connecting to the shut down port. + * If that fails, the process will be killed hard with stopProcess(). + * + * If the nice shutdown fails, then an Exception is thrown and the test should fail. + * + * @param port The shut down port. + * @param processThread The process to stop. + */ + public static void stopApplication(int port, ProcessThread processThread) throws Throwable { + if (processThread == null) { + System.out.println("RunnerUtil.stopApplication ignored since proc is null"); + return; + } + try { + System.out.println("RunnerUtil.stopApplication waiting to for shutdown"); + OutputAnalyzer output = ProcessTools.executeTestJvm( + "-classpath", + System.getProperty("test.class.path", "."), + "Shutdown", + Integer.toString(port)); + // Verify that both the Shutdown command and the Application finished ok. + output.shouldHaveExitValue(0); + processThread.joinAndThrow(); + processThread.getOutput().shouldHaveExitValue(0); + } catch (Throwable t) { + System.out.println("RunnerUtil.stopApplication failed. Will kill it hard: " + t); + processThread.stopProcess(); + throw t; + } + } + + /** + * Creates a jar file. + * @param args Command to the jar tool. + */ + public static void createJar(String... args) { + System.out.println("Running: jar " + Arrays.toString(args)); + sun.tools.jar.Main jar = new sun.tools.jar.Main(System.out, System.err, "jar"); + if (!jar.run(args)) { + throw new RuntimeException("jar failed: args=" + Arrays.toString(args)); + } + } + + /** + * Read process info for the running Application. + * The Application writes its info to a file with this format: + * shutdownPort=42994 + * pid=19597 + * done + * + * The final "done" is used to make sure the complete file has been written + * before we try to read it. + * This function will wait until the file is available. + * + * @param filename Path to file to read. + * @return The ProcessInfo containing pid and shutdownPort. + */ + public static ProcessInfo readProcessInfo(String filename) throws Throwable { + System.out.println("Reading port and pid from file: " + filename); + File file = new File(filename); + String content = null; + + // Read file or wait for it to be created. + while (true) { + content = readFile(file); + if (content != null && content.indexOf("done") >= 0) { + break; + } + Thread.sleep(100); + } + + ProcessInfo info = new ProcessInfo(); + // search for a line with format: key=nnn + Pattern pattern = Pattern.compile("(\\w*)=([0-9]+)\\r?\\n"); + Matcher matcher = pattern.matcher(content); + while (matcher.find()) { + String key = matcher.group(1); + int value = Integer.parseInt(matcher.group(2)); + if ("pid".equals(key)) { + info.pid = value; + } else if ("shutdownPort".equals(key)) { + info.shutdownPort = value; + } + } + System.out.println("processInfo.pid:" + info.pid); + System.out.println("processInfo.shutdownPort:" + info.shutdownPort); + return info; + } + + /** + * Read the content of a file. + * @param file The file to read. + * @return The file content or null if file does not exists. + */ + public static String readFile(File file) throws IOException { + if (!file.exists()) { + return null; + } + try { + byte[] bytes = Files.readAllBytes(file.toPath()); + String content = new String(bytes); + return content; + } catch (IOException e) { + e.printStackTrace(); + throw e; + } + } + + /** + * Helper class with info of the running Application. + */ + public static class ProcessInfo { + public int pid = -1; + public int shutdownPort = -1; + } + +}