avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From leosu...@apache.org
Subject cvs commit: jakarta-avalon-excalibur/util/src/java/org/apache/excalibur/util Delegate.java
Date Thu, 03 Oct 2002 16:58:48 GMT
leosutic    2002/10/03 09:58:48

  Modified:    util/src/java/org/apache/excalibur/util Delegate.java
  Log:
  Changed the default classloader for proxies to be the context classloader instead of the
interface classloader.
  Added an equals() method on the proxy (required for MultiDelegates).
  
  Revision  Changes    Path
  1.7       +277 -233  jakarta-avalon-excalibur/util/src/java/org/apache/excalibur/util/Delegate.java
  
  Index: Delegate.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/util/src/java/org/apache/excalibur/util/Delegate.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Delegate.java	3 Oct 2002 15:12:45 -0000	1.6
  +++ Delegate.java	3 Oct 2002 16:58:48 -0000	1.7
  @@ -1,233 +1,277 @@
  -/*
  -
  - ============================================================================
  -                   The Apache Software License, Version 1.1
  - ============================================================================
  -
  - Copyright (C) @year@ The Apache Software Foundation. All rights reserved.
  -
  - Redistribution and use in source and binary forms, with or without modifica-
  - tion, are permitted provided that the following conditions are met:
  -
  - 1. Redistributions of  source code must  retain the above copyright  notice,
  -    this list of conditions and the following disclaimer.
  -
  - 2. Redistributions in binary form must reproduce the above copyright notice,
  -    this list of conditions and the following disclaimer in the documentation
  -    and/or other materials provided with the distribution.
  -
  - 3. The end-user documentation included with the redistribution, if any, must
  -    include  the following  acknowledgment:  "This product includes  software
  -    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
  -    Alternately, this  acknowledgment may  appear in the software itself,  if
  -    and wherever such third-party acknowledgments normally appear.
  -
  - 4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
  -    must not be used to endorse or promote products derived from this  software
  -    without  prior written permission. For written permission, please contact
  -    apache@apache.org.
  -
  - 5. Products  derived from this software may not  be called "Apache", nor may
  -    "Apache" appear  in their name,  without prior written permission  of the
  -    Apache Software Foundation.
  -
  - THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  - FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
  - APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
  - INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
  - DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
  - OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
  - ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
  - (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
  - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  -
  - This software  consists of voluntary contributions made  by many individuals
  - on  behalf of the Apache Software  Foundation. For more  information on the
  - Apache Software Foundation, please see <http://www.apache.org/>.
  -
  -*/
  -package org.apache.excalibur.util;
  -
  -import java.lang.reflect.*;
  -
  -
  -/**
  - * Used to create a proxy for a method.  It is supposed to be as close to the
  - * C# delegate as possible.  The Delegate is only allowed to have one method,
  - * and all instances of it will call that one method.  You must also realize
  - * that only public methods on public classes can be turned into a Delegate.
  - *
  - * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
  - * @author <a href="mailto:leo.sutic@inspireinfrastructure.com">Leo Sutic</a>
  - */
  -public final class Delegate
  -{
  -    /**
  -     * Create a new delegate instance.  We use the instance with the specified
  -     * method name to forward requests to the delegate interface--which can
  -     * only have one method declared.
  -     *
  -     * @param instance           The object that has the method
  -     * @param methodName         The method name that implements the signature
  -     * @param delegateInterface  The interface that the delegate uses.
  -     *
  -     * @return the Delegate instance.  You have to cast it to the interface
  -     *         you passed in (<code>delegateInterface</code>).
  -     */
  -    public static Object newDelegate( Object instance, String methodName, Class delegateInterface)
  -    {
  -        ClassLoader loader = delegateInterface.getClassLoader();
  -        Class[] publicInterface = new Class[] { delegateInterface };
  -        Method[] interfaceMethods = delegateInterface.getDeclaredMethods();
  -
  -        if ( interfaceMethods.length != 1 )
  -        {
  -            throw new IllegalArgumentException("The delegate interface must have one (1)
and only one method.");
  -        }
  -
  -        Class[] signature = interfaceMethods[0].getParameterTypes();
  -        InvocationHandler handler = new DelegateHandler( instance, methodName, signature
);
  -
  -        return  Proxy.newProxyInstance( loader, publicInterface, handler );
  -    }
  -
  -    /**
  -     * Create a new delegate instance for a static method.  We use the instance
  -     * with the specified method name to forward requests to the delegate
  -     * interface--which can only have one method declared.  We do not require an instance
  -     *
  -     * @param klass              The class that has the static method
  -     * @param methodName         The method name that implements the signature
  -     * @param delegateInterface  The interface that the delegate uses.
  -     *
  -     * @return the Delegate instance.  You have to cast it to the interface
  -     *         you passed in (<code>delegateInterface</code>).
  -     */
  -    public static Object newDelegate( Class klass, String methodName, Class delegateInterface)
  -    {
  -        ClassLoader loader = delegateInterface.getClassLoader();
  -        Class[] publicInterface = new Class[] { delegateInterface };
  -        Method[] interfaceMethods = delegateInterface.getDeclaredMethods();
  -
  -        if ( interfaceMethods.length != 1 )
  -        {
  -            throw new IllegalArgumentException("The delegate interface must have one (1)
and only one method.");
  -        }
  -
  -        Class[] signature = interfaceMethods[0].getParameterTypes();
  -        InvocationHandler handler = new DelegateHandler( klass, methodName, signature );
  -
  -        return  Proxy.newProxyInstance( loader, publicInterface, handler );
  -    }
  -
  -    /**
  -     * The invocation handler for all delegates.
  -     */
  -    private static final class DelegateHandler implements InvocationHandler
  -    {
  -        private final Object m_instance;
  -        private final Method m_delegateMethod;
  -
  -        /**
  -         * Create a new InvocationHandler for the delegate we manufactured,
  -         * this version is used to delegate to objects.
  -         *
  -         * @param instance    The object instance that has the method
  -         * @param methodName  The method name that we forward messages to.
  -         * @param signature   The method signature used to ensure we have
  -         *                    a good delegate.
  -         */
  -        public DelegateHandler ( Object instance, String methodName, Class[] signature
)
  -        {
  -            m_instance = instance;
  -            m_delegateMethod = extractMethod( m_instance.getClass(), methodName, signature
);
  -        }
  -
  -        /**
  -         * Create a new InvocationHandler for the delegate we manufactured,
  -         * this version is used to delegate to static methods.
  -         *
  -         * @param klass       The class of the object containing the method
  -         * @param methodName  The method name that we forward messages to.
  -         * @param signature   The method signature used to ensure we have
  -         *                    a good delegate.
  -         */
  -        public DelegateHandler ( Class klass, String methodName, Class[] signature )
  -        {
  -            m_instance = null;
  -            m_delegateMethod = extractMethod( klass, methodName, signature );
  -        }
  -
  -        /**
  -         * Extract the Method instance we need for this delegate.  We examine
  -         * the instance class passed in for the method with the requested name.
  -         * When we find it, we save and use it every time we have a method call
  -         * on the delegate.
  -         *
  -         * @param klass       The class of the object containing the method
  -         * @param methodName  The method name that we forward messages to.
  -         * @param signature   The method signature used to ensure we have
  -         *                    a good delegate.
  -         */
  -        public Method extractMethod ( Class klass, String methodName, Class[] signature
)
  -        {
  -            Method[] methods = klass.getDeclaredMethods();
  -            Method delegate = null;
  -
  -            for ( int i = 0; i < methods.length; i++ )
  -            {
  -                if ( methods[i].getName().equals( methodName ) )
  -                {
  -                    Class[] parameters = methods[i].getParameterTypes();
  -
  -                    if ( parameters.length == signature.length )
  -                    {
  -                        boolean signatureOk = true;
  -
  -                        for ( int m = 0; m < signature.length; m++ )
  -                        {
  -                            if ( ! ( signature[m].equals( parameters[m] ) ) )
  -                            {
  -                                signatureOk = false;
  -                            }
  -                        }
  -
  -                        if ( signatureOk )
  -                        {
  -                            delegate = methods[i];
  -                        }
  -                    }
  -                }
  -            }
  -
  -            if ( delegate == null )
  -            {
  -                throw new IllegalArgumentException( "There is no valid method with the
required interface" );
  -            }
  -
  -            return delegate;
  -        }
  -
  -        /**
  -         * Call the proxied delegate method.
  -         *
  -         * @param proxy  The original object we are forwarding calls to.
  -         * @param m      The method we are ignoring( the delegated method
  -         *               may not have the same name )
  -         * @param args   The arguments passed to the method
  -         *
  -         * @return the results of the invocation in the form of an Object
  -         *
  -         * @throws IllegalAccessException  When the method or proxy object
  -         *                                 is not accessible
  -         * @throws InvocationTargetException  When the method throws an
  -         *                                    exception
  -         */
  -        public Object invoke( Object proxy, Method m, Object[] args )
  -            throws IllegalAccessException, InvocationTargetException
  -        {
  -            return m_delegateMethod.invoke( m_instance, args );
  -        }
  -    }
  -}
  +/*
  +
  + ============================================================================
  +                   The Apache Software License, Version 1.1
  + ============================================================================
  +
  + Copyright (C) @year@ The Apache Software Foundation. All rights reserved.
  +
  + Redistribution and use in source and binary forms, with or without modifica-
  + tion, are permitted provided that the following conditions are met:
  +
  + 1. Redistributions of  source code must  retain the above copyright  notice,
  +    this list of conditions and the following disclaimer.
  +
  + 2. Redistributions in binary form must reproduce the above copyright notice,
  +    this list of conditions and the following disclaimer in the documentation
  +    and/or other materials provided with the distribution.
  +
  + 3. The end-user documentation included with the redistribution, if any, must
  +    include  the following  acknowledgment:  "This product includes  software
  +    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
  +    Alternately, this  acknowledgment may  appear in the software itself,  if
  +    and wherever such third-party acknowledgments normally appear.
  +
  + 4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
  +    must not be used to endorse or promote products derived from this  software
  +    without  prior written permission. For written permission, please contact
  +    apache@apache.org.
  +
  + 5. Products  derived from this software may not  be called "Apache", nor may
  +    "Apache" appear  in their name,  without prior written permission  of the
  +    Apache Software Foundation.
  +
  + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  + FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
  + APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
  + INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
  + DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
  + OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
  + ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
  + (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
  + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  +
  + This software  consists of voluntary contributions made  by many individuals
  + on  behalf of the Apache Software  Foundation. For more  information on the
  + Apache Software Foundation, please see <http://www.apache.org/>.
  +
  +*/
  +package org.apache.excalibur.util;
  +
  +import java.lang.reflect.*;
  +
  +
  +/**
  + * Used to create a proxy for a method.  It is supposed to be as close to the
  + * C# delegate as possible.  The Delegate is only allowed to have one method,
  + * and all instances of it will call that one method.  You must also realize
  + * that only public methods on public classes can be turned into a Delegate.
  + *
  + * <p>Two delegates are considered equal if and only if:
  + *
  + * <ul>
  + * <li>They both refer to the same instance. That is, the <code>instance</code>
  + *   parameter passed to the newDelegate method was the same for both. The
  + *   instances are compared with the identity equality operator, <code>==</code>.
  + * <li>They refer to the same method as resolved by <code>Method.equals</code>.
  + * </ul>
  + *
  + * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
  + * @author <a href="mailto:leo.sutic@inspireinfrastructure.com">Leo Sutic</a>
  + */
  +public final class Delegate
  +{
  +    /**
  +     * Create a new delegate instance.  We use the instance with the specified
  +     * method name to forward requests to the delegate interface--which can
  +     * only have one method declared.
  +     *
  +     * @param instance           The object that has the method
  +     * @param methodName         The method name that implements the signature
  +     * @param delegateInterface  The interface that the delegate uses.
  +     *
  +     * @return the Delegate instance.  You have to cast it to the interface
  +     *         you passed in (<code>delegateInterface</code>).
  +     */
  +    public static Object newDelegate( Object instance, String methodName, Class delegateInterface
)
  +    {
  +        ClassLoader loader = Thread.currentThread ().getContextClassLoader ();
  +        if( loader == null )
  +        {
  +            loader = delegateInterface.getClassLoader();
  +        }
  +        
  +        Class[] publicInterface = new Class[] { delegateInterface };
  +        Method[] interfaceMethods = delegateInterface.getDeclaredMethods();
  +
  +        if ( interfaceMethods.length != 1 )
  +        {
  +            throw new IllegalArgumentException("The delegate interface must have one (1)
and only one method.");
  +        }
  +
  +        Class[] signature = interfaceMethods[0].getParameterTypes();
  +        InvocationHandler handler = new DelegateHandler( instance, methodName, signature
);
  +
  +        return  Proxy.newProxyInstance( loader, publicInterface, handler );
  +    }
  +
  +    /**
  +     * Create a new delegate instance for a static method.  We use the instance
  +     * with the specified method name to forward requests to the delegate
  +     * interface--which can only have one method declared.  We do not require an instance
  +     *
  +     * @param klass              The class that has the static method
  +     * @param methodName         The method name that implements the signature
  +     * @param delegateInterface  The interface that the delegate uses.
  +     *
  +     * @return the Delegate instance.  You have to cast it to the interface
  +     *         you passed in (<code>delegateInterface</code>).
  +     */
  +    public static Object newDelegate( Class klass, String methodName, Class delegateInterface)
  +    {
  +        ClassLoader loader = Thread.currentThread ().getContextClassLoader ();
  +        if( loader == null )
  +        {
  +            loader = delegateInterface.getClassLoader();
  +        }
  +        
  +        Class[] publicInterface = new Class[] { delegateInterface };
  +        Method[] interfaceMethods = delegateInterface.getDeclaredMethods();
  +
  +        if ( interfaceMethods.length != 1 )
  +        {
  +            throw new IllegalArgumentException("The delegate interface must have one (1)
and only one method.");
  +        }
  +
  +        Class[] signature = interfaceMethods[0].getParameterTypes();
  +        InvocationHandler handler = new DelegateHandler( klass, methodName, signature );
  +
  +        return  Proxy.newProxyInstance( loader, publicInterface, handler );
  +    }
  +
  +    /**
  +     * The invocation handler for all delegates.
  +     */
  +    private static final class DelegateHandler implements InvocationHandler
  +    {
  +        private final Object m_instance;
  +        private final Method m_delegateMethod;
  +
  +        /**
  +         * Create a new InvocationHandler for the delegate we manufactured,
  +         * this version is used to delegate to objects.
  +         *
  +         * @param instance    The object instance that has the method
  +         * @param methodName  The method name that we forward messages to.
  +         * @param signature   The method signature used to ensure we have
  +         *                    a good delegate.
  +         */
  +        public DelegateHandler ( Object instance, String methodName, Class[] signature
)
  +        {
  +            m_instance = instance;
  +            m_delegateMethod = extractMethod( m_instance.getClass(), methodName, signature
);
  +        }
  +
  +        /**
  +         * Create a new InvocationHandler for the delegate we manufactured,
  +         * this version is used to delegate to static methods.
  +         *
  +         * @param klass       The class of the object containing the method
  +         * @param methodName  The method name that we forward messages to.
  +         * @param signature   The method signature used to ensure we have
  +         *                    a good delegate.
  +         */
  +        public DelegateHandler ( Class klass, String methodName, Class[] signature )
  +        {
  +            m_instance = null;
  +            m_delegateMethod = extractMethod( klass, methodName, signature );
  +        }
  +
  +        /**
  +         * Extract the Method instance we need for this delegate.  We examine
  +         * the instance class passed in for the method with the requested name.
  +         * When we find it, we save and use it every time we have a method call
  +         * on the delegate.
  +         *
  +         * @param klass       The class of the object containing the method
  +         * @param methodName  The method name that we forward messages to.
  +         * @param signature   The method signature used to ensure we have
  +         *                    a good delegate.
  +         */
  +        public Method extractMethod ( Class klass, String methodName, Class[] signature
)
  +        {
  +            Method[] methods = klass.getDeclaredMethods();
  +            Method delegate = null;
  +
  +            for ( int i = 0; i < methods.length; i++ )
  +            {
  +                if ( methods[i].getName().equals( methodName ) )
  +                {
  +                    Class[] parameters = methods[i].getParameterTypes();
  +
  +                    if ( parameters.length == signature.length )
  +                    {
  +                        boolean signatureOk = true;
  +
  +                        for ( int m = 0; m < signature.length; m++ )
  +                        {
  +                            if ( ! ( signature[m].equals( parameters[m] ) ) )
  +                            {
  +                                signatureOk = false;
  +                            }
  +                        }
  +
  +                        if ( signatureOk )
  +                        {
  +                            delegate = methods[i];
  +                        }
  +                    }
  +                }
  +            }
  +
  +            if ( delegate == null )
  +            {
  +                throw new IllegalArgumentException( "There is no valid method with the
required interface" );
  +            }
  +
  +            return delegate;
  +        }
  +
  +        /**
  +         * Call the proxied delegate method.
  +         *
  +         * @param proxy  The original object we are forwarding calls to.
  +         * @param m      The method we are ignoring( the delegated method
  +         *               may not have the same name )
  +         * @param args   The arguments passed to the method
  +         *
  +         * @return the results of the invocation in the form of an Object
  +         *
  +         * @throws IllegalAccessException  When the method or proxy object
  +         *                                 is not accessible
  +         * @throws InvocationTargetException  When the method throws an
  +         *                                    exception
  +         */
  +        public Object invoke( Object proxy, Method m, Object[] args )
  +            throws IllegalAccessException, InvocationTargetException
  +        {
  +            if( m.getName().equals( "equals" ) && args.length == 1 )
  +            {
  +                Object other = args[0];
  +                
  +                if( other instanceof Proxy )
  +                {
  +                    DelegateHandler otherHandler = (DelegateHandler) Proxy.getInvocationHandler(
other );
  +                    if ( otherHandler.m_instance == m_instance && 
  +                        otherHandler.m_delegateMethod.equals( m_delegateMethod ) )
  +                    {
  +                        return Boolean.TRUE;
  +                    }
  +                    else
  +                    {
  +                        return Boolean.FALSE;
  +                    }
  +                }
  +                else
  +                {
  +                    return Boolean.FALSE;
  +                }
  +            }
  +            else
  +            {
  +                return m_delegateMethod.invoke( m_instance, args );
  +            }
  +        }
  +    }
  +}
  
  
  

--
To unsubscribe, e-mail:   <mailto:avalon-cvs-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-cvs-help@jakarta.apache.org>


Mime
View raw message