001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.util.io;
017:
018: import java.io.Externalizable;
019: import java.io.IOException;
020: import java.io.InvalidClassException;
021: import java.io.NotSerializableException;
022: import java.io.ObjectOutput;
023: import java.io.ObjectStreamConstants;
024: import java.io.OutputStream;
025: import java.io.Serializable;
026: import java.lang.reflect.Field;
027: import java.util.ArrayList;
028: import java.util.Arrays;
029:
030: import org.apache.openejb.util.ArrayStack;
031:
032: public class ObjectOutputStream extends OutputStream implements
033: ObjectOutput, ObjectStreamConstants {
034:
035: // private Handles handles;
036: private OutputStream out;
037: private ArrayStack classDescStack;
038: private byte buf[] = new byte[5000];
039: private int count;
040:
041: public ObjectOutputStream(OutputStream out) throws IOException {
042: this .out = out;
043:
044: classDescStack = new ArrayStack();
045: }
046:
047: public void reset() throws IOException {
048: resetStream();
049: count = 0;
050: }
051:
052: public void serializeObject(Object obj, OutputStream out)
053: throws NotSerializableException, IOException {
054: this .out = out;
055: serializeObject(obj);
056: }
057:
058: public void serializeObject(Object obj)
059: throws NotSerializableException, IOException {
060:
061: if (!Serializable.class.isAssignableFrom(obj.getClass())
062: && !Externalizable.class.isAssignableFrom(obj
063: .getClass())) {
064: throw new NotSerializableException(obj.getClass().getName());
065: }
066:
067: reset();
068:
069: writeShort(STREAM_MAGIC);
070: writeShort(STREAM_VERSION);
071: writeObject(obj);
072:
073: }
074:
075: public void writeObject(Object obj) throws IOException {
076: try {
077: if (obj == null) {
078: write(TC_NULL);
079: return;
080: }
081: Class clazz = obj.getClass();
082: ClassDescriptor classDesc = null;
083:
084: if (clazz == ClassDescriptor.class)
085: classDesc = (ClassDescriptor) obj;
086: else
087: classDesc = ClassDescriptor.lookupInternal(clazz);
088:
089: if (classDesc == null) {
090: write(TC_NULL);
091: return;
092: }
093:
094: int tmpInt = findWireOffset(obj);
095: if (tmpInt >= 0) {
096: write(TC_REFERENCE);
097: tmpInt += baseWireHandle;
098:
099: write((tmpInt >>> 24) & 0xFF);
100: write((tmpInt >>> 16) & 0xFF);
101: write((tmpInt >>> 8) & 0xFF);
102: write((tmpInt >>> 0) & 0xFF);
103:
104: return;
105: }
106:
107: if (obj instanceof Class) {
108: write(TC_CLASS);
109: write(TC_CLASSDESC);
110: writeUTF(classDesc.getName());
111: long value = classDesc.getSerialVersionUID();
112:
113: write((int) (value >>> 56) & 0xFF);
114: write((int) (value >>> 48) & 0xFF);
115: write((int) (value >>> 40) & 0xFF);
116: write((int) (value >>> 32) & 0xFF);
117: write((int) (value >>> 24) & 0xFF);
118: write((int) (value >>> 16) & 0xFF);
119: write((int) (value >>> 8) & 0xFF);
120: write((int) (value >>> 0) & 0xFF);
121:
122: assignWireOffset(classDesc);
123: classDesc.writeClassInfo(this );
124: write(TC_ENDBLOCKDATA);
125: writeObject(classDesc.getSuperclass());
126: assignWireOffset(clazz);
127: return;
128: }
129:
130: if (obj instanceof ClassDescriptor) {
131: write(TC_CLASSDESC);
132: writeUTF(classDesc.getName());
133: long value = classDesc.getSerialVersionUID();
134:
135: write((int) (value >>> 56) & 0xFF);
136: write((int) (value >>> 48) & 0xFF);
137: write((int) (value >>> 40) & 0xFF);
138: write((int) (value >>> 32) & 0xFF);
139: write((int) (value >>> 24) & 0xFF);
140: write((int) (value >>> 16) & 0xFF);
141: write((int) (value >>> 8) & 0xFF);
142: write((int) (value >>> 0) & 0xFF);
143:
144: assignWireOffset(classDesc);
145: write(classDesc.flags);
146: tmpInt = classDesc.fields.length;
147: write((tmpInt >>> 8) & 0xFF);
148: write((tmpInt >>> 0) & 0xFF);
149: FieldDescriptor field;
150: for (int i = 0; i < classDesc.fields.length; i++) {
151: field = classDesc.fields[i];
152: write((int) field.typeCode);
153: writeUTF(field.name);
154: if (!field.type.isPrimitive())
155: writeObject(field.typeString);
156: }
157: write(TC_ENDBLOCKDATA);
158: writeObject(classDesc.getSuperclass());
159: return;
160: }
161: if (obj instanceof String) {
162: write(TC_STRING);
163: String s = ((String) obj).intern();
164: assignWireOffset(s);
165: writeUTF(s);
166: return;
167: }
168: if (clazz.isArray()) {
169: write(TC_ARRAY);
170: writeObject(classDesc);
171: assignWireOffset(obj);
172:
173: Class type = clazz.getComponentType();
174: if (type.isPrimitive()) {
175: if (type == Integer.TYPE) {
176: int[] array = (int[]) obj;
177: tmpInt = array.length;
178:
179: write((tmpInt >>> 24) & 0xFF);
180: write((tmpInt >>> 16) & 0xFF);
181: write((tmpInt >>> 8) & 0xFF);
182: write((tmpInt >>> 0) & 0xFF);
183:
184: int value;
185: for (int i = 0; i < tmpInt; i++) {
186: value = array[i];
187:
188: write((value >>> 24) & 0xFF);
189: write((value >>> 16) & 0xFF);
190: write((value >>> 8) & 0xFF);
191: write((value >>> 0) & 0xFF);
192:
193: }
194: return;
195: } else if (type == Byte.TYPE) {
196: byte[] array = (byte[]) obj;
197: tmpInt = array.length;
198:
199: write((tmpInt >>> 24) & 0xFF);
200: write((tmpInt >>> 16) & 0xFF);
201: write((tmpInt >>> 8) & 0xFF);
202: write((tmpInt >>> 0) & 0xFF);
203:
204: write(array, 0, tmpInt);
205: return;
206: } else if (type == Long.TYPE) {
207: long[] array = (long[]) obj;
208: tmpInt = array.length;
209:
210: write((tmpInt >>> 24) & 0xFF);
211: write((tmpInt >>> 16) & 0xFF);
212: write((tmpInt >>> 8) & 0xFF);
213: write((tmpInt >>> 0) & 0xFF);
214:
215: long value;
216: for (int i = 0; i < tmpInt; i++) {
217: value = array[i];
218:
219: write((int) (value >>> 56) & 0xFF);
220: write((int) (value >>> 48) & 0xFF);
221: write((int) (value >>> 40) & 0xFF);
222: write((int) (value >>> 32) & 0xFF);
223: write((int) (value >>> 24) & 0xFF);
224: write((int) (value >>> 16) & 0xFF);
225: write((int) (value >>> 8) & 0xFF);
226: write((int) (value >>> 0) & 0xFF);
227:
228: }
229: return;
230: } else if (type == Float.TYPE) {
231: float[] array = (float[]) obj;
232: tmpInt = array.length;
233:
234: write((tmpInt >>> 24) & 0xFF);
235: write((tmpInt >>> 16) & 0xFF);
236: write((tmpInt >>> 8) & 0xFF);
237: write((tmpInt >>> 0) & 0xFF);
238:
239: int value;
240: for (int i = 0; i < tmpInt; i++) {
241: value = Float.floatToIntBits(array[i]);
242:
243: write((value >>> 24) & 0xFF);
244: write((value >>> 16) & 0xFF);
245: write((value >>> 8) & 0xFF);
246: write((value >>> 0) & 0xFF);
247:
248: }
249: return;
250: } else if (type == Double.TYPE) {
251: double[] array = (double[]) obj;
252: tmpInt = array.length;
253:
254: write((tmpInt >>> 24) & 0xFF);
255: write((tmpInt >>> 16) & 0xFF);
256: write((tmpInt >>> 8) & 0xFF);
257: write((tmpInt >>> 0) & 0xFF);
258:
259: long value;
260: for (int i = 0; i < tmpInt; i++) {
261: value = Double.doubleToLongBits(array[i]);
262:
263: write((int) (value >>> 56) & 0xFF);
264: write((int) (value >>> 48) & 0xFF);
265: write((int) (value >>> 40) & 0xFF);
266: write((int) (value >>> 32) & 0xFF);
267: write((int) (value >>> 24) & 0xFF);
268: write((int) (value >>> 16) & 0xFF);
269: write((int) (value >>> 8) & 0xFF);
270: write((int) (value >>> 0) & 0xFF);
271:
272: }
273: return;
274: } else if (type == Short.TYPE) {
275: short[] array = (short[]) obj;
276: tmpInt = array.length;
277:
278: write((tmpInt >>> 24) & 0xFF);
279: write((tmpInt >>> 16) & 0xFF);
280: write((tmpInt >>> 8) & 0xFF);
281: write((tmpInt >>> 0) & 0xFF);
282:
283: short value;
284: for (int i = 0; i < tmpInt; i++) {
285: value = array[i];
286:
287: write((value >>> 8) & 0xFF);
288: write((value >>> 0) & 0xFF);
289:
290: }
291: return;
292: } else if (type == Character.TYPE) {
293: char[] array = (char[]) obj;
294: tmpInt = array.length;
295:
296: write((tmpInt >>> 24) & 0xFF);
297: write((tmpInt >>> 16) & 0xFF);
298: write((tmpInt >>> 8) & 0xFF);
299: write((tmpInt >>> 0) & 0xFF);
300:
301: char value;
302: for (int i = 0; i < tmpInt; i++) {
303: value = array[i];
304:
305: write((value >>> 8) & 0xFF);
306: write((value >>> 0) & 0xFF);
307:
308: }
309: return;
310: } else if (type == Boolean.TYPE) {
311: boolean[] array = (boolean[]) obj;
312: tmpInt = array.length;
313:
314: write((tmpInt >>> 24) & 0xFF);
315: write((tmpInt >>> 16) & 0xFF);
316: write((tmpInt >>> 8) & 0xFF);
317: write((tmpInt >>> 0) & 0xFF);
318:
319: for (int i = 0; i < tmpInt; i++) {
320: write(array[i] ? 1 : 0);
321: }
322: return;
323: } else {
324: throw new InvalidClassException(clazz.getName());
325: }
326: } else {
327: Object[] array = (Object[]) obj;
328: int length = array.length;
329:
330: write((length >>> 24) & 0xFF);
331: write((length >>> 16) & 0xFF);
332: write((length >>> 8) & 0xFF);
333: write((length >>> 0) & 0xFF);
334:
335: for (int i = 0; i < length; i++)
336: writeObject(array[i]);
337: }
338: return;
339: }
340: write(TC_OBJECT);
341: writeObject(classDesc);
342: assignWireOffset(obj);
343:
344: if (classDesc.isExternalizable()) {
345: writeExternal((Externalizable) obj);
346: return;
347: }
348:
349: int stackMark = classDescStack.size();
350: try {
351:
352: ClassDescriptor super ClassDesc;
353: while ((super ClassDesc = classDesc.getSuperclass()) != null) {
354: classDescStack.push(classDesc);
355: classDesc = super ClassDesc;
356: }
357:
358: do {
359: if (classDesc.hasWriteObjectMethod()) {
360: /* DMB: NOT COMPLETE - Should start writing in block data format
361: * and state the size of the data to come.
362: */
363:
364: /* DMB: NOT COMPLETE - Should Invoke the writeObject
365: * mehtod on the object.
366: * Invoking the write object method requires a
367: * sublcass of java.io.ObjectOutputStream to be
368: * passed in. This implementation is not a subclass
369: * of java.io.ObjectOutputStream.
370: */
371:
372: /* DMB: NOT COMPLETE - Should stop writing in block data format.
373: * Denote the end of this mode by writing a terminator to the stream.
374: */
375:
376: } else {
377: FieldDescriptor[] fields = classDesc
378: .getFields();
379: Field field;
380: if (fields.length > 0) {
381: for (int i = 0; i < fields.length; i++) {
382: field = fields[i].getField();
383: if (field == null)
384: throw new InvalidClassException(
385: clazz.getName(),
386: "Nonexistent field "
387: + fields[i]
388: .getName());
389: try {
390: switch (fields[i].getTypeCode()) {
391: case 'B':
392: write(field.getByte(obj));
393: break;
394: case 'C':
395: char charvalue = field
396: .getChar(obj);
397: write((charvalue >>> 8) & 0xFF);
398: write((charvalue >>> 0) & 0xFF);
399: break;
400: case 'I':
401: int intvalue = field
402: .getInt(obj);
403: write((intvalue >>> 24) & 0xFF);
404: write((intvalue >>> 16) & 0xFF);
405: write((intvalue >>> 8) & 0xFF);
406: write((intvalue >>> 0) & 0xFF);
407: break;
408: case 'Z':
409: write((field.getBoolean(obj) ? 1
410: : 0));
411: break;
412: case 'J':
413: long longvalue = field
414: .getLong(obj);
415: write((int) (longvalue >>> 56) & 0xFF);
416: write((int) (longvalue >>> 48) & 0xFF);
417: write((int) (longvalue >>> 40) & 0xFF);
418: write((int) (longvalue >>> 32) & 0xFF);
419: write((int) (longvalue >>> 24) & 0xFF);
420: write((int) (longvalue >>> 16) & 0xFF);
421: write((int) (longvalue >>> 8) & 0xFF);
422: write((int) (longvalue >>> 0) & 0xFF);
423: break;
424: case 'F':
425: int floatvalue = Float
426: .floatToIntBits(field
427: .getFloat(obj));
428: write((floatvalue >>> 24) & 0xFF);
429: write((floatvalue >>> 16) & 0xFF);
430: write((floatvalue >>> 8) & 0xFF);
431: write((floatvalue >>> 0) & 0xFF);
432: break;
433: case 'D':
434: long doublevalue = Double
435: .doubleToLongBits(field
436: .getDouble(obj));
437: write((int) (doublevalue >>> 56) & 0xFF);
438: write((int) (doublevalue >>> 48) & 0xFF);
439: write((int) (doublevalue >>> 40) & 0xFF);
440: write((int) (doublevalue >>> 32) & 0xFF);
441: write((int) (doublevalue >>> 24) & 0xFF);
442: write((int) (doublevalue >>> 16) & 0xFF);
443: write((int) (doublevalue >>> 8) & 0xFF);
444: write((int) (doublevalue >>> 0) & 0xFF);
445: break;
446: case 'S':
447: short shortvalue = field
448: .getShort(obj);
449: write((shortvalue >>> 8) & 0xFF);
450: write((shortvalue >>> 0) & 0xFF);
451: break;
452: case '[':
453: case 'L':
454: writeObject(field.get(obj));
455: break;
456: default:
457: throw new InvalidClassException(
458: clazz.getName());
459: }
460: } catch (IllegalAccessException e) {
461: throw (InvalidClassException) new InvalidClassException(
462: clazz.getName(), e
463: .getMessage())
464: .initCause(e);
465: } finally {
466: }
467: }
468: }
469: }
470: } while (classDescStack.size() > stackMark
471: && (classDesc = (ClassDescriptor) classDescStack
472: .pop()) != null);
473:
474: } finally {
475: /* If an error occcured, make sure we set the stack back
476: * the way it was before we started.
477: */
478:
479: }
480:
481: } finally {
482: }
483: }
484:
485: public void writeString(String s) throws IOException {
486: writeObject(s);
487: }
488:
489: private void writeExternal(Externalizable ext) throws IOException {
490: // if (useDeprecatedExternalizableFormat) {
491: if (false) {
492: /* JDK 1.1 external data format.
493: * Don't write in block data mode and no terminator tag.
494: */
495: /* This method accepts a java.io.OutputStream as a parameter */
496: ext.writeExternal(this );
497: } else {
498: /* JDK 1.2 Externalizable data format writes in block data mode
499: * and terminates externalizable data with TAG_ENDBLOCKDATA.
500: */
501: /* DMB: NOT COMPLETE - Should start writing in block data format.
502: * This states the size of the data to come
503: */
504:
505: try {
506: /* This method accepts a java.io.ObjectOutputStream as a parameter */
507: ext.writeExternal(this );
508: } finally {
509: /* DMB: NOT COMPLETE - Should stop writing in block data format.
510: * Denote the end of this mode by writing a terminator to the stream.
511: */
512:
513: }
514: }
515: }
516:
517: public void writeException(Throwable th) throws IOException {
518: /* DMB: NOT COMPLETE - Must write exceptions that occur during serialization
519: * to the stream.
520: */
521:
522: }
523:
524: public void writeReset() throws IOException {
525: /* DMB: NOT COMPLETE - Must write the reset byte when the reset() method
526: * is called.
527: */
528:
529: }
530:
531: /* public void write(int b) throws IOException {
532: out.write(b);
533: }
534: */
535: /* public void write(byte b[], int off, int len) throws IOException {
536: for (int i = 0 ; i < len ; i++) {
537: write(b[off + i]);
538: }
539: }
540: */
541:
542: public void write(int b) {
543: try {
544: buf[count++] = (byte) b;
545: } catch (ArrayIndexOutOfBoundsException e) {
546: byte newbuf[] = new byte[Math.max(buf.length << 1, count)];
547: System.arraycopy(buf, 0, newbuf, 0, count - 1);
548: buf = newbuf;
549: }
550: }
551:
552: public synchronized void write(byte b[], int off, int len) {
553: if (len == 0)
554: return;
555:
556: int newcount = count + len;
557: if (newcount > buf.length) {
558: byte newbuf[] = new byte[Math
559: .max(buf.length << 1, newcount)];
560: System.arraycopy(buf, 0, newbuf, 0, count);
561: buf = newbuf;
562: }
563: System.arraycopy(b, off, buf, count, len);
564: count = newcount;
565: }
566:
567: public void flush() throws IOException {
568: // out.flush();
569: }
570:
571: public byte[] toByteArray() {
572: byte newbuf[] = new byte[count];
573: System.arraycopy(buf, 0, newbuf, 0, count);
574: return newbuf;
575: }
576:
577: public int size() {
578: return count;
579: }
580:
581: public final void writeBoolean(boolean v) throws IOException {
582: write(v ? 1 : 0);
583: }
584:
585: public final void writeByte(int v) throws IOException {
586: write(v);
587: }
588:
589: public final void writeShort(int v) throws IOException {
590: write((v >>> 8) & 0xFF);
591: write((v >>> 0) & 0xFF);
592: }
593:
594: public final void writeChar(int v) throws IOException {
595: write((v >>> 8) & 0xFF);
596: write((v >>> 0) & 0xFF);
597: }
598:
599: public final void writeInt(int v) throws IOException {
600: write((v >>> 24) & 0xFF);
601: write((v >>> 16) & 0xFF);
602: write((v >>> 8) & 0xFF);
603: write((v >>> 0) & 0xFF);
604: }
605:
606: public final void writeLong(long v) throws IOException {
607: write((int) (v >>> 56) & 0xFF);
608: write((int) (v >>> 48) & 0xFF);
609: write((int) (v >>> 40) & 0xFF);
610: write((int) (v >>> 32) & 0xFF);
611: write((int) (v >>> 24) & 0xFF);
612: write((int) (v >>> 16) & 0xFF);
613: write((int) (v >>> 8) & 0xFF);
614: write((int) (v >>> 0) & 0xFF);
615: }
616:
617: public final void writeFloat(float v) throws IOException {
618: writeInt(Float.floatToIntBits(v));
619: }
620:
621: public final void writeDouble(double v) throws IOException {
622: writeLong(Double.doubleToLongBits(v));
623: }
624:
625: public final void writeBytes(String s) throws IOException {
626: int tmpLen = s.length();
627: for (int i = 0; i < tmpLen; i++) {
628: write((byte) s.charAt(i));
629: }
630: }
631:
632: public final void writeChars(String s) throws IOException {
633: int tmpLen = s.length();
634: for (int i = 0; i < tmpLen; i++) {
635: int v = s.charAt(i);
636: write((v >>> 8) & 0xFF);
637: write((v >>> 0) & 0xFF);
638: }
639: }
640:
641: /* These are to speed up the writing of strings.
642: * This method is called frequently and placing these here
643: * prevents constant allocation and garbage collection.
644: */
645:
646: private char[] utfCharBuf = new char[32];
647:
648: public final void writeUTF(String str) throws IOException {
649:
650: int len = str.length();
651:
652: if (utfCharBuf.length < len)
653: utfCharBuf = new char[len];
654:
655: str.getChars(0, len, utfCharBuf, 0);
656:
657: int mark = count;
658: write(0);
659: write(0);
660: for (int i = 0; i < len; i++) {
661: int c = utfCharBuf[i];
662: if ((c >= 0x0001) && (c <= 0x007F)) {
663: write(c);
664: } else if (c > 0x07FF) {
665: write(0xE0 | ((c >> 12) & 0x0F));
666: write(0x80 | ((c >> 6) & 0x3F));
667: write(0x80 | ((c >> 0) & 0x3F));
668: } else {
669: write(0xC0 | ((c >> 6) & 0x1F));
670: write(0x80 | ((c >> 0) & 0x3F));
671: }
672: }
673:
674: // if (tmpUtflen > 65535)throw new UTFDataFormatException();
675:
676: len = count - mark - 2;
677: buf[mark] = (byte) ((len >>> 8) & 0xFF);
678: buf[mark + 1] = (byte) ((len >>> 0) & 0xFF);
679:
680: }
681:
682: /* Object references are mapped to the wire handles through a hashtable
683: * WireHandles are integers generated by the ObjectOutputStream,
684: * they need only be unique within a stream.
685: * Objects are assigned sequential handles and stored in wireHandle2Object.
686: * The handle for an object is its index in wireHandle2Object.
687: * Object with the "same" hashcode are chained using wireHash2Handle.
688: * The hashcode of objects is used to index through the wireHash2Handle.
689: * -1 is the marker for unused cells in wireNextHandle
690: */
691: private ArrayList wireHandle2Object;
692: private int nextWireOffset;
693:
694: /* the next five members implement an inline hashtable. */
695: private int[] wireHash2Handle;
696: private int[] wireNextHandle;
697: private int wireHashSizePower = 2;
698: private int wireHashLoadFactor = 7;
699: private int wireHashCapacity = (1 << wireHashSizePower)
700: * wireHashLoadFactor;
701:
702: /*
703: * Insert the specified object into the hash array and link if
704: * necessary. Put the new object into the hash table and link the
705: * previous to it. Newer objects occur earlier in the list.
706: */
707: private void hashInsert(Object obj, int offset) {
708: int hash = System.identityHashCode(obj);
709: int index = (hash & 0x7FFFFFFF) % wireHash2Handle.length;
710: wireNextHandle[offset] = wireHash2Handle[index];
711: wireHash2Handle[index] = offset;
712: }
713:
714: /*
715: * Locate and return if found the handle for the specified object.
716: * -1 is returned if the object does not occur in the array of
717: * known objects.
718: */
719: private int findWireOffset(Object obj) {
720: int hash = System.identityHashCode(obj);
721: int index = (hash & 0x7FFFFFFF) % wireHash2Handle.length;
722:
723: for (int handle = wireHash2Handle[index]; handle >= 0; handle = wireNextHandle[handle]) {
724:
725: if (wireHandle2Object.get(handle) == obj)
726: return handle;
727: }
728: return -1;
729: }
730:
731: /* Allocate a handle for an object.
732: * The Vector is indexed by the wireHandleOffset
733: * and contains the object.
734: * Allow caller to specify the hash method for the object.
735: */
736: private void assignWireOffset(Object obj) throws IOException {
737: if (nextWireOffset == wireNextHandle.length) {
738: int[] oldnexthandles = wireNextHandle;
739: wireNextHandle = new int[nextWireOffset * 2];
740: System.arraycopy(oldnexthandles, 0, wireNextHandle, 0,
741: nextWireOffset);
742: }
743: if (nextWireOffset >= wireHashCapacity) {
744: growWireHash2Handle();
745: }
746: wireHandle2Object.add(obj);
747: hashInsert(obj, nextWireOffset);
748: nextWireOffset++;
749: return;
750: }
751:
752: private void growWireHash2Handle() {
753:
754: wireHashSizePower++;
755: wireHash2Handle = new int[(1 << wireHashSizePower) - 1];
756: Arrays.fill(wireHash2Handle, -1);
757:
758: for (int i = 0; i < nextWireOffset; i++) {
759: wireNextHandle[i] = 0;
760: }
761:
762: for (int i = 0; i < wireHandle2Object.size(); i++) {
763: hashInsert(wireHandle2Object.get(i), i);
764: }
765:
766: wireHashCapacity = (1 << wireHashSizePower)
767: * wireHashLoadFactor;
768: }
769:
770: /*
771: * Internal reset function to reinitialize the state of the stream.
772: * Reset state of things changed by using the stream.
773: */
774: private void resetStream() throws IOException {
775: if (wireHandle2Object == null) {
776: wireHandle2Object = new ArrayList();
777: wireNextHandle = new int[4];
778: wireHash2Handle = new int[(1 << wireHashSizePower) - 1];
779: } else {
780:
781: wireHandle2Object.clear();
782: for (int i = 0; i < nextWireOffset; i++) {
783: wireNextHandle[i] = 0;
784: }
785: }
786: nextWireOffset = 0;
787: Arrays.fill(wireHash2Handle, -1);
788:
789: if (classDescStack == null)
790: classDescStack = new ArrayStack();
791: else
792: classDescStack.setSize(0);
793:
794: }
795: }
|