    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 getInstance();
    093
    094            Object getOriginalRetVal();
    095
    096            void override();
    097        }
    098
    099        public static class ControllerImpl implements Controller {
    100            private boolean vetoed;
    101            private Object retVal;
    102            private boolean overridden;
    103            private Object instance;
    104
    105            public void veto() {
    106                vetoed = true;
    107            }
    108
    109            public void clear() {
    110                vetoed = false;
    111                overridden = false;
    112                retVal = null;
    113                instance = null;
    114            }
    115
    116            public boolean isVetoed() {
    117                return vetoed;
    118            }
    119            public void setOriginalRetVal(Object retVal) {
    120                this.retVal = retVal;
    121            }
    122
    123            public Object getOriginalRetVal() {
    124                return retVal;
    125            }
    126
    127            public boolean isOverridden() {
    128                return overridden;
    129            }
    130
    131            public void instance(Object instance) {
    132                this.instance = instance;
    133            }
    134
    135            public Object getInstance() {
    136                return instance;
    137            }
    138
    139            public void override() {
    140                overridden = true;
    141            }
    142        }
    143
    144        public class ControllerWrapper implements Controller {
    145            private final ThreadLocal<Controller> threadLocal;
    146
    147            public ControllerWrapper(ThreadLocal<Controller> threadLocal) {
    148                this.threadLocal = threadLocal;
    149            }
    150
    151            public void veto() {
    152                threadLocal.get().veto();
    153            }
    154
    155            public void clear() {
    156                threadLocal.get().clear();
    157            }
    158
    159            public boolean isVetoed() {
    160                return threadLocal.get().isVetoed();
    161            }
    162
    163            public void setOriginalRetVal(Object retVal) {
    164                threadLocal.get().setOriginalRetVal(retVal);
    165            }
    166
    167            public Object getOriginalRetVal() {
    168                return threadLocal.get().getOriginalRetVal();
    169            }
    170
    171            public boolean isOverridden() {
    172                return threadLocal.get().isOverridden();
    173            }
    174
    175            public void instance(Object instance) {
    176                threadLocal.get().instance(instance);
    177
    178            }
    179
    180            public Object getInstance() {
    181                return threadLocal.get().getInstance();
    182            }
    183
    184            public void override() {
    185                threadLocal.get().override();
    186            }
    187        }
    188
    189        public String getDescriptor() {
    190            return "Intercepted";
    191        }
    192    }