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 }