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 }