blob: 893e5174668ce2f590957078a9613bc49881c915 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.api.util;
import org.apache.directory.api.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public final class MethodUtils
{
/** The logger. */
private static final Logger LOG = LoggerFactory.getLogger( MethodUtils.class );
/**
* Private constructor.
*/
private MethodUtils()
{
}
/**
* A replacement for {@link java.lang.Class#getMethod} with extended capability.
*
* <p>
* This method returns parameter-list assignment-compatible method as well as
* exact-signature matching method.
*
* @param clazz The class which will be queried for the method.
* @param candidateMethodName Name of the method been looked for.
* @param candidateParameterTypes Types of the parameters in the signature of the method being loooked for.
* @return The Method found.
* @throws NoSuchMethodException when the method cannot be found
*/
public static Method getAssignmentCompatibleMethod( Class<?> clazz,
String candidateMethodName,
Class<?>[] candidateParameterTypes
) throws NoSuchMethodException
{
if ( LOG.isDebugEnabled() )
{
StringBuilder buf = new StringBuilder();
buf.append( "call to getAssignmentCompatibleMethod(): \n\tclazz = " );
buf.append( clazz.getName() );
buf.append( "\n\tcandidateMethodName = " );
buf.append( candidateMethodName );
buf.append( "\n\tcandidateParameterTypes = " );
for ( Class<?> argClass : candidateParameterTypes )
{
buf.append( "\n\t\t" );
buf.append( argClass.getName() );
}
if ( LOG.isDebugEnabled() )
{
LOG.debug( buf.toString() );
}
}
try
{
// Look for exactly the same signature.
Method exactMethod = clazz.getMethod( candidateMethodName, candidateParameterTypes );
if ( exactMethod != null )
{
return exactMethod;
}
}
catch ( Exception e )
{
if ( LOG.isInfoEnabled() )
{
LOG.info( I18n.msg( I18n.MSG_17009_NO_EXACT_MATCH, candidateMethodName, e ) );
}
}
/**
* Look for the assignment-compatible signature.
*/
// Get all methods of the class.
Method[] methods = clazz.getMethods();
// For each method of the class...
for ( int mx = 0; mx < methods.length; mx++ )
{
// If the method name does not match...
if ( !candidateMethodName.equals( methods[mx].getName() ) )
{
// ... Go on with the next method.
continue;
}
// ... Get parameter types list.
Class<?>[] parameterTypes = methods[mx].getParameterTypes();
// If parameter types list length mismatch...
if ( parameterTypes.length != candidateParameterTypes.length )
{
// ... Go on with the next method.
continue;
}
// If parameter types list length is OK...
// ... For each parameter of the method...
for ( int px = 0; px < parameterTypes.length; px++ )
{
// ... If the parameter is not assignment-compatible with the candidate parameter type...
if ( !parameterTypes[px].isAssignableFrom( candidateParameterTypes[px] ) )
{
// ... Go on with the next method.
break;
}
}
// Return the only one possible and found method.
return methods[mx];
}
throw new NoSuchMethodException( clazz.getName() + "." + candidateMethodName
+ "(" + Arrays.toString( candidateParameterTypes ) + ")" );
}
}