001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.proxy.factory.util;
019    
020    import java.lang.reflect.Method;
021    import java.lang.reflect.Modifier;
022    import java.util.Collection;
023    import java.util.HashMap;
024    import java.util.HashSet;
025    import java.util.Iterator;
026    import java.util.Map;
027    import java.util.Set;
028    
029    /**
030     * A useful superclass for {@link ProxyClassGenerator} implementations.
031     *
032     * @author James Carman
033     * @since 1.0
034     */
035    public abstract class AbstractProxyClassGenerator implements ProxyClassGenerator
036    {
037    //----------------------------------------------------------------------------------------------------------------------
038    // Static Methods
039    //----------------------------------------------------------------------------------------------------------------------
040    
041        /**
042         * Returns all methods that a proxy class must implement from the proxy interfaces.  This method makes sure there
043         * are no method signature clashes. For methods with the same signature (name and parameter types), the one
044         * encountered first will be returned in the result. Final methods are also excluded from the result.
045         *
046         * @param proxyClasses the interfaces the proxy class must implement
047         * @return all methods that the proxy class must implement
048         */
049        public static Method[] getImplementationMethods( Class[] proxyClasses )
050        {
051            final Map signatureMethodMap = new HashMap();
052            final Set finalizedSignatures = new HashSet();
053            for( int i = 0; i < proxyClasses.length; i++ )
054            {
055                Class proxyInterface = proxyClasses[i];
056                final Method[] methods = proxyInterface.getMethods();
057                for( int j = 0; j < methods.length; j++ )
058                {
059                    final MethodSignature signature = new MethodSignature( methods[j] );
060                    if( Modifier.isFinal( methods[j].getModifiers() ) )
061                    {
062                        finalizedSignatures.add( signature );
063                    }
064                    else if( !signatureMethodMap.containsKey( signature ) )
065                    {
066                        signatureMethodMap.put( signature, methods[j] );
067                    }
068                }
069            }
070            final Collection resultingMethods = signatureMethodMap.values();
071            for( Iterator i = finalizedSignatures.iterator(); i.hasNext(); )
072            {
073                MethodSignature signature = ( MethodSignature ) i.next();
074                resultingMethods.remove( signatureMethodMap.get( signature ) );
075            }
076            return ( Method[] ) resultingMethods.toArray( new Method[resultingMethods.size()] );
077        }
078    }
079