blob: 9916ee9de465a691b523a3bd45764d75783bf03c [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996-2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.beans;
27
28import java.lang.ref.Reference;
29import java.lang.ref.WeakReference;
30
31import java.lang.reflect.Method;
32
33import java.util.List;
34import java.util.ArrayList;
35
36/**
37 * A MethodDescriptor describes a particular method that a Java Bean
38 * supports for external access from other components.
39 */
40
41public class MethodDescriptor extends FeatureDescriptor {
42
43 private Reference<Method> methodRef;
44
45 private String[] paramNames;
46
47 private List params;
48
49 private ParameterDescriptor parameterDescriptors[];
50
51 /**
52 * Constructs a <code>MethodDescriptor</code> from a
53 * <code>Method</code>.
54 *
55 * @param method The low-level method information.
56 */
57 public MethodDescriptor(Method method) {
58 this(method, null);
59 }
60
61
62 /**
63 * Constructs a <code>MethodDescriptor</code> from a
64 * <code>Method</code> providing descriptive information for each
65 * of the method's parameters.
66 *
67 * @param method The low-level method information.
68 * @param parameterDescriptors Descriptive information for each of the
69 * method's parameters.
70 */
71 public MethodDescriptor(Method method,
72 ParameterDescriptor parameterDescriptors[]) {
73 setName(method.getName());
74 setMethod(method);
75 this.parameterDescriptors = parameterDescriptors;
76 }
77
78 /**
79 * Gets the method that this MethodDescriptor encapsualtes.
80 *
81 * @return The low-level description of the method
82 */
83 public synchronized Method getMethod() {
84 Method method = getMethod0();
85 if (method == null) {
86 Class cls = getClass0();
87 if (cls != null) {
88 Class[] params = getParams();
89 if (params == null) {
90 for (int i = 0; i < 3; i++) {
91 // Find methods for up to 2 params. We are guessing here.
92 // This block should never execute unless the classloader
93 // that loaded the argument classes disappears.
94 method = Introspector.findMethod(cls, getName(), i, null);
95 if (method != null) {
96 break;
97 }
98 }
99 } else {
100 method = Introspector.findMethod(cls, getName(),
101 params.length, params);
102 }
103 setMethod(method);
104 }
105 }
106 return method;
107 }
108
109 private synchronized void setMethod(Method method) {
110 if (method == null) {
111 return;
112 }
113 if (getClass0() == null) {
114 setClass0(method.getDeclaringClass());
115 }
116 setParams(getParameterTypes(getClass0(), method));
117 this.methodRef = getSoftReference(method);
118 }
119
120 private Method getMethod0() {
121 return (this.methodRef != null)
122 ? this.methodRef.get()
123 : null;
124 }
125
126 private synchronized void setParams(Class[] param) {
127 if (param == null) {
128 return;
129 }
130 paramNames = new String[param.length];
131 params = new ArrayList(param.length);
132 for (int i = 0; i < param.length; i++) {
133 paramNames[i] = param[i].getName();
134 params.add(new WeakReference(param[i]));
135 }
136 }
137
138 // pp getParamNames used as an optimization to avoid method.getParameterTypes.
139 String[] getParamNames() {
140 return paramNames;
141 }
142
143 private synchronized Class[] getParams() {
144 Class[] clss = new Class[params.size()];
145
146 for (int i = 0; i < params.size(); i++) {
147 Reference ref = (Reference)params.get(i);
148 Class cls = (Class)ref.get();
149 if (cls == null) {
150 return null;
151 } else {
152 clss[i] = cls;
153 }
154 }
155 return clss;
156 }
157
158 /**
159 * Gets the ParameterDescriptor for each of this MethodDescriptor's
160 * method's parameters.
161 *
162 * @return The locale-independent names of the parameters. May return
163 * a null array if the parameter names aren't known.
164 */
165 public ParameterDescriptor[] getParameterDescriptors() {
166 return parameterDescriptors;
167 }
168
169 /*
170 public String toString() {
171 String message = "name=" + getName();
172 Class cls = getClass0();
173 if (cls != null) {
174 message += ", class=";
175 message += cls.getName();
176 }
177 String[] names = getParamNames();
178 if (names != null) {
179 for (int i = 0; i < names.length; i++) {
180 message += ", param=" + names[i];
181 }
182 }
183 return message;
184 } */
185
186 /*
187 * Package-private constructor
188 * Merge two method descriptors. Where they conflict, give the
189 * second argument (y) priority over the first argument (x).
190 * @param x The first (lower priority) MethodDescriptor
191 * @param y The second (higher priority) MethodDescriptor
192 */
193
194 MethodDescriptor(MethodDescriptor x, MethodDescriptor y) {
195 super(x,y);
196
197 methodRef = x.methodRef;
198 if (y.methodRef != null) {
199 methodRef = y.methodRef;
200 }
201 params = x.params;
202 if (y.params != null) {
203 params = y.params;
204 }
205 paramNames = x.paramNames;
206 if (y.paramNames != null) {
207 paramNames = y.paramNames;
208 }
209
210 parameterDescriptors = x.parameterDescriptors;
211 if (y.parameterDescriptors != null) {
212 parameterDescriptors = y.parameterDescriptors;
213 }
214 }
215
216 /*
217 * Package-private dup constructor
218 * This must isolate the new object from any changes to the old object.
219 */
220 MethodDescriptor(MethodDescriptor old) {
221 super(old);
222
223 methodRef = old.methodRef;
224 params = old.params;
225 paramNames = old.paramNames;
226
227 if (old.parameterDescriptors != null) {
228 int len = old.parameterDescriptors.length;
229 parameterDescriptors = new ParameterDescriptor[len];
230 for (int i = 0; i < len ; i++) {
231 parameterDescriptors[i] = new ParameterDescriptor(old.parameterDescriptors[i]);
232 }
233 }
234 }
235
236}