View Javadoc

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 }