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   * Appends two packets together.
    28   *
    29   * @version $Revision$
    30   */
    31  final public class AppendedPacket implements Packet {
    32
    33      private final Packet first;
    34      private final Packet last;
    35
    36      private final int capacity;
    37      private final int firstCapacity;
    38
    39      static public Packet join(Packet first, Packet last) {
    40          if( first.hasRemaining() ) {
    41              if( last.hasRemaining() ) {
    42
    43                  //TODO: this might even be a rejoin of the same continous buffer.
    44                  //It would be good if we detected that and avoided just returned the buffer.
    45
    46                  return new AppendedPacket(first.slice(), last.slice());
    47              } else {
    48                  return first.slice();
    49              }
    50          } else {
    51              if( last.hasRemaining() ) {
    52                  return last.slice();
    53              } else {
    54                  return EmptyPacket.EMPTY_PACKET;
    55              }
    56          }
    57      }
    58
    59      /***
    60       * @deprecated use {@see #join(Packet, Packet)} instead.
    61       */
    62      public AppendedPacket(Packet first, Packet second) {
    63          this.first = first;
    64          this.last = second;
    65          this.firstCapacity = first.capacity();
    66          this.capacity = first.capacity()+last.capacity();
    67          clear();
    68      }
    69
    70      public void position(int position) {
    71          if( position <= firstCapacity ) {
    72              last.position(0);
    73              first.position(position);
    74          } else {
    75              last.position(position-firstCapacity);
    76              first.position(firstCapacity);
    77          }
    78      }
    79
    80      public void limit(int limit) {
    81          if( limit <= firstCapacity ) {
    82              last.limit(0);
    83              first.limit(limit);
    84          } else {
    85              last.limit(limit-firstCapacity);
    86              first.limit(firstCapacity);
    87          }
    88      }
    89
    90      public Packet slice() {
    91          return join(first,last);
    92      }
    93
    94      public Packet duplicate() {
    95          return new AppendedPacket(first.duplicate(), last.duplicate());
    96      }
    97
    98      public Object duplicate(ClassLoader cl) throws IOException {
    99          try {
    100             Class pclazz = cl.loadClass(Packet.class.getName());
    101             Class clazz = cl.loadClass(AppendedPacket.class.getName());
    102             Constructor constructor = clazz.getConstructor(new Class[]{pclazz, pclazz});
    103             return constructor.newInstance(new Object[]{first.duplicate(cl), last.duplicate(cl)});
    104         } catch (Throwable e) {
    105             throw (IOException)new IOException("Could not duplicate packet in a different classloader: "+e).initCause(e);
    106         }
    107     }
    108
    109     public void flip() {
    110         limit(position());
    111         position(0);
    112     }
    113
    114     public int position() {
    115         return first.position()+last.position();
    116     }
    117
    118     public int limit() {
    119         return first.limit()+last.limit();
    120     }
    121
    122     public int remaining() {
    123         return first.remaining()+last.remaining();
    124     }
    125
    126     public void rewind() {
    127         first.rewind();
    128         last.rewind();
    129     }
    130
    131     public boolean hasRemaining() {
    132         return first.hasRemaining()||last.hasRemaining();
    133     }
    134
    135     public void clear() {
    136         first.clear();
    137         last.clear();
    138     }
    139
    140     public int capacity() {
    141         return capacity;
    142     }
    143
    144     public void writeTo(OutputStream out) throws IOException {
    145         first.writeTo(out);
    146         last.writeTo(out);
    147     }
    148
    149     public void writeTo(DataOutput out) throws IOException {
    150         first.writeTo(out);
    151         last.writeTo(out);
    152     }
    153
    154
    155     /***
    156      * @see org.activeio.Packet#read()
    157      */
    158     public int read() {
    159         if( first.hasRemaining() ) {
    160             return first.read();
    161         } else if( last.hasRemaining() ) {
    162             return last.read();
    163         } else {
    164             return -1;
    165         }
    166     }
    167
    168     /***
    169      * @see org.activeio.Packet#read(byte[], int, int)
    170      */
    171     public int read(byte[] data, int offset, int length) {
    172
    173         int rc1 = first.read(data, offset, length);
    174         if( rc1==-1 ) {
    175             int rc2 = last.read(data, offset, length);
    176             return ( rc2==-1 ) ? -1 : rc2;
    177         } else {
    178             int rc2 = last.read(data, offset+rc1, length-rc1);
    179             return ( rc2==-1 ) ? rc1 : rc1+rc2;
    180         }
    181
    182     }
    183
    184     /***
    185      * @see org.activeio.Packet#write(int)
    186      */
    187     public boolean write(int data) {
    188         if( first.hasRemaining() ) {
    189             return first.write(data);
    190         } else if( last.hasRemaining() ) {
    191             return last.write(data);
    192         } else {
    193             return false;
    194         }
    195     }
    196
    197     /***
    198      * @see org.activeio.Packet#write(byte[], int, int)
    199      */
    200     public int write(byte[] data, int offset, int length) {
    201         int rc1 = first.write(data, offset, length);
    202         if( rc1==-1 ) {
    203             int rc2 = last.write(data, offset, length);
    204             return ( rc2==-1 ) ? -1 : rc2;
    205         } else {
    206             int rc2 = last.write(data, offset+rc1, length-rc1);
    207             return ( rc2==-1 ) ? rc1 : rc1+rc2;
    208         }
    209     }
    210
    211     public int read(Packet dest) {
    212 	    int rc = first.read(dest);
    213 	    rc += last.read(dest);
    214 	    return rc;
    215     }
    216
    217     public String toString() {
    218         return "{position="+position()+",limit="+limit()+",capacity="+capacity()+"}";
    219     }
    220
    221     public Object narrow(Class target) {
    222         if( target.isAssignableFrom(getClass()) ) {
    223             return this;
    224         }
    225         Object object = first.narrow(target);
    226         if( object == null )
    227             object = last.narrow(target);
    228         return object;
    229     }
    230
    231     public ByteSequence asByteSequence() {
    232         // TODO: implement me
    233         return null;
    234     }
    235
    236     public byte[] sliceAsBytes() {
    237         // TODO: implement me
    238         return null;
    239     }
    240
    241     public void dispose() {
    242         first.dispose();
    243         last.dispose();
    244     }
    245
    246 }