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