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 }