griffon/test/AbstractClosureProxy.java

`AbstractClosureProxy.java`
`001 /* 002 * Copyright 2008-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package griffon.test; 017 018 import groovy.lang.Closure; 019 020 /** 021 * Skeleton implementation of a wrapper class for closures that allows 022 * you to intercept invocations of the closure. The wrapper can be used 023 * anywhere that the target closure can be used. 024 */ 025 @SuppressWarnings("serial") 026 public abstract class AbstractClosureProxy extends Closure { 027 private Closure target; 028 029 /** 030 * Creates a new instance that wraps the target closure and sends 031 * profiling events to the given profiler log. 032 * @param closure The target closure to wrap. 033 */ 034 public AbstractClosureProxy(Closure closure) { 035 super(closure.getOwner(), closure.getThisObject()); 036 target = closure; 037 } 038 039 /** 040 * This method is called before the target closure is invoked. 041 * This is a passive interceptor, so you cannot prevent the 042 * call to the target closure. You can modify the arguments, 043 * though, but it's not recommended unless you really know 044 * what you're doing. 045 * @param args The arguments passed to the closure. 046 */ 047 protected abstract void doBeforeCall(Object[] args); 048 049 /** 050 * This method is called after the target closure is invoked. 051 * It will be triggered whether or not an exception is thrown 052 * by the target closure. 053 * @param args The arguments passed to the closure. 054 */ 055 protected abstract void doAfterCall(Object[] args); 056 057 /** 058 * Called when a new instance of the proxy needs to be created for 059 * the given closure. Usually the implementation simply creates a 060 * new instance of the current class, copying over the existing 061 * proxy properties: 062 * <pre> 063 * return new MyClosureProxy(c, this.field1, ...) 064 * </pre> 065 * @param c The closure to wrap/proxy. 066 */ 067 protected abstract Closure createWrapper(Closure c); 068 069 /** 070 * This is the important one: logs entry and exit of the closure call. 071 */ 072 @Override 073 public Object call(Object[] objects) { 074 doBeforeCall(objects); 075 076 try { 077 return target.call(objects); 078 } 079 finally { 080 doAfterCall(objects); 081 } 082 } 083 084 /** 085 * Compares based on identities, but unlike the standard implementation 086 * this one will return <code>true</code> if the given object is the 087 * target closure for this wrapper as well. 088 */ 089 @Override 090 public boolean equals(Object obj) { 091 return this == obj || target == obj; 092 } 093 094 @Override 095 public int hashCode() { 096 return target.hashCode(); 097 } 098 099 @Override 100 public Closure curry(Object[] objects) { 101 return createWrapper(target.curry(objects)); 102 } 103 104 @Override 105 public boolean isCase(Object o) { 106 return target.isCase(o); 107 } 108 109 @Override 110 public Closure asWritable() { 111 return target.asWritable(); 112 } 113 114 @Override 115 public Object getProperty(String property) { 116 return target.getProperty(property); 117 } 118 119 @Override 120 public void setProperty(String s, Object o) { 121 target.setProperty(s, o); 122 } 123 124 @Override 125 public int getMaximumNumberOfParameters() { 126 return target.getMaximumNumberOfParameters(); 127 } 128 129 @Override 130 public Class<?>[] getParameterTypes() { 131 return target.getParameterTypes(); 132 } 133 134 @Override 135 public Object getDelegate() { 136 return target.getDelegate(); 137 } 138 139 @Override 140 public void setDelegate(Object o) { 141 target.setDelegate(o); 142 } 143 144 @Override 145 public int getDirective() { 146 return target.getDirective(); 147 } 148 149 @Override 150 public void setDirective(int i) { 151 target.setDirective(i); 152 } 153 154 @Override 155 public int getResolveStrategy() { 156 return target.getResolveStrategy(); 157 } 158 159 @Override 160 public void setResolveStrategy(int i) { 161 target.setResolveStrategy(i); 162 } 163 }`