001 /*
002 * Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.beans;
027
028 import java.lang.ref.Reference;
029 import java.lang.ref.WeakReference;
030
031 import java.lang.reflect.Method;
032
033 import java.util.List;
034 import java.util.ArrayList;
035
036 /**
037 * A MethodDescriptor describes a particular method that a Java Bean
038 * supports for external access from other components.
039 */
040
041 public class MethodDescriptor extends FeatureDescriptor {
042
043 private Reference<Method> methodRef;
044
045 private String[] paramNames;
046
047 private List params;
048
049 private ParameterDescriptor parameterDescriptors[];
050
051 /**
052 * Constructs a <code>MethodDescriptor</code> from a
053 * <code>Method</code>.
054 *
055 * @param method The low-level method information.
056 */
057 public MethodDescriptor(Method method) {
058 this (method, null);
059 }
060
061 /**
062 * Constructs a <code>MethodDescriptor</code> from a
063 * <code>Method</code> providing descriptive information for each
064 * of the method's parameters.
065 *
066 * @param method The low-level method information.
067 * @param parameterDescriptors Descriptive information for each of the
068 * method's parameters.
069 */
070 public MethodDescriptor(Method method,
071 ParameterDescriptor parameterDescriptors[]) {
072 setName(method.getName());
073 setMethod(method);
074 this .parameterDescriptors = parameterDescriptors;
075 }
076
077 /**
078 * Gets the method that this MethodDescriptor encapsualtes.
079 *
080 * @return The low-level description of the method
081 */
082 public synchronized Method getMethod() {
083 Method method = getMethod0();
084 if (method == null) {
085 Class cls = getClass0();
086 if (cls != null) {
087 Class[] params = getParams();
088 if (params == null) {
089 for (int i = 0; i < 3; i++) {
090 // Find methods for up to 2 params. We are guessing here.
091 // This block should never execute unless the classloader
092 // that loaded the argument classes disappears.
093 method = Introspector.findMethod(cls,
094 getName(), i, null);
095 if (method != null) {
096 break;
097 }
098 }
099 } 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) ? this .methodRef.get() : null;
122 }
123
124 private synchronized void setParams(Class[] param) {
125 if (param == null) {
126 return;
127 }
128 paramNames = new String[param.length];
129 params = new ArrayList(param.length);
130 for (int i = 0; i < param.length; i++) {
131 paramNames[i] = param[i].getName();
132 params.add(new WeakReference(param[i]));
133 }
134 }
135
136 // pp getParamNames used as an optimization to avoid method.getParameterTypes.
137 String[] getParamNames() {
138 return paramNames;
139 }
140
141 private synchronized Class[] getParams() {
142 Class[] clss = new Class[params.size()];
143
144 for (int i = 0; i < params.size(); i++) {
145 Reference ref = (Reference) params.get(i);
146 Class cls = (Class) ref.get();
147 if (cls == null) {
148 return null;
149 } else {
150 clss[i] = cls;
151 }
152 }
153 return clss;
154 }
155
156 /**
157 * Gets the ParameterDescriptor for each of this MethodDescriptor's
158 * method's parameters.
159 *
160 * @return The locale-independent names of the parameters. May return
161 * a null array if the parameter names aren't known.
162 */
163 public ParameterDescriptor[] getParameterDescriptors() {
164 return parameterDescriptors;
165 }
166
167 /*
168 public String toString() {
169 String message = "name=" + getName();
170 Class cls = getClass0();
171 if (cls != null) {
172 message += ", class=";
173 message += cls.getName();
174 }
175 String[] names = getParamNames();
176 if (names != null) {
177 for (int i = 0; i < names.length; i++) {
178 message += ", param=" + names[i];
179 }
180 }
181 return message;
182 } */
183
184 /*
185 * Package-private constructor
186 * Merge two method descriptors. Where they conflict, give the
187 * second argument (y) priority over the first argument (x).
188 * @param x The first (lower priority) MethodDescriptor
189 * @param y The second (higher priority) MethodDescriptor
190 */
191
192 MethodDescriptor(MethodDescriptor x, MethodDescriptor y) {
193 super (x, y);
194
195 methodRef = x.methodRef;
196 if (y.methodRef != null) {
197 methodRef = y.methodRef;
198 }
199 params = x.params;
200 if (y.params != null) {
201 params = y.params;
202 }
203 paramNames = x.paramNames;
204 if (y.paramNames != null) {
205 paramNames = y.paramNames;
206 }
207
208 parameterDescriptors = x.parameterDescriptors;
209 if (y.parameterDescriptors != null) {
210 parameterDescriptors = y.parameterDescriptors;
211 }
212 }
213
214 /*
215 * Package-private dup constructor
216 * This must isolate the new object from any changes to the old object.
217 */
218 MethodDescriptor(MethodDescriptor old) {
219 super (old);
220
221 methodRef = old.methodRef;
222 params = old.params;
223 paramNames = old.paramNames;
224
225 if (old.parameterDescriptors != null) {
226 int len = old.parameterDescriptors.length;
227 parameterDescriptors = new ParameterDescriptor[len];
228 for (int i = 0; i < len; i++) {
229 parameterDescriptors[i] = new ParameterDescriptor(
230 old.parameterDescriptors[i]);
231 }
232 }
233 }
234
235 }
|