1 /***
2 *
3 * Copyright 2004 Hiram Chirino
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 * use this file except in compliance with the License. You may obtain a copy of
7 * the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17 package org.activeio.packet;
18
19 import java.io.DataOutput;
20 import java.io.IOException;
21 import java.io.OutputStream;
22 import java.lang.reflect.Constructor;
23
24 import org.activeio.Packet;
25
26 /***
27 * Provides a Packet implementation that is directly backed by a <code>byte[]</code>.
28 *
29 * @version $Revision$
30 */
31 final public class ByteArrayPacket implements Packet {
32
33 private final byte buffer[];
34
35 private final int offset;
36 private final int capacity;
37 private int position;
38 private int limit;
39 private int remaining;
40
41
42 public ByteArrayPacket(byte buffer[]) {
43 this(buffer,0, buffer.length);
44 }
45
46 public ByteArrayPacket(byte buffer[], int offset, int capacity) {
47 this.buffer = buffer;
48 this.offset=offset;
49 this.capacity=capacity;
50 this.position = 0;
51 this.limit = capacity;
52 this.remaining = limit-position;
53 }
54
55 public int position() {
56 return position;
57 }
58
59 public void position(int position) {
60 this.position = position;
61 remaining = limit-position;
62 }
63
64 public int limit() {
65 return limit;
66 }
67
68 public void limit(int limit) {
69 this.limit = limit;
70 remaining = limit-position;
71 }
72
73 public void flip() {
74 limit = position;
75 position = 0;
76 remaining = limit - position;
77 }
78
79 public int remaining() {
80 return remaining;
81 }
82
83 public void rewind() {
84 position = 0;
85 remaining = limit - position;
86 }
87
88 public boolean hasRemaining() {
89 return remaining > 0;
90 }
91
92 public void clear() {
93 position = 0;
94 limit = capacity;
95 remaining = limit - position;
96 }
97
98 public int capacity() {
99 return capacity;
100 }
101
102 public Packet slice() {
103 return new ByteArrayPacket(buffer, offset+position, remaining);
104 }
105
106 public Packet duplicate() {
107 return new ByteArrayPacket(buffer, offset, capacity);
108 }
109
110 public Object duplicate(ClassLoader cl) throws IOException {
111 try{
112 Class clazz = cl.loadClass(ByteArrayPacket.class.getName());
113 Constructor constructor = clazz.getConstructor(new Class[]{byte[].class, int.class, int.class});
114 return constructor.newInstance(new Object[]{buffer, new Integer(offset), new Integer(capacity())});
115 } catch (Throwable e) {
116 throw (IOException)new IOException("Could not duplicate packet in a different classloader: "+e).initCause(e);
117 }
118 }
119
120 public void writeTo(OutputStream out) throws IOException {
121 out.write(buffer, offset+position, remaining);
122 position=limit;
123 remaining = limit-position;
124 }
125
126 public void writeTo(DataOutput out) throws IOException {
127 out.write(buffer, offset+position, remaining);
128 position=limit;
129 remaining = limit-position;
130 }
131
132 /***
133 * @see org.activeio.Packet#read()
134 */
135 public int read() {
136 if( !(remaining > 0) )
137 return -1;
138 int rc = buffer[offset+position];
139 position++;
140 remaining = limit-position;
141 return rc & 0xff;
142 }
143
144 /***
145 * @see org.activeio.Packet#read(byte[], int, int)
146 */
147 public int read(byte[] data, int offset, int length) {
148 if( !(remaining > 0) )
149 return -1;
150
151 int copyLength = ((length <= remaining) ? length : remaining);
152 System.arraycopy(buffer, this.offset+position, data, offset, copyLength);
153 position += copyLength;
154 remaining = limit-position;
155 return copyLength;
156 }
157
158 /***
159 * @see org.activeio.Packet#write(int)
160 */
161 public boolean write(int data) {
162 if( !(remaining > 0) )
163 return false;
164 buffer[offset+position]=(byte) data;
165 position++;
166 remaining = limit-position;
167 return true;
168 }
169
170 /***
171 * @see org.activeio.Packet#write(byte[], int, int)
172 */
173 public int write(byte[] data, int offset, int length) {
174 if( !(remaining > 0) )
175 return -1;
176
177 int copyLength = ((length <= remaining) ? length : remaining);
178 System.arraycopy(data, offset, buffer, this.offset+position, copyLength);
179 position+=copyLength;
180 remaining = limit-position;
181 return copyLength;
182 }
183
184 public ByteSequence asByteSequence() {
185 return new ByteSequence(buffer, offset+position, remaining);
186 }
187
188 /***
189 * @see org.activeio.Packet#sliceAsBytes()
190 */
191 public byte[] sliceAsBytes() {
192 if( buffer.length == remaining ) {
193 return buffer;
194 } else {
195 byte rc[] = new byte[remaining];
196 int op = position;
197 write(rc,0,remaining);
198 position=op;
199 remaining = limit-position;
200 return rc;
201 }
202 }
203
204 /***
205 * @param dest
206 * @return the number of bytes read into the dest.
207 */
208 public int read(Packet dest) {
209 int a = dest.remaining();
210 int rc = ((a <= remaining) ? a : remaining);
211 if( rc > 0 ) {
212 dest.write( buffer, offset+position, rc);
213 position = position+rc;
214 remaining = limit-position;
215 }
216 return rc;
217 }
218
219 public String toString() {
220 return "{position="+position+",limit="+limit+",capacity="+capacity+"}";
221 }
222
223 public Object narrow(Class target) {
224 if( target.isAssignableFrom(getClass()) ) {
225 return this;
226 }
227 return null;
228 }
229
230 public byte[] getBuffer() {
231 return buffer;
232 }
233
234 public void dispose() {
235 }
236 }