1 package org.apache.fulcrum.yaafi.service.advice;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.lang.reflect.InvocationHandler;
23 import java.lang.reflect.Proxy;
24
25 import org.apache.avalon.framework.configuration.Configuration;
26 import org.apache.avalon.framework.configuration.ConfigurationException;
27 import org.apache.avalon.framework.configuration.Reconfigurable;
28 import org.apache.avalon.framework.context.Context;
29 import org.apache.avalon.framework.context.ContextException;
30 import org.apache.avalon.framework.context.Contextualizable;
31 import org.apache.avalon.framework.logger.AbstractLogEnabled;
32 import org.apache.avalon.framework.service.ServiceException;
33 import org.apache.avalon.framework.service.ServiceManager;
34 import org.apache.avalon.framework.service.Serviceable;
35 import org.apache.fulcrum.yaafi.framework.constant.AvalonYaafiConstants;
36 import org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorFactory;
37 import org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorInvocationHandler;
38 import org.apache.fulcrum.yaafi.framework.util.ReadWriteLock;
39 import org.apache.fulcrum.yaafi.framework.util.Validate;
40
41 /**
42 * Simple service providing interceptor advices for ordinary POJOs. Since the
43 * implementation uses Dynamic Proxies only methods invoked by an interface
44 * can be advised.
45 *
46 * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
47 */
48
49 public class AdviceServiceImpl
50 extends AbstractLogEnabled
51 implements AdviceService, Serviceable, Contextualizable, Reconfigurable
52 {
53 /** the service manager supplied by the Avalon framework */
54 private ServiceManager serviceManager;
55
56 /** the YAAFI kernel lock */
57 private ReadWriteLock readWriteLock;
58
59 /** the list of default interceptors */
60 private String[] defaultInterceptorList;
61
62
63
64
65
66 /**
67 * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
68 */
69 public void service(ServiceManager serviceManager) throws ServiceException
70 {
71 this.serviceManager = serviceManager;
72 }
73
74 /**
75 * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
76 */
77 public void contextualize(Context context) throws ContextException
78 {
79 this.readWriteLock = (ReadWriteLock) context.get(AvalonYaafiConstants.URN_YAAFI_KERNELLOCK);
80 }
81
82 /**
83 * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
84 */
85 public void configure(Configuration configuration) throws ConfigurationException
86 {
87 Configuration[] interceptorConfigList = configuration.getChild("interceptors").getChildren("interceptor");
88 this.defaultInterceptorList = new String[interceptorConfigList.length];
89
90 for( int i=0; i<interceptorConfigList.length; i++ )
91 {
92 this.defaultInterceptorList[i] = interceptorConfigList[i].getValue();
93 }
94 }
95
96 /**
97 * @see org.apache.avalon.framework.configuration.Reconfigurable#reconfigure(org.apache.avalon.framework.configuration.Configuration)
98 */
99 public void reconfigure(Configuration configuration) throws ConfigurationException
100 {
101 this.configure(configuration);
102 }
103
104
105
106
107
108 /**
109 * @see org.apache.fulcrum.yaafi.service.advice.AdviceService#advice(java.lang.Object)
110 */
111 public Object advice(Object object)
112 {
113 Validate.notNull(object,"object");
114 return this.advice( this.getDefaultInterceptorList(), object );
115 }
116
117 /**
118 * @see org.apache.fulcrum.yaafi.service.advice.AdviceService#advice(java.lang.String, java.lang.Object)
119 */
120 public Object advice(String name, Object object)
121 {
122 Validate.notNull(object,"object");
123 return this.doAdvice( name, this.getDefaultInterceptorList(), object );
124 }
125
126 /**
127 * @see org.apache.fulcrum.yaafi.service.advice.AdviceService#advice(java.lang.String[], java.lang.Object)
128 */
129 public Object advice(String [] interceptorList, Object object)
130 {
131 Validate.notNull(object,"object");
132 String className = object.getClass().getName();
133 return this.doAdvice(className, interceptorList, object);
134 }
135
136 /**
137 * @see org.apache.fulcrum.yaafi.service.advice.AdviceService#advice(java.lang.String, java.lang.String[], java.lang.Object)
138 */
139 public Object advice(String name, String [] interceptorList, Object object )
140 {
141 Validate.notNull(object,"object");
142 return this.doAdvice(name, interceptorList, object);
143 }
144
145 /**
146 * @see org.apache.fulcrum.yaafi.service.advice.AdviceService#isAdviced(java.lang.Object)
147 */
148 public boolean isAdviced(Object object)
149 {
150 InvocationHandler invocationHandler = null;
151
152 if ((object != null ) && Proxy.isProxyClass(object.getClass()))
153 {
154 invocationHandler = Proxy.getInvocationHandler(object);
155
156 if (invocationHandler instanceof AvalonInterceptorInvocationHandler)
157 {
158 return true;
159 }
160 else
161 {
162 return false;
163 }
164 }
165
166 return false;
167 }
168
169
170
171
172
173 /**
174 * Does the actual work of advising the object.
175 *
176 * @param name the name of the object to be advised
177 * @param interceptorList the list of interceptor services to advise the object
178 * @param object the object to be advised
179 * @return the advised object.
180 */
181 protected Object doAdvice(String name, String [] interceptorList, Object object )
182 {
183 Validate.notEmpty(name,"name");
184 Validate.notNull(interceptorList,"interceptorList");
185 Validate.notNull(object,"object");
186
187 Object result = null;
188 String clazzName = object.getClass().getName();
189
190
191
192 if( interceptorList.length == 0 )
193 {
194 if( this.getLogger().isInfoEnabled() )
195 {
196 String msg = "Skipping creation of dynamic proxy since no interceptors are requested : " + name;
197 this.getLogger().info(msg);
198 }
199
200 return object;
201 }
202
203
204
205 if( this.isAdviced(object) )
206 {
207 if( this.getLogger().isInfoEnabled() )
208 {
209 String msg = "Skipping creation of dynamic proxy since it is already advised : " + name;
210 this.getLogger().info(msg);
211 }
212
213 return object;
214 }
215
216
217
218 try
219 {
220 result = AvalonInterceptorFactory.create(
221 clazzName,
222 name,
223 this.getServiceManager(),
224 interceptorList,
225 object,
226 this.getReadWriteLock()
227 );
228 }
229 catch (ServiceException e)
230 {
231 String msg = "Unable to advice the object : " + name;
232 this.getLogger().error(msg,e);
233 throw new IllegalArgumentException(msg);
234 }
235
236 return result;
237 }
238
239 /**
240 * @return Returns the readWriteLock.
241 */
242 private ReadWriteLock getReadWriteLock()
243 {
244 return readWriteLock;
245 }
246
247 /**
248 * @return Returns the serviceManager.
249 */
250 private ServiceManager getServiceManager()
251 {
252 return serviceManager;
253 }
254
255 /**
256 * @return Returns the defaultInterceptorList.
257 */
258 private String[] getDefaultInterceptorList()
259 {
260 return defaultInterceptorList;
261 }
262 }