1 45 package org.openejb.util.io; 46 47 48 import java.io.Externalizable ; 49 import java.io.IOException ; 50 import java.io.InvalidClassException ; 51 import java.io.NotSerializableException ; 52 import java.io.ObjectOutput ; 53 import java.io.ObjectStreamConstants ; 54 import java.io.OutputStream ; 55 import java.io.Serializable ; 56 import java.lang.reflect.Field ; 57 import java.util.ArrayList ; 58 import java.util.Arrays ; 59 60 import org.openejb.util.ArrayStack; 61 62 96 public class ObjectOutputStream extends OutputStream implements ObjectOutput , ObjectStreamConstants { 97 98 107 private OutputStream out; 109 private ArrayStack classDescStack; 110 private byte buf[] = new byte[5000]; 111 114 private int count; 115 116 public ObjectOutputStream(OutputStream out) throws IOException { 117 this.out = out; 118 119 classDescStack = new ArrayStack(); 120 } 121 122 public void reset() throws IOException { 123 resetStream(); 124 count = 0; 125 } 126 127 public void serializeObject(Object obj, OutputStream out) throws NotSerializableException , IOException { 128 this.out = out; 129 serializeObject(obj); 130 } 131 132 public void serializeObject(Object obj) throws NotSerializableException , IOException { 133 134 if ( !Serializable .class.isAssignableFrom(obj.getClass()) && !Externalizable .class.isAssignableFrom(obj.getClass()) ) { 135 throw new NotSerializableException (obj.getClass().getName()); 136 } 137 138 reset(); 139 140 writeShort(STREAM_MAGIC); 141 writeShort(STREAM_VERSION); 142 writeObject(obj); 143 144 } 145 146 147 public void writeObject(Object obj) throws IOException { 148 try { 149 if ( obj == null ) { 150 write(TC_NULL); 151 return; 152 } 153 Class clazz = obj.getClass(); 154 ClassDescriptor classDesc = null; 155 156 if ( clazz == ClassDescriptor.class ) classDesc = (ClassDescriptor)obj; 157 else classDesc = ClassDescriptor.lookupInternal(clazz); 158 159 if ( classDesc == null ) { 160 write(TC_NULL); 161 return; 162 } 163 164 int tmpInt = findWireOffset(obj); 165 if ( tmpInt >= 0 ) { 166 write(TC_REFERENCE); 167 tmpInt += baseWireHandle; 168 write((tmpInt >>> 24) & 0xFF); 170 write((tmpInt >>> 16) & 0xFF); 171 write((tmpInt >>> 8) & 0xFF); 172 write((tmpInt >>> 0) & 0xFF); 173 return; 175 } 176 177 if ( obj instanceof Class ) { 178 write(TC_CLASS); 179 write(TC_CLASSDESC); 180 writeUTF(classDesc.getName()); 181 long value = classDesc.getSerialVersionUID(); 182 write((int)(value >>> 56) & 0xFF); 184 write((int)(value >>> 48) & 0xFF); 185 write((int)(value >>> 40) & 0xFF); 186 write((int)(value >>> 32) & 0xFF); 187 write((int)(value >>> 24) & 0xFF); 188 write((int)(value >>> 16) & 0xFF); 189 write((int)(value >>> 8) & 0xFF); 190 write((int)(value >>> 0) & 0xFF); 191 assignWireOffset(classDesc); 193 classDesc.writeClassInfo(this); 194 write(TC_ENDBLOCKDATA); 195 writeObject(classDesc.getSuperclass()); 196 assignWireOffset(clazz); 197 return; 198 } 199 200 if ( obj instanceof ClassDescriptor ) { 201 write(TC_CLASSDESC); 202 writeUTF(classDesc.getName()); 203 long value = classDesc.getSerialVersionUID(); 204 write((int)(value >>> 56) & 0xFF); 206 write((int)(value >>> 48) & 0xFF); 207 write((int)(value >>> 40) & 0xFF); 208 write((int)(value >>> 32) & 0xFF); 209 write((int)(value >>> 24) & 0xFF); 210 write((int)(value >>> 16) & 0xFF); 211 write((int)(value >>> 8) & 0xFF); 212 write((int)(value >>> 0) & 0xFF); 213 assignWireOffset(classDesc); 215 write(classDesc.flags); 216 tmpInt = classDesc.fields.length; 217 write((tmpInt >>> 8) & 0xFF); 218 write((tmpInt >>> 0) & 0xFF); 219 FieldDescriptor field; 220 for ( int i=0; i < classDesc.fields.length; i++ ) { 221 field = classDesc.fields[i]; 222 write((int)field.typeCode); 223 writeUTF(field.name); 224 if ( !field.type.isPrimitive() ) writeObject(field.typeString); 225 } 226 write(TC_ENDBLOCKDATA); 227 writeObject(classDesc.getSuperclass()); 228 return; 229 } 230 if ( obj instanceof String ) { 231 write(TC_STRING); 232 String s = ((String )obj).intern(); 233 assignWireOffset(s); 234 writeUTF(s); 235 return; 236 } 237 if ( clazz.isArray() ) { 238 write(TC_ARRAY); 239 writeObject(classDesc); 240 assignWireOffset(obj); 241 242 Class type = clazz.getComponentType(); 243 if ( type.isPrimitive() ) { 244 if ( type == Integer.TYPE ) { 245 int[] array = (int[])obj; 246 tmpInt = array.length; 247 write((tmpInt >>> 24) & 0xFF); 249 write((tmpInt >>> 16) & 0xFF); 250 write((tmpInt >>> 8) & 0xFF); 251 write((tmpInt >>> 0) & 0xFF); 252 int value; 254 for ( int i = 0; i < tmpInt; i++ ) { 255 value = array[i]; 256 write((value >>> 24) & 0xFF); 258 write((value >>> 16) & 0xFF); 259 write((value >>> 8) & 0xFF); 260 write((value >>> 0) & 0xFF); 261 } 263 return; 264 } else if ( type == Byte.TYPE ) { 265 byte[] array = (byte[])obj; 266 tmpInt = array.length; 267 write((tmpInt >>> 24) & 0xFF); 269 write((tmpInt >>> 16) & 0xFF); 270 write((tmpInt >>> 8) & 0xFF); 271 write((tmpInt >>> 0) & 0xFF); 272 write(array, 0, tmpInt); 274 return; 275 } else if ( type == Long.TYPE ) { 276 long[] array = (long[])obj; 277 tmpInt = array.length; 278 write((tmpInt >>> 24) & 0xFF); 280 write((tmpInt >>> 16) & 0xFF); 281 write((tmpInt >>> 8) & 0xFF); 282 write((tmpInt >>> 0) & 0xFF); 283 long value; 285 for ( int i = 0; i < tmpInt; i++ ) { 286 value = array[i]; 287 write((int)(value >>> 56) & 0xFF); 289 write((int)(value >>> 48) & 0xFF); 290 write((int)(value >>> 40) & 0xFF); 291 write((int)(value >>> 32) & 0xFF); 292 write((int)(value >>> 24) & 0xFF); 293 write((int)(value >>> 16) & 0xFF); 294 write((int)(value >>> 8) & 0xFF); 295 write((int)(value >>> 0) & 0xFF); 296 } 298 return; 299 } else if ( type == Float.TYPE ) { 300 float[] array = (float[])obj; 301 tmpInt = array.length; 302 write((tmpInt >>> 24) & 0xFF); 304 write((tmpInt >>> 16) & 0xFF); 305 write((tmpInt >>> 8) & 0xFF); 306 write((tmpInt >>> 0) & 0xFF); 307 int value; 309 for ( int i = 0; i < tmpInt; i++ ) { 310 value = Float.floatToIntBits(array[i]); 311 write((value >>> 24) & 0xFF); 313 write((value >>> 16) & 0xFF); 314 write((value >>> 8) & 0xFF); 315 write((value >>> 0) & 0xFF); 316 } 318 return; 319 } else if ( type == Double.TYPE ) { 320 double[] array = (double[])obj; 321 tmpInt = array.length; 322 write((tmpInt >>> 24) & 0xFF); 324 write((tmpInt >>> 16) & 0xFF); 325 write((tmpInt >>> 8) & 0xFF); 326 write((tmpInt >>> 0) & 0xFF); 327 long value; 329 for ( int i = 0; i < tmpInt; i++ ) { 330 value = Double.doubleToLongBits(array[i]); 331 write((int)(value >>> 56) & 0xFF); 333 write((int)(value >>> 48) & 0xFF); 334 write((int)(value >>> 40) & 0xFF); 335 write((int)(value >>> 32) & 0xFF); 336 write((int)(value >>> 24) & 0xFF); 337 write((int)(value >>> 16) & 0xFF); 338 write((int)(value >>> 8) & 0xFF); 339 write((int)(value >>> 0) & 0xFF); 340 } 342 return; 343 } else if ( type == Short.TYPE ) { 344 short[] array = (short[])obj; 345 tmpInt = array.length; 346 write((tmpInt >>> 24) & 0xFF); 348 write((tmpInt >>> 16) & 0xFF); 349 write((tmpInt >>> 8) & 0xFF); 350 write((tmpInt >>> 0) & 0xFF); 351 short value; 353 for ( int i = 0; i < tmpInt; i++ ) { 354 value = array[i]; 355 write((value >>> 8) & 0xFF); 357 write((value >>> 0) & 0xFF); 358 } 360 return; 361 } else if ( type == Character.TYPE ) { 362 char[] array = (char[])obj; 363 tmpInt = array.length; 364 write((tmpInt >>> 24) & 0xFF); 366 write((tmpInt >>> 16) & 0xFF); 367 write((tmpInt >>> 8) & 0xFF); 368 write((tmpInt >>> 0) & 0xFF); 369 char value; 371 for ( int i = 0; i < tmpInt; i++ ) { 372 value = array[i]; 373 write((value >>> 8) & 0xFF); 375 write((value >>> 0) & 0xFF); 376 } 378 return; 379 } else if ( type == Boolean.TYPE ) { 380 boolean[] array = (boolean[])obj; 381 tmpInt = array.length; 382 write((tmpInt >>> 24) & 0xFF); 384 write((tmpInt >>> 16) & 0xFF); 385 write((tmpInt >>> 8) & 0xFF); 386 write((tmpInt >>> 0) & 0xFF); 387 for ( int i = 0; i < tmpInt; i++ ) { 389 write(array[i] ? 1 : 0); 390 } 391 return; 392 } else { 393 throw new InvalidClassException (clazz.getName()); 394 } 395 } else { 396 Object [] array = (Object [])obj; 397 int length = array.length; 398 write((length >>> 24) & 0xFF); 400 write((length >>> 16) & 0xFF); 401 write((length >>> 8) & 0xFF); 402 write((length >>> 0) & 0xFF); 403 for ( int i = 0; i < length; i++ ) writeObject(array[i]); 405 } 406 return; 407 } 408 write(TC_OBJECT); 409 writeObject(classDesc); 410 assignWireOffset(obj); 411 if ( classDesc.isExternalizable() ) { 413 writeExternal((Externalizable )obj); 414 return; 415 } 416 417 int stackMark = classDescStack.size(); 418 try { 419 420 ClassDescriptor superClassDesc; 421 while ( (superClassDesc = classDesc.getSuperclass()) != null ) { 422 classDescStack.push(classDesc); 423 classDesc = superClassDesc; 424 } 425 426 do { 428 if ( classDesc.hasWriteObjectMethod() ) { 429 432 440 444 } else { 447 FieldDescriptor[] fields = classDesc.getFields(); 448 Field field; 449 if ( fields.length > 0 ) { 450 for ( int i=0; i< fields.length; i++ ) { 451 field = fields[i].getField(); 452 if ( field == null ) throw new InvalidClassException (clazz.getName(), "Nonexistent field " + fields[i].getName()); 453 try { 454 switch ( fields[i].getTypeCode() ) { 455 case 'B': 456 write(field.getByte(obj)); 457 break; 458 case 'C': 459 char charvalue = field.getChar(obj); 460 write((charvalue >>> 8) & 0xFF); 461 write((charvalue >>> 0) & 0xFF); 462 break; 463 case 'I': 464 int intvalue = field.getInt(obj); 465 write((intvalue >>> 24) & 0xFF); 466 write((intvalue >>> 16) & 0xFF); 467 write((intvalue >>> 8) & 0xFF); 468 write((intvalue >>> 0) & 0xFF); 469 break; 470 case 'Z': 471 write((field.getBoolean(obj)?1:0) ); 472 break; 473 case 'J': 474 long longvalue = field.getLong(obj); 475 write((int)(longvalue >>> 56) & 0xFF); 476 write((int)(longvalue >>> 48) & 0xFF); 477 write((int)(longvalue >>> 40) & 0xFF); 478 write((int)(longvalue >>> 32) & 0xFF); 479 write((int)(longvalue >>> 24) & 0xFF); 480 write((int)(longvalue >>> 16) & 0xFF); 481 write((int)(longvalue >>> 8) & 0xFF); 482 write((int)(longvalue >>> 0) & 0xFF); 483 break; 484 case 'F': 485 int floatvalue = Float.floatToIntBits(field.getFloat(obj)); 486 write((floatvalue >>> 24) & 0xFF); 487 write((floatvalue >>> 16) & 0xFF); 488 write((floatvalue >>> 8) & 0xFF); 489 write((floatvalue >>> 0) & 0xFF); 490 break; 491 case 'D': 492 long doublevalue = Double.doubleToLongBits(field.getDouble(obj)); 493 write((int)(doublevalue >>> 56) & 0xFF); 494 write((int)(doublevalue >>> 48) & 0xFF); 495 write((int)(doublevalue >>> 40) & 0xFF); 496 write((int)(doublevalue >>> 32) & 0xFF); 497 write((int)(doublevalue >>> 24) & 0xFF); 498 write((int)(doublevalue >>> 16) & 0xFF); 499 write((int)(doublevalue >>> 8) & 0xFF); 500 write((int)(doublevalue >>> 0) & 0xFF); 501 break; 502 case 'S': 503 short shortvalue = field.getShort(obj); 504 write((shortvalue >>> 8) & 0xFF); 505 write((shortvalue >>> 0) & 0xFF); 506 break; 507 case '[': 508 case 'L': 509 writeObject(field.get(obj)); 510 break; 511 default: throw new InvalidClassException (clazz.getName()); 512 } 513 } catch ( IllegalAccessException e ) { 514 throw new InvalidClassException (clazz.getName(), e.getMessage()); 515 } finally { 516 } 517 } 518 } 519 } 520 }while ( classDescStack.size() > stackMark && (classDesc = (ClassDescriptor)classDescStack.pop()) != null ); 521 522 } finally { 523 526 } 528 529 } finally { 530 } 531 } 532 533 public void writeString(String s) throws IOException { 534 writeObject(s); 535 } 536 537 private void writeExternal(Externalizable ext) throws IOException { 538 if ( false ) { 540 543 544 ext.writeExternal(this); 545 } else { 546 549 552 try { 554 555 ext.writeExternal(this); 556 } finally { 557 560 } 563 } 564 } 565 566 567 568 569 public void writeException(Throwable th) throws IOException { 570 573 574 } 575 576 public void writeReset() throws IOException { 577 580 581 } 582 583 584 585 594 598 607 613 618 public void write(int b) { 619 try { 620 buf[count++] = (byte)b; 621 } catch ( ArrayIndexOutOfBoundsException e ) { 622 byte newbuf[] = new byte[Math.max(buf.length << 1, count)]; 623 System.arraycopy(buf, 0, newbuf, 0, count-1); 624 buf = newbuf; 625 } 626 } 627 628 636 public synchronized void write(byte b[], int off, int len) { 637 if ( len == 0 ) return; 638 639 int newcount = count + len; 640 if ( newcount > buf.length ) { 641 byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)]; 642 System.arraycopy(buf, 0, newbuf, 0, count); 643 buf = newbuf; 644 } 645 System.arraycopy(b, off, buf, count, len); 646 count = newcount; 647 } 648 649 650 659 public void flush() throws IOException { 660 } 662 663 671 public byte[] toByteArray() { 672 byte newbuf[] = new byte[count]; 673 System.arraycopy(buf, 0, newbuf, 0, count); 674 return newbuf; 675 } 676 677 683 public int size() { 684 return count; 685 } 686 687 688 697 public final void writeBoolean(boolean v) throws IOException { 698 write(v ? 1 : 0); 699 } 700 701 708 public final void writeByte(int v) throws IOException { 709 write(v); 710 } 711 712 719 public final void writeShort(int v) throws IOException { 720 write((v >>> 8) & 0xFF); 721 write((v >>> 0) & 0xFF); 722 } 723 724 731 public final void writeChar(int v) throws IOException { 732 write((v >>> 8) & 0xFF); 733 write((v >>> 0) & 0xFF); 734 } 735 736 743 public final void writeInt(int v) throws IOException { 744 write((v >>> 24) & 0xFF); 745 write((v >>> 16) & 0xFF); 746 write((v >>> 8) & 0xFF); 747 write((v >>> 0) & 0xFF); 748 } 749 750 757 public final void writeLong(long v) throws IOException { 758 write((int)(v >>> 56) & 0xFF); 759 write((int)(v >>> 48) & 0xFF); 760 write((int)(v >>> 40) & 0xFF); 761 write((int)(v >>> 32) & 0xFF); 762 write((int)(v >>> 24) & 0xFF); 763 write((int)(v >>> 16) & 0xFF); 764 write((int)(v >>> 8) & 0xFF); 765 write((int)(v >>> 0) & 0xFF); 766 } 767 768 777 public final void writeFloat(float v) throws IOException { 778 writeInt(Float.floatToIntBits(v)); 779 } 780 781 790 public final void writeDouble(double v) throws IOException { 791 writeLong(Double.doubleToLongBits(v)); 792 } 793 794 802 public final void writeBytes(String s) throws IOException { 803 int tmpLen = s.length(); 804 for ( int i = 0 ; i < tmpLen ; i++ ) { 805 write((byte)s.charAt(i)); 806 } 807 } 808 809 815 public final void writeChars(String s) throws IOException { 816 int tmpLen = s.length(); 817 for ( int i = 0 ; i < tmpLen ; i++ ) { 818 int v = s.charAt(i); 819 write((v >>> 8) & 0xFF); 820 write((v >>> 0) & 0xFF); 821 } 822 } 823 824 828 829 private char[] utfCharBuf = new char[32]; 830 public final void writeUTF(String str) throws IOException { 831 832 int len = str.length(); 833 834 if ( utfCharBuf.length < len ) utfCharBuf = new char[len]; 835 836 str.getChars(0,len,utfCharBuf,0); 837 838 int mark = count; 839 write(0); write(0); for ( int i = 0 ; i < len ; i++ ) { 842 int c = utfCharBuf[i]; 843 if ( (c >= 0x0001) && (c <= 0x007F) ) { 844 write(c); 845 } else if ( c > 0x07FF ) { 846 write(0xE0 | ((c >> 12) & 0x0F)); 847 write(0x80 | ((c >> 6) & 0x3F)); 848 write(0x80 | ((c >> 0) & 0x3F)); 849 } else { 850 write(0xC0 | ((c >> 6) & 0x1F)); 851 write(0x80 | ((c >> 0) & 0x3F)); 852 } 853 } 854 857 len = count-mark-2; 858 buf[mark] = (byte)((len >>> 8) & 0xFF); 859 buf[mark+1] = (byte)((len >>> 0) & 0xFF); 860 861 862 } 863 864 873 private ArrayList wireHandle2Object; 874 private int nextWireOffset; 875 876 877 private int[] wireHash2Handle; private int[] wireNextHandle; private int wireHashSizePower = 2; private int wireHashLoadFactor = 7; private int wireHashCapacity = (1 << wireHashSizePower) * wireHashLoadFactor; 882 883 888 private void hashInsert(Object obj, int offset) { 889 int hash = System.identityHashCode(obj); 890 int index = (hash & 0x7FFFFFFF) % wireHash2Handle.length; 891 wireNextHandle[offset] = wireHash2Handle[index]; 892 wireHash2Handle[index] = offset; 893 } 894 899 private int findWireOffset(Object obj) { 900 int hash = System.identityHashCode(obj); 901 int index = (hash & 0x7FFFFFFF) % wireHash2Handle.length; 902 903 for ( int handle = wireHash2Handle[index]; 904 handle >= 0; 905 handle = wireNextHandle[handle] ) { 906 907 if ( wireHandle2Object.get(handle) == obj ) 908 return handle; 909 } 910 return -1; 911 } 912 913 918 private void assignWireOffset(Object obj) 919 throws IOException 920 { 921 if ( nextWireOffset == wireNextHandle.length ) { 922 int[] oldnexthandles = wireNextHandle; 923 wireNextHandle = new int[nextWireOffset*2]; 924 System.arraycopy(oldnexthandles, 0, 925 wireNextHandle, 0, 926 nextWireOffset); 927 } 928 if ( nextWireOffset >= wireHashCapacity ) { 929 growWireHash2Handle(); 930 } 931 wireHandle2Object.add(obj); 932 hashInsert(obj, nextWireOffset); 933 nextWireOffset++; 934 return; 935 } 936 937 private void growWireHash2Handle() { 938 wireHashSizePower++; 940 wireHash2Handle = new int[(1 << wireHashSizePower) - 1]; 941 Arrays.fill(wireHash2Handle, -1); 942 943 for ( int i = 0; i < nextWireOffset; i++ ) { 944 wireNextHandle[i] = 0; 945 } 946 947 for ( int i = 0; i < wireHandle2Object.size(); i++ ) { 949 hashInsert(wireHandle2Object.get(i), i); 950 } 951 952 wireHashCapacity = (1 << wireHashSizePower) * wireHashLoadFactor; 953 } 954 955 959 private void resetStream() throws IOException { 960 if ( wireHandle2Object == null ) { 961 wireHandle2Object = new ArrayList (); 962 wireNextHandle = new int[4]; 963 wireHash2Handle = new int[ (1 << wireHashSizePower) - 1]; 964 } else { 965 966 wireHandle2Object.clear(); 969 for ( int i = 0; i < nextWireOffset; i++ ) { 970 wireNextHandle[i] = 0; 971 } 972 } 973 nextWireOffset = 0; 974 Arrays.fill(wireHash2Handle, -1); 975 976 if ( classDescStack == null ) 977 classDescStack = new ArrayStack(); 978 else classDescStack.setSize(0); 979 980 981 } 982 } | Popular Tags |