1 package org.sapia.soto.aop; 2 3 import net.sf.cglib.proxy.Enhancer; 4 import net.sf.cglib.proxy.Factory; 5 6 import org.sapia.soto.ConfigurationException; 7 import org.sapia.soto.ServiceMetaData; 8 import org.sapia.soto.util.Utils; 9 import org.sapia.soto.util.matcher.PathPattern; 10 import org.sapia.soto.util.matcher.Pattern; 11 12 import java.lang.reflect.Method ; 13 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 import java.util.List ; 17 import java.util.Map ; 18 19 20 30 public class Adviser { 31 private List _methods = new ArrayList (); 32 private List _adviceDefs = new ArrayList (); 33 private List _groups = new ArrayList (); 34 private Pattern[] _interfaces; 35 36 39 public Adviser() { 40 super(); 41 } 42 43 46 public void init(ServiceMetaData meta) throws Exception { 47 Object proxy = advise(meta.getService()); 48 meta.setService(proxy); 49 } 50 51 58 public Object advise(Object toAdvise) throws Exception { 59 if (!matchesImplements(toAdvise)) { 60 return toAdvise; 61 } 62 63 MethodPointCut pc; 64 List methods; 65 List adviceRefs; 66 List groupRefs; 67 List advices; 68 AdviceRef ref; 69 GroupRef groupRef; 70 71 Map defs = filterDefs(); 72 Map groups = filterGroups(defs); 73 AdviceInterceptor interceptor; 74 boolean advised; 75 76 if (advised = isAdvised(toAdvise)) { 77 interceptor = getInterceptor(toAdvise); 78 } else { 79 interceptor = new AdviceInterceptor(toAdvise.getClass()); 80 } 81 82 Method meth; 83 84 for (int i = 0; i < _methods.size(); i++) { 85 pc = (MethodPointCut) _methods.get(i); 86 adviceRefs = pc.getAdviceRefs(); 87 groupRefs = pc.getGroupRefs(); 88 advices = new ArrayList (adviceRefs.size()); 89 methods = pc.scanMethods(toAdvise.getClass()); 90 91 for (int j = 0; j < groupRefs.size(); j++) { 92 groupRef = (GroupRef) groupRefs.get(j); 93 94 List resolved = groupRef.resolve(groups); 95 advices.addAll(resolved); 96 } 97 98 for (int j = 0; j < adviceRefs.size(); j++) { 99 ref = (AdviceRef) adviceRefs.get(j); 100 advices.add(ref.resolve(defs)); 101 } 102 103 for (int j = 0; j < methods.size(); j++) { 104 Invoker delegate = new Invoker(advices); 105 meth = (Method ) methods.get(j); 106 107 if (Factory.class.isAssignableFrom(meth.getDeclaringClass())) { 108 meth = interceptor.getAdvisedClass().getDeclaredMethod(meth.getName(), 109 meth.getParameterTypes()); 110 } 111 112 interceptor.addInvoker(meth, delegate); 113 } 114 115 advices.clear(); 116 } 117 118 Object proxy; 119 120 if (advised) { 121 proxy = toAdvise; 122 } else { 123 proxy = Enhancer.create(toAdvise.getClass(), Utils.getClasses(toAdvise), 124 interceptor); 125 Utils.copyFields(toAdvise, proxy); 126 } 127 128 return proxy; 129 } 130 131 135 public void clear() { 136 _adviceDefs.clear(); 138 _adviceDefs = null; 139 _groups.clear(); 140 _groups = null; 141 _methods.clear(); 142 _methods = null; 143 } 144 145 151 public void setImplements(String interfaces) { 152 String [] interfacePatterns = Utils.split(interfaces, ',', true); 153 _interfaces = new Pattern[interfacePatterns.length]; 154 155 for (int i = 0; i < interfacePatterns.length; i++) { 156 _interfaces[i] = PathPattern.parse(interfacePatterns[i], '.', false); 157 } 158 } 159 160 169 public boolean matchesImplements(Object o) { 170 if (_interfaces == null) { 171 return true; 172 } 173 174 Class [] interfaces = Utils.getClasses(o); 175 boolean[] matched = new boolean[_interfaces.length]; 176 Pattern pattern; 177 178 for (int i = 0; i < interfaces.length; i++) { 179 for (int j = 0; j < _interfaces.length; j++) { 180 pattern = (Pattern) _interfaces[j]; 181 182 if (pattern.matches(interfaces[i].getName())) { 183 matched[j] = true; 184 } 185 } 186 } 187 188 for (int i = 0; i < matched.length; i++) { 189 if (!matched[i]) { 190 return false; 191 } 192 } 193 194 return true; 195 } 196 197 202 public MethodPointCut createMethod() { 203 MethodPointCut pc = new MethodPointCut(); 204 _methods.add(pc); 205 206 return pc; 207 } 208 209 214 public AdviceDef createAdviceDef() { 215 AdviceDef def = new AdviceDef(); 216 _adviceDefs.add(def); 217 218 return def; 219 } 220 221 226 public Group createGroup() { 227 Group g = new Group(); 228 _groups.add(g); 229 230 return g; 231 } 232 233 241 public static boolean isAdvised(Object obj) { 242 try { 243 AdviceInterceptor interceptor = (AdviceInterceptor) ((Factory) obj).getCallback(0); 244 245 return true; 246 } catch (ClassCastException e) { 247 return false; 248 } 249 } 250 251 259 public static AdviceInterceptor getInterceptor(Object obj) { 260 try { 261 return (AdviceInterceptor) ((Factory) obj).getCallback(0); 262 } catch (ClassCastException e) { 263 return null; 264 } 265 } 266 267 private Map filterDefs() throws ConfigurationException { 268 Map defs = new HashMap (); 269 AdviceDef def; 270 271 for (int i = 0; i < _adviceDefs.size(); i++) { 272 def = (AdviceDef) _adviceDefs.get(i); 273 274 if (def.getId() == null) { 275 throw new ConfigurationException( 276 "'id' attribute not specified on advice definition"); 277 } 278 279 defs.put(def.getId(), def); 280 } 281 282 return defs; 283 } 284 285 private Map filterGroups(Map defs) throws ConfigurationException { 286 Map groups = new HashMap (); 287 Group group; 288 289 for (int i = 0; i < _groups.size(); i++) { 290 group = (Group) _groups.get(i); 291 292 if (group.getId() == null) { 293 throw new ConfigurationException( 294 "'id' attribute not specified on advice definition"); 295 } 296 297 group.resolve(defs); 298 299 groups.put(group.getId(), group); 300 } 301 302 return groups; 303 } 304 } 305 | Popular Tags |