1 22 package org.jboss.iiop.rmi; 23 24 import java.lang.reflect.Method ; 25 import java.lang.reflect.Field ; 26 import java.lang.reflect.Modifier ; 27 28 import java.io.ObjectStreamClass ; 29 import java.io.Serializable ; 30 import java.io.Externalizable ; 31 import java.util.ArrayList ; 32 33 42 public abstract class ContainerAnalysis 43 extends ClassAnalysis 44 { 45 47 48 protected final byte M_OVERLOADED = 1; 49 50 51 protected final byte M_READ = 2; 52 53 54 protected final byte M_WRITE = 4; 55 56 57 protected final byte M_READONLY = 8; 58 59 60 protected final byte M_INHERITED = 16; 61 62 66 protected final byte M_WRITEOBJECT = 32; 67 68 69 70 protected final byte F_CONSTANT = 1; 71 72 76 protected final byte F_SPFFIELD = 2; 77 78 80 83 protected Method [] methods; 84 85 88 protected byte[] m_flags; 89 90 96 protected int[] mutators; 97 98 101 protected Field [] fields; 102 103 106 protected byte[] f_flags; 107 108 112 protected long classHashCode = 0; 113 114 119 protected String repositoryId; 120 121 126 protected String memberPrefix, memberPostfix; 127 128 131 protected InterfaceAnalysis[] interfaces; 132 133 136 protected ValueAnalysis[] abstractBaseValuetypes; 137 138 141 protected AttributeAnalysis[] attributes; 142 143 146 protected ConstantAnalysis[] constants; 147 148 151 protected OperationAnalysis[] operations; 152 153 154 156 private static final org.jboss.logging.Logger logger = 157 org.jboss.logging.Logger.getLogger(ContainerAnalysis.class); 158 159 161 protected ContainerAnalysis(Class cls) 162 { 163 super(cls); 164 165 if (cls == java.lang.Object .class || 166 cls == java.io.Serializable .class || 167 cls == java.io.Externalizable .class) 168 throw new IllegalArgumentException ("Cannot analyze special class: " + 169 cls.getName()); 170 171 this.cls = cls; 172 } 173 174 protected void doAnalyze() 175 throws RMIIIOPViolationException 176 { 177 analyzeInterfaces(); 178 analyzeMethods(); 179 analyzeFields(); 180 calculateClassHashCode(); 181 calculateRepositoryId(); 182 analyzeAttributes(); 183 analyzeConstants(); 184 analyzeOperations(); 185 fixupOverloadedOperationNames(); 186 } 187 188 190 193 public InterfaceAnalysis[] getInterfaces() 194 { 195 logger.debug(cls + " Interface count: " + interfaces.length); 196 return (InterfaceAnalysis[])interfaces.clone(); 197 } 198 199 202 public ValueAnalysis[] getAbstractBaseValuetypes() 203 { 204 logger.debug(cls + " Abstract base valuetype count: " + abstractBaseValuetypes.length); 205 return (ValueAnalysis[])abstractBaseValuetypes.clone(); 206 } 207 208 211 public AttributeAnalysis[] getAttributes() 212 { 213 logger.debug(cls + " Attribute count: " + attributes.length); 214 return (AttributeAnalysis[])attributes.clone(); 215 } 216 217 220 public ConstantAnalysis[] getConstants() 221 { 222 logger.debug(cls + " Constants count: " + constants.length); 223 return (ConstantAnalysis[])constants.clone(); 224 } 225 226 229 public OperationAnalysis[] getOperations() 230 { 231 logger.debug(cls + " Operations count: " + operations.length); 232 return (OperationAnalysis[])operations.clone(); 233 } 234 235 238 public String getRepositoryId() 239 { 240 return repositoryId; 241 } 242 243 248 public String getMemberRepositoryId(String memberName) 249 { 250 return memberPrefix + escapeIRName(memberName) + memberPostfix; 251 } 252 253 257 public String getIDLModuleName() 258 { 259 if (idlModuleName == null) { 260 String pkgName = cls.getPackage().getName(); 261 StringBuffer b = new StringBuffer (); 262 263 while (!"".equals(pkgName)) { 264 int idx = pkgName.indexOf('.'); 265 String n = (idx == -1) ? pkgName : pkgName.substring(0, idx); 266 267 b.append("::").append(Util.javaToIDLName(n)); 268 269 pkgName = (idx == -1) ? "" : pkgName.substring(idx+1); 270 } 271 idlModuleName = b.toString(); 272 } 273 return idlModuleName; 274 } 275 276 278 281 protected String toHexString(int i) 282 { 283 String s = Integer.toHexString(i).toUpperCase(); 284 285 if (s.length() < 8) 286 return "00000000".substring(0, 8 - s.length()) + s; 287 else 288 return s; 289 } 290 293 protected String toHexString(long l) 294 { 295 String s = Long.toHexString(l).toUpperCase(); 296 297 if (s.length() < 16) 298 return "0000000000000000".substring(0, 16 - s.length()) + s; 299 else 300 return s; 301 } 302 303 306 protected boolean isAccessor(Method m) 307 { 308 Class returnType = m.getReturnType(); 309 310 if (!m.getName().startsWith("get")) 311 if (!m.getName().startsWith("is") || !(returnType == Boolean.TYPE)) 312 return false; 313 if (returnType == Void.TYPE) 314 return false; 315 if (m.getParameterTypes().length != 0) 316 return false; 317 318 return hasNonAppExceptions(m); 319 } 320 321 324 protected boolean isMutator(Method m) 325 { 326 if (!m.getName().startsWith("set")) 327 return false; 328 if (m.getReturnType() != Void.TYPE) 329 return false; 330 if (m.getParameterTypes().length != 1) 331 return false; 332 return hasNonAppExceptions(m); 333 } 334 335 339 protected boolean hasNonAppExceptions(Method m) 340 { 341 Class [] ex = m.getExceptionTypes(); 342 343 for (int i = 0; i < ex.length; ++i) 344 if (!java.rmi.RemoteException .class.isAssignableFrom(ex[i])) 345 return false; 346 return true; 347 } 348 349 354 protected void analyzeFields() 355 { 356 logger.debug(cls + " analyzeFields"); 357 358 fields = cls.getDeclaredFields(); 360 f_flags = new byte[fields.length]; 361 362 for (int i = 0; i < fields.length; ++i) { 363 int mods = fields[i].getModifiers(); 364 365 if (Modifier.isFinal(mods) && 366 Modifier.isStatic(mods) && 367 Modifier.isPublic(mods)) 368 f_flags[i] |= F_CONSTANT; 369 } 370 371 logger.debug(cls + " analyzeFields fields=" + fields.length); 372 } 373 374 378 protected void analyzeInterfaces() 379 throws RMIIIOPViolationException 380 { 381 logger.debug(cls + " analyzeInterfaces"); 382 383 Class [] intfs = cls.getInterfaces(); 384 ArrayList a = new ArrayList (); 385 ArrayList b = new ArrayList (); 386 387 for (int i = 0; i < intfs.length; ++i) { 388 if (intfs[i] == java.rmi.Remote .class) 390 continue; 391 if (intfs[i] == java.io.Serializable .class) 393 continue; 394 if (intfs[i] == java.io.Externalizable .class) 396 continue; 397 if (!RmiIdlUtil.isAbstractValueType(intfs[i])) { 398 a.add(InterfaceAnalysis.getInterfaceAnalysis(intfs[i])); 399 } 400 else { 401 b.add(ValueAnalysis.getValueAnalysis(intfs[i])); 402 } 403 } 404 405 interfaces = new InterfaceAnalysis[a.size()]; 406 interfaces = (InterfaceAnalysis[])a.toArray(interfaces); 407 408 abstractBaseValuetypes = new ValueAnalysis[b.size()]; 409 abstractBaseValuetypes = (ValueAnalysis[])b.toArray(abstractBaseValuetypes); 410 411 logger.debug(cls + " analyzeInterfaces interfaces=" + interfaces.length + " abstractBaseValueTypes=" + abstractBaseValuetypes.length); 412 } 413 414 419 protected void analyzeMethods() 420 { 421 logger.debug(cls + " analyzeMethods"); 422 423 if (cls.isInterface() && java.rmi.Remote .class.isAssignableFrom(cls)) 428 methods = cls.getMethods(); 429 else 430 methods = cls.getDeclaredMethods(); 431 m_flags = new byte[methods.length]; 432 mutators = new int[methods.length]; 433 434 for (int i = 0; i < methods.length; ++i) 436 mutators[i] = -1; for (int i = 0; i < methods.length; ++i) { 438 logger.debug("analyzeMethods(): method["+i+"].getName()=\"" + 439 methods[i].getName() + "\"."); 440 441 if (isAccessor(methods[i]) && (m_flags[i]&M_READ) == 0) { 442 String attrName = attributeReadName(methods[i].getName()); 443 Class iReturn = methods[i].getReturnType(); 444 for (int j = i+1; j < methods.length; ++j) { 445 if (isMutator(methods[j]) && (m_flags[j]&M_WRITE) == 0 && 446 attrName.equals(attributeWriteName(methods[j].getName()))) { 447 Class [] jParams = methods[j].getParameterTypes(); 448 if (jParams.length == 1 && jParams[0] == iReturn) { 449 m_flags[i] |= M_READ; 450 m_flags[j] |= M_WRITE; 451 mutators[i] = j; 452 break; 453 } 454 } 455 } 456 } else if (isMutator(methods[i]) && (m_flags[i]&M_WRITE) == 0) { 457 String attrName = attributeWriteName(methods[i].getName()); 458 Class [] iParams = methods[i].getParameterTypes(); 459 for (int j = i+1; j < methods.length; ++j) { 460 if (isAccessor(methods[j]) && (m_flags[j]&M_READ) == 0 && 461 attrName.equals(attributeReadName(methods[j].getName()))) { 462 Class jReturn = methods[j].getReturnType(); 463 if (iParams.length == 1 && iParams[0] == jReturn) { 464 m_flags[i] |= M_WRITE; 465 m_flags[j] |= M_READ; 466 mutators[j] = i; 467 break; 468 } 469 } 470 } 471 } 472 } 473 474 for (int i = 0; i < methods.length; ++i) 476 if ((m_flags[i] & (M_READ|M_WRITE)) == 0 && isAccessor(methods[i])) 477 m_flags[i] |= M_READONLY; 478 479 for (int i = 0; i < methods.length; ++i) { 481 if ((m_flags[i] & (M_READ|M_WRITE|M_READONLY)) == 0) { 482 String iName = methods[i].getName(); 483 484 for (int j = i+1; j < methods.length; ++j) { 485 if (iName.equals(methods[j].getName())) { 486 m_flags[i] |= M_OVERLOADED; 487 m_flags[j] |= M_OVERLOADED; 488 } 489 } 490 } 491 492 if (methods[i].getDeclaringClass() != cls) 493 m_flags[i] |= M_INHERITED; 494 } 495 496 logger.debug(cls + " analyzeMethods methods=" + methods.length); 497 } 498 499 503 protected String attributeReadName(String name) 504 { 505 if (name.startsWith("get")) 506 name = name.substring(3); 507 else if (name.startsWith("is")) 508 name = name.substring(2); 509 else 510 throw new IllegalArgumentException ("Not an accessor: " + name); 511 512 return name; 513 } 514 515 519 protected String attributeWriteName(String name) 520 { 521 if (name.startsWith("set")) 522 name = name.substring(3); 523 else 524 throw new IllegalArgumentException ("Not an accessor: " + name); 525 526 return name; 527 } 528 529 533 protected void analyzeConstants() 534 throws RMIIIOPViolationException 535 { 536 logger.debug(cls + " analyzeConstants"); 537 538 ArrayList a = new ArrayList (); 539 540 for (int i = 0; i < fields.length; ++i) { 541 logger.debug("f_flags["+i+"]=" + f_flags[i]); 542 if ((f_flags[i] & F_CONSTANT) == 0) 543 continue; 544 545 Class type = fields[i].getType(); 546 547 if (!type.isPrimitive() && type != java.lang.String .class) { 549 if (cls.isInterface()) 551 throw new RMIIIOPViolationException( 552 "Field \"" + fields[i].getName() + "\" of interface \"" + 553 cls.getName() + "\" is a constant, but not of one " + 554 "of the primitive types, or String.", "1.2.3"); 555 556 continue; 557 } 558 559 String name = fields[i].getName(); 560 561 Object value; 562 try { 563 value = fields[i].get(null); 564 } catch (Exception ex) { 565 throw new RuntimeException (ex.toString()); 566 } 567 568 logger.debug("Constant["+i+"] name= " + name); 569 logger.debug("Constant["+i+"] type= " + type.getName()); 570 logger.debug("Constant["+i+"] value= " + value); 571 a.add(new ConstantAnalysis(name, type, value)); 572 } 573 574 constants = new ConstantAnalysis[a.size()]; 575 constants = (ConstantAnalysis[])a.toArray(constants); 576 logger.debug(cls + " analyzeConstants constant=" + a.size()); 577 } 578 579 583 protected void analyzeAttributes() 584 throws RMIIIOPViolationException 585 { 586 logger.debug(cls + " analyzeAttributes"); 587 588 ArrayList a = new ArrayList (); 589 590 for (int i = 0; i < methods.length; ++i) { 591 logger.debug("m_flags["+i+"]=" + m_flags[i]); 592 595 if ((m_flags[i] & (M_READ|M_READONLY)) != 0) { 596 String name = attributeReadName(methods[i].getName()); 598 599 logger.debug("Attribute["+i+"] name= " + name); 600 if ((m_flags[i]&M_READONLY) != 0) 601 a.add(new AttributeAnalysis(name, methods[i])); 602 else 603 a.add(new AttributeAnalysis(name, methods[i], 604 methods[mutators[i]])); 605 } 606 } 607 608 attributes = new AttributeAnalysis[a.size()]; 609 attributes = (AttributeAnalysis[])a.toArray(attributes); 610 611 logger.debug(cls + " analyzeAttributes attributes=" + a.size()); 612 } 613 614 620 protected void analyzeOperations() 621 throws RMIIIOPViolationException 622 { 623 logger.debug(cls + " analyzeOperations"); 624 operations = new OperationAnalysis[0]; 625 logger.debug(cls + " analyzeOperations operations=" + operations.length); 626 } 627 628 632 protected void fixupOverloadedOperationNames() 633 throws RMIIIOPViolationException 634 { 635 for (int i = 0; i < methods.length; ++i) { 636 if ((m_flags[i]&M_OVERLOADED) == 0) 637 continue; 638 639 OperationAnalysis oa = null; 641 String javaName = methods[i].getName(); 642 for (int opIdx = 0; oa == null && opIdx < operations.length; ++opIdx) 643 if (operations[opIdx].getMethod().equals(methods[i])) 644 oa = operations[opIdx]; 645 646 if (oa == null) 647 continue; 649 ParameterAnalysis[] parms = oa.getParameters(); 651 StringBuffer b = new StringBuffer (oa.getIDLName()); 652 if (parms.length == 0) 653 b.append("__"); 654 for (int j = 0; j < parms.length; ++j) { 655 String s = parms[j].getTypeIDLName(); 656 657 if (s.startsWith("::")) 658 s = s.substring(2); 659 660 if (s.startsWith("_")) { 661 s = s.substring(1); 663 } 664 665 b.append('_'); 666 667 while (!"".equals(s)) { 668 int idx = s.indexOf("::"); 669 670 b.append('_'); 671 672 if (idx == -1) { 673 b.append(s); 674 s = ""; 675 } else { 676 b.append(s.substring(0, idx)); 677 if (s.length() > idx + 2 && s.charAt(idx + 2) == '_') { 678 s = s.substring(idx + 3); 680 } else { 681 s = s.substring(idx + 2); 682 } 683 } 684 } 685 } 686 687 oa.setIDLName(b.toString()); 689 } 690 } 691 692 696 protected void fixupCaseNames() 697 throws RMIIIOPViolationException 698 { 699 ArrayList entries = getContainedEntries(); 700 boolean[] clash = new boolean[entries.size()]; 701 String [] upperNames = new String [entries.size()]; 702 703 for (int i = 0; i < entries.size(); ++i) { 704 AbstractAnalysis aa = (AbstractAnalysis)entries.get(i); 705 706 clash[i] = false; 707 upperNames[i] = aa.getIDLName().toUpperCase(); 708 709 for (int j = 0; j < i; ++j) { 710 if (upperNames[i].equals(upperNames[j])) { 711 clash[i] = true; 712 clash[j] = true; 713 } 714 } 715 } 716 717 for (int i = 0; i < entries.size(); ++i) { 718 if (!clash[i]) 719 continue; 720 721 AbstractAnalysis aa = (AbstractAnalysis)entries.get(i); 722 boolean noUpper = true; 723 String name = aa.getIDLName(); 724 StringBuffer b = new StringBuffer (name); 725 b.append('_'); 726 for (int j = 0; j < name.length(); ++j) { 727 if (!Character.isUpperCase(name.charAt(j))) 728 continue; 729 if (noUpper) 730 noUpper = false; 731 else 732 b.append('_'); 733 b.append(j); 734 } 735 736 aa.setIDLName(b.toString()); 737 } 738 } 739 740 746 abstract protected ArrayList getContainedEntries(); 747 748 753 protected void calculateClassHashCode() 754 { 755 if (cls.isInterface()) 757 classHashCode = 0; 758 else if (!Serializable .class.isAssignableFrom(cls)) 759 classHashCode = 0; 760 else if (Externalizable .class.isAssignableFrom(cls)) 761 classHashCode = 1; 762 else classHashCode = Util.getClassHashCode(cls); 764 } 765 766 769 protected String escapeIRName(String name) 770 { 771 StringBuffer b = new StringBuffer (); 772 773 for (int i = 0; i < name.length(); ++i) { 774 char c = name.charAt(i); 775 776 if (c < 256) 777 b.append(c); 778 else 779 b.append("\\U").append(toHexString((int)c)); 780 } 781 return b.toString(); 782 } 783 784 790 protected void calculateRepositoryId() 791 { 792 if (cls.isArray() || cls.isPrimitive()) 793 throw new IllegalArgumentException ("Not a class or interface."); 794 795 if (cls.isInterface() && 796 org.omg.CORBA.Object .class.isAssignableFrom(cls) && 797 org.omg.CORBA.portable.IDLEntity .class.isAssignableFrom(cls)) { 798 799 StringBuffer b = new StringBuffer ("IDL:"); 800 b.append(cls.getPackage().getName().replace('.', '/')); 801 b.append('/'); 802 String base = cls.getName(); 803 base = base.substring(base.lastIndexOf('.')+1); 804 b.append(base).append(":1.0"); 805 repositoryId = b.toString(); 806 } 807 else { 808 StringBuffer b = new StringBuffer ("RMI:"); 809 b.append(escapeIRName(cls.getName())); 810 memberPrefix = b.toString() + "."; 811 String hashStr = toHexString(classHashCode); 812 b.append(':').append(hashStr); 813 ObjectStreamClass osClass = ObjectStreamClass.lookup(cls); 814 if (osClass != null) { 815 long serialVersionUID = osClass.getSerialVersionUID(); 816 String SVUID = toHexString(serialVersionUID); 817 818 if (classHashCode != serialVersionUID) 819 b.append(':').append(SVUID); 820 memberPostfix = ":" + hashStr + ":" + SVUID; 821 } else 822 memberPostfix = ":" + hashStr; 823 824 repositoryId = b.toString(); 825 } 826 } 827 828 830 834 private String idlModuleName = null; 835 836 } 837 | Popular Tags |