1. /*
  2. * @(#)MethodDescriptor.java 1.31 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.beans;
  8. import java.lang.ref.Reference;
  9. import java.lang.ref.WeakReference;
  10. import java.lang.reflect.Method;
  11. import java.util.List;
  12. import java.util.ArrayList;
  13. import com.sun.beans.ObjectHandler;
  14. /**
  15. * A MethodDescriptor describes a particular method that a Java Bean
  16. * supports for external access from other components.
  17. */
  18. public class MethodDescriptor extends FeatureDescriptor {
  19. private Reference methodRef;
  20. private String[] paramNames;
  21. private List params;
  22. private ParameterDescriptor parameterDescriptors[];
  23. /**
  24. * Constructs a <code>MethodDescriptor</code> from a
  25. * <code>Method</code>.
  26. *
  27. * @param method The low-level method information.
  28. */
  29. public MethodDescriptor(Method method) {
  30. this(method, null);
  31. }
  32. /**
  33. * Constructs a <code>MethodDescriptor</code> from a
  34. * <code>Method</code> providing descriptive information for each
  35. * of the method's parameters.
  36. *
  37. * @param method The low-level method information.
  38. * @param parameterDescriptors Descriptive information for each of the
  39. * method's parameters.
  40. */
  41. public MethodDescriptor(Method method,
  42. ParameterDescriptor parameterDescriptors[]) {
  43. setName(method.getName());
  44. setMethod(method);
  45. this.parameterDescriptors = parameterDescriptors;
  46. }
  47. /**
  48. * Gets the method that this MethodDescriptor encapsualtes.
  49. *
  50. * @return The low-level description of the method
  51. */
  52. public synchronized Method getMethod() {
  53. Method method = getMethod0();
  54. if (method == null) {
  55. Class cls = getClass0();
  56. if (cls != null) {
  57. Class[] params = getParams();
  58. if (params == null) {
  59. for (int i = 0; i < 3; i++) {
  60. // Find methods for up to 2 params. We are guessing here.
  61. // This block should never execute unless the classloader
  62. // that loaded the argument classes disappears.
  63. method = Introspector.findMethod(cls, getName(), i, null);
  64. if (method != null) {
  65. break;
  66. }
  67. }
  68. } else {
  69. method = Introspector.findMethod(cls, getName(),
  70. params.length, params);
  71. }
  72. setMethod(method);
  73. }
  74. }
  75. return method;
  76. }
  77. private synchronized void setMethod(Method method) {
  78. if (method == null) {
  79. return;
  80. }
  81. if (getClass0() == null) {
  82. setClass0(method.getDeclaringClass());
  83. }
  84. setParams(method.getParameterTypes());
  85. methodRef = createReference(method, true);
  86. }
  87. private Method getMethod0() {
  88. return (Method)getObject(methodRef);
  89. }
  90. private synchronized void setParams(Class[] param) {
  91. if (param == null) {
  92. return;
  93. }
  94. paramNames = new String[param.length];
  95. params = new ArrayList(param.length);
  96. for (int i = 0; i < param.length; i++) {
  97. paramNames[i] = param[i].getName();
  98. params.add(new WeakReference(param[i]));
  99. }
  100. }
  101. // pp getParamNames used as an optimization to avoid method.getParameterTypes.
  102. String[] getParamNames() {
  103. return paramNames;
  104. }
  105. private synchronized Class[] getParams() {
  106. Class[] clss = new Class[params.size()];
  107. for (int i = 0; i < params.size(); i++) {
  108. Reference ref = (Reference)params.get(i);
  109. Class cls = (Class)ref.get();
  110. if (cls == null) {
  111. return null;
  112. } else {
  113. clss[i] = cls;
  114. }
  115. }
  116. return clss;
  117. }
  118. /**
  119. * Gets the ParameterDescriptor for each of this MethodDescriptor's
  120. * method's parameters.
  121. *
  122. * @return The locale-independent names of the parameters. May return
  123. * a null array if the parameter names aren't known.
  124. */
  125. public ParameterDescriptor[] getParameterDescriptors() {
  126. return parameterDescriptors;
  127. }
  128. /*
  129. public String toString() {
  130. String message = "name=" + getName();
  131. Class cls = getClass0();
  132. if (cls != null) {
  133. message += ", class=";
  134. message += cls.getName();
  135. }
  136. String[] names = getParamNames();
  137. if (names != null) {
  138. for (int i = 0; i < names.length; i++) {
  139. message += ", param=" + names[i];
  140. }
  141. }
  142. return message;
  143. } */
  144. /*
  145. * Package-private constructor
  146. * Merge two method descriptors. Where they conflict, give the
  147. * second argument (y) priority over the first argument (x).
  148. * @param x The first (lower priority) MethodDescriptor
  149. * @param y The second (higher priority) MethodDescriptor
  150. */
  151. MethodDescriptor(MethodDescriptor x, MethodDescriptor y) {
  152. super(x,y);
  153. methodRef = x.methodRef;
  154. if (y.methodRef != null) {
  155. methodRef = y.methodRef;
  156. }
  157. params = x.params;
  158. if (y.params != null) {
  159. params = y.params;
  160. }
  161. paramNames = x.paramNames;
  162. if (y.paramNames != null) {
  163. paramNames = y.paramNames;
  164. }
  165. parameterDescriptors = x.parameterDescriptors;
  166. if (y.parameterDescriptors != null) {
  167. parameterDescriptors = y.parameterDescriptors;
  168. }
  169. }
  170. /*
  171. * Package-private dup constructor
  172. * This must isolate the new object from any changes to the old object.
  173. */
  174. MethodDescriptor(MethodDescriptor old) {
  175. super(old);
  176. methodRef = old.methodRef;
  177. params = old.params;
  178. paramNames = old.paramNames;
  179. if (old.parameterDescriptors != null) {
  180. int len = old.parameterDescriptors.length;
  181. parameterDescriptors = new ParameterDescriptor[len];
  182. for (int i = 0; i < len ; i++) {
  183. parameterDescriptors[i] = new ParameterDescriptor(old.parameterDescriptors[i]);
  184. }
  185. }
  186. }
  187. }