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 <cs@schulte.it>, 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 5061 2015-05-31 13:20:40Z schulte $ 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 ⁑ DefaultInvoker</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:cs@schulte.it">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.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" ) 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> 73 * This method first passes the given invocation to the {@code preInvoke} method. If the result property of the 74 * invocation returned by the {@code preInvoke} method is an instance of {@code Throwable}, that instance will be 75 * thrown; otherwise the invocation returned by the {@code preInvoke} method is performed and then passed to the 76 * {@code postInvoke} method. If the result property of the invocation returned from the {@code postInvoke} method 77 * is an instance of {@code Throwable}, that instance will be thrown; otherwise the value of the result property is 78 * returned by this method. 79 * </p> 80 * 81 * @param invocation The invocation to perform. 82 * 83 * @return The return value of the invocation. If the declared return type of the method of the invocation is a 84 * primitive type, then the value returned by this method must be an instance of the corresponding primitive wrapper 85 * class; otherwise, it must be a type assignable to the declared return type of the method of the invocation. 86 * If the value returned by this method is {@code null} and the declared return type of the method of the invocation 87 * is primitive, then a {@code NullPointerException} will be thrown. If the value returned by this method is 88 * otherwise not compatible to the declared return type of the method of the invocation, a 89 * {@code ClassCastException} will be thrown. 90 * 91 * @throws Throwable The exception thrown from the method invocation. The exception's type must be assignable 92 * either to any of the exception types declared in the {@code throws} clause of the method of the invocation or to 93 * the unchecked exception types {@code java.lang.RuntimeException} or {@code java.lang.Error}. 94 * If a checked exception is thrown by this method that is not assignable to any of the exception types declared in 95 * the {@code throws} clause of the method of the invocation, then an {@code UndeclaredThrowableException} 96 * containing the exception that was thrown by this method will be thrown. 97 * 98 * @see #preInvoke(org.jomc.spi.Invocation) 99 * @see #postInvoke(org.jomc.spi.Invocation) 100 */ 101 public Object invoke( final Invocation invocation ) throws Throwable 102 { 103 Invocation current = invocation; 104 final Instance instance = (Instance) current.getContext().get( DefaultInvocation.INSTANCE_KEY ); 105 106 try 107 { 108 if ( instance != null && instance.isStateless() ) 109 { 110 try 111 { 112 current = this.preInvoke( current ); 113 } 114 catch ( final Throwable t ) 115 { 116 this.handleException( current, t ); 117 } 118 119 if ( !( current.getResult() instanceof Throwable ) ) 120 { 121 try 122 { 123 current.setResult( current.getMethod().invoke( current.getObject(), current.getArguments() ) ); 124 } 125 catch ( final Throwable t ) 126 { 127 this.handleException( current, t ); 128 } 129 } 130 131 try 132 { 133 current = this.postInvoke( current ); 134 } 135 catch ( final Throwable t ) 136 { 137 this.handleException( current, t ); 138 } 139 140 if ( current.getResult() instanceof Throwable ) 141 { 142 throw (Throwable) current.getResult(); 143 } 144 145 return current.getResult(); 146 } 147 else 148 { 149 synchronized ( invocation.getObject() ) 150 { 151 try 152 { 153 current = this.preInvoke( current ); 154 } 155 catch ( final Throwable t ) 156 { 157 this.handleException( current, t ); 158 } 159 160 if ( !( current.getResult() instanceof Throwable ) ) 161 { 162 try 163 { 164 current.setResult( current.getMethod().invoke( current.getObject(), 165 current.getArguments() ) ); 166 167 } 168 catch ( final Throwable t ) 169 { 170 this.handleException( current, t ); 171 } 172 } 173 174 try 175 { 176 current = this.postInvoke( current ); 177 } 178 catch ( final Throwable t ) 179 { 180 this.handleException( current, t ); 181 } 182 183 if ( current.getResult() instanceof Throwable ) 184 { 185 throw (Throwable) current.getResult(); 186 } 187 188 return current.getResult(); 189 } 190 } 191 } 192 finally 193 { 194 invocation.getContext().clear(); 195 } 196 } 197 198 /** 199 * Called before an invocation is performed. 200 * <p> 201 * Overriding classes may use this method to perform any kind of operation prior to an invocation and to create 202 * custom invocation instances. If an overriding class wishes to throw an exception, it may do so by setting the 203 * result property of the returned invocation to an instance of {@code Throwable} thrown as the result of the 204 * invocation. If an overriding class wishes to provide a custom {@code Invocation} class, it may do so by returning 205 * a different instance from this method. By default, this method does nothing and returns the given invocation 206 * unchanged. 207 * </p> 208 * 209 * @param invocation The invocation about to be performed. 210 * 211 * @return The processed invocation. 212 * 213 * @throws NullPointerException if {@code invocation} is {@code null}. 214 */ 215 public Invocation preInvoke( final Invocation invocation ) 216 { 217 if ( invocation == null ) 218 { 219 throw new NullPointerException( "invocation" ); 220 } 221 222 return invocation; 223 } 224 225 /** 226 * Called after an invocation has been performed. 227 * <p> 228 * Overriding classes may use this method to perform any kind of operation after an invocation has been 229 * performed and to maintain custom invocation instances. If an overriding class wishes to throw an exception, it 230 * may do so by setting the result property of the returned invocation to an instance of {@code Throwable} thrown as 231 * the result of the invocation. Since the result property of the given invocation already holds the result of the 232 * invocation (which may already be an instance of {@code Throwable}), care must be taken when updating that result. 233 * By default, this method does nothing and returns the given invocation unchanged. 234 * </p> 235 * 236 * @param invocation The performed invocation. 237 * 238 * @return The processed invocation. 239 * 240 * @throws NullPointerException if {@code invocation} is {@code null}. 241 */ 242 public Invocation postInvoke( final Invocation invocation ) 243 { 244 if ( invocation == null ) 245 { 246 throw new NullPointerException( "invocation" ); 247 } 248 249 return invocation; 250 } 251 252 /** 253 * Called whenever an exception has been caught. 254 * <p> 255 * Overriding classes may use this method for handling exceptions. By default, this method updates the result of 256 * the given invocation with the given throwable. If that throwable is an instance of 257 * {@code InvocationTargetException}, this method updates the result with the value of that exception's target 258 * exception. If the result of the given invocation already is an instance of {@code Throwable}, this method does 259 * not update the result. 260 * </p> 261 * 262 * @param invocation The invocation to update. 263 * @param t The throwable to update {@code invocation} with. 264 */ 265 public void handleException( final Invocation invocation, final Throwable t ) 266 { 267 if ( invocation != null && !( invocation.getResult() instanceof Throwable ) ) 268 { 269 if ( t instanceof InvocationTargetException 270 && ( (InvocationTargetException) t ).getTargetException() != null ) 271 { 272 invocation.setResult( ( (InvocationTargetException) t ).getTargetException() ); 273 return; 274 } 275 276 invocation.setResult( t ); 277 } 278 } 279 280 // SECTION-END 281 // SECTION-START[Constructors] 282 // <editor-fold defaultstate="collapsed" desc=" Generated Constructors "> 283 /** Creates a new {@code DefaultInvoker} instance. */ 284 @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" ) 285 public DefaultInvoker() 286 { 287 // SECTION-START[Default Constructor] 288 super(); 289 // SECTION-END 290 } 291 // </editor-fold> 292 // SECTION-END 293 // SECTION-START[Dependencies] 294 // SECTION-END 295 // SECTION-START[Properties] 296 // SECTION-END 297 // SECTION-START[Messages] 298 // SECTION-END 299 300 }