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 }