home *** CD-ROM | disk | FTP | other *** search
/ Dynamic HTML Construction Kit / Dynamic HTML Construction Kit.iso / earthlink / nscomm / java40.jar / java / io / ObjectOutputStream.class (.txt) < prev    next >
Encoding:
Java Class File  |  1997-11-03  |  8.6 KB  |  620 lines

  1. package java.io;
  2.  
  3. import java.util.Stack;
  4.  
  5. public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants {
  6.    private boolean blockDataMode;
  7.    private byte[] buf;
  8.    private int count;
  9.    private OutputStream out;
  10.    private DataOutputStream dos;
  11.    private IOException abortIOException;
  12.    private Object[] wireHandle2Object;
  13.    private int[] wireNextHandle;
  14.    private int[] wireHash2Handle;
  15.    private int nextWireOffset;
  16.    private Object currentObject;
  17.    private ObjectStreamClass currentClassDesc;
  18.    private Stack classDescStack;
  19.    private boolean enableReplace;
  20.    private Object[] replaceObjects;
  21.    private int nextReplaceOffset;
  22.    private int recursionDepth;
  23.  
  24.    public ObjectOutputStream(OutputStream var1) throws IOException {
  25.       this.out = var1;
  26.       this.dos = new DataOutputStream(this);
  27.       this.buf = new byte[1024];
  28.       this.writeStreamHeader();
  29.       this.resetStream();
  30.    }
  31.  
  32.    public final void writeObject(Object var1) throws IOException {
  33.       Object var2 = this.currentObject;
  34.       ObjectStreamClass var3 = this.currentClassDesc;
  35.       boolean var4 = this.setBlockData(false);
  36.       ++this.recursionDepth;
  37.  
  38.       try {
  39.          if (this.serializeNullAndRepeat(var1)) {
  40.             return;
  41.          }
  42.  
  43.          if (this.checkSpecialClasses(var1)) {
  44.             return;
  45.          }
  46.  
  47.          if (this.enableReplace) {
  48.             Object var17 = this.replaceObject(var1);
  49.             if (var1 != var17) {
  50.                if (!(var17 instanceof Serializable)) {
  51.                   String var8 = var17.getClass().getName();
  52.                   throw new NotSerializableException(var8);
  53.                }
  54.  
  55.                if (this.serializeNullAndRepeat(var17)) {
  56.                   this.addReplacement(var1, var17);
  57.                   return;
  58.                }
  59.  
  60.                this.addReplacement(var1, var17);
  61.                if (this.checkSpecialClasses(var17)) {
  62.                   return;
  63.                }
  64.  
  65.                var1 = var17;
  66.             }
  67.          }
  68.  
  69.          this.outputObject(var1);
  70.       } catch (ObjectStreamException var14) {
  71.          ObjectStreamException var7 = var14;
  72.          if (this.abortIOException == null) {
  73.             try {
  74.                this.setBlockData(false);
  75.                this.writeCode(123);
  76.                this.resetStream();
  77.                this.writeObject(var7);
  78.                this.resetStream();
  79.                this.abortIOException = var7;
  80.             } catch (IOException var13) {
  81.                this.abortIOException = new StreamCorruptedException(((Throwable)var13).getMessage());
  82.             }
  83.          }
  84.       } catch (IOException var15) {
  85.          if (this.abortIOException == null) {
  86.             this.abortIOException = var15;
  87.          }
  88.       } finally {
  89.          --this.recursionDepth;
  90.          this.currentObject = var2;
  91.          this.currentClassDesc = var3;
  92.          this.setBlockData(var4);
  93.       }
  94.  
  95.       IOException var5 = this.abortIOException;
  96.       if (this.recursionDepth == 0) {
  97.          this.abortIOException = null;
  98.       }
  99.  
  100.       if (var5 != null) {
  101.          throw var5;
  102.       }
  103.    }
  104.  
  105.    private boolean checkSpecialClasses(Object var1) throws IOException {
  106.       if (var1 instanceof Class) {
  107.          this.outputClass((Class)var1);
  108.          return true;
  109.       } else if (var1 instanceof ObjectStreamClass) {
  110.          this.outputClassDescriptor((ObjectStreamClass)var1);
  111.          return true;
  112.       } else if (var1 instanceof String) {
  113.          this.outputString((String)var1);
  114.          return true;
  115.       } else if (var1.getClass().isArray()) {
  116.          this.outputArray(var1);
  117.          return true;
  118.       } else {
  119.          return false;
  120.       }
  121.    }
  122.  
  123.    public final void defaultWriteObject() throws IOException {
  124.       if (this.currentObject != null && this.currentClassDesc != null) {
  125.          if (this.currentClassDesc.getFieldSequence() != null) {
  126.             boolean var1 = this.setBlockData(false);
  127.             this.outputClassFields(this.currentObject, this.currentClassDesc.forClass(), this.currentClassDesc.getFieldSequence());
  128.             this.setBlockData(var1);
  129.          }
  130.  
  131.       } else {
  132.          throw new NotActiveException("defaultWriteObject");
  133.       }
  134.    }
  135.  
  136.    public void reset() throws IOException {
  137.       if (this.currentObject == null && this.currentClassDesc == null) {
  138.          this.setBlockData(false);
  139.          this.writeCode(121);
  140.          this.resetStream();
  141.          this.abortIOException = null;
  142.       } else {
  143.          throw new IOException("Illegal call to reset");
  144.       }
  145.    }
  146.  
  147.    private void resetStream() throws IOException {
  148.       this.wireHandle2Object = new Object[100];
  149.       this.wireNextHandle = new int[100];
  150.       this.wireHash2Handle = new int[101];
  151.  
  152.       for(int var1 = 0; var1 < this.wireHash2Handle.length; ++var1) {
  153.          this.wireHash2Handle[var1] = -1;
  154.       }
  155.  
  156.       this.classDescStack = new Stack();
  157.       this.nextWireOffset = 0;
  158.       this.replaceObjects = null;
  159.       this.nextReplaceOffset = 0;
  160.       this.setBlockData(true);
  161.    }
  162.  
  163.    protected void annotateClass(Class var1) throws IOException {
  164.    }
  165.  
  166.    protected Object replaceObject(Object var1) throws IOException {
  167.       return var1;
  168.    }
  169.  
  170.    protected final boolean enableReplaceObject(boolean var1) throws SecurityException {
  171.       boolean var2 = this.enableReplace;
  172.       if (var1) {
  173.          ClassLoader var3 = this.getClass().getClassLoader();
  174.          if (var3 == null) {
  175.             this.enableReplace = true;
  176.             return var2;
  177.          } else {
  178.             throw new SecurityException("Not trusted class");
  179.          }
  180.       } else {
  181.          this.enableReplace = false;
  182.          return var2;
  183.       }
  184.    }
  185.  
  186.    protected void writeStreamHeader() throws IOException {
  187.       this.writeShort(-21267);
  188.       this.writeShort(5);
  189.    }
  190.  
  191.    private void outputString(String var1) throws IOException {
  192.       this.assignWireOffset(var1);
  193.       this.writeCode(116);
  194.       this.writeUTF(var1);
  195.    }
  196.  
  197.    private void outputClass(Class var1) throws IOException {
  198.       this.writeCode(118);
  199.       ObjectStreamClass var2 = ObjectStreamClass.lookup(var1);
  200.       if (var2 == null) {
  201.          throw new NotSerializableException(var1.getName());
  202.       } else {
  203.          this.outputClassDescriptor(var2);
  204.          this.assignWireOffset(var1);
  205.       }
  206.    }
  207.  
  208.    private void outputClassDescriptor(ObjectStreamClass var1) throws IOException {
  209.       if (!this.serializeNullAndRepeat(var1)) {
  210.          this.writeCode(114);
  211.          String var2 = var1.getName();
  212.          this.writeUTF(var2);
  213.          this.writeLong(var1.getSerialVersionUID());
  214.          this.assignWireOffset(var1);
  215.          var1.write(this);
  216.          boolean var3 = this.setBlockData(true);
  217.          this.annotateClass(var1.forClass());
  218.          this.setBlockData(var3);
  219.          this.writeCode(120);
  220.          ObjectStreamClass var4 = var1.getSuperclass();
  221.          this.outputClassDescriptor(var4);
  222.       }
  223.    }
  224.  
  225.    private void outputArray(Object var1) throws IOException {
  226.       Class var2 = var1.getClass();
  227.       ObjectStreamClass var3 = ObjectStreamClass.lookup(var2);
  228.       this.writeCode(117);
  229.       this.outputClassDescriptor(var3);
  230.       this.assignWireOffset(var1);
  231.       Class var6 = var2.getComponentType();
  232.       if (var6.isPrimitive()) {
  233.          if (var6 == Integer.TYPE) {
  234.             int[] var30 = (int[])var1;
  235.             int var22 = var30.length;
  236.             this.writeInt(var22);
  237.  
  238.             for(int var14 = 0; var14 < var22; ++var14) {
  239.                this.writeInt(var30[var14]);
  240.             }
  241.  
  242.          } else if (var6 == Byte.TYPE) {
  243.             byte[] var29 = (byte[])var1;
  244.             int var21 = var29.length;
  245.             this.writeInt(var21);
  246.             this.write(var29, 0, var21);
  247.          } else if (var6 == Long.TYPE) {
  248.             long[] var28 = (long[])var1;
  249.             int var20 = var28.length;
  250.             this.writeInt(var20);
  251.  
  252.             for(int var13 = 0; var13 < var20; ++var13) {
  253.                this.writeLong(var28[var13]);
  254.             }
  255.  
  256.          } else if (var6 == Float.TYPE) {
  257.             float[] var27 = (float[])var1;
  258.             int var19 = var27.length;
  259.             this.writeInt(var19);
  260.  
  261.             for(int var12 = 0; var12 < var19; ++var12) {
  262.                this.writeFloat(var27[var12]);
  263.             }
  264.  
  265.          } else if (var6 == Double.TYPE) {
  266.             double[] var26 = (double[])var1;
  267.             int var18 = var26.length;
  268.             this.writeInt(var18);
  269.  
  270.             for(int var11 = 0; var11 < var18; ++var11) {
  271.                this.writeDouble(var26[var11]);
  272.             }
  273.  
  274.          } else if (var6 == Short.TYPE) {
  275.             short[] var25 = (short[])var1;
  276.             int var17 = var25.length;
  277.             this.writeInt(var17);
  278.  
  279.             for(int var10 = 0; var10 < var17; ++var10) {
  280.                this.writeShort(var25[var10]);
  281.             }
  282.  
  283.          } else if (var6 == Character.TYPE) {
  284.             char[] var24 = (char[])var1;
  285.             int var16 = var24.length;
  286.             this.writeInt(var16);
  287.  
  288.             for(int var9 = 0; var9 < var16; ++var9) {
  289.                this.writeChar(var24[var9]);
  290.             }
  291.  
  292.          } else if (var6 != Boolean.TYPE) {
  293.             throw new InvalidClassException(var2.getName());
  294.          } else {
  295.             boolean[] var23 = (boolean[])var1;
  296.             int var15 = var23.length;
  297.             this.writeInt(var15);
  298.  
  299.             for(int var8 = 0; var8 < var15; ++var8) {
  300.                this.writeBoolean(var23[var8]);
  301.             }
  302.  
  303.          }
  304.       } else {
  305.          Object[] var7 = var1;
  306.          int var5 = var7.length;
  307.          this.writeInt(var5);
  308.  
  309.          for(int var4 = 0; var4 < var5; ++var4) {
  310.             this.writeObject(var7[var4]);
  311.          }
  312.  
  313.       }
  314.    }
  315.  
  316.    private void outputObject(Object var1) throws IOException {
  317.       this.currentObject = var1;
  318.       Class var2 = var1.getClass();
  319.       this.currentClassDesc = ObjectStreamClass.lookup(var2);
  320.       if (this.currentClassDesc == null) {
  321.          throw new NotSerializableException(var2.getName());
  322.       } else {
  323.          this.writeCode(115);
  324.          this.outputClassDescriptor(this.currentClassDesc);
  325.          this.assignWireOffset(var1);
  326.          if (this.currentClassDesc.isExternalizable()) {
  327.             Externalizable var9 = (Externalizable)var1;
  328.             var9.writeExternal(this);
  329.          } else {
  330.             int var3 = this.classDescStack.size();
  331.  
  332.             try {
  333.                ObjectStreamClass var6;
  334.                while((var6 = this.currentClassDesc.getSuperclass()) != null) {
  335.                   this.classDescStack.push(this.currentClassDesc);
  336.                   this.currentClassDesc = var6;
  337.                }
  338.  
  339.                do {
  340.                   if (this.currentClassDesc.hasWriteObject()) {
  341.                      this.setBlockData(true);
  342.                      this.invokeObjectWriter(var1, this.currentClassDesc.forClass());
  343.                      this.setBlockData(false);
  344.                      this.writeCode(120);
  345.                   } else {
  346.                      this.defaultWriteObject();
  347.                   }
  348.                } while(this.classDescStack.size() > var3 && (this.currentClassDesc = (ObjectStreamClass)this.classDescStack.pop()) != null);
  349.             } finally {
  350.                this.classDescStack.setSize(var3);
  351.             }
  352.  
  353.          }
  354.       }
  355.    }
  356.  
  357.    private boolean serializeNullAndRepeat(Object var1) throws IOException {
  358.       if (var1 == null) {
  359.          this.writeCode(112);
  360.          return true;
  361.       } else {
  362.          if (this.replaceObjects != null) {
  363.             for(int var2 = 0; var2 < this.nextReplaceOffset; var2 += 2) {
  364.                if (this.replaceObjects[var2] == var1) {
  365.                   var1 = this.replaceObjects[var2 + 1];
  366.                   break;
  367.                }
  368.             }
  369.          }
  370.  
  371.          int var3 = this.findWireOffset(var1);
  372.          if (var3 >= 0) {
  373.             this.writeCode(113);
  374.             this.writeInt(var3 + 8257536);
  375.             return true;
  376.          } else {
  377.             return false;
  378.          }
  379.       }
  380.    }
  381.  
  382.    private int findWireOffset(Object var1) {
  383.       int var2 = System.identityHashCode(var1);
  384.       int var3 = (var2 & Integer.MAX_VALUE) % this.wireHash2Handle.length;
  385.  
  386.       for(int var4 = this.wireHash2Handle[var3]; var4 >= 0; var4 = this.wireNextHandle[var4]) {
  387.          if (this.wireHandle2Object[var4] == var1) {
  388.             return var4;
  389.          }
  390.       }
  391.  
  392.       return -1;
  393.    }
  394.  
  395.    private void assignWireOffset(Object var1) throws IOException {
  396.       if (this.nextWireOffset == this.wireHandle2Object.length) {
  397.          Object[] var2 = this.wireHandle2Object;
  398.          this.wireHandle2Object = new Object[this.nextWireOffset * 2];
  399.          System.arraycopy(var2, 0, this.wireHandle2Object, 0, this.nextWireOffset);
  400.          int[] var3 = this.wireNextHandle;
  401.          this.wireNextHandle = new int[this.nextWireOffset * 2];
  402.          System.arraycopy(var3, 0, this.wireNextHandle, 0, this.nextWireOffset);
  403.       }
  404.  
  405.       this.wireHandle2Object[this.nextWireOffset] = var1;
  406.       this.hashInsert(var1, this.nextWireOffset);
  407.       ++this.nextWireOffset;
  408.    }
  409.  
  410.    private void hashInsert(Object var1, int var2) {
  411.       int var3 = System.identityHashCode(var1);
  412.       int var4 = (var3 & Integer.MAX_VALUE) % this.wireHash2Handle.length;
  413.       this.wireNextHandle[var2] = this.wireHash2Handle[var4];
  414.       this.wireHash2Handle[var4] = var2;
  415.    }
  416.  
  417.    private void addReplacement(Object var1, Object var2) {
  418.       if (this.replaceObjects == null) {
  419.          this.replaceObjects = new Object[10];
  420.       }
  421.  
  422.       if (this.nextReplaceOffset == this.replaceObjects.length) {
  423.          Object[] var3 = this.replaceObjects;
  424.          this.replaceObjects = new Object[2 + this.nextReplaceOffset * 2];
  425.          System.arraycopy(var3, 0, this.replaceObjects, 0, this.nextReplaceOffset);
  426.       }
  427.  
  428.       this.replaceObjects[this.nextReplaceOffset++] = var1;
  429.       this.replaceObjects[this.nextReplaceOffset++] = var2;
  430.    }
  431.  
  432.    private void writeCode(int var1) throws IOException {
  433.       this.writeByte(var1);
  434.    }
  435.  
  436.    public void write(int var1) throws IOException {
  437.       if (this.count >= this.buf.length) {
  438.          this.drain();
  439.       }
  440.  
  441.       this.buf[this.count++] = (byte)var1;
  442.    }
  443.  
  444.    public void write(byte[] var1) throws IOException {
  445.       this.write(var1, 0, var1.length);
  446.    }
  447.  
  448.    public void write(byte[] var1, int var2, int var3) throws IOException {
  449.       if (var3 < 0) {
  450.          throw new IndexOutOfBoundsException();
  451.       } else {
  452.          int var4 = this.buf.length - this.count;
  453.          if (var3 <= var4) {
  454.             System.arraycopy(var1, var2, this.buf, this.count, var3);
  455.             this.count += var3;
  456.          } else {
  457.             this.drain();
  458.             if (this.blockDataMode) {
  459.                if (var3 <= 255) {
  460.                   this.out.write(119);
  461.                   this.out.write(var3);
  462.                } else {
  463.                   this.out.write(122);
  464.                   this.out.write(var3 >> 24 & 255);
  465.                   this.out.write(var3 >> 16 & 255);
  466.                   this.out.write(var3 >> 8 & 255);
  467.                   this.out.write(var3 & 255);
  468.                }
  469.             }
  470.  
  471.             this.out.write(var1, var2, var3);
  472.          }
  473.       }
  474.    }
  475.  
  476.    public void flush() throws IOException {
  477.       this.drain();
  478.       this.out.flush();
  479.    }
  480.  
  481.    protected void drain() throws IOException {
  482.       if (this.count != 0) {
  483.          if (this.blockDataMode) {
  484.             if (this.count <= 255) {
  485.                this.out.write(119);
  486.                this.out.write(this.count);
  487.             } else {
  488.                this.out.write(122);
  489.                this.out.write(this.count >> 24 & 255);
  490.                this.out.write(this.count >> 16 & 255);
  491.                this.out.write(this.count >> 8 & 255);
  492.                this.out.write(this.count & 255);
  493.             }
  494.          }
  495.  
  496.          this.out.write(this.buf, 0, this.count);
  497.          this.count = 0;
  498.       }
  499.    }
  500.  
  501.    public void close() throws IOException {
  502.       this.flush();
  503.       this.out.close();
  504.    }
  505.  
  506.    private boolean setBlockData(boolean var1) throws IOException {
  507.       if (this.blockDataMode == var1) {
  508.          return var1;
  509.       } else {
  510.          this.drain();
  511.          this.blockDataMode = var1;
  512.          return !var1;
  513.       }
  514.    }
  515.  
  516.    public void writeBoolean(boolean var1) throws IOException {
  517.       if (this.count >= this.buf.length) {
  518.          this.drain();
  519.       }
  520.  
  521.       this.buf[this.count++] = (byte)(var1 ? 1 : 0);
  522.    }
  523.  
  524.    public void writeByte(int var1) throws IOException {
  525.       if (this.count >= this.buf.length) {
  526.          this.drain();
  527.       }
  528.  
  529.       this.buf[this.count++] = (byte)var1;
  530.    }
  531.  
  532.    public void writeShort(int var1) throws IOException {
  533.       if (this.count + 2 > this.buf.length) {
  534.          this.drain();
  535.       }
  536.  
  537.       this.buf[this.count++] = (byte)(var1 >>> 8);
  538.       this.buf[this.count++] = (byte)var1;
  539.    }
  540.  
  541.    public void writeChar(int var1) throws IOException {
  542.       if (this.count + 2 > this.buf.length) {
  543.          this.drain();
  544.       }
  545.  
  546.       this.buf[this.count++] = (byte)(var1 >>> 8);
  547.       this.buf[this.count++] = (byte)var1;
  548.    }
  549.  
  550.    public void writeInt(int var1) throws IOException {
  551.       if (this.count + 4 > this.buf.length) {
  552.          this.drain();
  553.       }
  554.  
  555.       this.buf[this.count++] = (byte)(var1 >>> 24);
  556.       this.buf[this.count++] = (byte)(var1 >>> 16);
  557.       this.buf[this.count++] = (byte)(var1 >>> 8);
  558.       this.buf[this.count++] = (byte)var1;
  559.    }
  560.  
  561.    public void writeLong(long var1) throws IOException {
  562.       if (this.count + 8 > this.buf.length) {
  563.          this.drain();
  564.       }
  565.  
  566.       this.buf[this.count++] = (byte)((int)(var1 >>> 56));
  567.       this.buf[this.count++] = (byte)((int)(var1 >>> 48));
  568.       this.buf[this.count++] = (byte)((int)(var1 >>> 40));
  569.       this.buf[this.count++] = (byte)((int)(var1 >>> 32));
  570.       this.buf[this.count++] = (byte)((int)(var1 >>> 24));
  571.       this.buf[this.count++] = (byte)((int)(var1 >>> 16));
  572.       this.buf[this.count++] = (byte)((int)(var1 >>> 8));
  573.       this.buf[this.count++] = (byte)((int)var1);
  574.    }
  575.  
  576.    public void writeFloat(float var1) throws IOException {
  577.       int var2 = Float.floatToIntBits(var1);
  578.       if (this.count + 4 > this.buf.length) {
  579.          this.drain();
  580.       }
  581.  
  582.       this.buf[this.count++] = (byte)(var2 >>> 24);
  583.       this.buf[this.count++] = (byte)(var2 >>> 16);
  584.       this.buf[this.count++] = (byte)(var2 >>> 8);
  585.       this.buf[this.count++] = (byte)var2;
  586.    }
  587.  
  588.    public void writeDouble(double var1) throws IOException {
  589.       long var3 = Double.doubleToLongBits(var1);
  590.       if (this.count + 8 > this.buf.length) {
  591.          this.drain();
  592.       }
  593.  
  594.       this.buf[this.count++] = (byte)((int)(var3 >>> 56));
  595.       this.buf[this.count++] = (byte)((int)(var3 >>> 48));
  596.       this.buf[this.count++] = (byte)((int)(var3 >>> 40));
  597.       this.buf[this.count++] = (byte)((int)(var3 >>> 32));
  598.       this.buf[this.count++] = (byte)((int)(var3 >>> 24));
  599.       this.buf[this.count++] = (byte)((int)(var3 >>> 16));
  600.       this.buf[this.count++] = (byte)((int)(var3 >>> 8));
  601.       this.buf[this.count++] = (byte)((int)var3);
  602.    }
  603.  
  604.    public void writeBytes(String var1) throws IOException {
  605.       this.dos.writeBytes(var1);
  606.    }
  607.  
  608.    public void writeChars(String var1) throws IOException {
  609.       this.dos.writeChars(var1);
  610.    }
  611.  
  612.    public void writeUTF(String var1) throws IOException {
  613.       this.dos.writeUTF(var1);
  614.    }
  615.  
  616.    private native void outputClassFields(Object var1, Class var2, int[] var3) throws IOException, InvalidClassException;
  617.  
  618.    private native boolean invokeObjectWriter(Object var1, Class var2) throws IOException;
  619. }
  620.