    001    /*****************************************************************************
    002     * Copyright (c) PicoContainer Organization. All rights reserved.            *
    003     * ------------------------------------------------------------------------- *
    004     * The software in this package is published under the terms of the BSD      *
    005     * style license a copy of which has been included with this distribution in *
    006     * the LICENSE.txt file.                                                     *
    007     *                                                                           *
    008     *****************************************************************************/
    009    package org.picocontainer.behaviors;
    010
    011    import org.picocontainer.ComponentAdapter;
    012    import org.picocontainer.PicoContainer;
    013
    014    import java.util.Map;
    015    import java.util.HashMap;
    016    import java.lang.reflect.Method;
    017    import java.lang.reflect.InvocationTargetException;
    018    import java.io.Serializable;
    019
    020    /** @author Paul Hammant */
    021    @SuppressWarnings("serial")
    022    public class Intercepted<T> extends HiddenImplementation {
    023
    024        private final Map<Class, Object> pres = new HashMap<Class, Object>();
    025        private final Map<Class, Object> posts = new HashMap<Class, Object>();
    026        private Controller controller = new ControllerWrapper(new InterceptorThreadLocal());
    027
    028        public Intercepted(ComponentAdapter delegate) {
    029            super(delegate);
    030        }
    031
    032        public void addPreInvocation(Class type, Object interceptor) {
    033            pres.put(type, interceptor);
    034        }
    035
    036        public void addPostInvocation(Class type, Object interceptor) {
    037            posts.put(type, interceptor);
    038        }
    039
    040        @Override
    041        protected Object invokeMethod(Object componentInstance, Method method, Object[] args, PicoContainer container) throws Throwable {
    042            try {
    043                controller.clear();
    044                controller.instance(componentInstance);
    045                Object pre = pres.get(method.getDeclaringClass());
    046                if (pre != null) {
    047                    Object rv =  method.invoke(pre, args);
    048                    if (controller.isVetoed()) {
    049                        return rv;
    050                    }
    051                }
    052                Object result = method.invoke(componentInstance, args);
    053                controller.setOriginalRetVal(result);
    054                Object post = posts.get(method.getDeclaringClass());
    055                if (post != null) {
    056                    Object rv = method.invoke(post, args);
    057                    if (controller.isOverridden()) {
    058                        return rv;
    059                    }
    060                }
    061                return result;
    062            } catch (final InvocationTargetException ite) {
    063                throw ite.getTargetException();
    064            }
    065        }
    066
    067        public Controller getController() {
    068            return controller;
    069        }
    070
    071        public static class InterceptorThreadLocal extends ThreadLocal implements Serializable {
    072
    073
    074            protected Object initialValue() {
    075                return new ControllerImpl();
    076            }
    077        }
    078
    079        public interface Controller {
    080            void veto();
    081
    082            void clear();
    083
    084            boolean isVetoed();
    085
    086            void setOriginalRetVal(Object retVal);
    087
    088            boolean isOverridden();
    089
    090            void instance(Object instance);
    091
    092            Object getOriginalRetVal();
    093
    094            void override();
    095        }
    096
    097        public static class ControllerImpl implements Controller {
    098            private boolean vetoed;
    099            private Object retVal;
    100            private boolean overridden;
    101            private Object instance;
    102
    103            public void veto() {
    104                vetoed = true;
    105            }
    106
    107            public void clear() {
    108                vetoed = false;
    109                overridden = false;
    110                retVal = null;
    111                instance = null;
    112            }
    113
    114            public boolean isVetoed() {
    115                return vetoed;
    116            }
    117            public void setOriginalRetVal(Object retVal) {
    118                this.retVal = retVal;
    119            }
    120
    121            public Object getOriginalRetVal() {
    122                return retVal;
    123            }
    124
    125            public boolean isOverridden() {
    126                return overridden;
    127            }
    128
    129            public void instance(Object instance) {
    130                this.instance = instance;
    131            }
    132
    133            public void override() {
    134                overridden = true;
    135            }
    136        }
    137
    138        public class ControllerWrapper implements Controller {
    139            private final ThreadLocal threadLocal;
    140
    141            public ControllerWrapper(ThreadLocal threadLocal) {
    142                this.threadLocal = threadLocal;
    143            }
    144
    145            public void veto() {
    146                ((Controller) threadLocal.get()).veto();
    147            }
    148
    149            public void clear() {
    150                ((Controller) threadLocal.get()).clear();
    151            }
    152
    153            public boolean isVetoed() {
    154                return ((Controller) threadLocal.get()).isVetoed();
    155            }
    156
    157            public void setOriginalRetVal(Object retVal) {
    158                ((Controller) threadLocal.get()).setOriginalRetVal(retVal);
    159            }
    160
    161            public Object getOriginalRetVal() {
    162                return ((Controller) threadLocal.get()).getOriginalRetVal();
    163            }
    164
    165            public boolean isOverridden() {
    166                return ((Controller) threadLocal.get()).isOverridden();
    167            }
    168
    169            public void instance(Object instance) {
    170                ((Controller) threadLocal.get()).instance(instance);
    171
    172            }
    173
    174            public void override() {
    175                ((Controller) threadLocal.get()).override();
    176            }
    177        }
    178
    179        public String getDescriptor() {
    180            return "Intercepted";
    181        }
    182    }