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 * https://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.apache.directory.api.i18n.I18n; 024import org.slf4j.Logger; 025import org.slf4j.LoggerFactory; 026 027import java.lang.reflect.Method; 028import java.util.Arrays; 029 030 031/** 032 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 033 */ 034public final class MethodUtils 035{ 036 /** The logger. */ 037 private static final Logger LOG = LoggerFactory.getLogger( MethodUtils.class ); 038 039 040 /** 041 * Private constructor. 042 */ 043 private MethodUtils() 044 { 045 } 046 047 048 /** 049 * A replacement for {@link java.lang.Class#getMethod} with extended capability. 050 * 051 * <p> 052 * This method returns parameter-list assignment-compatible method as well as 053 * exact-signature matching method. 054 * 055 * @param clazz The class which will be queried for the method. 056 * @param candidateMethodName Name of the method been looked for. 057 * @param candidateParameterTypes Types of the parameters in the signature of the method being loooked for. 058 * @return The Method found. 059 * @throws NoSuchMethodException when the method cannot be found 060 */ 061 public static Method getAssignmentCompatibleMethod( Class<?> clazz, 062 String candidateMethodName, 063 Class<?>[] candidateParameterTypes 064 ) throws NoSuchMethodException 065 { 066 if ( LOG.isDebugEnabled() ) 067 { 068 StringBuilder buf = new StringBuilder(); 069 buf.append( "call to getAssignmentCompatibleMethod(): \n\tclazz = " ); 070 buf.append( clazz.getName() ); 071 buf.append( "\n\tcandidateMethodName = " ); 072 buf.append( candidateMethodName ); 073 buf.append( "\n\tcandidateParameterTypes = " ); 074 075 for ( Class<?> argClass : candidateParameterTypes ) 076 { 077 buf.append( "\n\t\t" ); 078 buf.append( argClass.getName() ); 079 } 080 081 if ( LOG.isDebugEnabled() ) 082 { 083 LOG.debug( buf.toString() ); 084 } 085 } 086 087 try 088 { 089 // Look for exactly the same signature. 090 Method exactMethod = clazz.getMethod( candidateMethodName, candidateParameterTypes ); 091 092 if ( exactMethod != null ) 093 { 094 return exactMethod; 095 } 096 } 097 catch ( Exception e ) 098 { 099 if ( LOG.isInfoEnabled() ) 100 { 101 LOG.info( I18n.msg( I18n.MSG_17009_NO_EXACT_MATCH, candidateMethodName, e ) ); 102 } 103 } 104 105 /** 106 * Look for the assignment-compatible signature. 107 */ 108 109 // Get all methods of the class. 110 Method[] methods = clazz.getMethods(); 111 112 // For each method of the class... 113 for ( int mx = 0; mx < methods.length; mx++ ) 114 { 115 // If the method name does not match... 116 if ( !candidateMethodName.equals( methods[mx].getName() ) ) 117 { 118 // ... Go on with the next method. 119 continue; 120 } 121 122 // ... Get parameter types list. 123 Class<?>[] parameterTypes = methods[mx].getParameterTypes(); 124 125 // If parameter types list length mismatch... 126 if ( parameterTypes.length != candidateParameterTypes.length ) 127 { 128 // ... Go on with the next method. 129 continue; 130 } 131 // If parameter types list length is OK... 132 // ... For each parameter of the method... 133 for ( int px = 0; px < parameterTypes.length; px++ ) 134 { 135 // ... If the parameter is not assignment-compatible with the candidate parameter type... 136 if ( !parameterTypes[px].isAssignableFrom( candidateParameterTypes[px] ) ) 137 { 138 // ... Go on with the next method. 139 break; 140 } 141 } 142 143 // Return the only one possible and found method. 144 return methods[mx]; 145 } 146 147 throw new NoSuchMethodException( clazz.getName() + "." + candidateMethodName 148 + "(" + Arrays.toString( candidateParameterTypes ) + ")" ); 149 } 150}