All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.simpleframework.transport.SegmentBuilder Maven / Gradle / Ivy

/*
 * SegmentBuilder.java February 2008
 *
 * Copyright (C) 2008, Niall Gallagher 
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General 
 * Public License along with this library; if not, write to the 
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA  02111-1307  USA
 */

package org.simpleframework.transport;

import java.io.IOException;
import java.util.LinkedList;

/**
 * The SegmentBuilder object is used to build segments
 * such that they are of a sufficient size to deliver in a write.
 * This basically ensures that each packet is of a sufficiently
 * large size, if not then it transfers bytes from packets higher
 * up the queue to ones lower down, ensuring a minimum packet size.
 * 
 * @author Niall Gallagher
 *
 * @see org.simpleframework.transport.Writer
 */
class SegmentBuilder {

   /**
    * This is the packet queue that is used to queue packets.
    */
   private final Queue queue;
   
   /**
    * Constructor for the SegmentBuilder object. This 
    * is used to create a queue of packets such that each packet is
    * of a minimum size. To ensure packets are of a minimum size
    * this aggregates them by moving bytes between packets.
    */
   public SegmentBuilder() {
      this(1024);
   }
   
   /**
    * Constructor for the SegmentBuilder object. This 
    * is used to create a queue of packets such that each packet is
    * of a minimum size. To ensure packets are of a minimum size
    * this aggregates them by moving bytes between packets.
    *
    * @param size this is the size to aggregate each packet to
    */   
   public SegmentBuilder(int size) {
      this.queue = new Queue();
   }
   
   /**
    * This will aggregate the queued packets in to a packet that is
    * at least the minimum required size. If there are none in the
    * queue then this will return null. Also if the queued packets
    * are of zero length this will return null.
    * 
    * @return this returns a packet from the queue of packets
    */
   public Segment build() throws IOException {
      Packet packet = queue.peek();
      
      if(packet == null) {
         return null;
      }
      return create(packet);
   }

   /**
    * This will aggregate the queued packets in to a packet that is
    * at least the minimum required size. If there are none in the
    * queue then this will return null. Also if the queued packets
    * are of zero length this will return null.
    * 
    * @packet this is the packet to wrap within a closer packet
    * 
    * @return this returns a packet from the queue of packets
    */
   private Segment create(Packet packet) throws IOException {
      int length = packet.length();
      
      if(length <= 0) {
         packet.close(); 
         queue.poll();
      
         return build(); 
      }
      return new Segment(packet, queue);
   }

   /**
    * This will aggregate the queued packets in to a packet that is
    * at least the minimum required size. If there are none in the
    * queue then this will return null. Also if the queued packets
    * are of zero length this will return null.
    * 
    * @packet this is a new packet to be added to the packet queue
    * 
    * @return this returns a packet from the queue of packets
    */
   public Segment build(Packet packet) throws IOException {
      boolean update = queue.offer(packet);
      long sequence = packet.sequence();
      
      if(!update) {
         throw new PacketException("Could not aggregate packet " + sequence);
      }      
      return build();
   }   
   
   /**
    * This returns the total length of all packets within the queue.
    * This can be used to determine if any packets can be created
    * using the aggregate method. If the length is zero
    * there are no packets waiting to be aggregated.
    * 
    * @return this returns the total length of all queued packets
    */
   public int length() throws IOException{
      int count = 0;
      
      for(Packet packet : queue) {
         count += packet.length();
      }
      return count;
   }
   
   /**
    * This is used to close all packets within the builder. This
    * is done when there is an error or the client has closed the
    * connection from their size. This is important as it releases
    * any resources occupied by the queued packets.
    */
   public void close() throws IOException {
      for(Packet packet : queue) {
         packet.close();
      }
      queue.clear();
   }
   
   /**
    * The Queue object is used to create a queue of
    * packets that represent the order the packets have been added
    * to the builder. This order ensures that the packets can
    * be reassembled on the client size as a complete resource.
    * 
    * @author Niall Gallagher
    */
   private class Queue extends LinkedList {
 
      /**
       * Constructor for the SegmentBuilder object. This
       * is used to create a queue to order the packets that are
       * to be aggregated and delivered to a client.
       */
      public Queue() {
         super();
      }
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy