1 55 56 package org.apache.bsf.util.event.generator; 57 58 import java.io.*; 59 import org.apache.bsf.debug.util.DebugLog; 60 61 66 public class EventAdapterGenerator 67 { 68 public static AdapterClassLoader ldr = new AdapterClassLoader(); 69 static Class EVENTLISTENER = null; 70 static String CLASSPACKAGE = "org/apache/bsf/util/event/adapters/"; 71 static String WRITEDIRECTORY = null; 72 73 static byte CLASSHEADER[]; 75 static short BASECPCOUNT; static byte BASECP[]; static byte FIXEDCLASSBYTES[]; 80 static byte INITMETHOD[]; 82 83 84 static 85 { 86 String USERCLASSPACKAGE = System.getProperty("DynamicEventClassPackage", 87 ""); 88 89 if (!USERCLASSPACKAGE.equals("")) 90 { 91 CLASSPACKAGE = USERCLASSPACKAGE; 92 } 93 94 if(CLASSPACKAGE.length() > 0 ) 95 { 96 CLASSPACKAGE = CLASSPACKAGE.replace('\\','/'); 97 if(!CLASSPACKAGE.endsWith("/")) 98 { CLASSPACKAGE = CLASSPACKAGE+"/"; } 99 } 100 WRITEDIRECTORY = System.getProperty("DynamicEventClassWriteDirectory",CLASSPACKAGE); 101 if(WRITEDIRECTORY.length() > 0 ) 102 { 103 WRITEDIRECTORY = WRITEDIRECTORY.replace('\\','/'); 104 if(!WRITEDIRECTORY.endsWith("/")) 105 { WRITEDIRECTORY = WRITEDIRECTORY+"/"; } 106 } 107 try 108 { EVENTLISTENER = Class.forName("java.util.EventListener"); } 109 catch(ClassNotFoundException ex) 110 { 111 System.err.println(ex.getMessage()); 112 ex.printStackTrace(); 113 } 114 115 CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(byte)0xCA); CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(byte)0xFE); CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(byte)0xBA); CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(byte)0xBE); CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(short)3); CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(short)45); 123 BASECPCOUNT = 17; 126 BASECP = Bytecode.addUtf8(BASECP,"()V"); 128 129 BASECP = Bytecode.addUtf8(BASECP,"<init>"); 131 132 BASECP = Bytecode.addUtf8(BASECP,"Code"); 134 135 BASECP = Bytecode.addUtf8(BASECP,"eventProcessor"); 137 138 BASECP = Bytecode.addUtf8(BASECP,"java/lang/Object"); 140 141 BASECP = Bytecode.addUtf8(BASECP,"org/apache/bsf/util/event/EventAdapterImpl"); 143 144 BASECP = Bytecode.addUtf8(BASECP,"org/apache/bsf/util/event/EventProcessor"); 146 147 BASECP = Bytecode.addUtf8(BASECP,"(Ljava/lang/String;[Ljava/lang/Object;)V"); 149 150 BASECP = Bytecode.addUtf8(BASECP,"Lorg/apache/bsf/util/event/EventProcessor;"); 152 153 BASECP = Bytecode.addClass(BASECP,(short)5); 156 BASECP = Bytecode.addClass(BASECP,(short)6); 159 BASECP = Bytecode.addClass(BASECP,(short)7); 162 BASECP = Bytecode.addNameAndType(BASECP,(short)2,(short)1); 165 BASECP = Bytecode.addNameAndType(BASECP,(short)4,(short)9); 168 BASECP = Bytecode.addFieldRef(BASECP,(short)11,(short)14); 170 171 BASECP = Bytecode.addMethodRef(BASECP,(short)11,(short)13); 173 174 FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)0x21); FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)20); FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)11); FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)1); FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)19); FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)0); 182 INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)2); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)3); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(long)17); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(long)5); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(byte)0x2A); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(byte)0xB7); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)16); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(byte)0xB1); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)0); INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)0); 201 } 202 203 204 public static Class makeEventAdapterClass(Class listenerType,boolean writeClassFile) 205 { 206 DebugLog.stdoutPrintln("EventAdapterGenerator", DebugLog.BSF_LOG_L3); 207 208 if( EVENTLISTENER.isAssignableFrom(listenerType) ) 209 { 210 boolean exceptionable = false; 211 boolean nonExceptionable = false; 212 byte constantPool[] = null; 213 short cpBaseIndex; 214 short cpCount = 0; 215 short cpExceptionBaseIndex; 216 short exceptionableCount; 217 short nonExceptionableCount; 218 219 220 String listenerTypeName = listenerType.getName(); 221 DebugLog.stdoutPrintln(" ListenerTypeName: "+listenerTypeName, 222 DebugLog.BSF_LOG_L3); 223 String adapterClassName = 224 CLASSPACKAGE+ 225 (listenerTypeName.endsWith("Listener") 226 ? listenerTypeName.substring(0, listenerTypeName.length() - 8) 227 : listenerTypeName).replace('.', '_') + 228 "Adapter"; 229 String finalAdapterClassName = adapterClassName; 230 Class cached = null; 231 int suffixIndex = 0; 232 233 do 234 { 235 if (null != (cached = ldr.getLoadedClass(finalAdapterClassName))) 236 { 237 DebugLog.stdoutPrintln("cached: "+cached, DebugLog.BSF_LOG_L3); 238 try 239 { 240 if (!listenerType.isAssignableFrom(cached)) 241 finalAdapterClassName = adapterClassName + "_" + suffixIndex++; 242 else 243 return cached; 244 } 245 catch(VerifyError ex) 246 { 247 System.err.println(ex.getMessage()); 248 ex.printStackTrace(); 249 return cached; 250 } 251 } 252 } 253 while (cached != null); 254 255 String eventListenerName = listenerTypeName.replace('.', '/'); 256 257 258 java.lang.reflect.Method lms[] = listenerType.getMethods(); 259 260 261 cpCount += 4; 264 265 constantPool = Bytecode.addUtf8(constantPool,eventListenerName); 267 268 constantPool = Bytecode.addUtf8(constantPool,finalAdapterClassName); 270 271 constantPool = Bytecode.addClass(constantPool,(short)17); 273 274 constantPool = Bytecode.addClass(constantPool,(short)18); 276 277 for (int i = 0 ; i < lms.length ; ++i) 279 { 280 Class exceptionTypes[] = lms[i].getExceptionTypes(); 281 if( 0 < exceptionTypes.length) 282 { exceptionable = true; } 283 else 284 { nonExceptionable = true; } 285 } 286 287 288 290 nonExceptionableCount = 0; 291 if(nonExceptionable) 292 { 293 nonExceptionableCount = 3; 294 cpCount += nonExceptionableCount; 295 296 constantPool = Bytecode.addUtf8(constantPool,"processEvent"); 298 299 constantPool = Bytecode.addNameAndType(constantPool,(short)21,(short)8); 301 302 303 constantPool = Bytecode.addInterfaceMethodRef(constantPool,(short)12,(short)22); 305 } 306 307 308 310 exceptionableCount = 0; 311 if(exceptionable) 312 { 313 int classIndex = BASECPCOUNT + cpCount + 1; 314 int nameIndex = BASECPCOUNT + cpCount + 0; 315 int natIndex = BASECPCOUNT + cpCount + 3; 316 317 exceptionableCount = 5; 318 cpCount += exceptionableCount; 319 320 constantPool = Bytecode.addUtf8(constantPool,"processExceptionableEvent"); 322 323 constantPool = Bytecode.addUtf8(constantPool,"java/lang/Exception"); 325 326 constantPool = Bytecode.addClass(constantPool,(short)classIndex); 328 329 constantPool = Bytecode.addNameAndType(constantPool,(short)nameIndex,(short)8); 331 332 constantPool = Bytecode.addInterfaceMethodRef(constantPool,(short)12,(short)natIndex); 334 335 } 336 337 cpBaseIndex = (short)(BASECPCOUNT + cpCount); 339 DebugLog.stderrPrintln("cpBaseIndex: " + cpBaseIndex, DebugLog.BSF_LOG_L3); 340 341 for (int i = 0 ; i < lms.length ; ++i) 342 { 343 String eventMethodName = lms[i].getName(); 344 String eventName = lms[i].getParameterTypes()[0].getName().replace('.','/'); 345 cpCount += 3; 346 constantPool = Bytecode.addUtf8(constantPool,eventMethodName); 348 constantPool = Bytecode.addUtf8(constantPool,("(L" + eventName + ";)V")); 349 constantPool = Bytecode.addString(constantPool,(short)(BASECPCOUNT+cpCount-3)); 350 } 351 352 boolean propertyChangeFlag[] = new boolean[lms.length]; 353 int cpIndexPCE = 0; 354 for (int i = 0 ; i < lms.length ; ++i) 355 { 356 String eventName = lms[i].getParameterTypes()[0].getName().replace('.','/'); 357 if(eventName.equalsIgnoreCase("java/beans/PropertyChangeEvent")) 359 { 360 propertyChangeFlag[i] = true; 361 if( 0 == cpIndexPCE ) 362 { 363 constantPool = Bytecode.addUtf8(constantPool,eventName); 364 constantPool = Bytecode.addUtf8(constantPool,"getPropertyName"); 365 constantPool = Bytecode.addUtf8(constantPool,"()Ljava/lang/String;"); 366 constantPool = Bytecode.addClass(constantPool,(short)(BASECPCOUNT + cpCount)); 367 constantPool = Bytecode.addNameAndType(constantPool, 368 (short)(BASECPCOUNT + cpCount + 1), 369 (short)(BASECPCOUNT + cpCount + 2)); 370 constantPool = Bytecode.addMethodRef(constantPool, 371 (short)(BASECPCOUNT + cpCount + 3), 372 (short)(BASECPCOUNT + cpCount + 4)); 373 cpCount += 6; 374 cpIndexPCE = BASECPCOUNT + cpCount - 1; 375 376 } 377 } 378 else 379 { propertyChangeFlag[i] = false; } 380 } 381 382 cpExceptionBaseIndex = (short)(BASECPCOUNT + cpCount); 383 DebugLog.stderrPrintln("cpExceptionBaseIndex: " + cpExceptionBaseIndex, DebugLog.BSF_LOG_L3); 384 385 int excpIndex[][] = new int[lms.length][]; 386 for (int i = 0 ; i < lms.length ; ++i) 387 { 388 Class exceptionTypes[] = lms[i].getExceptionTypes(); 389 excpIndex[i] = new int[exceptionTypes.length]; 390 for ( int j = 0 ; j < exceptionTypes.length ; j++) 391 { 392 constantPool = Bytecode.addUtf8(constantPool,exceptionTypes[j].getName().replace('.', '/')); 393 constantPool = Bytecode.addClass(constantPool,(short)(BASECPCOUNT+cpCount)); 394 excpIndex[i][j] = BASECPCOUNT + cpCount + 1; 395 cpCount += 2; 396 } 397 } 398 399 400 401 403 404 byte newClass[] = CLASSHEADER; short count = (short)(BASECPCOUNT + cpCount); 406 newClass = ByteUtility.addBytes(newClass,count); newClass = ByteUtility.addBytes(newClass,BASECP); newClass = ByteUtility.addBytes(newClass,constantPool); newClass = ByteUtility.addBytes(newClass,FIXEDCLASSBYTES); newClass = ByteUtility.addBytes(newClass,(short)(lms.length+1)); newClass = ByteUtility.addBytes(newClass,INITMETHOD); 414 415 416 for (int i = 0 ; i < lms.length ; ++i) 417 { 418 newClass = ByteUtility.addBytes(newClass,(short)1); newClass = ByteUtility.addBytes(newClass,(short)(cpBaseIndex+3*i+0)); newClass = ByteUtility.addBytes(newClass,(short)(cpBaseIndex+3*i+1)); newClass = ByteUtility.addBytes(newClass,(short)1); newClass = ByteUtility.addBytes(newClass,(short)3); 424 int length = 32; 426 if( 0 < excpIndex[i].length ) 427 { length += 5 + 8 * ( 1 + excpIndex[i].length ); } 428 if(propertyChangeFlag[i]) 429 { length += 2; } 430 newClass = ByteUtility.addBytes(newClass,(long)length); 432 newClass = ByteUtility.addBytes(newClass,(short)6); newClass = ByteUtility.addBytes(newClass,(short)3); 436 length = 20; 438 if(exceptionable && 0 < excpIndex[i].length) 439 { length += 5; } 440 if(propertyChangeFlag[i]) 441 { length += 2; } 442 newClass = ByteUtility.addBytes(newClass,(long)length); 444 newClass = ByteUtility.addBytes(newClass,(byte)0x2A); newClass = ByteUtility.addBytes(newClass,(byte)0xB4); newClass = ByteUtility.addBytes(newClass,(short)15); 449 450 if(propertyChangeFlag[i]) 451 { newClass = ByteUtility.addBytes(newClass,(byte)0x2B); newClass = ByteUtility.addBytes(newClass,(byte)0xB6); newClass = ByteUtility.addBytes(newClass,(short)cpIndexPCE); } 456 else 457 { newClass = ByteUtility.addBytes(newClass,(byte)0x12); newClass = ByteUtility.addBytes(newClass,(byte)(cpBaseIndex+3*i+2)); } 462 463 newClass = ByteUtility.addBytes(newClass,(byte)0x04); newClass = ByteUtility.addBytes(newClass,(byte)0xBD); newClass = ByteUtility.addBytes(newClass,(short)10); newClass = ByteUtility.addBytes(newClass,(byte)0x59); newClass = ByteUtility.addBytes(newClass,(byte)0x03); newClass = ByteUtility.addBytes(newClass,(byte)0x2B); newClass = ByteUtility.addBytes(newClass,(byte)0x53); newClass = ByteUtility.addBytes(newClass,(byte)0xB9); 472 length = 23; if(exceptionable && nonExceptionable) 475 { if( 0 < lms[i].getExceptionTypes().length ) 477 { length += 5; } 478 } 479 else if(exceptionable) 480 { length += 2; } 481 newClass = ByteUtility.addBytes(newClass,(short)length); 483 newClass = ByteUtility.addBytes(newClass,(byte)0x03); newClass = ByteUtility.addBytes(newClass,(byte)0x00); newClass = ByteUtility.addBytes(newClass,(byte)0xB1); 487 if(exceptionable && 0 < excpIndex[i].length) 488 { newClass = ByteUtility.addBytes(newClass,(byte)0x4D); newClass = ByteUtility.addBytes(newClass,(byte)0x2C); newClass = ByteUtility.addBytes(newClass,(byte)0xBF); newClass = ByteUtility.addBytes(newClass,(byte)0x57); newClass = ByteUtility.addBytes(newClass,(byte)0xB1); 496 length = excpIndex[i].length; 498 newClass = ByteUtility.addBytes(newClass,(short)(1+length)); for( int j = 0 ; j < length ; j++ ) 500 { newClass = ByteUtility.addBytes(newClass,(short)0); if(propertyChangeFlag[i]) 503 { 504 newClass = ByteUtility.addBytes(newClass,(short)21); newClass = ByteUtility.addBytes(newClass,(short)22); } 507 else 508 { 509 newClass = ByteUtility.addBytes(newClass,(short)19); newClass = ByteUtility.addBytes(newClass,(short)20); } 512 newClass = ByteUtility.addBytes(newClass,(short)excpIndex[i][j]); } 514 newClass = ByteUtility.addBytes(newClass,(short)0); if(propertyChangeFlag[i]) 517 { 518 newClass = ByteUtility.addBytes(newClass,(short)21); newClass = ByteUtility.addBytes(newClass,(short)25); } 521 else 522 { 523 newClass = ByteUtility.addBytes(newClass,(short)19); newClass = ByteUtility.addBytes(newClass,(short)23); } 526 if(nonExceptionable) 527 { newClass = ByteUtility.addBytes(newClass,(short)26); } else { newClass = ByteUtility.addBytes(newClass,(short)23); } } 531 else 532 { newClass = ByteUtility.addBytes(newClass,(short)0); } newClass = ByteUtility.addBytes(newClass,(short)0); 537 538 } 539 newClass = ByteUtility.addBytes(newClass,(short)0); 542 543 DebugLog.stdoutPrintln("adapterName: " + finalAdapterClassName, 544 DebugLog.BSF_LOG_L3); 545 DebugLog.stdoutPrintln("cpCount: " + count + " = " + BASECPCOUNT + " + " + cpCount, DebugLog.BSF_LOG_L3); 546 DebugLog.stdoutPrintln("methodCount: " + (lms.length+1), DebugLog.BSF_LOG_L3); 547 549 550 553 if (writeClassFile) 554 { 555 try 556 { 557 FileOutputStream fos = new FileOutputStream(WRITEDIRECTORY+finalAdapterClassName+".class"); 558 fos.write(newClass); 559 fos.close(); 560 } 561 catch(IOException ex) 562 { 563 System.err.println(ex.getMessage()); 564 ex.printStackTrace(); 565 } 566 567 try 568 { 569 Class ret = ldr.loadClass(finalAdapterClassName); 570 DebugLog.stdoutPrintln("EventAdapterGenerator: " + 571 ret.getName() + 572 " dynamically generated", DebugLog.BSF_LOG_L3); 573 return ret; 574 } 575 catch (ClassNotFoundException ex) 576 { 577 System.err.println(ex.getMessage()); 578 ex.printStackTrace(); 579 } 580 } 581 582 try 583 { 584 Class ret = ldr.defineClass(finalAdapterClassName,newClass); 585 DebugLog.stdoutPrintln("EventAdapterGenerator: " + 586 ret.getName() + 587 " dynamically generated", 588 DebugLog.BSF_LOG_L3); 589 return ret; 590 } 591 catch(Exception ex) 592 { 593 System.err.println(ex.getMessage()); 594 ex.printStackTrace(); 595 } 596 } 597 else 598 { 599 System.err.println("EventAdapterGenerator ListenerType invalid: listenerType = " + listenerType); 600 } 601 return null; 602 } 603 } 604 | Popular Tags |