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 public class Intercepted<T> extends HiddenImplementation {
022
023 private final Map<Class, Object> pres = new HashMap<Class, Object>();
024 private final Map<Class, Object> posts = new HashMap<Class, Object>();
025 private Controller controller = new ControllerWrapper(new InterceptorThreadLocal());
026
027 public Intercepted(ComponentAdapter delegate) {
028 super(delegate);
029 }
030
031 public void addPreInvocation(Class type, Object interceptor) {
032 pres.put(type, interceptor);
033 }
034
035 public void addPostInvocation(Class type, Object interceptor) {
036 posts.put(type, interceptor);
037 }
038
039 protected Object invokeMethod(Method method, Object[] args, PicoContainer container) throws Throwable {
040 Object componentInstance = getDelegate().getComponentInstance(container);
041 try {
042 controller.clear();
043 controller.instance(componentInstance);
044 Object pre = pres.get(method.getDeclaringClass());
045 if (pre != null) {
046 Object rv = method.invoke(pre, args);
047 if (controller.isVetoed()) {
048 return rv;
049 }
050 }
051 Object result = method.invoke(componentInstance, args);
052 controller.setOriginalRetVal(result);
053 Object post = posts.get(method.getDeclaringClass());
054 if (post != null) {
055 Object rv = method.invoke(post, args);
056 if (controller.isOverridden()) {
057 return rv;
058 }
059 }
060 return result;
061 } catch (final InvocationTargetException ite) {
062 throw ite.getTargetException();
063 }
064 }
065
066 public Controller getController() {
067 return controller;
068 }
069
070 public static class InterceptorThreadLocal extends ThreadLocal implements Serializable {
071 protected Object initialValue() {
072 return new ControllerImpl();
073 }
074 }
075
076 public interface Controller {
077 void veto();
078
079 void clear();
080
081 boolean isVetoed();
082
083 void setOriginalRetVal(Object retVal);
084
085 boolean isOverridden();
086
087 void instance(Object instance);
088
089 Object getOriginalRetVal();
090
091 void override();
092 }
093
094 public static class ControllerImpl implements Controller {
095 private boolean vetoed;
096 private Object retVal;
097 private boolean overridden;
098 private Object instance;
099
100 public void veto() {
101 vetoed = true;
102 }
103
104 public void clear() {
105 vetoed = false;
106 overridden = false;
107 retVal = null;
108 instance = null;
109 }
110
111 public boolean isVetoed() {
112 return vetoed;
113 }
114 public void setOriginalRetVal(Object retVal) {
115 this.retVal = retVal;
116 }
117
118 public Object getOriginalRetVal() {
119 return retVal;
120 }
121
122 public boolean isOverridden() {
123 return overridden;
124 }
125
126 public void instance(Object instance) {
127 this.instance = instance;
128 }
129
130 public void override() {
131 overridden = true;
132 }
133 }
134
135 public class ControllerWrapper implements Controller {
136 private final ThreadLocal threadLocal;
137
138 public ControllerWrapper(ThreadLocal threadLocal) {
139 this.threadLocal = threadLocal;
140 }
141
142 public void veto() {
143 ((Controller) threadLocal.get()).veto();
144 }
145
146 public void clear() {
147 ((Controller) threadLocal.get()).clear();
148 }
149
150 public boolean isVetoed() {
151 return ((Controller) threadLocal.get()).isVetoed();
152 }
153
154 public void setOriginalRetVal(Object retVal) {
155 ((Controller) threadLocal.get()).setOriginalRetVal(retVal);
156 }
157
158 public Object getOriginalRetVal() {
159 return ((Controller) threadLocal.get()).getOriginalRetVal();
160 }
161
162 public boolean isOverridden() {
163 return ((Controller) threadLocal.get()).isOverridden();
164 }
165
166 public void instance(Object instance) {
167 ((Controller) threadLocal.get()).instance(instance);
168
169 }
170
171 public void override() {
172 ((Controller) threadLocal.get()).override();
173 }
174 }
175
176
177
178 protected String getName() {
179 return "Intercepted:";
180 }
181 }