001 // SECTION-START[License Header] 002 // <editor-fold defaultstate="collapsed" desc=" Generated License "> 003 /* 004 * Java Object Management and Configuration 005 * Copyright (C) Christian Schulte, 2005-206 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 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 021 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 022 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 023 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 024 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 025 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 026 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 027 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 029 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 * 031 * $JOMC: DefaultInvoker.java 4381 2012-03-04 19:29:29Z schulte2005 $ 032 * 033 */ 034 // </editor-fold> 035 // SECTION-END 036 package org.jomc.ri; 037 038 import java.lang.reflect.InvocationTargetException; 039 import org.jomc.model.Instance; 040 import org.jomc.spi.Invocation; 041 import org.jomc.spi.Invoker; 042 043 // SECTION-START[Documentation] 044 // <editor-fold defaultstate="collapsed" desc=" Generated Documentation "> 045 /** 046 * Default {@code Invoker} implementation. 047 * 048 * <dl> 049 * <dt><b>Identifier:</b></dt><dd>org.jomc.ri.DefaultInvoker</dd> 050 * <dt><b>Name:</b></dt><dd>JOMC RI</dd> 051 * <dt><b>Abstract:</b></dt><dd>No</dd> 052 * <dt><b>Final:</b></dt><dd>No</dd> 053 * <dt><b>Stateless:</b></dt><dd>No</dd> 054 * </dl> 055 * 056 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 1.0 057 * @version 1.0 058 */ 059 // </editor-fold> 060 // SECTION-END 061 // SECTION-START[Annotations] 062 // <editor-fold defaultstate="collapsed" desc=" Generated Annotations "> 063 @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" ) 064 // </editor-fold> 065 // SECTION-END 066 public class DefaultInvoker implements Invoker 067 { 068 // SECTION-START[DefaultInvoker] 069 070 /** 071 * Performs a method invocation on an object. 072 * <p>This method first passes the given invocation to the {@code preInvoke} method. If the result property of the 073 * invocation returned by the {@code preInvoke} method is an instance of {@code Throwable}, that instance will be 074 * thrown; otherwise the invocation returned by the {@code preInvoke} method is performed and then passed to the 075 * {@code postInvoke} method. If the result property of the invocation returned from the {@code postInvoke} method 076 * is an instance of {@code Throwable}, that instance will be thrown; otherwise the value of the result property is 077 * returned by this method.</p> 078 * 079 * @param invocation The invocation to perform. 080 * 081 * @return The return value of the invocation. If the declared return type of the method of the invocation is a 082 * primitive type, then the value returned by this method must be an instance of the corresponding primitive wrapper 083 * class; otherwise, it must be a type assignable to the declared return type of the method of the invocation. 084 * If the value returned by this method is {@code null} and the declared return type of the method of the invocation 085 * is primitive, then a {@code NullPointerException} will be thrown. If the value returned by this method is 086 * otherwise not compatible to the declared return type of the method of the invocation, a 087 * {@code ClassCastException} will be thrown. 088 * 089 * @throws Throwable The exception thrown from the method invocation. The exception's type must be assignable 090 * either to any of the exception types declared in the {@code throws} clause of the method of the invocation or to 091 * the unchecked exception types {@code java.lang.RuntimeException} or {@code java.lang.Error}. 092 * If a checked exception is thrown by this method that is not assignable to any of the exception types declared in 093 * the {@code throws} clause of the method of the invocation, then an {@code UndeclaredThrowableException} 094 * containing the exception that was thrown by this method will be thrown. 095 * 096 * @see #preInvoke(org.jomc.spi.Invocation) 097 * @see #postInvoke(org.jomc.spi.Invocation) 098 */ 099 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 }