alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (BrokenConnectionTest.java)

This example Java source code file (BrokenConnectionTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

breakable, breakableserversocket, breakwhenserialized, class, countlistener, exception, ioexception, jmxconnectorserver, jmxserviceurl, listener_name, management, net, network, objectname, operation, reflection, rmi, string, testaction, util

The BrokenConnectionTest.java Java example source code

/*
 * 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;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java BrokenConnectionTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.