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.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      // Avalon Service Lifecycle Implementation
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     // Service interface implementation
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     // Service implementation
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         // do nothing if no interceptor services are requested
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         // skip creating a dynamic proxy if it is already advised
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         // create the advised object
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 }