657b9db1ba
Updated files with 2011, 2012 and 2013 years according to the file's last updated date Reviewed-by: tbell, lancea, chegar
807 lines
29 KiB
Java
807 lines
29 KiB
Java
/*
|
|
* Copyright (c) 2003, 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.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 4940957 8025205
|
|
* @summary Tests behaviour when connections break
|
|
* @author Eamonn McManus
|
|
* @run clean BrokenConnectionTest
|
|
* @run build BrokenConnectionTest
|
|
* @run main BrokenConnectionTest
|
|
*/
|
|
|
|
import java.io.*;
|
|
import java.lang.reflect.*;
|
|
import java.nio.channels.ServerSocketChannel;
|
|
import java.net.*;
|
|
import java.rmi.server.*;
|
|
import java.util.*;
|
|
|
|
import java.rmi.UnmarshalException;
|
|
|
|
import javax.management.*;
|
|
import javax.management.remote.*;
|
|
import javax.management.remote.rmi.*;
|
|
|
|
// resolve ambiguity
|
|
import java.lang.reflect.Proxy;
|
|
|
|
public class BrokenConnectionTest {
|
|
private static ObjectName DELEGATE_NAME;
|
|
private static ObjectName BREAK_NAME;
|
|
private static ObjectName LISTENER_NAME;
|
|
public static void main(String[] args) throws Exception {
|
|
DELEGATE_NAME =
|
|
new ObjectName("JMImplementation:type=MBeanServerDelegate");
|
|
BREAK_NAME = new ObjectName("test:type=Break");
|
|
LISTENER_NAME = new ObjectName("test:type=Listener");
|
|
|
|
String failed = "";
|
|
|
|
final String[] protos = {"rmi", "jmxmp"};
|
|
|
|
for (int i = 0; i < protos.length; i++) {
|
|
final String proto = protos[i];
|
|
System.out.println();
|
|
System.out.println("------- Testing for " + proto + " -------");
|
|
try {
|
|
if (!test(proto))
|
|
failed += " " + proto;
|
|
} catch (Exception e) {
|
|
System.out.println("FAILED WITH EXCEPTION:");
|
|
e.printStackTrace(System.out);
|
|
failed += " " + proto;
|
|
}
|
|
}
|
|
|
|
System.out.println();
|
|
|
|
if (failed.length() > 0) {
|
|
System.out.println("TEST FAILED FOR:" + failed);
|
|
System.exit(1);
|
|
}
|
|
|
|
System.out.println("Test passed");
|
|
}
|
|
|
|
private static boolean test(String proto) throws Exception {
|
|
if (proto.equals("rmi"))
|
|
return rmiTest();
|
|
else if (proto.equals("jmxmp"))
|
|
return jmxmpTest();
|
|
else
|
|
throw new AssertionError(proto);
|
|
}
|
|
|
|
private static interface Breakable {
|
|
public JMXConnectorServer createConnectorServer(MBeanServer mbs)
|
|
throws IOException;
|
|
public void setBroken(boolean broken);
|
|
}
|
|
|
|
private static interface TestAction {
|
|
public String toString();
|
|
public boolean test(MBeanServerConnection mbsc, Breakable breakable)
|
|
throws Exception;
|
|
}
|
|
|
|
private static abstract class Operation implements TestAction {
|
|
public String toString() {
|
|
return opName() + ", break, " + opName();
|
|
}
|
|
void init(MBeanServerConnection mbsc) throws Exception {}
|
|
abstract String opName();
|
|
public boolean test(MBeanServerConnection mbsc, Breakable breakable)
|
|
throws Exception {
|
|
init(mbsc);
|
|
operation(mbsc);
|
|
System.out.println("Client ran " + opName() + " OK");
|
|
breakable.setBroken(true);
|
|
System.out.println("Broke connection, run " + opName() + " again");
|
|
try {
|
|
operation(mbsc);
|
|
System.out.println("TEST FAILED: " + opName() +
|
|
" should fail!");
|
|
return false;
|
|
} catch (IOException e) {
|
|
System.out.println("Got IOException as expected (" + e + ")");
|
|
}
|
|
return true;
|
|
}
|
|
abstract void operation(MBeanServerConnection mbsc) throws Exception;
|
|
}
|
|
|
|
private static TestAction[] tests = {
|
|
new Operation() {
|
|
String opName() {
|
|
return "getDefaultDomain";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.getDefaultDomain();
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "addNotificationListener(NL)";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.addNotificationListener(DELEGATE_NAME,
|
|
new CountListener(), null, null);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "addNotificationListener(MB)";
|
|
}
|
|
void init(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.createMBean(CountListener.class.getName(),
|
|
LISTENER_NAME);
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.addNotificationListener(DELEGATE_NAME, LISTENER_NAME,
|
|
null, null);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "removeNotificationListener(NL)";
|
|
}
|
|
void init(MBeanServerConnection mbsc) throws Exception {
|
|
for (int i = 0; i < NLISTENERS; i++) {
|
|
NotificationListener l = new CountListener();
|
|
mbsc.addNotificationListener(DELEGATE_NAME, l, null, null);
|
|
listeners.add(l);
|
|
}
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
NotificationListener l = (NotificationListener)
|
|
listeners.remove(0);
|
|
mbsc.removeNotificationListener(DELEGATE_NAME, l, null, null);
|
|
}
|
|
static final int NLISTENERS = 2;
|
|
List/*<NotificationListener>*/ listeners = new ArrayList();
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "removeNotificationListener(MB)";
|
|
}
|
|
void init(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.createMBean(CountListener.class.getName(),
|
|
LISTENER_NAME);
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
try {
|
|
mbsc.removeNotificationListener(DELEGATE_NAME,
|
|
LISTENER_NAME,
|
|
null, null);
|
|
throw new IllegalArgumentException("removeNL should not " +
|
|
"have worked!");
|
|
} catch (ListenerNotFoundException e) {
|
|
// normal - there isn't one!
|
|
}
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "createMBean(className, objectName)";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
ObjectName name =
|
|
new ObjectName("test:instance=" + nextInstance());
|
|
mbsc.createMBean(CountListener.class.getName(), name);
|
|
}
|
|
private synchronized int nextInstance() {
|
|
return ++instance;
|
|
}
|
|
private int instance;
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "getAttribute";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.getAttribute(DELEGATE_NAME, "ImplementationName");
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "getAttributes";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.getAttribute(DELEGATE_NAME, "ImplementationName");
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "getDomains";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.getDomains();
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "getMBeanCount";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.getMBeanCount();
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "getMBeanInfo";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.getMBeanInfo(DELEGATE_NAME);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "getObjectInstance";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.getObjectInstance(DELEGATE_NAME);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "invoke";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.invoke(BREAK_NAME, "doNothing", new Object[0],
|
|
new String[0]);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "isInstanceOf";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.isInstanceOf(DELEGATE_NAME, "whatsit");
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "isRegistered";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.isRegistered(DELEGATE_NAME);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "queryMBeans";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.queryMBeans(new ObjectName("*:*"), null);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "queryNames";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.queryNames(new ObjectName("*:*"), null);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "setAttribute";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
mbsc.setAttribute(BREAK_NAME,
|
|
new Attribute("Nothing", null));
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "setAttributes";
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
AttributeList attrs = new AttributeList();
|
|
attrs.add(new Attribute("Nothing", null));
|
|
mbsc.setAttributes(BREAK_NAME, attrs);
|
|
}
|
|
},
|
|
new Operation() {
|
|
String opName() {
|
|
return "unregisterMBean";
|
|
}
|
|
void init(MBeanServerConnection mbsc) throws Exception {
|
|
for (int i = 0; i < NBEANS; i++) {
|
|
ObjectName name = new ObjectName("test:instance=" + i);
|
|
mbsc.createMBean(CountListener.class.getName(), name);
|
|
names.add(name);
|
|
}
|
|
}
|
|
void operation(MBeanServerConnection mbsc) throws Exception {
|
|
ObjectName name = (ObjectName) names.remove(0);
|
|
mbsc.unregisterMBean(name);
|
|
}
|
|
private static final int NBEANS = 2;
|
|
private List/*<ObjectName>*/ names = new ArrayList();
|
|
},
|
|
new TestAction() {
|
|
public String toString() {
|
|
return "break during send for setAttribute";
|
|
}
|
|
public boolean test(MBeanServerConnection mbsc,
|
|
Breakable breakable) throws Exception {
|
|
Attribute attr =
|
|
new Attribute("Break", new BreakWhenSerialized(breakable));
|
|
try {
|
|
mbsc.setAttribute(BREAK_NAME, attr);
|
|
System.out.println("TEST FAILED: setAttribute with " +
|
|
"BreakWhenSerializable did not fail!");
|
|
return false;
|
|
} catch (IOException e) {
|
|
System.out.println("Got IOException as expected: " + e);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
},
|
|
new TestAction() {
|
|
public String toString() {
|
|
return "break during receive for getAttribute";
|
|
}
|
|
public boolean test(MBeanServerConnection mbsc,
|
|
Breakable breakable) throws Exception {
|
|
try {
|
|
mbsc.getAttribute(BREAK_NAME, "Break");
|
|
System.out.println("TEST FAILED: getAttribute of " +
|
|
"BreakWhenSerializable did not fail!");
|
|
return false;
|
|
} catch (IOException e) {
|
|
System.out.println("Got IOException as expected: " + e);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
},
|
|
};
|
|
|
|
public static interface BreakMBean {
|
|
public BreakWhenSerialized getBreak();
|
|
public void setBreak(BreakWhenSerialized x);
|
|
// public void breakOnNotify();
|
|
public void doNothing();
|
|
public void setNothing(Object x);
|
|
}
|
|
|
|
public static class Break
|
|
extends NotificationBroadcasterSupport implements BreakMBean {
|
|
public Break(Breakable breakable) {
|
|
this.breakable = breakable;
|
|
}
|
|
|
|
public BreakWhenSerialized getBreak() {
|
|
return new BreakWhenSerialized(breakable);
|
|
}
|
|
|
|
public void setBreak(BreakWhenSerialized x) {
|
|
throw new IllegalArgumentException("setBreak worked but " +
|
|
"should not!");
|
|
}
|
|
|
|
// public void breakOnNotify() {
|
|
// Notification broken = new Notification("type", "source", 0L);
|
|
// broken.setUserData(new BreakWhenSerialized(breakable));
|
|
// sendNotification(broken);
|
|
// }
|
|
|
|
public void doNothing() {}
|
|
|
|
public void setNothing(Object x) {}
|
|
|
|
private final Breakable breakable;
|
|
}
|
|
|
|
private static class BreakWhenSerialized implements Serializable {
|
|
BreakWhenSerialized(Breakable breakable) {
|
|
this.breakable = breakable;
|
|
}
|
|
|
|
private void writeObject(ObjectOutputStream out) throws IOException {
|
|
breakable.setBroken(true);
|
|
}
|
|
|
|
private final transient Breakable breakable;
|
|
}
|
|
|
|
private static class FailureNotificationFilter
|
|
implements NotificationFilter {
|
|
public boolean isNotificationEnabled(Notification n) {
|
|
System.out.println("Filter: " + n + " (" + n.getType() + ")");
|
|
|
|
final String failed =
|
|
JMXConnectionNotification.FAILED;
|
|
return (n instanceof JMXConnectionNotification
|
|
&& n.getType().equals(JMXConnectionNotification.FAILED));
|
|
}
|
|
}
|
|
|
|
public static interface CountListenerMBean {}
|
|
|
|
public static class CountListener
|
|
implements CountListenerMBean, NotificationListener {
|
|
public synchronized void handleNotification(Notification n, Object h) {
|
|
count++;
|
|
}
|
|
|
|
int count;
|
|
}
|
|
|
|
private static boolean test(Breakable breakable)
|
|
throws Exception {
|
|
boolean alreadyMissedFailureNotif = false;
|
|
String failed = "";
|
|
for (int i = 1; i <= tests.length; i++) {
|
|
TestAction ta = tests[i - 1];
|
|
System.out.println();
|
|
System.out.println("Test " + i + ": " + ta);
|
|
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
|
|
Break breakMBean = new Break(breakable);
|
|
mbs.registerMBean(breakMBean, BREAK_NAME);
|
|
JMXConnectorServer cs = breakable.createConnectorServer(mbs);
|
|
System.out.println("Created and started connector server");
|
|
JMXServiceURL addr = cs.getAddress();
|
|
JMXConnector cc = JMXConnectorFactory.connect(addr);
|
|
CountListener failureListener = new CountListener();
|
|
NotificationFilter failureFilter = new FailureNotificationFilter();
|
|
cc.addConnectionNotificationListener(failureListener,
|
|
failureFilter,
|
|
null);
|
|
MBeanServerConnection mbsc = cc.getMBeanServerConnection();
|
|
System.out.println("Client connected OK");
|
|
boolean thisok = ta.test(mbsc, breakable);
|
|
|
|
try {
|
|
System.out.println("Stopping server");
|
|
cs.stop();
|
|
} catch (IOException e) {
|
|
System.out.println("Ignoring exception on stop: " + e);
|
|
}
|
|
if (thisok) {
|
|
System.out.println("Waiting for failure notif");
|
|
// pass or test timeout. see 8025205
|
|
do {
|
|
Thread.sleep(100);
|
|
} while (failureListener.count < 1);
|
|
|
|
Thread.sleep(1000); // if more notif coming ...
|
|
if (failureListener.count > 1) {
|
|
System.out.println("Got too many failure notifs: " +
|
|
failureListener.count);
|
|
thisok = false;
|
|
}
|
|
}
|
|
if (!thisok)
|
|
failed = failed + " " + i;
|
|
System.out.println("Test " + i + (thisok ? " passed" : " FAILED"));
|
|
breakable.setBroken(false);
|
|
}
|
|
if (failed.equals(""))
|
|
return true;
|
|
else {
|
|
System.out.println("FAILING CASES:" + failed);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static class BreakableRMI implements Breakable {
|
|
public JMXConnectorServer createConnectorServer(MBeanServer mbs)
|
|
throws IOException {
|
|
JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
|
|
Map env = new HashMap();
|
|
env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
|
|
brssf);
|
|
JMXConnectorServer cs =
|
|
JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
|
|
cs.start();
|
|
return cs;
|
|
}
|
|
|
|
public void setBroken(boolean broken) {
|
|
brssf.setBroken(broken);
|
|
}
|
|
|
|
private final BreakableRMIServerSocketFactory brssf =
|
|
new BreakableRMIServerSocketFactory();
|
|
}
|
|
|
|
private static boolean rmiTest() throws Exception {
|
|
System.out.println("RMI broken connection test");
|
|
Breakable breakable = new BreakableRMI();
|
|
return test(breakable);
|
|
}
|
|
|
|
private static class BreakableRMIServerSocketFactory
|
|
implements RMIServerSocketFactory {
|
|
|
|
public synchronized ServerSocket createServerSocket(int port)
|
|
throws IOException {
|
|
if (broken)
|
|
throw new IOException("ServerSocket has been broken");
|
|
BreakableServerSocket bss = new BreakableServerSocket(port);
|
|
bssList.add(bss);
|
|
return bss;
|
|
}
|
|
|
|
synchronized void setBroken(boolean broken) {
|
|
this.broken = broken;
|
|
// System.out.println("BRSSF.setBroken(" + broken + ")");
|
|
for (Iterator it = bssList.iterator(); it.hasNext(); ) {
|
|
BreakableServerSocket bss = (BreakableServerSocket) it.next();
|
|
// System.out.println((broken ? "" : "un") + "break " + bss);
|
|
bss.setBroken(broken);
|
|
}
|
|
}
|
|
|
|
private final List/*<BreakableServerSocket>*/ bssList =
|
|
new ArrayList();
|
|
private boolean broken = false;
|
|
}
|
|
|
|
private static class BreakableJMXMP implements Breakable {
|
|
BreakableJMXMP() throws IOException {
|
|
bss = new BreakableServerSocket(0);
|
|
}
|
|
|
|
public JMXConnectorServer createConnectorServer(MBeanServer mbs)
|
|
throws IOException {
|
|
try {
|
|
InvocationHandler scsih =
|
|
new SocketConnectionServerInvocationHandler(bss);
|
|
final String mcs =
|
|
"javax.management.remote.generic.MessageConnectionServer";
|
|
final Class messageConnectionServerClass = Class.forName(mcs);
|
|
final Class[] proxyInterfaces = {messageConnectionServerClass};
|
|
Object socketConnectionServer =
|
|
Proxy.newProxyInstance(this.getClass().getClassLoader(),
|
|
proxyInterfaces,
|
|
scsih);
|
|
Map env = new HashMap();
|
|
env.put("jmx.remote.message.connection.server",
|
|
socketConnectionServer);
|
|
final String gcs =
|
|
"javax.management.remote.generic.GenericConnectorServer";
|
|
final Class genericConnectorServerClass = Class.forName(gcs);
|
|
final Class[] constrTypes = {Map.class, MBeanServer.class};
|
|
final Constructor constr =
|
|
genericConnectorServerClass.getConstructor(constrTypes);
|
|
JMXConnectorServer cs = (JMXConnectorServer)
|
|
constr.newInstance(new Object[] {env, mbs});
|
|
cs.start();
|
|
return cs;
|
|
} catch (Exception e) {
|
|
e.printStackTrace(System.out);
|
|
throw new AssertionError(e);
|
|
}
|
|
}
|
|
|
|
public void setBroken(boolean broken) {
|
|
bss.setBroken(broken);
|
|
}
|
|
|
|
private final BreakableServerSocket bss;
|
|
}
|
|
|
|
private static boolean jmxmpTest() throws Exception {
|
|
System.out.println("JMXMP broken connection test");
|
|
try {
|
|
Class.forName("javax.management.remote.generic.GenericConnector");
|
|
} catch (ClassNotFoundException e) {
|
|
System.out.println("Optional classes not present, skipping test");
|
|
return true;
|
|
}
|
|
Breakable breakable = new BreakableJMXMP();
|
|
return test(breakable);
|
|
}
|
|
|
|
private static class BreakableServerSocket extends ServerSocket {
|
|
BreakableServerSocket(int port) throws IOException {
|
|
super();
|
|
ss = new ServerSocket(port);
|
|
}
|
|
|
|
synchronized void setBroken(boolean broken) {
|
|
this.broken = broken;
|
|
// System.out.println("BSS.setBroken(" + broken + ")");
|
|
if (!broken)
|
|
return;
|
|
for (Iterator it = sList.iterator(); it.hasNext(); ) {
|
|
Socket s = (Socket) it.next();
|
|
try {
|
|
// System.out.println("Break: " + s);
|
|
s.close();
|
|
} catch (IOException e) {
|
|
System.out.println("Unable to close socket: " + s +
|
|
", ignoring (" + e + ")");
|
|
}
|
|
it.remove();
|
|
}
|
|
}
|
|
|
|
public void bind(SocketAddress endpoint) throws IOException {
|
|
ss.bind(endpoint);
|
|
}
|
|
|
|
public void bind(SocketAddress endpoint, int backlog)
|
|
throws IOException {
|
|
ss.bind(endpoint, backlog);
|
|
}
|
|
|
|
public InetAddress getInetAddress() {
|
|
return ss.getInetAddress();
|
|
}
|
|
|
|
public int getLocalPort() {
|
|
return ss.getLocalPort();
|
|
}
|
|
|
|
public SocketAddress getLocalSocketAddress() {
|
|
return ss.getLocalSocketAddress();
|
|
}
|
|
|
|
public Socket accept() throws IOException {
|
|
// System.out.println("BSS.accept");
|
|
Socket s = ss.accept();
|
|
// System.out.println("BSS.accept returned: " + s);
|
|
if (broken)
|
|
s.close();
|
|
else
|
|
sList.add(s);
|
|
return s;
|
|
}
|
|
|
|
public void close() throws IOException {
|
|
ss.close();
|
|
}
|
|
|
|
public ServerSocketChannel getChannel() {
|
|
return ss.getChannel();
|
|
}
|
|
|
|
public boolean isBound() {
|
|
return ss.isBound();
|
|
}
|
|
|
|
public boolean isClosed() {
|
|
return ss.isClosed();
|
|
}
|
|
|
|
public void setSoTimeout(int timeout) throws SocketException {
|
|
ss.setSoTimeout(timeout);
|
|
}
|
|
|
|
public int getSoTimeout() throws IOException {
|
|
return ss.getSoTimeout();
|
|
}
|
|
|
|
public void setReuseAddress(boolean on) throws SocketException {
|
|
ss.setReuseAddress(on);
|
|
}
|
|
|
|
public boolean getReuseAddress() throws SocketException {
|
|
return ss.getReuseAddress();
|
|
}
|
|
|
|
public String toString() {
|
|
return "BreakableServerSocket wrapping " + ss.toString();
|
|
}
|
|
|
|
public void setReceiveBufferSize (int size) throws SocketException {
|
|
ss.setReceiveBufferSize(size);
|
|
}
|
|
|
|
public int getReceiveBufferSize() throws SocketException {
|
|
return ss.getReceiveBufferSize();
|
|
}
|
|
|
|
private final ServerSocket ss;
|
|
private final List/*<Socket>*/ sList = new ArrayList();
|
|
private boolean broken = false;
|
|
}
|
|
|
|
/* We do a lot of messy reflection stuff here because we don't
|
|
want to reference the optional parts of the JMX Remote API in
|
|
an environment (J2SE) where they won't be present. */
|
|
|
|
/* This class implements the logic that allows us to pretend that
|
|
we have a class that looks like this:
|
|
class SocketConnectionServer implements MessageConnectionServer {
|
|
public MessageConnection accept() throws IOException {...}
|
|
public JMXServiceURL getAddress() {...}
|
|
public void start(Map env) throws IOException {...}
|
|
public void stop() throws IOException {...}
|
|
}
|
|
*/
|
|
private static class SocketConnectionServerInvocationHandler
|
|
implements InvocationHandler {
|
|
SocketConnectionServerInvocationHandler(ServerSocket ss) {
|
|
this.ss = ss;
|
|
}
|
|
|
|
public Object invoke(Object proxy, Method method, Object[] args)
|
|
throws Exception {
|
|
final String mname = method.getName();
|
|
try {
|
|
if (mname.equals("accept"))
|
|
return accept();
|
|
else if (mname.equals("getAddress"))
|
|
return getAddress();
|
|
else if (mname.equals("start"))
|
|
start((Map) args[0]);
|
|
else if (mname.equals("stop"))
|
|
stop();
|
|
else // probably a method inherited from Object
|
|
return method.invoke(this, args);
|
|
} catch (InvocationTargetException ite) {
|
|
Throwable t = ite.getCause();
|
|
if (t instanceof IOException) {
|
|
throw (IOException)t;
|
|
} else if (t instanceof RuntimeException) {
|
|
throw (RuntimeException)t;
|
|
} else {
|
|
throw ite;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private Object/*MessageConnection*/ accept() throws Exception {
|
|
System.out.println("SCSIH.accept()");
|
|
Socket s = ss.accept();
|
|
Class socketConnectionClass =
|
|
Class.forName("com.sun.jmx.remote.socket.SocketConnection");
|
|
Constructor constr =
|
|
socketConnectionClass.getConstructor(new Class[] {Socket.class});
|
|
return constr.newInstance(new Object[] {s});
|
|
// InvocationHandler scih = new SocketConnectionInvocationHandler(s);
|
|
// Class messageConnectionClass =
|
|
// Class.forName("javax.management.generic.MessageConnection");
|
|
// return Proxy.newProxyInstance(this.getClass().getClassLoader(),
|
|
// new Class[] {messageConnectionClass},
|
|
// scih);
|
|
}
|
|
|
|
private JMXServiceURL getAddress() throws Exception {
|
|
System.out.println("SCSIH.getAddress()");
|
|
return new JMXServiceURL("jmxmp", null, ss.getLocalPort());
|
|
}
|
|
|
|
private void start(Map env) throws IOException {
|
|
System.out.println("SCSIH.start(" + env + ")");
|
|
}
|
|
|
|
private void stop() throws IOException {
|
|
System.out.println("SCSIH.stop()");
|
|
}
|
|
|
|
private final ServerSocket ss;
|
|
}
|
|
}
|