/*
 * Copyright 2002-2007 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 4168475 4520754
 * @summary Tests for the removal of some of the exception based control flow
 * @author Mark Davidson
 */

import infos.ComponentBeanInfo;

import java.awt.Button;
import java.awt.Component;
import java.awt.List;
import java.awt.Menu;
import java.awt.Panel;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JCheckBox;

public class Test4520754 {
    /**
     * This is here to force the BeanInfo classes to be compiled
     */
    private static final Class[] COMPILE = {
            ComponentBeanInfo.class,
            FooBarBeanInfo.class,
            WombatBeanInfo.class,
    };

    public static void main(String[] args) {
        // ensure that 4168475 does not regress
        test4168475(Component.class);
        // AWT classes (sun.beans.infos.ComponentBeanInfo)
        test(null, Button.class, Component.class, List.class, Menu.class, Panel.class);
        // Swing classes (dt.jar)
        test(null, JApplet.class, JButton.class, JCheckBox.class);
        // user defined classes
        test(Boolean.TRUE, Wombat.class, Foo.class, FooBar.class);
    }

    private static void test(Boolean mark, Class... types) {
        for (Class type : types) {
            BeanInfo info = getBeanInfo(mark, type);
            if (info == null) {
                throw new Error("could not find BeanInfo for " + type);
            }
            if (mark != info.getBeanDescriptor().getValue("test")) {
                throw new Error("could not find marked BeanInfo for " + type);
            }
        }
        Introspector.flushCaches();
    }

    private static BeanInfo getBeanInfo(Boolean mark, Class type) {
        System.out.println("test=" + mark + " for " + type);
        BeanInfo info;
        try {
            info = Introspector.getBeanInfo(type);
        } catch (IntrospectionException exception) {
            throw new Error("unexpected exception", exception);
        }
        if (info == null) {
            throw new Error("could not find BeanInfo for " + type);
        }
        if (mark != info.getBeanDescriptor().getValue("test")) {
            throw new Error("could not find marked BeanInfo for " + type);
        }
        return info;
    }

    /**
     * This is a regression test to ensure that 4168475 does not regress.
     */
    private static void test4168475(Class type) {
        String[] newPath = {"infos"};
        String[] oldPath = Introspector.getBeanInfoSearchPath();

        Introspector.setBeanInfoSearchPath(newPath);
        BeanInfo info = getBeanInfo(Boolean.TRUE, type);
        Introspector.setBeanInfoSearchPath(oldPath);

        PropertyDescriptor[] pds = info.getPropertyDescriptors();
        if (pds.length != 1) {
            throw new Error("could not find custom BeanInfo for " + type);
        }
        Introspector.flushCaches();
    }
}
