View Javadoc

1   // SECTION-START[License Header]
2   // <editor-fold defaultstate="collapsed" desc=" Generated License ">
3   /*
4    *   Java Object Management and Configuration
5    *   Copyright (C) Christian Schulte, 2005-206
6    *   All rights reserved.
7    *
8    *   Redistribution and use in source and binary forms, with or without
9    *   modification, are permitted provided that the following conditions
10   *   are met:
11   *
12   *     o Redistributions of source code must retain the above copyright
13   *       notice, this list of conditions and the following disclaimer.
14   *
15   *     o Redistributions in binary form must reproduce the above copyright
16   *       notice, this list of conditions and the following disclaimer in
17   *       the documentation and/or other materials provided with the
18   *       distribution.
19   *
20   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
21   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
24   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   *   $JOMC: DefaultInvoker.java 4381 2012-03-04 19:29:29Z schulte2005 $
32   *
33   */
34  // </editor-fold>
35  // SECTION-END
36  package org.jomc.ri;
37  
38  import java.lang.reflect.InvocationTargetException;
39  import org.jomc.model.Instance;
40  import org.jomc.spi.Invocation;
41  import org.jomc.spi.Invoker;
42  
43  // SECTION-START[Documentation]
44  // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
45  /**
46   * Default {@code Invoker} implementation.
47   *
48   * <dl>
49   *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.DefaultInvoker</dd>
50   *   <dt><b>Name:</b></dt><dd>JOMC RI</dd>
51   *   <dt><b>Abstract:</b></dt><dd>No</dd>
52   *   <dt><b>Final:</b></dt><dd>No</dd>
53   *   <dt><b>Stateless:</b></dt><dd>No</dd>
54   * </dl>
55   *
56   * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 1.0
57   * @version 1.0
58   */
59  // </editor-fold>
60  // SECTION-END
61  // SECTION-START[Annotations]
62  // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
63  @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.2.2", comments = "See http://jomc.sourceforge.net/jomc/1.2/jomc-tools-1.2.2" )
64  // </editor-fold>
65  // SECTION-END
66  public class DefaultInvoker implements Invoker
67  {
68      // SECTION-START[DefaultInvoker]
69  
70      /**
71       * Performs a method invocation on an object.
72       * <p>This method first passes the given invocation to the {@code preInvoke} method. If the result property of the
73       * invocation returned by the {@code preInvoke} method is an instance of {@code Throwable}, that instance will be
74       * thrown; otherwise the invocation returned by the {@code preInvoke} method is performed and then passed to the
75       * {@code postInvoke} method. If the result property of the invocation returned from the {@code postInvoke} method
76       * is an instance of {@code Throwable}, that instance will be thrown; otherwise the value of the result property is
77       * returned by this method.</p>
78       *
79       * @param invocation The invocation to perform.
80       *
81       * @return The return value of the invocation. If the declared return type of the method of the invocation is a
82       * primitive type, then the value returned by this method must be an instance of the corresponding primitive wrapper
83       * class; otherwise, it must be a type assignable to the declared return type of the method of the invocation.
84       * If the value returned by this method is {@code null} and the declared return type of the method of the invocation
85       * is primitive, then a {@code NullPointerException} will be thrown. If the value returned by this method is
86       * otherwise not compatible to the declared return type of the method of the invocation, a
87       * {@code ClassCastException} will be thrown.
88       *
89       * @throws Throwable The exception thrown from the method invocation. The exception's type must be assignable
90       * either to any of the exception types declared in the {@code throws} clause of the method of the invocation or to
91       * the unchecked exception types {@code java.lang.RuntimeException} or {@code java.lang.Error}.
92       * If a checked exception is thrown by this method that is not assignable to any of the exception types declared in
93       * the {@code throws} clause of the method of the invocation, then an {@code UndeclaredThrowableException}
94       * containing the exception that was thrown by this method will be thrown.
95       *
96       * @see #preInvoke(org.jomc.spi.Invocation)
97       * @see #postInvoke(org.jomc.spi.Invocation)
98       */
99      public Object invoke( final Invocation invocation ) throws Throwable
100     {
101         Invocation current = invocation;
102         final Instance instance = (Instance) current.getContext().get( DefaultInvocation.INSTANCE_KEY );
103 
104         try
105         {
106             if ( instance != null && instance.isStateless() )
107             {
108                 try
109                 {
110                     current = this.preInvoke( current );
111                 }
112                 catch ( final Throwable t )
113                 {
114                     this.handleException( current, t );
115                 }
116 
117                 if ( !( current.getResult() instanceof Throwable ) )
118                 {
119                     try
120                     {
121                         current.setResult( current.getMethod().invoke( current.getObject(), current.getArguments() ) );
122                     }
123                     catch ( final Throwable t )
124                     {
125                         this.handleException( current, t );
126                     }
127                 }
128 
129                 try
130                 {
131                     current = this.postInvoke( current );
132                 }
133                 catch ( final Throwable t )
134                 {
135                     this.handleException( current, t );
136                 }
137 
138                 if ( current.getResult() instanceof Throwable )
139                 {
140                     throw (Throwable) current.getResult();
141                 }
142 
143                 return current.getResult();
144             }
145             else
146             {
147                 synchronized ( invocation.getObject() )
148                 {
149                     try
150                     {
151                         current = this.preInvoke( current );
152                     }
153                     catch ( final Throwable t )
154                     {
155                         this.handleException( current, t );
156                     }
157 
158                     if ( !( current.getResult() instanceof Throwable ) )
159                     {
160                         try
161                         {
162                             current.setResult( current.getMethod().invoke( current.getObject(),
163                                                                            current.getArguments() ) );
164 
165                         }
166                         catch ( final Throwable t )
167                         {
168                             this.handleException( current, t );
169                         }
170                     }
171 
172                     try
173                     {
174                         current = this.postInvoke( current );
175                     }
176                     catch ( final Throwable t )
177                     {
178                         this.handleException( current, t );
179                     }
180 
181                     if ( current.getResult() instanceof Throwable )
182                     {
183                         throw (Throwable) current.getResult();
184                     }
185 
186                     return current.getResult();
187                 }
188             }
189         }
190         finally
191         {
192             invocation.getContext().clear();
193         }
194     }
195 
196     /**
197      * Called before an invocation is performed.
198      * <p>Overriding classes may use this method to perform any kind of operation prior to an invocation and to create
199      * custom invocation instances. If an overriding class wishes to throw an exception, it may do so by setting the
200      * result property of the returned invocation to an instance of {@code Throwable} thrown as the result of the
201      * invocation. If an overriding class wishes to provide a custom {@code Invocation} class, it may do so by returning
202      * a different instance from this method. By default, this method does nothing and returns the given invocation
203      * unchanged.</p>
204      *
205      * @param invocation The invocation about to be performed.
206      *
207      * @return The processed invocation.
208      *
209      * @throws NullPointerException if {@code invocation} is {@code null}.
210      */
211     public Invocation preInvoke( final Invocation invocation )
212     {
213         if ( invocation == null )
214         {
215             throw new NullPointerException( "invocation" );
216         }
217 
218         return invocation;
219     }
220 
221     /**
222      * Called after an invocation has been performed.
223      * <p>Overriding classes may use this method to perform any kind of operation after an invocation has been
224      * performed and to maintain custom invocation instances. If an overriding class wishes to throw an exception, it
225      * may do so by setting the result property of the returned invocation to an instance of {@code Throwable} thrown as
226      * the result of the invocation. Since the result property of the given invocation already holds the result of the
227      * invocation (which may already be an instance of {@code Throwable}), care must be taken when updating that result.
228      * By default, this method does nothing and returns the given invocation unchanged.</p>
229      *
230      * @param invocation The performed invocation.
231      *
232      * @return The processed invocation.
233      *
234      * @throws NullPointerException if {@code invocation} is {@code null}.
235      */
236     public Invocation postInvoke( final Invocation invocation )
237     {
238         if ( invocation == null )
239         {
240             throw new NullPointerException( "invocation" );
241         }
242 
243         return invocation;
244     }
245 
246     /**
247      * Called whenever an exception has been caught.
248      * <p>Overriding classes may use this method for handling exceptions. By default, this method updates the result of
249      * the given invocation with the given throwable. If that throwable is an instance of
250      * {@code InvocationTargetException}, this method updates the result with the value of that exception's target
251      * exception. If the result of the given invocation already is an instance of {@code Throwable}, this method does
252      * not update the result.</p>
253      *
254      * @param invocation The invocation to update.
255      * @param t The throwable to update {@code invocation} with.
256      */
257     public void handleException( final Invocation invocation, final Throwable t )
258     {
259         if ( invocation != null && !( invocation.getResult() instanceof Throwable ) )
260         {
261             if ( t instanceof InvocationTargetException
262                  && ( (InvocationTargetException) t ).getTargetException() != null )
263             {
264                 invocation.setResult( ( (InvocationTargetException) t ).getTargetException() );
265                 return;
266             }
267 
268             invocation.setResult( t );
269         }
270     }
271 
272     // SECTION-END
273     // SECTION-START[Constructors]
274     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
275     /** Creates a new {@code DefaultInvoker} instance. */
276     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.2.2", comments = "See http://jomc.sourceforge.net/jomc/1.2/jomc-tools-1.2.2" )
277     public DefaultInvoker()
278     {
279         // SECTION-START[Default Constructor]
280         super();
281         // SECTION-END
282     }
283     // </editor-fold>
284     // SECTION-END
285     // SECTION-START[Dependencies]
286     // SECTION-END
287     // SECTION-START[Properties]
288     // SECTION-END
289     // SECTION-START[Messages]
290     // SECTION-END
291 }