001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.util; 021 022 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026import java.lang.reflect.Method; 027import java.util.Arrays; 028 029 030/** 031 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 032 */ 033public final class MethodUtils 034{ 035 /** The logger. */ 036 private static final Logger LOG = LoggerFactory.getLogger( MethodUtils.class ); 037 038 039 /** 040 * Private constructor. 041 */ 042 private MethodUtils() 043 { 044 } 045 046 047 /** 048 * A replacement for {@link java.lang.Class#getMethod} with extended capability. 049 * 050 * <p> 051 * This method returns parameter-list assignment-compatible method as well as 052 * exact-signature matching method. 053 * 054 * @param clazz The class which will be queried for the method. 055 * @param candidateMethodName Name of the method been looked for. 056 * @param candidateParameterTypes Types of the parameters in the signature of the method being loooked for. 057 * @return The Method found. 058 * @throws NoSuchMethodException when the method cannot be found 059 */ 060 public static Method getAssignmentCompatibleMethod( Class<?> clazz, 061 String candidateMethodName, 062 Class<?>[] candidateParameterTypes 063 ) throws NoSuchMethodException 064 { 065 if ( LOG.isDebugEnabled() ) 066 { 067 StringBuilder buf = new StringBuilder(); 068 buf.append( "call to getAssignmentCompatibleMethod(): \n\tclazz = " ); 069 buf.append( clazz.getName() ); 070 buf.append( "\n\tcandidateMethodName = " ); 071 buf.append( candidateMethodName ); 072 buf.append( "\n\tcandidateParameterTypes = " ); 073 074 for ( Class<?> argClass : candidateParameterTypes ) 075 { 076 buf.append( "\n\t\t" ); 077 buf.append( argClass.getName() ); 078 } 079 080 LOG.debug( buf.toString() ); 081 } 082 083 try 084 { 085 // Look for exactly the same signature. 086 Method exactMethod = clazz.getMethod( candidateMethodName, candidateParameterTypes ); 087 088 if ( exactMethod != null ) 089 { 090 return exactMethod; 091 } 092 } 093 catch ( Exception e ) 094 { 095 LOG.info( "Could not find accessible exact match for candidateMethod {}", candidateMethodName, e ); 096 } 097 098 /** 099 * Look for the assignment-compatible signature. 100 */ 101 102 // Get all methods of the class. 103 Method[] methods = clazz.getMethods(); 104 105 // For each method of the class... 106 for ( int mx = 0; mx < methods.length; mx++ ) 107 { 108 // If the method name does not match... 109 if ( !candidateMethodName.equals( methods[mx].getName() ) ) 110 { 111 // ... Go on with the next method. 112 continue; 113 } 114 115 // ... Get parameter types list. 116 Class<?>[] parameterTypes = methods[mx].getParameterTypes(); 117 118 // If parameter types list length mismatch... 119 if ( parameterTypes.length != candidateParameterTypes.length ) 120 { 121 // ... Go on with the next method. 122 continue; 123 } 124 // If parameter types list length is OK... 125 // ... For each parameter of the method... 126 for ( int px = 0; px < parameterTypes.length; px++ ) 127 { 128 // ... If the parameter is not assignment-compatible with the candidate parameter type... 129 if ( !parameterTypes[px].isAssignableFrom( candidateParameterTypes[px] ) ) 130 { 131 // ... Go on with the next method. 132 break; 133 } 134 } 135 136 // Return the only one possible and found method. 137 return methods[mx]; 138 } 139 140 throw new NoSuchMethodException( clazz.getName() + "." + candidateMethodName 141 + "(" + Arrays.toString( candidateParameterTypes ) + ")" ); 142 } 143}