/*
 * Copyright (c) 2003, 2015, 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 4915825 4921009 4934965 4977469 8019584
 * @key randomness
 * @summary Tests behavior when client or server gets object of unknown class
 * @author Eamonn McManus
 *
 * @run clean MissingClassTest SingleClassLoader
 * @run build MissingClassTest SingleClassLoader
 * @run main MissingClassTest
 */

/*
  Tests that clients and servers react correctly when they receive
  objects of unknown classes.  This can happen easily due to version
  skew or missing jar files on one end or the other.  The default
  behaviour of causing a connection to die because of the resultant
  IOException is not acceptable!  We try sending attributes and invoke
  parameters to the server of classes it doesn't know, and we try
  sending attributes, exceptions and notifications to the client of
  classes it doesn't know.

  We also test objects that are of known class but not serializable.
  The test cases are similar.
 */

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerFactory;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectionNotification;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;

public class MissingClassTest {
    private static final int NNOTIFS = 50;

    private static ClassLoader clientLoader, serverLoader;
    private static Object serverUnknown;
    private static Exception clientUnknown;
    private static ObjectName on;
    private static final Object[] NO_OBJECTS = new Object[0];
    private static final String[] NO_STRINGS = new String[0];

    private static final Object unserializableObject = Thread.currentThread();

    private static boolean isInstance(Object o, String cn) {
        try {
            Class<?> c = Class.forName(cn);
            return c.isInstance(o);
        } catch (ClassNotFoundException x) {
            return false;
        }
    }

    public static void main(String[] args) throws Exception {
        System.out.println("Test that the client or server end of a " +
                           "connection does not fail if sent an object " +
                           "it cannot deserialize");

        on = new ObjectName("test:type=Test");

        ClassLoader testLoader = MissingClassTest.class.getClassLoader();
        clientLoader =
            new SingleClassLoader("$ServerUnknown$", HashMap.class,
                                  testLoader);
        serverLoader =
            new SingleClassLoader("$ClientUnknown$", Exception.class,
                                  testLoader);
        serverUnknown =
            clientLoader.loadClass("$ServerUnknown$").newInstance();
        clientUnknown = (Exception)
            serverLoader.loadClass("$ClientUnknown$").newInstance();

        final String[] protos = {"rmi", /*"iiop",*/ "jmxmp"};
        boolean ok = true;
        for (int i = 0; i < protos.length; i++) {
            try {
                ok &= test(protos[i]);
            } catch (Exception e) {
                System.out.println("TEST FAILED WITH EXCEPTION:");
                e.printStackTrace(System.out);
                ok = false;
            }
        }

        if (ok)
            System.out.println("Test passed");
        else {
            throw new RuntimeException("TEST FAILED");
        }
    }

    private static boolean test(String proto) throws Exception {
        System.out.println("Testing for proto " + proto);

        boolean ok = true;

        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
        mbs.createMBean(Test.class.getName(), on);

        JMXConnectorServer cs;
        JMXServiceURL url = new JMXServiceURL(proto, null, 0);
        Map<String,Object> serverMap = new HashMap<>();
        serverMap.put(JMXConnectorServerFactory.DEFAULT_CLASS_LOADER,
                      serverLoader);

        // make sure no auto-close at server side
        serverMap.put("jmx.remote.x.server.connection.timeout", "888888888");

        try {
            cs = JMXConnectorServerFactory.newJMXConnectorServer(url,
                                                                 serverMap,
                                                                 mbs);
        } catch (MalformedURLException e) {
            System.out.println("System does not recognize URL: " + url +
                               "; ignoring");
            return true;
        }
        cs.start();
        JMXServiceURL addr = cs.getAddress();
        Map<String,Object> clientMap = new HashMap<>();
        clientMap.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,
                      clientLoader);

        System.out.println("Connecting for client-unknown test");

        JMXConnector client = JMXConnectorFactory.connect(addr, clientMap);

        // add a listener to verify no failed notif
        CNListener cnListener = new CNListener();
        client.addConnectionNotificationListener(cnListener, null, null);

        MBeanServerConnection mbsc = client.getMBeanServerConnection();

        System.out.println("Getting attribute with class unknown to client");
        try {
            Object result = mbsc.getAttribute(on, "ClientUnknown");
            System.out.println("TEST FAILS: getAttribute for class " +
                               "unknown to client should fail, returned: " +
                               result);
            ok = false;
        } catch (IOException e) {
            Throwable cause = e.getCause();
            if (isInstance(cause, "org.omg.CORBA.MARSHAL"))  // see CR 4935098
                cause = cause.getCause();
            if (cause instanceof ClassNotFoundException) {
                System.out.println("Success: got an IOException wrapping " +
                                   "a ClassNotFoundException");
            } else {
                System.out.println("TEST FAILS: Caught IOException (" + e +
                                   ") but cause should be " +
                                   "ClassNotFoundException: " + cause);
                ok = false;
            }
        }

        System.out.println("Doing queryNames to ensure connection alive");
        Set<ObjectName> names = mbsc.queryNames(null, null);
        System.out.println("queryNames returned " + names);

        System.out.println("Provoke exception of unknown class");
        try {
            mbsc.invoke(on, "throwClientUnknown", NO_OBJECTS, NO_STRINGS);
            System.out.println("TEST FAILS: did not get exception");
            ok = false;
        } catch (IOException e) {
            Throwable wrapped = e.getCause();
            if (isInstance(wrapped, "org.omg.CORBA.MARSHAL"))  // see CR 4935098
                wrapped = wrapped.getCause();
            if (wrapped instanceof ClassNotFoundException) {
                System.out.println("Success: got an IOException wrapping " +
                                   "a ClassNotFoundException: " +
                                   wrapped);
            } else {
                System.out.println("TEST FAILS: Got IOException but cause " +
                                   "should be ClassNotFoundException: ");
                if (wrapped == null)
                    System.out.println("(null)");
                else
                    wrapped.printStackTrace(System.out);
                ok = false;
            }
        } catch (Exception e) {
            System.out.println("TEST FAILS: Got wrong exception: " +
                               "should be IOException with cause " +
                               "ClassNotFoundException:");
            e.printStackTrace(System.out);
            ok = false;
        }

        System.out.println("Doing queryNames to ensure connection alive");
        names = mbsc.queryNames(null, null);
        System.out.println("queryNames returned " + names);

        ok &= notifyTest(client, mbsc);

        System.out.println("Doing queryNames to ensure connection alive");
        names = mbsc.queryNames(null, null);
        System.out.println("queryNames returned " + names);

        for (int i = 0; i < 2; i++) {
            boolean setAttribute = (i == 0); // else invoke
            String what = setAttribute ? "setAttribute" : "invoke";
            System.out.println("Trying " + what +
                               " with class unknown to server");
            try {
                if (setAttribute) {
                    mbsc.setAttribute(on, new Attribute("ServerUnknown",
                                                        serverUnknown));
                } else {
                    mbsc.invoke(on, "useServerUnknown",
                                new Object[] {serverUnknown},
                                new String[] {"java.lang.Object"});
                }
                System.out.println("TEST FAILS: " + what + " with " +
                                   "class unknown to server should fail " +
                                   "but did not");
                ok = false;
            } catch (IOException e) {
                Throwable cause = e.getCause();
                if (isInstance(cause, "org.omg.CORBA.MARSHAL"))  // see CR 4935098
                    cause = cause.getCause();
                if (cause instanceof ClassNotFoundException) {
                    System.out.println("Success: got an IOException " +
                                       "wrapping a ClassNotFoundException");
                } else {
                    System.out.println("TEST FAILS: Caught IOException (" + e +
                                       ") but cause should be " +
                                       "ClassNotFoundException: " + cause);
                    e.printStackTrace(System.out); // XXX
                    ok = false;
                }
            }
        }

        System.out.println("Doing queryNames to ensure connection alive");
        names = mbsc.queryNames(null, null);
        System.out.println("queryNames returned " + names);

        System.out.println("Trying to get unserializable attribute");
        try {
            mbsc.getAttribute(on, "Unserializable");
            System.out.println("TEST FAILS: get unserializable worked " +
                               "but should not");
            ok = false;
        } catch (IOException e) {
            System.out.println("Success: got an IOException: " + e +
                               " (cause: " + e.getCause() + ")");
        }

        System.out.println("Doing queryNames to ensure connection alive");
        names = mbsc.queryNames(null, null);
        System.out.println("queryNames returned " + names);

        System.out.println("Trying to set unserializable attribute");
        try {
            Attribute attr =
                new Attribute("Unserializable", unserializableObject);
            mbsc.setAttribute(on, attr);
            System.out.println("TEST FAILS: set unserializable worked " +
                               "but should not");
            ok = false;
        } catch (IOException e) {
            System.out.println("Success: got an IOException: " + e +
                               " (cause: " + e.getCause() + ")");
        }

        System.out.println("Doing queryNames to ensure connection alive");
        names = mbsc.queryNames(null, null);
        System.out.println("queryNames returned " + names);

        System.out.println("Trying to throw unserializable exception");
        try {
            mbsc.invoke(on, "throwUnserializable", NO_OBJECTS, NO_STRINGS);
            System.out.println("TEST FAILS: throw unserializable worked " +
                               "but should not");
            ok = false;
        } catch (IOException e) {
            System.out.println("Success: got an IOException: " + e +
                               " (cause: " + e.getCause() + ")");
        }

        client.removeConnectionNotificationListener(cnListener);
        ok = ok && !cnListener.failed;

        client.close();
        cs.stop();

        if (ok)
            System.out.println("Test passed for protocol " + proto);

        System.out.println();
        return ok;
    }

    private static class TestListener implements NotificationListener {
        TestListener(LostListener ll) {
            this.lostListener = ll;
        }

        public void handleNotification(Notification n, Object h) {
            /* Connectors can handle unserializable notifications in
               one of two ways.  Either they can arrange for the
               client to get a NotSerializableException from its
               fetchNotifications call (RMI connector), or they can
               replace the unserializable notification by a
               JMXConnectionNotification.NOTIFS_LOST (JMXMP
               connector).  The former case is handled by code within
               the connector client which will end up sending a
               NOTIFS_LOST to our LostListener.  The logic here
               handles the latter case by converting it into the
               former.
             */
            if (n instanceof JMXConnectionNotification
                && n.getType().equals(JMXConnectionNotification.NOTIFS_LOST)) {
                lostListener.handleNotification(n, h);
                return;
            }

            synchronized (result) {
                if (!n.getType().equals("interesting")
                    || !n.getUserData().equals("known")) {
                    System.out.println("TestListener received strange notif: "
                                       + notificationString(n));
                    result.failed = true;
                    result.notifyAll();
                } else {
                    result.knownCount++;
                    if (result.knownCount == NNOTIFS)
                        result.notifyAll();
                }
            }
        }

        private LostListener lostListener;
    }

    private static class LostListener implements NotificationListener {
        public void handleNotification(Notification n, Object h) {
            synchronized (result) {
                handle(n, h);
            }
        }

        private void handle(Notification n, Object h) {
            if (!(n instanceof JMXConnectionNotification)) {
                System.out.println("LostListener received strange notif: " +
                                   notificationString(n));
                result.failed = true;
                result.notifyAll();
                return;
            }

            JMXConnectionNotification jn = (JMXConnectionNotification) n;
            if (!jn.getType().equals(jn.NOTIFS_LOST)) {
                System.out.println("Ignoring JMXConnectionNotification: " +
                                   notificationString(jn));
                return;
            }
            final String msg = jn.getMessage();
            if ((!msg.startsWith("Dropped ")
                 || !msg.endsWith("classes were missing locally"))
                && (!msg.startsWith("Not serializable: "))) {
                System.out.println("Surprising NOTIFS_LOST getMessage: " +
                                   msg);
            }
            if (!(jn.getUserData() instanceof Long)) {
                System.out.println("JMXConnectionNotification userData " +
                                   "not a Long: " + jn.getUserData());
                result.failed = true;
            } else {
                int lost = ((Long) jn.getUserData()).intValue();
                result.lostCount += lost;
                if (result.lostCount == NNOTIFS*2)
                    result.notifyAll();
            }
        }
    }

    private static class TestFilter implements NotificationFilter {
        public boolean isNotificationEnabled(Notification n) {
            return (n.getType().equals("interesting"));
        }
    }

    private static class Result {
        int knownCount, lostCount;
        boolean failed;
    }
    private static Result result;

    /* Send a bunch of notifications to exercise the logic to recover
       from unknown notification classes.  We have four kinds of
       notifications: "known" ones are of a class known to the client
       and which match its filters; "unknown" ones are of a class that
       match the client's filters but that the client can't load;
       "tricky" ones are unserializable; and "boring" notifications
       are of a class that the client knows but that doesn't match its
       filters.  We emit NNOTIFS notifications of each kind.  We do a
       random shuffle on these 4*NNOTIFS notifications so it is likely
       that we will cover the various different cases in the logic.

       Specifically, what we are testing here is the logic that
       recovers from a fetchNotifications request that gets a
       ClassNotFoundException.  Because the request can contain
       several notifications, the client doesn't know which of them
       generated the exception.  So it redoes a request that asks for
       just one notification.  We need to be sure that this works when
       that one notification is of an unknown class and when it is of
       a known class, and in both cases when there are filtered
       notifications that are skipped.

       We are also testing the behaviour in the server when it tries
       to include an unserializable notification in the response to a
       fetchNotifications, and in the client when that happens.

       If the test succeeds, the listener should receive the NNOTIFS
       "known" notifications, and the connection listener should
       receive an indication of NNOTIFS lost notifications
       representing the "unknown" notifications.

       We depend on some implementation-specific features here:

       1. The buffer size is sufficient to contain the 4*NNOTIFS
       notifications which are all sent at once, before the client
       gets a chance to start receiving them.

       2. When one or more notifications are dropped because they are
       of unknown classes, the NOTIFS_LOST notification contains a
       userData that is a Long with a count of the number dropped.

       3. If a notification is not serializable on the server, the
       client gets told about it somehow, rather than having it just
       dropped on the floor.  The somehow might be through an RMI
       exception, or it might be by the server replacing the
       unserializable notif by a JMXConnectionNotification.NOTIFS_LOST.
    */
    private static boolean notifyTest(JMXConnector client,
                                      MBeanServerConnection mbsc)
            throws Exception {
        System.out.println("Send notifications including unknown ones");
        result = new Result();
        LostListener ll = new LostListener();
        client.addConnectionNotificationListener(ll, null, null);
        TestListener nl = new TestListener(ll);
        mbsc.addNotificationListener(on, nl, new TestFilter(), null);
        mbsc.invoke(on, "sendNotifs", NO_OBJECTS, NO_STRINGS);

        // wait for the listeners to receive all their notifs
        // or to fail
        long deadline = System.currentTimeMillis() + 60000;
        long remain;
        while ((remain = deadline - System.currentTimeMillis()) >= 0) {
            synchronized (result) {
                if (result.failed
                    || (result.knownCount >= NNOTIFS
                        && result.lostCount >= NNOTIFS*2))
                    break;
                result.wait(remain);
            }
        }
        Thread.sleep(2);  // allow any spurious extra notifs to arrive
        if (result.failed) {
            System.out.println("TEST FAILS: Notification strangeness");
            return false;
        } else if (result.knownCount == NNOTIFS
                   && result.lostCount == NNOTIFS*2) {
            System.out.println("Success: received known notifications and " +
                               "got NOTIFS_LOST for unknown and " +
                               "unserializable ones");
            return true;
        } else if (result.knownCount >= NNOTIFS
                || result.lostCount >= NNOTIFS*2) {
            System.out.println("TEST FAILS: Received too many notifs: " +
                    "known=" + result.knownCount + "; lost=" + result.lostCount);
            return false;
        } else {
            System.out.println("TEST FAILS: Timed out without receiving " +
                               "all notifs: known=" + result.knownCount +
                               "; lost=" + result.lostCount);
            return false;
        }
    }

    public static interface TestMBean {
        public Object getClientUnknown() throws Exception;
        public void throwClientUnknown() throws Exception;
        public void setServerUnknown(Object o) throws Exception;
        public void useServerUnknown(Object o) throws Exception;
        public Object getUnserializable() throws Exception;
        public void setUnserializable(Object un) throws Exception;
        public void throwUnserializable() throws Exception;
        public void sendNotifs() throws Exception;
    }

    public static class Test extends NotificationBroadcasterSupport
            implements TestMBean {

        public Object getClientUnknown() {
            return clientUnknown;
        }

        public void throwClientUnknown() throws Exception {
            throw clientUnknown;
        }

        public void setServerUnknown(Object o) {
            throw new IllegalArgumentException("setServerUnknown succeeded "+
                                               "but should not have");
        }

        public void useServerUnknown(Object o) {
            throw new IllegalArgumentException("useServerUnknown succeeded "+
                                               "but should not have");
        }

        public Object getUnserializable() {
            return unserializableObject;
        }

        public void setUnserializable(Object un) {
            throw new IllegalArgumentException("setUnserializable succeeded " +
                                               "but should not have");
        }

        public void throwUnserializable() throws Exception {
            throw new Exception() {
                private Object unserializable = unserializableObject;
            };
        }

        public void sendNotifs() {
            /* We actually send the same four notification objects
               NNOTIFS times each.  This doesn't particularly matter,
               but note that the MBeanServer will replace "this" by
               the sender's ObjectName the first time.  Since that's
               always the same, no problem.  */
            Notification known =
                new Notification("interesting", this, 1L, 1L, "known");
            known.setUserData("known");
            Notification unknown =
                new Notification("interesting", this, 1L, 1L, "unknown");
            unknown.setUserData(clientUnknown);
            Notification boring =
                new Notification("boring", this, 1L, 1L, "boring");
            Notification tricky =
                new Notification("interesting", this, 1L, 1L, "tricky");
            tricky.setUserData(unserializableObject);

            // check that the tricky notif is indeed unserializable
            try {
                new ObjectOutputStream(new ByteArrayOutputStream())
                    .writeObject(tricky);
                throw new RuntimeException("TEST INCORRECT: tricky notif is " +
                                           "serializable");
            } catch (NotSerializableException e) {
                // OK: tricky notif is not serializable
            } catch (IOException e) {
                throw new RuntimeException("TEST INCORRECT: tricky notif " +
                                            "serialization check failed");
            }

            /* Now shuffle an imaginary deck of cards where K, U, T, and
               B (known, unknown, tricky, boring) each appear NNOTIFS times.
               We explicitly seed the random number generator so we
               can reproduce rare test failures if necessary.  We only
               use a StringBuffer so we can print the shuffled deck --
               otherwise we could just emit the notifications as the
               cards are placed.  */
            long seed = System.currentTimeMillis();
            System.out.println("Random number seed is " + seed);
            Random r = new Random(seed);
            int knownCount = NNOTIFS;   // remaining K cards
            int unknownCount = NNOTIFS; // remaining U cards
            int trickyCount = NNOTIFS;  // remaining T cards
            int boringCount = NNOTIFS;  // remaining B cards
            StringBuffer notifList = new StringBuffer();
            for (int i = NNOTIFS * 4; i > 0; i--) {
                int rand = r.nextInt(i);
                // use rand to pick a card from the remaining ones
                if ((rand -= knownCount) < 0) {
                    notifList.append('k');
                    knownCount--;
                } else if ((rand -= unknownCount) < 0) {
                    notifList.append('u');
                    unknownCount--;
                } else if ((rand -= trickyCount) < 0) {
                    notifList.append('t');
                    trickyCount--;
                } else {
                    notifList.append('b');
                    boringCount--;
                }
            }
            if (knownCount != 0 || unknownCount != 0
                || trickyCount != 0 || boringCount != 0) {
                throw new RuntimeException("TEST INCORRECT: Shuffle failed: " +
                                   "known=" + knownCount +" unknown=" +
                                   unknownCount + " tricky=" + trickyCount +
                                   " boring=" + boringCount +
                                   " deal=" + notifList);
            }
            String notifs = notifList.toString();
            System.out.println("Shuffle: " + notifs);
            for (int i = 0; i < NNOTIFS * 4; i++) {
                Notification n;
                switch (notifs.charAt(i)) {
                case 'k': n = known; break;
                case 'u': n = unknown; break;
                case 't': n = tricky; break;
                case 'b': n = boring; break;
                default:
                    throw new RuntimeException("TEST INCORRECT: Bad shuffle char: " +
                                               notifs.charAt(i));
                }
                sendNotification(n);
            }
        }
    }

    private static String notificationString(Notification n) {
        return n.getClass().getName() + "/" + n.getType() + " \"" +
            n.getMessage() + "\" <" + n.getUserData() + ">";
    }

    //
    private static class CNListener implements NotificationListener {
        public void handleNotification(Notification n, Object o) {
            if (n instanceof JMXConnectionNotification) {
                JMXConnectionNotification jn = (JMXConnectionNotification)n;
                if (JMXConnectionNotification.FAILED.equals(jn.getType())) {
                    failed = true;
                }
            }
        }

        public boolean failed = false;
    }
}
