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 }