View Javadoc
1   package org.apache.fulcrum.yaafi.service.advice;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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.interceptor.AvalonInterceptorFactory;
36  import org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorInvocationHandler;
37  import org.apache.fulcrum.yaafi.framework.util.Validate;
38  
39  /**
40   * Simple service providing interceptor advices for ordinary POJOs. Since the
41   * implementation uses Dynamic Proxies only methods invoked by an interface can
42   * be advised.
43   *
44   * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
45   */
46  
47  public class AdviceServiceImpl extends AbstractLogEnabled
48  		implements AdviceService, Serviceable, Contextualizable, Reconfigurable {
49  	/** the service manager supplied by the Avalon framework */
50  	private ServiceManager serviceManager;
51  
52  	/** the list of default interceptors */
53  	private String[] defaultInterceptorList;
54  
55  	/////////////////////////////////////////////////////////////////////////
56  	// Avalon Service Lifecycle Implementation
57  	/////////////////////////////////////////////////////////////////////////
58  
59  	/**
60  	 * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
61  	 */
62  	public void service(ServiceManager serviceManager) throws ServiceException {
63  		this.serviceManager = serviceManager;
64  	}
65  
66  	/**
67  	 * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
68  	 */
69  	public void contextualize(Context context) throws ContextException {
70  		// nothing to do
71  	}
72  
73  	/**
74  	 * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
75  	 */
76  	public void configure(Configuration configuration) throws ConfigurationException {
77  		Configuration[] interceptorConfigList = configuration.getChild("interceptors").getChildren("interceptor");
78  		this.defaultInterceptorList = new String[interceptorConfigList.length];
79  		for (int i = 0; i < interceptorConfigList.length; i++) {
80  			this.defaultInterceptorList[i] = interceptorConfigList[i].getValue();
81  		}
82  	}
83  
84  	/**
85  	 * @see org.apache.avalon.framework.configuration.Reconfigurable#reconfigure(org.apache.avalon.framework.configuration.Configuration)
86  	 */
87  	public void reconfigure(Configuration configuration) throws ConfigurationException {
88  		this.configure(configuration);
89  	}
90  
91  	/////////////////////////////////////////////////////////////////////////
92  	// Service interface implementation
93  	/////////////////////////////////////////////////////////////////////////
94  
95  	/**
96  	 * @see org.apache.fulcrum.yaafi.service.advice.AdviceService#advice(java.lang.Object)
97  	 */
98  	public Object advice(Object object) {
99  		Validate.notNull(object, "object");
100 		return this.advice(this.getDefaultInterceptorList(), object);
101 	}
102 
103 	/*
104 	 * (non-Javadoc)
105 	 * 
106 	 * @see org.apache.fulcrum.yaafi.service.advice.AdviceService#advice(java.lang.
107 	 * String, java.lang.Object)
108 	 */
109 	public Object advice(String name, Object object) {
110 		Validate.notNull(object, "object");
111 		return this.doAdvice(name, this.getDefaultInterceptorList(), object);
112 	}
113 
114 	/*
115 	 * (non-Javadoc)
116 	 * 
117 	 * @see
118 	 * org.apache.fulcrum.yaafi.service.advice.AdviceService#advice(java.lang.String
119 	 * [], java.lang.Object)
120 	 */
121 	public Object advice(String[] interceptorList, Object object) {
122 		Validate.notNull(object, "object");
123 		String className = object.getClass().getName();
124 		return this.doAdvice(className, interceptorList, object);
125 	}
126 
127 	/*
128 	 * (non-Javadoc)
129 	 * 
130 	 * @see org.apache.fulcrum.yaafi.service.advice.AdviceService#advice(java.lang.
131 	 * String, java.lang.String[], java.lang.Object)
132 	 */
133 	public Object advice(String name, String[] interceptorList, Object object) {
134 		Validate.notNull(object, "object");
135 		return this.doAdvice(name, interceptorList, object);
136 	}
137 
138 	/*
139 	 * (non-Javadoc)
140 	 * 
141 	 * @see
142 	 * org.apache.fulcrum.yaafi.service.advice.AdviceService#isAdviced(java.lang.
143 	 * Object)
144 	 */
145 	public boolean isAdviced(Object object) {
146 		InvocationHandler invocationHandler = null;
147 
148 		if (object != null && Proxy.isProxyClass(object.getClass())) {
149 			invocationHandler = Proxy.getInvocationHandler(object);
150 			return invocationHandler instanceof AvalonInterceptorInvocationHandler;
151 		}
152 
153 		return false;
154 	}
155 
156 	/////////////////////////////////////////////////////////////////////////
157 	// Service implementation
158 	/////////////////////////////////////////////////////////////////////////
159 
160 	/**
161 	 * Does the actual work of advising the object.
162 	 *
163 	 * @param name            the name of the object to be advised
164 	 * @param interceptorList the list of interceptor services to advise the object
165 	 * @param object          the object to be advised
166 	 * @return the advised object.
167 	 */
168 	protected Object doAdvice(String name, String[] interceptorList, Object object) {
169 		Validate.notEmpty(name, "name");
170 		Validate.notNull(interceptorList, "interceptorList");
171 		Validate.notNull(object, "object");
172 
173 		Object result = null;
174 		String clazzName = object.getClass().getName();
175 
176 		// do nothing if no interceptor services are requested
177 
178 		if (interceptorList.length == 0) {
179 			if (this.getLogger().isInfoEnabled()) {
180 				String msg = "Skipping creation of dynamic proxy since no interceptors are requested : " + name;
181 				this.getLogger().info(msg);
182 			}
183 
184 			return object;
185 		}
186 
187 		// skip creating a dynamic proxy if it is already advised
188 
189 		if (this.isAdviced(object)) {
190 			if (this.getLogger().isInfoEnabled()) {
191 				String msg = "Skipping creation of dynamic proxy since it is already advised : " + name;
192 				this.getLogger().info(msg);
193 			}
194 
195 			return object;
196 		}
197 
198 		// create the advised object
199 
200 		try {
201 			result = AvalonInterceptorFactory.create(clazzName, name, this.getServiceManager(), interceptorList,
202 					object);
203 		} catch (ServiceException e) {
204 			String msg = "Unable to advice the object : " + name;
205 			this.getLogger().error(msg, e);
206 			throw new IllegalArgumentException(msg);
207 		}
208 
209 		return result;
210 	}
211 
212 	/**
213 	 * @return Returns the serviceManager.
214 	 */
215 	private ServiceManager getServiceManager() {
216 		return serviceManager;
217 	}
218 
219 	/**
220 	 * @return Returns the defaultInterceptorList.
221 	 */
222 	private String[] getDefaultInterceptorList() {
223 		return defaultInterceptorList;
224 	}
225 }