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 }