8164518: JShell: Add failover case of explicitly listening to "localhost"

Reviewed-by: jlahoda
This commit is contained in:
Robert Field 2016-08-31 10:35:51 -07:00
parent 2a62da3a63
commit 7dceb3e785
7 changed files with 116 additions and 13 deletions

View File

@ -51,8 +51,6 @@ import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
import jdk.jshell.spi.ExecutionEnv;
import static jdk.jshell.execution.Util.failOverExecutionControlGenerator;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toList;
import static jdk.jshell.Util.expunge;
/**
@ -120,7 +118,8 @@ public class JShell implements AutoCloseable {
this.executionControlGenerator = b.executionControlGenerator==null
? failOverExecutionControlGenerator(
JDIDefaultExecutionControl.launch(),
JDIDefaultExecutionControl.listen())
JDIDefaultExecutionControl.listen("localhost"),
JDIDefaultExecutionControl.listen(null))
: b.executionControlGenerator;
this.maps = new SnippetMaps(this);

View File

@ -77,17 +77,19 @@ public class JDIDefaultExecutionControl extends JDIExecutionControl {
* @return the generator
*/
public static ExecutionControl.Generator launch() {
return env -> create(env, true);
return env -> create(env, true, null);
}
/**
* Creates an ExecutionControl instance based on a JDI
* {@code ListeningConnector}.
*
* @param host explicit hostname to use, if null use discovered
* hostname, applies to listening only (!isLaunch)
* @return the generator
*/
public static ExecutionControl.Generator listen() {
return env -> create(env, false);
public static ExecutionControl.Generator listen(String host) {
return env -> create(env, false, host);
}
/**
@ -100,10 +102,15 @@ public class JDIDefaultExecutionControl extends JDIExecutionControl {
*
* @param env the context passed by
* {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
* @param isLaunch does JDI do the launch? That is, LaunchingConnector,
* otherwise we start explicitly and use ListeningConnector
* @param host explicit hostname to use, if null use discovered
* hostname, applies to listening only (!isLaunch)
* @return the channel
* @throws IOException if there are errors in set-up
*/
private static JDIDefaultExecutionControl create(ExecutionEnv env, boolean isLaunch) throws IOException {
private static JDIDefaultExecutionControl create(ExecutionEnv env,
boolean isLaunch, String host) throws IOException {
try (final ServerSocket listener = new ServerSocket(0)) {
// timeout after 60 seconds
listener.setSoTimeout(60000);
@ -111,7 +118,7 @@ public class JDIDefaultExecutionControl extends JDIExecutionControl {
// Set-up the JDI connection
JDIInitiator jdii = new JDIInitiator(port,
env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch);
env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, host);
VirtualMachine vm = jdii.vm();
Process process = jdii.process();

View File

@ -56,9 +56,11 @@ public class JDIInitiator {
* @param remoteAgent full class name of remote agent to launch
* @param isLaunch does JDI do the launch? That is, LaunchingConnector,
* otherwise we start explicitly and use ListeningConnector
* @param host explicit hostname to use, if null use discovered
* hostname, applies to listening only (!isLaunch)
*/
public JDIInitiator(int port, List<String> remoteVMOptions,
String remoteAgent, boolean isLaunch) {
public JDIInitiator(int port, List<String> remoteVMOptions, String remoteAgent,
boolean isLaunch, String host) {
this.remoteAgent = remoteAgent;
String connectorName
= isLaunch
@ -72,6 +74,9 @@ public class JDIInitiator {
= isLaunch
? launchArgs(port, String.join(" ", remoteVMOptions))
: new HashMap<>();
if (host != null && !isLaunch) {
argumentName2Value.put("localAddress", host);
}
this.connectorArgs = mergeConnectorArgs(connector, argumentName2Value);
this.vm = isLaunch
? launchTarget()

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2016, 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 8164518
* @summary Tests for standard JDI connector (without failover) -- launching
* @modules jdk.jshell/jdk.jshell.execution
* @build KullaTesting ExecutionControlTestBase
* @run testng JDILaunchingExecutionControlTest
*/
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import jdk.jshell.execution.JDIDefaultExecutionControl;
@Test
public class JDILaunchingExecutionControlTest extends ExecutionControlTestBase {
@BeforeMethod
@Override
public void setUp() {
setUp(builder -> builder.executionEngine(JDIDefaultExecutionControl.launch()));
}
}

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 8131029 8159935 8160127
* @bug 8131029 8159935 8160127 8164518
* @summary Tests for alternate JDI connector -- listening
* @modules jdk.jshell/jdk.jshell.execution
* @build KullaTesting ExecutionControlTestBase
@ -41,6 +41,6 @@ public class JDIListeningExecutionControlTest extends ExecutionControlTestBase {
@BeforeMethod
@Override
public void setUp() {
setUp(builder -> builder.executionEngine(JDIDefaultExecutionControl.listen()));
setUp(builder -> builder.executionEngine(JDIDefaultExecutionControl.listen(null)));
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2016, 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 8164518
* @summary Tests for alternate JDI connector -- listening to "localhost"
* @modules jdk.jshell/jdk.jshell.execution
* @build KullaTesting ExecutionControlTestBase
* @run testng JDIListeningLocalhostExecutionControlTest
*/
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import jdk.jshell.execution.JDIDefaultExecutionControl;
@Test
public class JDIListeningLocalhostExecutionControlTest extends ExecutionControlTestBase {
@BeforeMethod
@Override
public void setUp() {
setUp(builder -> builder.executionEngine(JDIDefaultExecutionControl.listen("localhost")));
}
}

View File

@ -159,7 +159,7 @@ class MyExecutionControl extends JDIExecutionControl {
+ System.getProperty("path.separator")
+ System.getProperty("user.dir"));
JDIInitiator jdii = new JDIInitiator(port,
opts, REMOTE_AGENT, true);
opts, REMOTE_AGENT, true, null);
VirtualMachine vm = jdii.vm();
Process process = jdii.process();