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