Path: blob/master/src/java.desktop/share/classes/java/beans/MethodDescriptor.java
41152 views
/*1* Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.beans;2627import java.lang.ref.Reference;28import java.lang.ref.WeakReference;29import java.lang.reflect.Method;30import java.util.List;31import java.util.ArrayList;3233/**34* A MethodDescriptor describes a particular method that a Java Bean35* supports for external access from other components.36*37* @since 1.138*/3940public class MethodDescriptor extends FeatureDescriptor {4142private final MethodRef methodRef = new MethodRef();4344private String[] paramNames;4546private List<WeakReference<Class<?>>> params;4748private ParameterDescriptor[] parameterDescriptors;4950/**51* Constructs a {@code MethodDescriptor} from a52* {@code Method}.53*54* @param method The low-level method information.55*/56public MethodDescriptor(Method method) {57this(method, null);58}596061/**62* Constructs a {@code MethodDescriptor} from a63* {@code Method} providing descriptive information for each64* of the method's parameters.65*66* @param method The low-level method information.67* @param parameterDescriptors Descriptive information for each of the68* method's parameters.69*/70public MethodDescriptor(Method method,71ParameterDescriptor[] parameterDescriptors) {72setName(method.getName());73setMethod(method);74this.parameterDescriptors = (parameterDescriptors != null)75? parameterDescriptors.clone()76: null;77}7879/**80* Gets the method that this MethodDescriptor encapsulates.81*82* @return The low-level description of the method83*/84public synchronized Method getMethod() {85Method method = this.methodRef.get();86if (method == null) {87Class<?> cls = getClass0();88String name = getName();89if ((cls != null) && (name != null)) {90Class<?>[] params = getParams();91if (params == null) {92for (int i = 0; i < 3; i++) {93// Find methods for up to 2 params. We are guessing here.94// This block should never execute unless the classloader95// that loaded the argument classes disappears.96method = Introspector.findMethod(cls, name, i, null);97if (method != null) {98break;99}100}101} else {102method = Introspector.findMethod(cls, name, params.length, params);103}104setMethod(method);105}106}107return method;108}109110private synchronized void setMethod(Method method) {111if (method == null) {112return;113}114if (getClass0() == null) {115setClass0(method.getDeclaringClass());116}117setParams(getParameterTypes(getClass0(), method));118this.methodRef.set(method);119}120121private synchronized void setParams(Class<?>[] param) {122if (param == null) {123return;124}125paramNames = new String[param.length];126params = new ArrayList<>(param.length);127for (int i = 0; i < param.length; i++) {128paramNames[i] = param[i].getName();129params.add(new WeakReference<Class<?>>(param[i]));130}131}132133// pp getParamNames used as an optimization to avoid method.getParameterTypes.134String[] getParamNames() {135return paramNames;136}137138private synchronized Class<?>[] getParams() {139Class<?>[] clss = new Class<?>[params.size()];140141for (int i = 0; i < params.size(); i++) {142Reference<? extends Class<?>> ref = (Reference<? extends Class<?>>)params.get(i);143Class<?> cls = ref.get();144if (cls == null) {145return null;146} else {147clss[i] = cls;148}149}150return clss;151}152153/**154* Gets the ParameterDescriptor for each of this MethodDescriptor's155* method's parameters.156*157* @return The locale-independent names of the parameters. May return158* a null array if the parameter names aren't known.159*/160public ParameterDescriptor[] getParameterDescriptors() {161return (this.parameterDescriptors != null)162? this.parameterDescriptors.clone()163: null;164}165166private static Method resolve(Method oldMethod, Method newMethod) {167if (oldMethod == null) {168return newMethod;169}170if (newMethod == null) {171return oldMethod;172}173return !oldMethod.isSynthetic() && newMethod.isSynthetic() ? oldMethod : newMethod;174}175176/*177* Package-private constructor178* Merge two method descriptors. Where they conflict, give the179* second argument (y) priority over the first argument (x).180* @param x The first (lower priority) MethodDescriptor181* @param y The second (higher priority) MethodDescriptor182*/183184MethodDescriptor(MethodDescriptor x, MethodDescriptor y) {185super(x, y);186187this.methodRef.set(resolve(x.methodRef.get(), y.methodRef.get()));188params = x.params;189if (y.params != null) {190params = y.params;191}192paramNames = x.paramNames;193if (y.paramNames != null) {194paramNames = y.paramNames;195}196197parameterDescriptors = x.parameterDescriptors;198if (y.parameterDescriptors != null) {199parameterDescriptors = y.parameterDescriptors;200}201}202203/*204* Package-private dup constructor205* This must isolate the new object from any changes to the old object.206*/207MethodDescriptor(MethodDescriptor old) {208super(old);209210this.methodRef.set(old.getMethod());211params = old.params;212paramNames = old.paramNames;213214if (old.parameterDescriptors != null) {215int len = old.parameterDescriptors.length;216parameterDescriptors = new ParameterDescriptor[len];217for (int i = 0; i < len ; i++) {218parameterDescriptors[i] = new ParameterDescriptor(old.parameterDescriptors[i]);219}220}221}222223void appendTo(StringBuilder sb) {224appendTo(sb, "method", this.methodRef.get());225if (this.parameterDescriptors != null) {226sb.append("; parameterDescriptors={");227for (ParameterDescriptor pd : this.parameterDescriptors) {228sb.append(pd).append(", ");229}230sb.setLength(sb.length() - 2);231sb.append("}");232}233}234}235236237