| 1 25 26 package com.rift.coad.lib.deployment.rmi; 28 29 import java.io.File ; 31 import java.io.FileWriter ; 32 import java.lang.reflect.Method ; 33 import java.lang.reflect.Type ; 34 import java.net.URLClassLoader ; 35 import java.net.URL ; 36 import java.util.StringTokenizer ; 37 import java.util.Vector ; 38 import java.util.Iterator ; 39 import java.util.regex.Matcher ; 40 import java.util.regex.Pattern ; 41 42 import org.apache.log4j.Logger; 44 45 import com.rift.coad.lib.bean.BeanPattern; 47 import com.rift.coad.lib.common.ClassUtil; 48 import com.rift.coad.lib.common.FileUtil; 49 import com.rift.coad.lib.common.RandomGuid; 50 import com.rift.coad.lib.common.ResourceReader; 51 import com.rift.coad.lib.deployment.BeanInfo; 52 53 60 public class TieGenerator { 61 62 private final static String TIE_TEMPLATE = 64 "com/rift/coad/lib/deployment/rmi/resources/TieTemplate.txt"; 65 private final static String METHOD_TEMPLATE = 66 "com/rift/coad/lib/deployment/rmi/resources/BasicMethodTemplate.txt"; 67 private final static String VOID_METHOD_TEMPLATE = 68 "com/rift/coad/lib/deployment/rmi/resources/" + 69 "VoidMethodTemplate.txt"; 70 private final static String CACHE_METHOD_TEMPLATE = 71 "com/rift/coad/lib/deployment/rmi/resources/CacheMethodTemplate.txt"; 72 private final static String KEY_CACHE_ADD_METHOD_TEMPLATE = 73 "com/rift/coad/lib/deployment/rmi/resources/" + 74 "KeyCacheAddMethodTemplate.txt"; 75 private final static String KEY_CACHE_FIND_METHOD_TEMPLATE = 76 "com/rift/coad/lib/deployment/rmi/resources/" + 77 "KeyCacheFindMethodTemplate.txt"; 78 private final static String KEY_CACHE_REMOVE_METHOD_TEMPLATE = 79 "com/rift/coad/lib/deployment/rmi/resources/" + 80 "KeyCacheRemoveMethodTemplate.txt"; 81 private final static String VOID_KEY_CACHE_REMOVE_METHOD_TEMPLATE = 82 "com/rift/coad/lib/deployment/rmi/resources/" + 83 "VoidKeyCacheRemoveMethodTemplate.txt"; 84 private final static String TRANSACTION_METHOD_TEMPLATE = 85 "com/rift/coad/lib/deployment/rmi/resources/" + 86 "TransactionBasicMethodTemplate.txt"; 87 private final static String TRANSACTION_VOID_METHOD_TEMPLATE = 88 "com/rift/coad/lib/deployment/rmi/resources/" + 89 "TransactionVoidMethodTemplate.txt"; 90 private final static String TRANSACTION_CACHE_METHOD_TEMPLATE = 91 "com/rift/coad/lib/deployment/rmi/resources/" + 92 "TransactionCacheMethodTemplate.txt"; 93 private final static String TRANSACTION_KEY_CACHE_ADD_METHOD_TEMPLATE = 94 "com/rift/coad/lib/deployment/rmi/resources/" + 95 "TransactionKeyCacheAddMethodTemplate.txt"; 96 private final static String TRANSACTION_KEY_CACHE_FIND_METHOD_TEMPLATE = 97 "com/rift/coad/lib/deployment/rmi/resources/" + 98 "TransactionKeyCacheFindMethodTemplate.txt"; 99 private final static String TRANSACTION_KEY_CACHE_REMOVE_METHOD_TEMPLATE = 100 "com/rift/coad/lib/deployment/rmi/resources/" + 101 "TransactionKeyCacheRemoveMethodTemplate.txt"; 102 private final static String  103 TRANSACTION_VOID_KEY_CACHE_REMOVE_METHOD_TEMPLATE = 104 "com/rift/coad/lib/deployment/rmi/resources/" + 105 "TransactionVoidKeyCacheRemoveMethodTemplate.txt"; 106 private final static String METHOD_PARAMETER = "%s%s p%d"; 107 private final static String PARAMETER = "%s p%d"; 108 private final static String TIE_CLASS_NAME = "%s_CoadTie"; 109 110 protected Logger log = 112 Logger.getLogger(TieGenerator.class.getName()); 113 114 private File dir = null; 116 private File targetDir = null; 117 private BeanInfo beanInfo = null; 118 private ClassLoader classLoader = null; 119 120 private String tieTemplate = null; 122 private String basicMethodTemplate = null; 123 private String voidMethodTemplate = null; 124 private String cacheMethodTemplate = null; 125 private String keyCacheAddMethodTemplate = null; 126 private String keyCacheFindMethodTemplate = null; 127 private String keyCacheRemoveMethodTemplate = null; 128 private String voidKeyCacheRemoveMethodTemplate = null; 129 private String transactionBasicMethodTemplate = null; 130 private String transactionVoidMethodTemplate = null; 131 private String transactionCacheMethodTemplate = null; 132 private String transactionKeyCacheAddMethodTemplate = null; 133 private String transactionKeyCacheFindMethodTemplate = null; 134 private String transactionKeyCacheRemoveMethodTemplate = null; 135 private String transactionVoidKeyCacheRemoveMethodTemplate = null; 136 137 145 public TieGenerator(File dir, File targetDir, BeanInfo beanInfo) throws 146 RMIException { 147 this.dir = dir; 148 this.targetDir = targetDir; 149 this.beanInfo = beanInfo; 150 initClassLoader(); 151 152 try { 153 tieTemplate = new ResourceReader(TIE_TEMPLATE).getDocument(); 154 basicMethodTemplate = 155 new ResourceReader(METHOD_TEMPLATE).getDocument(); 156 voidMethodTemplate = 157 new ResourceReader(VOID_METHOD_TEMPLATE).getDocument(); 158 cacheMethodTemplate = 159 new ResourceReader(CACHE_METHOD_TEMPLATE).getDocument(); 160 keyCacheAddMethodTemplate = 161 new ResourceReader(KEY_CACHE_ADD_METHOD_TEMPLATE) 162 .getDocument(); 163 keyCacheFindMethodTemplate = 164 new ResourceReader(KEY_CACHE_FIND_METHOD_TEMPLATE) 165 .getDocument(); 166 keyCacheRemoveMethodTemplate = 167 new ResourceReader(KEY_CACHE_REMOVE_METHOD_TEMPLATE) 168 .getDocument(); 169 voidKeyCacheRemoveMethodTemplate = 170 new ResourceReader(VOID_KEY_CACHE_REMOVE_METHOD_TEMPLATE) 171 .getDocument(); 172 transactionBasicMethodTemplate = 173 new ResourceReader(TRANSACTION_METHOD_TEMPLATE). 174 getDocument(); 175 transactionVoidMethodTemplate = 176 new ResourceReader(TRANSACTION_VOID_METHOD_TEMPLATE). 177 getDocument(); 178 transactionCacheMethodTemplate = 179 new ResourceReader( 180 TRANSACTION_CACHE_METHOD_TEMPLATE). 181 getDocument(); 182 transactionKeyCacheAddMethodTemplate = 183 new ResourceReader( 184 TRANSACTION_KEY_CACHE_ADD_METHOD_TEMPLATE) 185 .getDocument(); 186 transactionKeyCacheFindMethodTemplate = 187 new ResourceReader( 188 TRANSACTION_KEY_CACHE_FIND_METHOD_TEMPLATE) 189 .getDocument(); 190 transactionKeyCacheRemoveMethodTemplate = 191 new ResourceReader( 192 TRANSACTION_KEY_CACHE_REMOVE_METHOD_TEMPLATE) 193 .getDocument(); 194 transactionVoidKeyCacheRemoveMethodTemplate = 195 new ResourceReader( 196 TRANSACTION_VOID_KEY_CACHE_REMOVE_METHOD_TEMPLATE) 197 .getDocument(); 198 } catch (Exception ex) { 199 log.error("Failed retrieve the resource : " + ex.getMessage(),ex); 200 throw new RMIException("Failed retrieve the resource : " + 201 ex.getMessage(),ex); 202 } 203 } 204 205 206 211 public void generate() throws RMIException { 212 Class ref = getClass(beanInfo.getClassName()); 213 createTie(targetDir,ref); 214 215 Vector classes = beanInfo.getClasses(); 217 for (int index = 0; index < classes.size(); index++) { 218 ref = getClass((String )classes.get(index)); 219 createTie(targetDir,ref); 220 } 221 } 222 223 224 229 private void initClassLoader() throws RMIException { 230 try { 231 File [] jars = FileUtil.filter(dir.listFiles(),"jar"); 232 URL [] urls = new URL [jars.length + 1]; 233 urls[0] = dir.toURL(); 234 for (int index = 0; index < jars.length; index++) { 235 urls[index+1] = jars[index].toURL(); 236 } 237 238 classLoader = new URLClassLoader ( 239 urls,this.getClass().getClassLoader()); 240 } catch (Exception ex) { 241 log.error("Failed to init the class loader : " + ex.getMessage(),ex); 242 throw new RMIException("Failed to init the class loader : " + 243 ex.getMessage(),ex); 244 } 245 } 246 247 248 255 private Class getClass(String className) throws RMIException { 256 try { 257 return classLoader.loadClass(className); 258 } catch (Exception ex) { 259 log.error("Failed to retrieve the class: " + ex.getMessage(),ex); 260 throw new RMIException("Failed to retrieve the class : " + 261 ex.getMessage(),ex); 262 } 263 } 264 265 266 273 private File createPackageDir(File tmpDir,Class ref) throws RMIException { 274 try { 275 String className = ref.getCanonicalName(); 276 StringTokenizer tokenizer = new StringTokenizer (className,"."); 277 File base = tmpDir; 278 int numElements = tokenizer.countTokens() - 1; 279 String seperator = ""; 280 for(int count = 0; count < numElements; count++) { 281 File newDir = new File (base,tokenizer.nextToken()); 282 newDir.mkdir(); 283 base = newDir; 284 } 285 return base; 286 } catch (Exception ex) { 287 log.error("Failed to create the package: " + ex.getMessage(),ex); 288 throw new RMIException("Failed to create the package dir : " + 289 ex.getMessage(),ex); 290 } 291 } 292 293 294 301 private void createTie(File tmpDir,Class ref) throws RMIException { 302 try { 303 if (!ClassUtil.testForParent(ref, 304 java.rmi.Remote .class)) { 305 return; 307 } 308 File packageDir = createPackageDir(tmpDir,ref); 309 Vector interfaces = getInterfaces(ref); 310 String methods = ""; 311 Iterator iter = interfaces.iterator(); 312 String interfaceList = getImplements(ref); 313 while(iter.hasNext()) { 314 Class interfaceRef = (Class )iter.next(); 315 Method [] methodList = interfaceRef.getDeclaredMethods(); 316 for (int index = 0; index < methodList.length; index++) { 317 methods += generateCodeForMethod(methodList[index]); 318 } 319 } 320 321 String tieClassName = String.format(TIE_CLASS_NAME,ref. 323 getSimpleName()); 324 String tieClass = new String (tieTemplate); 325 tieClass = tieClass.replaceAll("%package%","package " + 326 ref.getPackage().getName() + ";"); 327 tieClass = tieClass.replaceAll("%tieClassName%",tieClassName); 328 tieClass = tieClass.replaceAll("%implements%",interfaceList); 329 tieClass = tieClass.replaceAll("%target%",ref.getName()); 330 tieClass = tieClass.replaceAll("%methods%",methods); 331 332 File tieClassFile = new File (packageDir,tieClassName + ".java"); 334 FileWriter fileWriter = new FileWriter (tieClassFile); 335 fileWriter.write(tieClass); 336 fileWriter.close(); 337 } catch (Exception ex) { 338 log.error("Failed to create the tie : " + ex.getMessage(),ex); 339 throw new RMIException("Failed to create the tie : " + 340 ex.getMessage(),ex); 341 } 342 } 343 344 345 353 private Vector getInterfaces(Class ref) throws RMIException { 354 if (ref == null) { 355 return new Vector (); 356 } else if (ref.getName().equals(java.lang.Object .class.getName())) { 357 return new Vector (); 358 } 359 Vector results = new Vector (); 360 Class [] interfaces = ref.getInterfaces(); 361 for (int index = 0; index < interfaces.length; index++) { 362 if (ClassUtil.testForParent(interfaces[index],"java.rmi.Remote")) { 363 results.add(interfaces[index]); 364 results.addAll(getInterfaces(interfaces[index])); 365 } 366 } 367 results.addAll(getInterfaces(ref.getSuperclass())); 368 return results; 369 } 370 371 378 public String getImplements(Class ref) throws RMIException { 379 String interfaceList = ""; 380 Class [] interfaces = ref.getInterfaces(); 381 for (int index = 0; index < interfaces.length; index++) { 382 if (ClassUtil.testForParent(interfaces[index],"java.rmi.Remote")) { 383 interfaceList += "," + interfaces[index].getName(); 384 } 385 } 386 return interfaceList; 387 } 388 389 390 397 private String generateCodeForMethod(Method method) 398 throws RMIException { 399 String methodName = method.getName(); 400 String returnType = classTypeToString(method.getReturnType()); 401 Class [] parametersTypes = method.getParameterTypes(); 402 String fullParameters = ""; 403 String parameters = ""; 404 String seperator = ""; 405 for (int index = 0; index < parametersTypes.length; index++) { 406 fullParameters += String.format(METHOD_PARAMETER,seperator, 407 classTypeToString(parametersTypes[index]),index+1); 408 parameters += String.format(PARAMETER,seperator,index+1); 409 seperator = ","; 410 } 411 412 Class [] exceptionList = method.getExceptionTypes(); 414 if (!findException(exceptionList, java.rmi.RemoteException .class)) { 415 throw new RMIException("Interface method [" + method.getName() + 416 "] must throw a java.rmi.RemoteException"); 417 } 418 419 String exceptions = ""; 421 seperator = ""; 422 for (int index = 0; index < exceptionList.length; index++) { 423 exceptions += seperator + exceptionList[index].getName(); 424 seperator = ","; 425 } 426 String template = new String (getTemplate(method)); 428 template = template.replaceAll("%methodName%",methodName); 429 template = template.replaceAll("%returnType%",returnType); 430 template = template.replaceAll("%fullParameters%",fullParameters); 431 template = template.replaceAll("%parameters%",parameters); 432 template = template.replaceAll("%exceptions%",exceptions); 433 return template; 434 } 435 436 437 443 private String classTypeToString(Class type) { 444 if (type.isArray()) { 446 return type.getComponentType().getName() + "[]"; 447 } 448 return type.getName(); 449 } 450 451 452 459 private String getTemplate(Method method) throws RMIException { 460 461 String methodName = method.getName(); 464 Pattern removePattern = Pattern.compile(BeanPattern.REMOVE_PATTERN); 465 Class [] parametersTypes = method.getParameterTypes(); 466 Class returnType = method.getReturnType(); 467 if (beanInfo.getCacheResults() && !beanInfo.getTransaction() && 468 (parametersTypes.length == 1) && ( 469 ClassUtil.testForParent(parametersTypes[0], 470 java.io.Serializable .class)) && removePattern.matcher(methodName) 471 .find() && returnType.getName().equals("void")) { 472 return voidKeyCacheRemoveMethodTemplate; 473 } else if (beanInfo.getCacheResults() && beanInfo.getTransaction() 474 && (parametersTypes.length == 1) && ( 475 ClassUtil.testForParent(parametersTypes[0], 476 java.io.Serializable .class)) && removePattern.matcher(methodName) 477 .find() && returnType.getName().equals("void")) { 478 return transactionVoidKeyCacheRemoveMethodTemplate; 479 } else if (beanInfo.getCacheResults() && !beanInfo.getTransaction() 480 && (parametersTypes.length == 1) && ( 481 ClassUtil.testForParent(parametersTypes[0], 482 java.io.Serializable .class)) && removePattern.matcher(methodName) 483 .find()) { 484 return keyCacheRemoveMethodTemplate; 485 } else if (beanInfo.getCacheResults() && beanInfo.getTransaction() 486 && (parametersTypes.length == 1) && ( 487 ClassUtil.testForParent(parametersTypes[0], 488 java.io.Serializable .class)) && removePattern.matcher(methodName) 489 .find()) { 490 return transactionKeyCacheRemoveMethodTemplate; 491 } else if (beanInfo.getCacheResults() && 492 removePattern.matcher(methodName).find()) { 493 throw new RMIException("The bean cache result flag is set but " + 494 "there is no way identifying this entry in cache. Must " + 495 "supply the index key as a serializable object to a remove " + 496 "method."); 497 } else if (returnType.getName().equals("void") && 498 !beanInfo.getTransaction()) { 499 return voidMethodTemplate; 500 } else if (returnType.getName().equals("void") && 501 beanInfo.getTransaction()) { 502 return transactionVoidMethodTemplate; 503 } 504 505 if (!ClassUtil.testForParent(returnType,java.rmi.Remote .class) && 507 !beanInfo.getTransaction()) { 508 return basicMethodTemplate; 509 } else if (!ClassUtil.testForParent(returnType,java.rmi.Remote .class) && 510 beanInfo.getTransaction()) { 511 return transactionBasicMethodTemplate; 512 } 513 514 Pattern findPattern = Pattern.compile(BeanPattern.FIND_PATTERN); 516 Pattern addPattern = Pattern.compile(BeanPattern.ADD_PATTERN); 517 if (beanInfo.getCacheResults() && !beanInfo.getTransaction() && 518 addPattern.matcher(methodName).find()) { 519 return keyCacheAddMethodTemplate; 520 } else if (beanInfo.getCacheResults() && beanInfo.getTransaction() && 521 addPattern.matcher(methodName).find()) { 522 return transactionKeyCacheAddMethodTemplate; 523 } else if (beanInfo.getCacheResults() && !beanInfo.getTransaction() 524 && findPattern.matcher(methodName).find()&& 525 (parametersTypes.length == 1) && ( 526 ClassUtil.testForParent(parametersTypes[0], 527 java.io.Serializable .class))) { 528 return keyCacheFindMethodTemplate; 529 } else if (beanInfo.getCacheResults() && beanInfo.getTransaction() 530 && findPattern.matcher(methodName).find()&& 531 (parametersTypes.length == 1) && ( 532 ClassUtil.testForParent(parametersTypes[0], 533 java.io.Serializable .class))) { 534 return transactionKeyCacheFindMethodTemplate; 535 } else if (beanInfo.getCacheResults() 536 && findPattern.matcher(methodName).find()&& 537 (parametersTypes.length != 1)) { 538 throw new RMIException("The bean cache result flag is set but " + 539 "there is no way identifying this entry in cache. Must " + 540 "supply the index key as a serializable object to a find " + 541 "method."); 542 } 543 544 if (beanInfo.getTransaction()) { 546 return transactionCacheMethodTemplate; 547 } else { 548 return cacheMethodTemplate; 549 } 550 } 551 552 553 561 private boolean findException(Class [] list, Class exception) { 562 for (int index = 0; index < list.length; index++) { 563 if (list[index].getName().equals(exception.getName())) { 564 return true; 565 } 566 } 567 return false; 568 } 569 } 570 | Popular Tags |