| 1 7 8 package java.io; 9 10 import java.io.ObjectStreamClass.WeakClassKey ; 11 import java.lang.ref.ReferenceQueue ; 12 import java.security.AccessController ; 13 import java.security.PrivilegedAction ; 14 import java.util.Arrays ; 15 import java.util.concurrent.ConcurrentHashMap ; 16 import java.util.concurrent.ConcurrentMap ; 17 import static java.io.ObjectStreamClass.processQueue ; 18 19 139 public class ObjectOutputStream 140 extends OutputStream implements ObjectOutput , ObjectStreamConstants  141 { 142 private static class Caches { 143 144 static final ConcurrentMap <WeakClassKey,Boolean > subclassAudits = 145 new ConcurrentHashMap <WeakClassKey,Boolean >(); 146 147 148 static final ReferenceQueue <Class <?>> subclassAuditsQueue = 149 new ReferenceQueue <Class <?>>(); 150 } 151 152 153 private final BlockDataOutputStream bout; 154 155 private final HandleTable handles; 156 157 private final ReplaceTable subs; 158 159 private int protocol = PROTOCOL_VERSION_2; 160 161 private int depth; 162 163 164 private byte[] primVals; 165 166 167 private final boolean enableOverride; 168 169 private boolean enableReplace; 170 171 173 private Object curObj; 174 175 private ObjectStreamClass curDesc; 176 177 private PutFieldImpl curPut; 178 179 201 public ObjectOutputStream(OutputStream out) throws IOException { 202 verifySubclass(); 203 bout = new BlockDataOutputStream(out); 204 handles = new HandleTable(10, (float) 3.00); 205 subs = new ReplaceTable(10, (float) 3.00); 206 enableOverride = false; 207 writeStreamHeader(); 208 bout.setBlockDataMode(true); 209 } 210 211 227 protected ObjectOutputStream() throws IOException , SecurityException { 228 SecurityManager sm = System.getSecurityManager(); 229 if (sm != null) { 230 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); 231 } 232 bout = null; 233 handles = null; 234 subs = null; 235 enableOverride = true; 236 } 237 238 258 public void useProtocolVersion(int version) throws IOException { 259 if (handles.size() != 0) { 260 throw new IllegalStateException ("stream non-empty"); 262 } 263 switch (version) { 264 case PROTOCOL_VERSION_1: 265 case PROTOCOL_VERSION_2: 266 protocol = version; 267 break; 268 269 default: 270 throw new IllegalArgumentException ( 271 "unknown version: " + version); 272 } 273 } 274 275 296 public final void writeObject(Object obj) throws IOException { 297 if (enableOverride) { 298 writeObjectOverride(obj); 299 return; 300 } 301 try { 302 writeObject0(obj, false); 303 } catch (IOException ex) { 304 if (depth == 0) { 305 writeFatalException(ex); 306 } 307 throw ex; 308 } 309 } 310 311 325 protected void writeObjectOverride(Object obj) throws IOException { 326 } 327 328 366 public void writeUnshared(Object obj) throws IOException { 367 try { 368 writeObject0(obj, true); 369 } catch (IOException ex) { 370 if (depth == 0) { 371 writeFatalException(ex); 372 } 373 throw ex; 374 } 375 } 376 377 386 public void defaultWriteObject() throws IOException { 387 if (curObj == null || curDesc == null) { 388 throw new NotActiveException ("not in call to writeObject"); 389 } 390 bout.setBlockDataMode(false); 391 defaultWriteFields(curObj, curDesc); 392 bout.setBlockDataMode(true); 393 } 394 395 405 public ObjectOutputStream.PutField putFields() throws IOException { 406 if (curPut == null) { 407 if (curObj == null || curDesc == null) { 408 throw new NotActiveException ("not in call to writeObject"); 409 } 410 curPut = new PutFieldImpl(curDesc); 411 } 412 return curPut; 413 } 414 415 424 public void writeFields() throws IOException { 425 if (curPut == null) { 426 throw new NotActiveException ("no current PutField object"); 427 } 428 bout.setBlockDataMode(false); 429 curPut.writeFields(); 430 bout.setBlockDataMode(true); 431 } 432 433 443 public void reset() throws IOException { 444 if (depth != 0) { 445 throw new IOException ("stream active"); 446 } 447 bout.setBlockDataMode(false); 448 bout.writeByte(TC_RESET); 449 clear(); 450 bout.setBlockDataMode(true); 451 } 452 453 469 protected void annotateClass(Class <?> cl) throws IOException { 470 } 471 472 493 protected void annotateProxyClass(Class <?> cl) throws IOException { 494 } 495 496 534 protected Object replaceObject(Object obj) throws IOException { 535 return obj; 536 } 537 538 558 protected boolean enableReplaceObject(boolean enable) 559 throws SecurityException  560 { 561 if (enable == enableReplace) { 562 return enable; 563 } 564 if (enable) { 565 SecurityManager sm = System.getSecurityManager(); 566 if (sm != null) { 567 sm.checkPermission(SUBSTITUTION_PERMISSION); 568 } 569 } 570 enableReplace = enable; 571 return !enableReplace; 572 } 573 574 582 protected void writeStreamHeader() throws IOException { 583 bout.writeShort(STREAM_MAGIC); 584 bout.writeShort(STREAM_VERSION); 585 } 586 587 612 protected void writeClassDescriptor(ObjectStreamClass desc) 613 throws IOException  614 { 615 desc.writeNonProxy(this); 616 } 617 618 625 public void write(int val) throws IOException { 626 bout.write(val); 627 } 628 629 636 public void write(byte[] buf) throws IOException { 637 bout.write(buf, 0, buf.length, false); 638 } 639 640 648 public void write(byte[] buf, int off, int len) throws IOException { 649 if (buf == null) { 650 throw new NullPointerException (); 651 } 652 int endoff = off + len; 653 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) { 654 throw new IndexOutOfBoundsException (); 655 } 656 bout.write(buf, off, len, false); 657 } 658 659 665 public void flush() throws IOException { 666 bout.flush(); 667 } 668 669 676 protected void drain() throws IOException { 677 bout.drain(); 678 } 679 680 686 public void close() throws IOException { 687 flush(); 688 clear(); 689 bout.close(); 690 } 691 692 699 public void writeBoolean(boolean val) throws IOException { 700 bout.writeBoolean(val); 701 } 702 703 710 public void writeByte(int val) throws IOException { 711 bout.writeByte(val); 712 } 713 714 721 public void writeShort(int val) throws IOException { 722 bout.writeShort(val); 723 } 724 725 732 public void writeChar(int val) throws IOException { 733 bout.writeChar(val); 734 } 735 736 743 public void writeInt(int val) throws IOException { 744 bout.writeInt(val); 745 } 746 747 754 public void writeLong(long val) throws IOException { 755 bout.writeLong(val); 756 } 757 758 765 public void writeFloat(float val) throws IOException { 766 bout.writeFloat(val); 767 } 768 769 776 public void writeDouble(double val) throws IOException { 777 bout.writeDouble(val); 778 } 779 780 787 public void writeBytes(String str) throws IOException { 788 bout.writeBytes(str); 789 } 790 791 798 public void writeChars(String str) throws IOException { 799 bout.writeChars(str); 800 } 801 802 815 public void writeUTF(String str) throws IOException { 816 bout.writeUTF(str); 817 } 818 819 825 public static abstract class PutField { 826 827 833 public abstract void put(String name, boolean val); 834 835 841 public abstract void put(String name, byte val); 842 843 849 public abstract void put(String name, char val); 850 851 857 public abstract void put(String name, short val); 858 859 865 public abstract void put(String name, int val); 866 867 873 public abstract void put(String name, long val); 874 875 881 public abstract void put(String name, float val); 882 883 889 public abstract void put(String name, double val); 890 891 897 public abstract void put(String name, Object val); 898 899 912 @Deprecated  913 public abstract void write(ObjectOutput out) throws IOException ; 914 } 915 916 917 920 int getProtocolVersion() { 921 return protocol; 922 } 923 924 928 void writeTypeString(String str) throws IOException { 929 int handle; 930 if (str == null) { 931 writeNull(); 932 } else if ((handle = handles.lookup(str)) != -1) { 933 writeHandle(handle); 934 } else { 935 writeString(str, false); 936 } 937 } 938 939 945 private void verifySubclass() { 946 Class cl = getClass(); 947 processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); 948 WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); 949 Boolean result = Caches.subclassAudits.get(key); 950 if (result == null) { 951 result = Boolean.valueOf(auditSubclass(cl)); 952 Caches.subclassAudits.putIfAbsent(key, result); 953 } 954 if (result.booleanValue()) { 955 return; 956 } 957 SecurityManager sm = System.getSecurityManager(); 958 if (sm != null) { 959 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); 960 } 961 } 962 963 968 private static boolean auditSubclass(final Class subcl) { 969 Boolean result = (Boolean ) AccessController.doPrivileged( 970 |