1/*
2 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package com.sun.beans.finder;
26
27import java.beans.BeanDescriptor;
28import java.beans.BeanInfo;
29import java.beans.MethodDescriptor;
30import java.beans.PropertyDescriptor;
31import java.lang.reflect.Method;
32
33/**
34 * This is utility class that provides functionality
35 * to find a {@link BeanInfo} for a JavaBean specified by its type.
36 *
37 * @since 1.7
38 *
39 * @author Sergey A. Malenkov
40 */
41public final class BeanInfoFinder
42        extends InstanceFinder<BeanInfo> {
43
44    private static final String DEFAULT = "sun.beans.infos";
45    private static final String DEFAULT_NEW = "com.sun.beans.infos";
46
47    public BeanInfoFinder() {
48        super(BeanInfo.class, true, "BeanInfo", DEFAULT);
49    }
50
51    private static boolean isValid(Class<?> type, Method method) {
52        return (method != null) && method.getDeclaringClass().isAssignableFrom(type);
53    }
54
55    @Override
56    protected BeanInfo instantiate(Class<?> type, String prefix, String name) {
57        if (DEFAULT.equals(prefix)) {
58            prefix = DEFAULT_NEW;
59        }
60        // this optimization will only use the BeanInfo search path
61        // if is has changed from the original
62        // or trying to get the ComponentBeanInfo
63        BeanInfo info = !DEFAULT_NEW.equals(prefix) || "ComponentBeanInfo".equals(name)
64                ? super.instantiate(type, prefix, name)
65                : null;
66
67        if (info != null) {
68            // make sure that the returned BeanInfo matches the class
69            BeanDescriptor bd = info.getBeanDescriptor();
70            if (bd != null) {
71                if (type.equals(bd.getBeanClass())) {
72                    return info;
73                }
74            }
75            else {
76                PropertyDescriptor[] pds = info.getPropertyDescriptors();
77                if (pds != null) {
78                    for (PropertyDescriptor pd : pds) {
79                        Method method = pd.getReadMethod();
80                        if (method == null) {
81                            method = pd.getWriteMethod();
82                        }
83                        if (isValid(type, method)) {
84                            return info;
85                        }
86                    }
87                }
88                else {
89                    MethodDescriptor[] mds = info.getMethodDescriptors();
90                    if (mds != null) {
91                        for (MethodDescriptor md : mds) {
92                            if (isValid(type, md.getMethod())) {
93                                return info;
94                            }
95                        }
96                    }
97                }
98            }
99        }
100        return null;
101    }
102}
103