KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > net > protocol > AbstractTCNetworkHeader


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.net.protocol;
5
6 import com.tc.bytes.TCByteBuffer;
7 import com.tc.bytes.TCByteBufferFactory;
8 import com.tc.util.Assert;
9
10 import java.util.zip.Adler32 JavaDoc;
11
12 /**
13  * TODO: document me
14  *
15  * @author teck
16  */

17 public abstract class AbstractTCNetworkHeader implements TCNetworkHeader {
18   protected static final int LENGTH_NOT_AVAIL = -1;
19
20   private static final byte[] EMTPY_BYTE_ARRAY = new byte[] {};
21   private static final byte[] FOUR_ZERO_BYTES = new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0 };
22
23   protected final int minLength;
24   protected final int maxLength;
25   protected TCByteBuffer data;
26   private final boolean localAllocation;
27
28   abstract protected void setHeaderLength(short headerLength);
29
30   /**
31    * Override this method to allow protocol parsers to wait before asking <code>getHeaderByteLength()</code>. This is
32    * really only useful if your header length data is not the first byte of your header
33    *
34    * @return true if the length of this header is available
35    */

36   protected boolean isHeaderLengthAvail() {
37     return true;
38   }
39
40   protected AbstractTCNetworkHeader(TCByteBuffer buffer, int min, int max) {
41     this.minLength = min;
42     this.maxLength = max;
43
44     if (buffer == null) {
45       this.data = TCByteBufferFactory.getInstance(false, max);
46       this.data.limit(min);
47       localAllocation = true;
48     } else {
49       this.data = buffer;
50       localAllocation = false;
51     }
52
53     Assert.eval(!this.data.isDirect());
54     Assert.eval(this.data.capacity() >= this.maxLength);
55     if (this.data.limit() % 4 != 0) { throw new AssertionError JavaDoc("buffer limit not a multiple of 4: " + this.data.limit()); }
56   }
57
58   protected AbstractTCNetworkHeader(int min, int max) {
59     this(null, min, max);
60   }
61
62   public TCByteBuffer getDataBuffer() {
63     return data;
64   }
65
66   abstract public void validate() throws TCProtocolException;
67
68   public void recycle() {
69     Assert.assertTrue(localAllocation);
70     if(data != null) {
71       data.recycle();
72       data = null;
73     }
74     else {
75       // data is already null. Probably called recycle twice !!
76
Thread.dumpStack();
77     }
78   }
79
80   private void setBytes(int pos, byte[] value) {
81     setBytes(pos, value, 0, value.length);
82   }
83
84   private void setBytes(int pos, byte[] value, int offset, int length) {
85     data.put(pos, value, offset, length);
86   }
87
88   protected byte getByte(int index) {
89     return data.get(index);
90   }
91
92   protected byte[] getBytes(int offset, int len) {
93     Assert.eval(len >= 0);
94
95     if (0 == len) { return EMTPY_BYTE_ARRAY; }
96
97     byte rv[] = new byte[len];
98     data.get(offset, rv, 0, len);
99
100     return rv;
101   }
102
103   protected void set4BitValue(int pos, boolean high, byte value) {
104     byte other4 = (byte) (data.get(pos) & (high ? 0x0F : 0xF0));
105     byte val = (byte) ((value << (high ? 4 : 0)) & (high ? 0xF0 : 0x0F));
106
107     data.put(pos, (byte) (val | other4));
108   }
109
110   protected byte get4BitValue(int pos, boolean high) {
111     byte bite = getByte(pos);
112
113     if (high) {
114       return (byte) ((bite >> 4) & 0x0F);
115     } else {
116       return (byte) (bite & 0x0F);
117     }
118   }
119
120   protected long computeAdler32Checksum(int pos, boolean set) {
121     Adler32 JavaDoc adler = new Adler32 JavaDoc();
122
123     // save off the existing checksum
124
byte cksum[] = getBytes(pos, 4);
125
126     // zero out the checksum bytes before doing the calculation
127
setBytes(pos, FOUR_ZERO_BYTES);
128     adler.update(data.array(), 0, getHeaderByteLength());
129
130     long rv = adler.getValue();
131
132     if (set) {
133       data.putUint(pos, rv);
134     } else {
135       // restore the original checksum bytes
136
setBytes(pos, cksum);
137     }
138
139     return rv;
140   }
141
142   protected void setLimit(int newLimit) {
143     data.limit(newLimit);
144   }
145
146   /**
147    * @param options zero-padded header option bytes. The byte array can be zero length and/or null to indicate that no
148    * options should be set in this header
149    */

150   public void setOptions(byte[] options) {
151     if (options == null) {
152       options = new byte[] {};
153     }
154
155     int optionsLen = options.length;
156
157     Assert.eval((optionsLen % 4) == 0);
158     Assert.eval(optionsLen <= (maxLength - minLength));
159
160     if (optionsLen > 0) {
161       setLimit(minLength + optionsLen);
162       setBytes(minLength, options);
163     } else {
164       setLimit(minLength);
165     }
166
167     setHeaderLength((byte) ((minLength + optionsLen) / 4));
168   }
169
170   public byte[] getOptions() {
171     return getBytes(minLength, getHeaderByteLength() - minLength);
172   }
173
174 }
Popular Tags