001 // SECTION-START[License Header]
002 // <editor-fold defaultstate="collapsed" desc=" Generated License ">
003 /*
004 * Copyright (c) 2009 The JOMC Project
005 * Copyright (c) 2005 Christian Schulte <cs@jomc.org>
006 * All rights reserved.
007 *
008 * Redistribution and use in source and binary forms, with or without
009 * modification, are permitted provided that the following conditions
010 * are met:
011 *
012 * o Redistributions of source code must retain the above copyright
013 * notice, this list of conditions and the following disclaimer.
014 *
015 * o Redistributions in binary form must reproduce the above copyright
016 * notice, this list of conditions and the following disclaimer in
017 * the documentation and/or other materials provided with the
018 * distribution.
019 *
020 * THIS SOFTWARE IS PROVIDED BY THE JOMC PROJECT AND CONTRIBUTORS "AS IS"
021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
022 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
023 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JOMC PROJECT OR
024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
027 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
028 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
029 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
030 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031 *
032 * $Id: DefaultInvoker.java 968 2009-11-18 06:08:28Z schulte2005 $
033 *
034 */
035 // </editor-fold>
036 // SECTION-END
037 package org.jomc.ri;
038
039 import java.lang.reflect.InvocationTargetException;
040 import org.jomc.model.Instance;
041 import org.jomc.spi.Invocation;
042 import org.jomc.spi.Invoker;
043
044 // SECTION-START[Documentation]
045 // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
046 /**
047 * Default {@code Invoker} implementation.
048 * @see DefaultInvocation
049 *
050 * @author <a href="mailto:cs@jomc.org">Christian Schulte</a> 1.0
051 * @version $Id: DefaultInvoker.java 968 2009-11-18 06:08:28Z schulte2005 $
052 */
053 // </editor-fold>
054 // SECTION-END
055 // SECTION-START[Annotations]
056 // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
057 @javax.annotation.Generated( value = "org.jomc.tools.JavaSources",
058 comments = "See http://jomc.sourceforge.net/jomc/1.0-alpha-8/jomc-tools" )
059 // </editor-fold>
060 // SECTION-END
061 public class DefaultInvoker implements Invoker
062 {
063 // SECTION-START[Invoker]
064
065 /**
066 * Performs a method invocation on an object.
067 * <p>This method first passes the given invocation to the {@code preInvoke} method. If the result property of the
068 * invocation returned by the {@code preInvoke} method is an instance of {@code Throwable}, that instance will be
069 * thrown; otherwise the invocation returned by the {@code preInvoke} method is performed and then passed to the
070 * {@code postInvoke} method. If the result property of the invocation returned from the {@code postInvoke} method
071 * is an instance of {@code Throwable}, that instance will be thrown; otherwise the value of the result property is
072 * returned by this method.</p>
073 *
074 * @param invocation The invocation to perform.
075 *
076 * @return The return value of the invocation. If the declared return type of the method of the invocation is a
077 * primitive type, then the value returned by this method must be an instance of the corresponding primitive wrapper
078 * class; otherwise, it must be a type assignable to the declared return type of the method of the invocation.
079 * If the value returned by this method is {@code null} and the declared return type of the method of the invocation
080 * is primitive, then a {@code NullPointerException} will be thrown. If the value returned by this method is
081 * otherwise not compatible to the declared return type of the method of the invocation, a
082 * {@code ClassCastException} will be thrown.
083 *
084 * @throws Throwable The exception thrown from the method invocation. The exception's type must be assignable
085 * either to any of the exception types declared in the {@code throws} clause of the method of the invocation or to
086 * the unchecked exception types {@code java.lang.RuntimeException} or {@code java.lang.Error}.
087 * If a checked exception is thrown by this method that is not assignable to any of the exception types declared in
088 * the {@code throws} clause of the method of the invocation, then an {@code UndeclaredThrowableException}
089 * containing the exception that was thrown by this method will be thrown.
090 *
091 * @see #preInvoke(org.jomc.spi.Invocation)
092 * @see #postInvoke(org.jomc.spi.Invocation)
093 */
094 public Object invoke( final Invocation invocation ) throws Throwable
095 {
096 Invocation current = invocation;
097 final Instance instance = (Instance) current.getContext().get( DefaultInvocation.INSTANCE_KEY );
098
099 try
100 {
101 if ( instance != null && instance.isStateless() )
102 {
103 current = this.preInvoke( current );
104 if ( current.getResult() instanceof Throwable )
105 {
106 throw (Throwable) current.getResult();
107 }
108
109 try
110 {
111 current.setResult( current.getMethod().invoke( current.getObject(), current.getArguments() ) );
112 }
113 catch ( final InvocationTargetException e )
114 {
115 current.setResult( e.getTargetException() != null ? e.getTargetException() : e );
116 }
117 catch ( final Throwable t )
118 {
119 current.setResult( t );
120 }
121
122 current = this.postInvoke( current );
123 if ( current.getResult() instanceof Throwable )
124 {
125 throw (Throwable) current.getResult();
126 }
127 }
128 else
129 {
130 synchronized ( invocation.getObject() )
131 {
132 current = this.preInvoke( current );
133 if ( current.getResult() instanceof Throwable )
134 {
135 throw (Throwable) current.getResult();
136 }
137
138 try
139 {
140 current.setResult( current.getMethod().invoke( current.getObject(), current.getArguments() ) );
141 }
142 catch ( final InvocationTargetException e )
143 {
144 current.setResult( e.getTargetException() != null ? e.getTargetException() : e );
145 }
146 catch ( final Throwable t )
147 {
148 current.setResult( t );
149 }
150
151 current = this.postInvoke( current );
152 if ( current.getResult() instanceof Throwable )
153 {
154 throw (Throwable) current.getResult();
155 }
156 }
157 }
158
159 return current.getResult();
160 }
161 finally
162 {
163 invocation.getContext().clear();
164 }
165 }
166
167 // SECTION-END
168 // SECTION-START[DefaultInvoker]
169 /**
170 * Called before an invocation is performed.
171 * <p>Overriding classes may use this method to perform any kind of operation prior to an invocation and to create
172 * custom invocation instances. If an overriding class wishes to throw an exception, it may do so by setting the
173 * result property of the returned invocation to an instance of {@code Throwable} thrown as the result of the
174 * invocation. If an overriding class wishes to provide a custom {@code Invocation} class, it may do so by returning
175 * a different instance from this method. By default, this method does nothing and returns the given invocation
176 * unchanged.</p>
177 *
178 * @param invocation The invocation about to be performed.
179 *
180 * @return The processed invocation.
181 *
182 * @throws NullPointerException if {@code invocation} is {@code null}.
183 */
184 public Invocation preInvoke( final Invocation invocation )
185 {
186 if ( invocation == null )
187 {
188 throw new NullPointerException( "invocation" );
189 }
190
191 return invocation;
192 }
193
194 /**
195 * Called after an invocation has been performed.
196 * <p>Overriding classes may use this method to perform any kind of operation after an invocation has been
197 * performed and to maintain custom invocation instances. If an overriding class wishes to throw an exception, it
198 * may do so by setting the result property of the returned invocation to an instance of {@code Throwable} thrown as
199 * the result of the invocation. Since the result property of the given invocation already holds the result of the
200 * invocation (which may already be an instance of {@code Throwable}), care must be taken when updating that result.
201 * By default, this method does nothing and returns the given invocation unchanged.</p>
202 *
203 * @param invocation The performed invocation.
204 *
205 * @return The processed invocation.
206 *
207 * @throws NullPointerException if {@code invocation} is {@code null}.
208 */
209 public Invocation postInvoke( final Invocation invocation )
210 {
211 if ( invocation == null )
212 {
213 throw new NullPointerException( "invocation" );
214 }
215
216 return invocation;
217 }
218
219 // SECTION-END
220 // SECTION-START[Constructors]
221 // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
222
223 /** Creates a new {@code DefaultInvoker} instance. */
224 @javax.annotation.Generated( value = "org.jomc.tools.JavaSources",
225 comments = "See http://jomc.sourceforge.net/jomc/1.0-alpha-8/jomc-tools" )
226 public DefaultInvoker()
227 {
228 // SECTION-START[Default Constructor]
229 super();
230 // SECTION-END
231 }
232 // </editor-fold>
233 // SECTION-END
234 // SECTION-START[Dependencies]
235 // SECTION-END
236 // SECTION-START[Properties]
237 // SECTION-END
238 // SECTION-START[Messages]
239 // SECTION-END
240 }