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 }