/*______________________________________________________________________________
 * 
 * net.innig.util.DelegatingProxy
 * 
 *______________________________________________________________________________
 * 
 * Copyright 2002 Paul Cantrell
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, 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 name of the author may not be used to endorse or promote
 *     products derived from this software without specific prior
 *     written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, 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.
 *_______________________________________________________________________________
 */

package net.innig.util;

import java.lang.reflect.*;

/**
    @see java.lang.reflect.Proxy
    @deprecated Too clever for its own good.  Just subclass DelegatingProxy instead.
*/
public final class WrappingProxy
    implements InvocationHandler
    {
    public static Object newProxyInstance(
            Class iface,
            Object delegate,
            InvocationHandler pre,
            InvocationHandler post)
        {
        if(!iface.isInterface())
            throw new IllegalArgumentException(iface.getName() + " is not an interface");
        if(!iface.isInstance(delegate))
            throw new IllegalArgumentException(
                "Delegate object is an instance of " + delegate.getClass().getName()
                + ", which does not implement " + iface.getName());
        return Proxy.newProxyInstance(
            iface.getClassLoader(),
            new Class[] { iface },
            new WrappingProxy(delegate, pre, post));
        }

    
    public static final InvocationHandler UNSUPPORTED_OPERATION_HANDLER =
        new InvocationHandler()
            {
            public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable
                { throw new UnsupportedOperationException(); }
            };
    
    
    public WrappingProxy(Object delegate, InvocationHandler pre, InvocationHandler post)
        {
        this.delegate = delegate;
        this.pre = pre;
        this.post = post;
        }
    
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable
        {
        if(pre != null)
            pre.invoke(proxy, method, args);
        try {
            return delegate.getClass()
                           .getMethod(
                                    method.getName(),
                                    method.getParameterTypes())
                           .invoke(delegate, args);
            }
        catch(NoSuchMethodException nsme)
            { throw new IllegalStateException("Unable to invoke WrappingProxy delegate: " + nsme); }
        catch(IllegalAccessException iae)
            { throw new IllegalStateException("Unable to invoke WrappingProxy delegate: " + iae); }
        catch(InvocationTargetException ite)
            { throw ite.getTargetException(); }
        // allow SecurityException to go out unchecked
        // (and also IllegalArgumentException, though it should never happen)
        finally
            {
            if(post != null)
                post.invoke(proxy, method, args);
            }
        }

    private final Object delegate;
    private final InvocationHandler pre, post;
    }


