View Javadoc
1 /* 2 Copyright (c) 2003, Laurent Caillette. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without modifica- 6 tion, are permitted provided that the following conditions are met: 7 8 1. Redistributions of source code must retain the above copyright notice, 9 this list of conditions and the following disclaimer. 10 11 2. Redistributions in binary form must reproduce the above copyright notice, 12 this list of conditions and the following disclaimer in the documentation 13 and/or other materials provided with the distribution. 14 15 3. The end-user documentation included with the redistribution, if any, must 16 include the following acknowledgment: "This product includes software 17 written by Laurent Caillette." 18 Alternately, this acknowledgment may appear in the software itself, if 19 and wherever such third-party acknowledgments normally appear. 20 21 4. The name "Laurent Caillette" must not be used to endorse or 22 promote products derived from this software without 23 prior written permission. For written permission, please contact 24 laurent.caillette@laposte.net 25 26 5. Products derived from this software may not be called 27 "Laurent Caillette", nor may "Laurent Caillette" appear 28 in their name, without prior written permission of the 29 author. 30 31 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 32 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 33 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 34 AUTHOR (LAURENT CAILLETTE) BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 36 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 37 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 */ 42 package tweed.invocation; 43 import java.io.Serializable; 44 import java.lang.reflect.Field; 45 import java.lang.reflect.Modifier; 46 import java.util.ArrayList; 47 import java.util.HashMap; 48 import org.apache.avalon.framework.logger.LogEnabled; 49 import org.apache.avalon.framework.logger.Logger; 50 import tweed.system.FunctionalException; 51 52 /*** 53 * This serializable object gathers fields of a {@link Command} object 54 * which should travel from client to server and vice-versa. 55 * Command implementors should not manipulate this class directly. 56 * 57 * @author Laurent Caillette 58 * @version $Id$ 59 */ 60 public final class ExternalizedCommand 61 implements 62 LogEnabled, 63 Serializable 64 { 65 66 private HashMap fieldValues = new HashMap() ; 67 private String serverCommandClassName = null ; 68 private FunctionalException exception = null ; 69 70 public void prepareServerInvocationOnClient( Command command ) { 71 serverCommandClassName = command.getServerSideClassName() ; 72 exception = null ; 73 Field[] allFields = getAllFields( command ) ; 74 75 StringBuffer buf = null ; 76 if( getLogger().isDebugEnabled() ) { 77 buf = new StringBuffer() ; 78 buf.append( "Preparing server invocation for command " + command ) ; 79 buf.append( "\n" ) ; 80 } 81 82 byte[] uses = getUses( allFields ) ; 83 for( int i = 0 ; i < allFields.length ; i++ ) { 84 byte use = uses[ i ] ; 85 switch( use ) { 86 case PARAM_IN : 87 if( getLogger().isDebugEnabled() ) { 88 buf.append( " IN: " + computeKey( allFields[ i ] ) + "\n" ) ; 89 } 90 saveField( command, allFields[ i ] ) ; 91 break ; 92 case PARAM_IN_OUT : 93 if( getLogger().isDebugEnabled() ) { 94 buf.append( " IN_OUT: " + computeKey( allFields[ i ] ) + "\n" ) ; 95 } 96 saveField( command, allFields[ i ] ) ; 97 break ; 98 case PARAM_OUT : 99 if( getLogger().isDebugEnabled() ) { 100 buf.append( " OUT: " + computeKey( allFields[ i ] ) + "\n" ) ; 101 } 102 clearField( allFields[ i ] ) ; 103 break ; 104 default : 105 if( getLogger().isDebugEnabled() ) { 106 buf.append( " NOTHING: " + computeKey( allFields[ i ] ) + "\n" ) ; 107 } 108 break ; 109 } 110 } 111 if( getLogger().isDebugEnabled() ) { 112 getLogger().debug( buf.toString() ) ; 113 } 114 } 115 116 public void prepareExecutionOnServer( Command command ) { 117 exception = null ; 118 Field[] allFields = getAllFields( command ) ; 119 byte[] uses = getUses( allFields ) ; 120 for( int i = 0 ; i < allFields.length ; i++ ) { 121 byte use = uses[ i ] ; 122 switch( use ) { 123 case PARAM_IN : 124 case PARAM_IN_OUT : 125 restituteField( command, allFields[ i ] ) ; 126 break ; 127 } 128 } 129 } 130 131 public void prepareReturnToClient( Command command ) { 132 serverCommandClassName = null ; 133 command.setException( exception ) ; 134 Field[] allFields = getAllFields( command ) ; 135 byte[] uses = getUses( allFields ) ; 136 for( int i = 0 ; i < allFields.length ; i++ ) { 137 byte use = uses[ i ] ; 138 switch( use ) { 139 case PARAM_IN_OUT : 140 case PARAM_OUT : 141 saveField( command, allFields[ i ] ) ; 142 break ; 143 case PARAM_IN : 144 clearField( allFields[ i ] ) ; 145 break ; 146 } 147 } 148 } 149 150 public void reconfigureOnClient( Command command ) { 151 Field[] allFields = getAllFields( command ) ; 152 byte[] uses = getUses( allFields ) ; 153 for( int i = 0 ; i < allFields.length ; i++ ) { 154 byte use = uses[ i ] ; 155 switch( use ) { 156 case PARAM_IN_OUT : 157 case PARAM_OUT : 158 restituteField( command, allFields[ i ] ) ; 159 break ; 160 } 161 } 162 } 163 164 public String getServerCommandClassName() { 165 return serverCommandClassName ; 166 } 167 168 public FunctionalException getException() { 169 return exception; 170 } 171 172 public void setException( FunctionalException exception ) { 173 this.exception = exception; 174 } 175 176 private boolean isSerializable( Field field ) { 177 return 178 ( ! Modifier.isTransient( field.getModifiers() ) ) && 179 ( ! Modifier.isFinal( field.getModifiers() ) ) && 180 ( ! Modifier.isStatic( field.getModifiers() ) ) 181 ; 182 } 183 184 private final static byte NOT_A_PARAM = 0 ; 185 private final static byte PARAM_IN = 1 << 0 ; 186 private final static byte PARAM_OUT = 1 << 1 ; 187 private final static byte PARAM_IN_OUT = PARAM_IN | PARAM_OUT ; 188 189 private byte[] getUses( Field[] fields ) { 190 byte[] uses = new byte[ fields.length ] ; 191 for( int i = 0 ; i < fields.length ; i++ ) { 192 Field field = fields[ i ] ; 193 if( isSerializable( field ) ) { 194 String fieldName = field.getName() ; 195 if( fieldName.startsWith( Command.PARAM_INOUT_PREFIX ) ) { 196 uses[ i ] = PARAM_IN_OUT ; 197 } else if( fieldName.startsWith( Command.PARAM_IN_PREFIX ) ) { 198 uses[ i ] = PARAM_IN ; 199 } else if( fieldName.startsWith( Command.PARAM_OUT_PREFIX ) ) { 200 uses[ i ] = PARAM_OUT ; 201 } else { 202 uses[ i ] = NOT_A_PARAM ; 203 } 204 } 205 } 206 return uses ; 207 } 208 209 private Field[] getAllFields( Command command ) { 210 ArrayList fieldList = new ArrayList() ; 211 Class commandClass = command.getClass() ; 212 while( ! Object.class.equals( commandClass ) ) { 213 Field[] fields = commandClass.getDeclaredFields() ; 214 for( int i = 0 ; i < fields.length ; i++ ) { 215 Field field = fields[ i ] ; 216 field.setAccessible( true ) ; 217 fieldList.add( field ) ; 218 } 219 commandClass = commandClass.getSuperclass() ; 220 } 221 Field[] fieldArray = new Field[ fieldList.size() ] ; 222 fieldArray = ( Field[] ) fieldList.toArray( fieldArray ) ; 223 return fieldArray ; 224 } 225 226 private void saveField( Command command, Field field ) { 227 String fieldKey = computeKey( field ) ; 228 try { 229 fieldValues.put( 230 fieldKey, 231 field.get( command ) 232 ) ; 233 } catch( IllegalArgumentException ex ) { 234 getLogger().error( 235 "Exception caught when saving field " + fieldKey, 236 ex 237 ) ; 238 throw ex ; 239 } catch( IllegalAccessException ex ) { 240 getLogger().error( 241 "Exception caught when saving field " + fieldKey, 242 ex 243 ) ; 244 throw new RuntimeException( ex ) ; 245 } 246 } 247 248 private void restituteField( Command command, Field field ) { 249 String fieldKey = computeKey( field ) ; 250 if( fieldValues.containsKey( fieldKey ) ) { 251 try { 252 Object value = fieldValues.get( fieldKey ) ; 253 field.set( command, value ) ; 254 } catch( IllegalArgumentException ex ) { 255 getLogger().error( 256 "Exception caught when saving field " + fieldKey, 257 ex 258 ) ; 259 throw new RuntimeException( ex ) ; 260 } catch( IllegalAccessException ex ) { 261 getLogger().error( 262 "Exception caught when saving field " + fieldKey, 263 ex 264 ) ; 265 throw new RuntimeException( ex ) ; 266 } 267 } else { 268 getLogger().warn( 269 "Could not restitute field '" + fieldKey + "' for Command " + 270 command.toString() 271 ) ; 272 } 273 } 274 275 private void clearField( Field field ) { 276 fieldValues.remove( computeKey( field ) ) ; 277 } 278 279 private String computeKey( Field field ) { 280 return field.getDeclaringClass().getName() + "#" + field.getName() ; 281 } 282 283 private transient Logger logger ; 284 285 public void enableLogging( Logger logger ) { 286 this.logger = logger ; 287 } 288 289 public Logger getLogger() { 290 return logger ; 291 } 292 293 }

This page was automatically generated by Maven