1 18 package org.apache.geronimo.interop.rmi.iiop; 19 20 import java.io.ByteArrayOutputStream ; 21 import java.io.DataOutputStream ; 22 import java.io.ObjectInput ; 23 import java.io.ObjectOutput ; 24 import java.io.ObjectStreamClass ; 25 import java.io.Serializable ; 26 import java.lang.reflect.Field ; 27 import java.lang.reflect.Method ; 28 import java.lang.reflect.Modifier ; 29 import java.security.DigestOutputStream ; 30 import java.security.MessageDigest ; 31 import java.util.ArrayList ; 32 import java.util.Arrays ; 33 import java.util.HashMap ; 34 import java.util.List ; 35 36 import org.apache.geronimo.interop.SystemException; 37 import org.apache.geronimo.interop.util.ArrayUtil; 38 import org.apache.geronimo.interop.util.ExceptionUtil; 39 import org.apache.geronimo.interop.util.JavaClass; 40 import org.apache.geronimo.interop.util.JavaType; 41 import org.apache.geronimo.interop.util.SystemUtil; 42 import org.apache.geronimo.interop.util.ThreadContext; 43 import org.omg.CORBA.TCKind ; 44 45 50 public class ValueType 51 { 52 public static ValueType getInstance(Class forClass) 53 { 54 ValueType vt = (ValueType)_valueTypeMap.get(forClass); 55 if (vt == null) 56 { 57 synchronized (_valueTypeMap) 58 { 59 vt = (ValueType)_valueTypeMap.get(forClass); 60 if (vt == null) 61 { 62 vt = new ValueType(); 63 _valueTypeMap.put(forClass, vt); 64 vt.init(forClass); 65 } 66 } 67 } 68 return vt; 69 } 70 71 public static ValueType getInstanceByID(String id) 72 { 73 ValueType vt = (ValueType)_idTypeMap.get(id); 75 if (vt == null) 76 { 77 synchronized (_idTypeMap) 78 { 79 vt = (ValueType)_idTypeMap.get(id); 80 if (vt == null) 81 { 82 Class theClass = getClass(id); 83 vt = getInstance(theClass); 84 _idTypeMap.put(id, vt); 85 } 86 } 87 } 88 return vt; 89 } 90 91 95 public Class _class; 96 97 public org.apache.geronimo.interop.rmi.iiop.ObjectHelper helper; 98 99 103 private static HashMap _valueTypeMap = new HashMap (); 104 105 private static HashMap _initMap = new HashMap (); 106 107 private static HashMap _idTypeMap = new HashMap (); 108 109 private static final boolean JDK14 = SystemUtil.isJDK14(); 110 111 private static Method _allocateNewObject; 112 113 private static Object [] _allocateNewObjectArgs; 114 115 private static Method _newInstance; 116 117 private ObjectStreamClass _objectStreamClass; 118 119 private Method _readExternal; 120 private Method _readObject; 121 private Method _readResolve; 122 private Method _writeExternal; 123 private Method _writeObject; 124 private Method _writeReplace; 125 126 130 static final int NULL_VALUE_TAG = 0; 131 static final int NO_TYPE_VALUE_TAG = 0x7fffff00; 132 static final int SINGLE_TYPE_VALUE_TAG = 0x7fffff02; 133 static final int TRUNCATABLE_NO_TYPE_VALUE_TAG = 0x7fffff08; 134 static final int TRUNCATABLE_SINGLE_TYPE_VALUE_TAG = 0x7fffff0a; 135 static final int TYPE_LIST_VALUE_TAG = 0x7fffff06; 136 static final int INDIRECTION_TAG = 0xffffffff; 137 138 static final int CASE_ARRAY = 1; 139 static final int CASE_CLASS = 2; 140 static final int CASE_IDL_ENTITY = 3; 141 static final int CASE_IDL_OBJECT = 4; 142 static final int CASE_STRING = 5; 143 144 static final ValueType OBJECT_VALUE_TYPE = getInstance(Object .class); 145 146 static final ValueType STRING_VALUE_TYPE = getInstance(String .class); 147 148 static final org.omg.CORBA.TypeCode TC_NULL = new TypeCode(TCKind.tk_null); 149 150 static TypeCode TC_ABSTRACT_BASE; 151 152 String id; 154 TypeCode tc; 155 156 ValueType parent; 157 158 ValueTypeField[] fields; 160 ValueType element; 162 boolean hasParentState; 163 boolean hasReadObject; 164 boolean hasReadOrWriteObject; 165 boolean hasWriteObject; 166 boolean hasReadResolve; 167 boolean hasWriteReplace; 168 169 boolean isAbstractInterface; 170 boolean isAny; 171 boolean isAnyOrObjectRefOrAbstractInterface; 172 boolean isArray; 173 boolean isExternalizable; 174 boolean isIDLEntity; 175 boolean isObjectRef; 176 177 int primitiveArray; 178 179 int readWriteCase; 180 181 boolean requiresCustomSerialization; 182 183 boolean skipCustomFlags; 185 189 static 190 { 191 TC_ABSTRACT_BASE = new TypeCode(TCKind.tk_abstract_interface); 192 TC_ABSTRACT_BASE.id("IDL:omg.org/CORBA/AbstractBase:1.0"); 193 TC_ABSTRACT_BASE.name(""); 194 195 try 196 { 197 if (JDK14) 198 { 199 _newInstance = java.io.ObjectStreamClass .class.getDeclaredMethod("newInstance", new Class [] {}); 200 _newInstance.setAccessible(true); 201 } 202 else 203 { 204 _allocateNewObject = java.io.ObjectInputStream .class.getDeclaredMethod("allocateNewObject", new Class [] { Class .class, Class .class }); 205 _allocateNewObject.setAccessible(true); 206 } 207 } 208 catch (Exception ex) 209 { 210 throw ExceptionUtil.getRuntimeException(ex); 211 } 212 } 213 214 218 public Object newInstance() 219 { 220 try 221 { 222 if (JDK14) 223 { 224 if (_class == Object .class) 225 { 226 return new Object (); 227 } 228 else 229 { 230 return _newInstance.invoke(_objectStreamClass, ArrayUtil.EMPTY_OBJECT_ARRAY); 231 } 232 } 233 else 234 { 235 return _allocateNewObject.invoke(null, _allocateNewObjectArgs); 236 } 237 } 238 catch (Exception ex) 239 { 240 throw ExceptionUtil.getRuntimeException(ex); 241 } 242 } 243 244 public String toString() 245 { 246 return "ValueType:" + JavaType.getName(_class); 247 } 248 249 public void readObject(Object _this, org.apache.geronimo.interop.rmi.iiop.ObjectInputStream input) 250 { 251 try 252 { 253 _readObject.invoke(_this, input.thisAsObjectArray); 254 } 255 catch (Exception ex) 256 { 257 throw ExceptionUtil.getRuntimeException(ex); 258 } 259 } 260 261 public void writeObject(Object _this, org.apache.geronimo.interop.rmi.iiop.ObjectOutputStream output) 262 { 263 try 264 { 265 _writeObject.invoke(_this, output.thisAsObjectArray); 266 } 267 catch (Exception ex) 268 { 269 throw ExceptionUtil.getRuntimeException(ex); 270 } 271 } 272 273 public Object readResolve(Object _this) 274 { 275 try 276 { 277 return _readResolve.invoke(_this, ArrayUtil.EMPTY_OBJECT_ARRAY); 278 } 279 catch (Exception ex) 280 { 281 throw ExceptionUtil.getRuntimeException(ex); 282 } 283 } 284 285 public Object writeReplace(Object _this) 286 { 287 try 288 { 289 return _writeReplace.invoke(_this, ArrayUtil.EMPTY_OBJECT_ARRAY); 290 } 291 catch (Exception ex) 292 { 293 throw ExceptionUtil.getRuntimeException(ex); 294 } 295 } 296 297 public void readExternal(Object _this, org.apache.geronimo.interop.rmi.iiop.ObjectInputStream input) 298 { 299 try 300 { 301 _readExternal.invoke(_this, input.thisAsObjectArray); 302 } 303 catch (Exception ex) 304 { 305 throw ExceptionUtil.getRuntimeException(ex); 306 } 307 } 308 309 public void writeExternal(Object _this, org.apache.geronimo.interop.rmi.iiop.ObjectOutputStream output) 310 { 311 try 312 { 313 _writeExternal.invoke(_this, output.thisAsObjectArray); 314 } 315 catch (Exception ex) 316 { 317 throw ExceptionUtil.getRuntimeException(ex); 318 } 319 } 320 321 325 protected void init(Class theClass) 326 { 327 boolean recursive = false; 328 if (_initMap.get(theClass) != null) 329 { 330 return; } 333 _initMap.put(theClass, Boolean.TRUE); 334 try 335 { 336 _class = theClass; 337 _objectStreamClass = ObjectStreamClass.lookup(_class); 338 if (org.omg.CORBA.Object .class.isAssignableFrom(theClass) 339 || javax.ejb.EJBHome .class.isAssignableFrom(theClass) 340 || javax.ejb.EJBObject .class.isAssignableFrom(theClass) 341 || java.rmi.Remote .class.isAssignableFrom(theClass)) 342 { 343 helper = ObjectRefHelper.getInstance(theClass); 344 isObjectRef = true; 345 readWriteCase = CASE_IDL_OBJECT; 346 } 347 else if (org.omg.CORBA.portable.IDLEntity .class.isAssignableFrom(theClass)) 348 { 349 helper = IDLEntityHelper.getInstance(theClass); 350 isIDLEntity = true; 351 readWriteCase = CASE_IDL_ENTITY; 352 } 353 else if (theClass == String .class) 354 { 355 helper = StringHelper.SINGLETON; 356 readWriteCase = CASE_STRING; 357 } 358 else if (theClass.isArray()) 359 { 360 Class elementClass = theClass.getComponentType(); 361 element = getInstance(elementClass); 362 isArray = true; 363 if (elementClass.isPrimitive()) 364 { 365 primitiveArray = PrimitiveType.get(elementClass); 366 helper = PrimitiveType.getArrayHelper(elementClass); 367 } 368 else 369 { 370 helper = new ArrayHelper(elementClass); 371 } 372 readWriteCase = CASE_ARRAY; 373 } 374 else if (theClass == Class .class) 375 { 376 readWriteCase = CASE_CLASS; 377 } 378 if (_allocateNewObject != null) 379 { 380 Class bc = _class; 381 while (Serializable .class.isAssignableFrom(bc) && (bc.getSuperclass() != null)) 382 { 383 bc = bc.getSuperclass(); 384 } 385 _allocateNewObjectArgs = new Object [] { _class, bc }; 386 } 387 388 isAny = _class == java.lang.Object .class 389 || _class == java.io.Externalizable .class 390 || _class == java.io.Serializable .class; 391 392 isExternalizable = java.io.Externalizable .class.isAssignableFrom(_class); 393 if (isExternalizable) 394 { 395 _readExternal = _class.getDeclaredMethod("readExternal", new Class [] { ObjectInput .class } ); 396 _writeExternal = _class.getDeclaredMethod("writeExternal", new Class [] { ObjectOutput .class } ); 397 } 398 399 if(recursive) 401 { 402 return; 403 } 404 405 406 java.lang.Class tmpClass = _class; 407 ArrayList fieldList = new ArrayList (); 408 Field [] javaFields = tmpClass.getDeclaredFields(); 409 410 Arrays.sort(javaFields, FieldComparator.SINGLETON); 412 413 int nf = javaFields.length; 416 for (int f = 0; f < nf; f++) 417 { 418 Field javaField = javaFields[f]; 419 int modifiers = javaField.getModifiers(); 420 if ((modifiers & (Modifier.STATIC | Modifier.TRANSIENT)) != 0) 421 { 422 continue; 423 } 424 if (! javaField.isAccessible()) 425 { 426 javaField.setAccessible(true); 427 } 428 ValueTypeField field = new ValueTypeField(javaField); 429 fieldList.add(field); 430 } 431 432 fields = (ValueTypeField[])fieldList.toArray(new ValueTypeField[fieldList.size()]); 433 434 Method [] methods = _class.getDeclaredMethods(); 437 int countThrowsRemoteException = 0; 438 int nm = methods.length; 439 for (int m = 0; m < nm; m++) 440 { 441 Method method = methods[m]; 442 Class [] types = method.getParameterTypes(); 443 if (types.length == 1 444 && types[0] == java.io.ObjectInputStream .class 445 && (method.getModifiers() & Modifier.PRIVATE) != 0 446 && method.getName().equals("readObject")) 447 { 448 _readObject = method; 449 if (! _readObject.isAccessible()) 450 { 451 _readObject.setAccessible(true); 452 } 453 } 454 if (types.length == 1 455 && types[0] == java.io.ObjectOutputStream .class 456 && (method.getModifiers() & Modifier.PRIVATE) != 0 457 && method.getName().equals("writeObject")) 458 { 459 _writeObject = method; 460 if (! _writeObject.isAccessible()) 461 { 462 _writeObject.setAccessible(true); 463 } 464 } 465 466 if (types.length == 0 467 && method.getReturnType() == java.lang.Object .class 468 && method.getName().equals("writeReplace")) 469 { 470 _writeReplace = method; 471 if (! _writeReplace.isAccessible()) 472 { 473 _writeReplace.setAccessible(true); 474 } 475 } 476 if (types.length == 0 477 && method.getReturnType() == java.lang.Object .class 478 && method.getName().equals("readResolve")) 479 { 480 _readResolve = method; 481 if (! _readResolve.isAccessible()) 482 { 483 _readResolve.setAccessible(true); 484 } 485 } 486 Class [] exceptions = method.getExceptionTypes(); 487 for (int i = 0; i < exceptions.length; i++) 488 { 489 Class exception = exceptions[i]; 490 if (exception.isAssignableFrom(java.rmi.RemoteException .class)) 491 { 492 countThrowsRemoteException++; 494 break; 495 } 496 } 497 } 498 499 hasReadOrWriteObject = _readObject != null || _writeObject != null; 500 hasReadObject = _readObject != null; 501 hasWriteObject = _writeObject != null; 502 hasWriteReplace = _writeReplace != null; 503 hasReadResolve = _readResolve != null; 504 505 isAbstractInterface = ! isObjectRef 506 && _class.isInterface() 507 && countThrowsRemoteException == methods.length; 508 509 Class superclass = _class.getSuperclass(); 510 if((superclass != null) && (superclass != java.lang.Object .class) && (!isIDLEntity )) 511 { 512 parent = getInstance(superclass); 513 } 514 515 hasParentState = parent != null 516 && (parent.fields.length > 0 517 || parent.isExternalizable 518 || parent.hasReadOrWriteObject 519 || parent.hasParentState); 520 521 requiresCustomSerialization = hasWriteObject || isExternalizable; 522 523 initRepositoryID(); 524 initTypeCode(); 525 526 isAnyOrObjectRefOrAbstractInterface = isAny || isObjectRef || isAbstractInterface; 527 } 528 catch (Exception ex) 529 { 530 throw ExceptionUtil.getRuntimeException(ex); 531 } 532 finally 533 { 534 if(!recursive) 535 { 536 _initMap.remove(theClass); 537 } 538 } 539 } 540 541 protected void initRepositoryID() 542 { 543 final String sixteenZeros = "0000000000000000"; 544 final int requiredLength = 16; 545 550 if (isArray && primitiveArray != 0) 551 { 552 id = "RMI:" + _class.getName() + ":" + sixteenZeros; 553 return; 554 } 555 if (_class == String .class) 556 { 557 id = "IDL:omg.org/CORBA/WStringValue:1.0"; 558 return; 559 } 560 if (isObjectRef) 561 { 562 id = "RMI:" + _class.getName() + ":" + sixteenZeros; 563 return; 564 } 565 if (_class == java.lang.Class .class) 566 { 567 id = "RMI:javax.rmi.CORBA.ClassDesc:2BABDA04587ADCCC:CFBF02CF5294176B"; 568 return; 569 } 570 if (_class == java.math.BigInteger .class) 571 { 572 id = "RMI:java.math.BigInteger:E2F79B6E7A470003:8CFC9F1FA93BFB1D"; 573 return; 574 } 575 if (_objectStreamClass == null) 576 { 577 id = "???"; 578 return; 579 } 580 long structuralUID = computeStructuralUID(this); 581 long serialVersionUID = _objectStreamClass.getSerialVersionUID(); 582 String structuralUIDString = Long.toHexString(structuralUID).toUpperCase(); 583 String serialVersionUIDString = Long.toHexString(serialVersionUID).toUpperCase(); 584 int currentLength; 585 int lengthNeeded; 586 currentLength = structuralUIDString.length(); 587 if (currentLength < requiredLength) 588 { 589 lengthNeeded = requiredLength - currentLength; 590 structuralUIDString = sixteenZeros.substring(0, lengthNeeded) + structuralUIDString; 591 } 592 currentLength = serialVersionUIDString.length(); 593 if (currentLength < requiredLength) 594 { 595 lengthNeeded = requiredLength - currentLength; 596 serialVersionUIDString = sixteenZeros.substring(0, lengthNeeded) + serialVersionUIDString; 597 } 598 id = "RMI:" + _class.getName() + ":" + structuralUIDString + ":" + serialVersionUIDString; 599 } 600 601 protected void initTypeCode() 602 { 603 if (isObjectRef) 604 { 605 tc = new TypeCode(TCKind.tk_objref); 606 tc.id(id); 607 tc.name(""); 608 } 609 else if (isArray || isIDLEntity || _class == String .class) 610 { 611 tc = new TypeCode(TCKind.tk_value_box); 612 tc.id(id); 613 tc.name(""); 614 if (_class == String .class) 615 { 616 tc.content_type(new TypeCode(TCKind.tk_wstring)); 617 } 618 else if (isArray) 619 { 620 TypeCode seqTC = new TypeCode(TCKind.tk_sequence); 621 if (primitiveArray != 0) 622 { 623 seqTC.content_type(PrimitiveType.getTypeCode(primitiveArray)); 624 } 625 else 626 { 627 seqTC.content_type(element.tc); 628 } 629 tc.content_type(seqTC); 630 } 631 else if (isIDLEntity) 632 { 633 } 635 } 636 else 637 { 638 tc = new TypeCode(TCKind.tk_value); 639 tc.id(id); 640 tc.name(""); 641 642 if (requiresCustomSerialization) 644 { 645 tc.type_modifier((short)1); 646 } 647 else if (isAbstractInterface) 648 { 649 tc.type_modifier((short)2); 650 } 651 else 652 { 653 tc.type_modifier((short)0); 654 } 655 if (parent == null) 656 { 657 tc.concrete_base_type(TC_NULL); 658 } 659 else 660 { 661 tc.concrete_base_type(TC_NULL); 663 } 665 tc.member_count(0); 667 } 668 } 669 670 static long computeStructuralUID(ValueType vt) 671 { 672 Class c = vt._class; 673 ObjectStreamClass osc = vt._objectStreamClass; 674 ByteArrayOutputStream devnull = new ByteArrayOutputStream (512); 675 long h = 0; 676 try 677 { 678 if (! java.io.Serializable .class.isAssignableFrom(c) 679 || c.isInterface()) 680 { 681 return 0; 682 } 683 if (java.io.Externalizable .class.isAssignableFrom(c)) 684 { 685 return 1; 686 } 687 MessageDigest md = MessageDigest.getInstance("SHA"); 688 DigestOutputStream mdo = new DigestOutputStream (devnull, md); 689 DataOutputStream data = new DataOutputStream (mdo); 690 if (vt.parent != null) 691 { 692 data.writeLong(computeStructuralUID(vt.parent)); 693 } 694 if (vt.hasWriteObject) 695 { 696 data.writeInt(2); 697 } 698 else 699 { 700 data.writeInt(1); 701 } 702 List fieldList = new ArrayList (vt.fields.length); 703 for (int i = 0; i < vt.fields.length; i++) 704 { 705 fieldList.add(vt.fields[i].javaField); 706 } 707 Field [] fields = (Field [])fieldList.toArray(new Field [fieldList.size()]); 708 Arrays.sort(fields, FieldByNameComparator.SINGLETON); 709 for (int i = 0; i < vt.fields.length; i++) 710 { 711 Field f = fields[i]; 712 data.writeUTF(f.getName()); 713 data.writeUTF(JavaClass.getSignature(f.getType())); 714 } 715 data.flush(); 716 byte[] hasharray = md.digest(); 717 for (int i = 0; i < Math.min(8, hasharray.length); i++) 718 { 719 h += (long)(hasharray[i] & 255) << (i * 8); 720 } 721 return h; 722 } 723 catch (Exception ex) 724 { 725 throw new SystemException(ex); 726 } 727 } 728 729 732 static Class getClass(String id) 733 { 734 if (id.startsWith("RMI:")) 735 { 736 int endClass = id.indexOf(':', 4); 737 if (endClass == -1) 738 { 739 throw new org.omg.CORBA.INV_IDENT (id); 740 } 741 String className = id.substring(4, endClass); 742 if (className.equals("javax.rmi.CORBA.ClassDesc")) 743 { 744 return Class .class; 745 } 746 else 747 { 748 return loadClass(className); 749 } 750 } 751 else if (id.equals("IDL:omg.org/CORBA/WStringValue:1.0")) 752 { 753 return java.lang.String .class; 754 } 755 else if (id.startsWith("IDL:omg.org/")) 756 { 757 int endClass = id.indexOf(':', 12); 758 if (endClass == -1) 759 { 760 throw new org.omg.CORBA.INV_IDENT (id); 761 } 762 String className = "org.omg" + id.substring( "IDL:omg.org".length(), endClass).replace('/', '.'); 763 return loadClass(className); 764 } 765 else if (id.startsWith("IDL:")) 766 { 767 int endClass = id.indexOf(':', 4); 768 if (endClass == -1) 769 { 770 throw new org.omg.CORBA.INV_IDENT (id); 771 } 772 String className = id.substring(4, endClass).replace('/', '.'); 773 return loadClass(className); 774 } 775 else 776 { 777 throw new org.omg.CORBA.INV_IDENT (id); 778 } 779 } 780 781 public Class getTheClass() 782 { 783 return _class; 784 } 785 786 static Class loadClass(String className) 787 { 788 return ThreadContext.loadClass(className); 789 } 790 } 791 | Popular Tags |