/*
 * Copyright 2004-2005 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * @test
 * @bug 5093922 2120055
 * @summary Test that NotificationBroadcasterSupport can be subclassed
 * and used with synchronized(this) without causing deadlock
 * @author Eamonn McManus
 * @run clean BroadcasterSupportDeadlockTest
 * @run build BroadcasterSupportDeadlockTest
 * @run main BroadcasterSupportDeadlockTest
 */

import java.lang.management.*;
import java.util.concurrent.*;
import javax.management.*;

public class BroadcasterSupportDeadlockTest {
    public static void main(String[] args) throws Exception {
        try {
            Class.forName(ManagementFactory.class.getName());
        } catch (Throwable t) {
            System.out.println("TEST CANNOT RUN: needs JDK 5 at least");
            return;
        }

        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        final BroadcasterMBean mbean = new Broadcaster();
        final ObjectName name = new ObjectName("test:type=Broadcaster");
        mbs.registerMBean(mbean, name);

        ThreadMXBean threads = ManagementFactory.getThreadMXBean();
        threads.setThreadContentionMonitoringEnabled(true);

        final Semaphore semaphore = new Semaphore(0);

        // Thread 1 - block the Broadcaster
        Thread t1 = new Thread() {
            public void run() {
                try {
                    mbs.invoke(name, "block",
                               new Object[] {semaphore},
                               new String[] {Semaphore.class.getName()});
                } catch (Exception e) {
                    e.printStackTrace(System.out);
                } finally {
                    System.out.println("TEST INCORRECT: block returned");
                    System.exit(1);
                }
            }
        };
        t1.setDaemon(true);
        t1.start();

        /* Wait for Thread 1 to be doing Object.wait().  It's very
           difficult to synchronize properly here so we wait for the
           semaphore, then wait a little longer for the mbs.invoke to
           run, then just in case that isn't enough, we wait for the
           thread to be in WAITING state.  This isn't foolproof,
           because the machine could be very slow and the
           Thread.getState() could find the thread in WAITING state
           due to some operation it does on its way to the one we're
           interested in.  */
        semaphore.acquire();
        Thread.sleep(100);
        while (t1.getState() != Thread.State.WAITING)
            Thread.sleep(1);

        // Thread 2 - try to add a listener
        final NotificationListener listener = new NotificationListener() {
            public void handleNotification(Notification n, Object h) {}
        };
        Thread t2 = new Thread() {
            public void run() {
                try {
                    mbs.addNotificationListener(name, listener, null, null);
                } catch (Exception e) {
                    System.out.println("TEST INCORRECT: addNL failed:");
                    e.printStackTrace(System.out);
                }
            }
        };
        t2.setDaemon(true);
        t2.start();

        /* Wait for Thread 2 to be blocked on the monitor or to
           succeed.  */
        Thread.sleep(100);

        for (int i = 0; i < 1000/*ms*/; i++) {
            t2.join(1/*ms*/);
            switch (t2.getState()) {
            case TERMINATED:
                System.out.println("TEST PASSED");
                return;
            case BLOCKED:
                java.util.Map<Thread,StackTraceElement[]> traces =
                    Thread.getAllStackTraces();
                showStackTrace("Thread 1", traces.get(t1));
                showStackTrace("Thread 2", traces.get(t2));
                System.out.println("TEST FAILED: deadlock");
                System.exit(1);
                break;
            default:
                break;
            }
        }

        System.out.println("TEST FAILED BUT DID NOT NOTICE DEADLOCK");
        Thread.sleep(10000);
        System.exit(1);
    }

    private static void showStackTrace(String title,
                                       StackTraceElement[] stack) {
        System.out.println("---" + title + "---");
        if (stack == null)
            System.out.println("<no stack trace???>");
        else {
            for (StackTraceElement elmt : stack)
                System.out.println("    " + elmt);
        }
        System.out.println();
    }

    public static interface BroadcasterMBean {
        public void block(Semaphore semaphore);
    }

    public static class Broadcaster
            extends NotificationBroadcasterSupport
            implements BroadcasterMBean {
        public synchronized void block(Semaphore semaphore) {
            Object lock = new Object();
            synchronized (lock) {
                try {
                    // Let the caller know that it can now wait for us to
                    // hit the WAITING state
                    semaphore.release();
                    lock.wait(); // block forever
                } catch (InterruptedException e) {
                    System.out.println("TEST INCORRECT: lock interrupted:");
                    e.printStackTrace(System.out);
                    System.exit(1);
                }
            }
        }
    }
}
