Source for gnu.inet.util.MessageInputStream

   1: /*
   2:  * MessageInputStream.java
   3:  * Copyright (C) 2002 The Free Software Foundation
   4:  * 
   5:  * This file is part of GNU inetlib, a library.
   6:  * 
   7:  * GNU inetlib is free software; you can redistribute it and/or modify
   8:  * it under the terms of the GNU General Public License as published by
   9:  * the Free Software Foundation; either version 2 of the License, or
  10:  * (at your option) any later version.
  11:  * 
  12:  * GNU inetlib is distributed in the hope that it will be useful,
  13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15:  * GNU General Public License for more details.
  16:  * 
  17:  * You should have received a copy of the GNU General Public License
  18:  * along with this library; if not, write to the Free Software
  19:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20:  *
  21:  * Linking this library statically or dynamically with other modules is
  22:  * making a combined work based on this library.  Thus, the terms and
  23:  * conditions of the GNU General Public License cover the whole
  24:  * combination.
  25:  *
  26:  * As a special exception, the copyright holders of this library give you
  27:  * permission to link this library with independent modules to produce an
  28:  * executable, regardless of the license terms of these independent
  29:  * modules, and to copy and distribute the resulting executable under
  30:  * terms of your choice, provided that you also meet, for each linked
  31:  * independent module, the terms and conditions of the license of that
  32:  * module.  An independent module is a module which is not derived from
  33:  * or based on this library.  If you modify this library, you may extend
  34:  * this exception to your version of the library, but you are not
  35:  * obliged to do so.  If you do not wish to do so, delete this
  36:  * exception statement from your version.
  37:  */
  38: 
  39: package gnu.inet.util;
  40: 
  41: import java.io.FilterInputStream;
  42: import java.io.InputStream;
  43: import java.io.IOException;
  44: 
  45: /**
  46:  * A utility class for feeding message contents to messages.
  47:  * This stream returns -1 from <code>read</code> when the stream termination
  48:  * sequence LF,END,LF is read from the underlying stream.
  49:  *
  50:  * @author <a href="mailto:dog@gnu.org">Chris Burdess</a>
  51:  */
  52: public class MessageInputStream
  53:   extends FilterInputStream
  54: {
  55: 
  56:   /**
  57:    * The stream termination octet ('.').
  58:    */
  59:   public static final int END = 46;
  60: 
  61:   /**
  62:    * The line termination octet ('\n').
  63:    */
  64:   public static final int LF = 10;
  65: 
  66:   protected boolean eof;
  67: 
  68:   protected int buf1 = -1;
  69:   protected int buf2 = -1;
  70: 
  71:   protected int markBuf1;
  72:   protected int markBuf2;
  73: 
  74:   /**
  75:    * Constructs a message input stream connected to the specified input stream.
  76:    */
  77:   public MessageInputStream(InputStream in)
  78:   {
  79:     super(in);
  80:     eof = false;
  81:   }
  82: 
  83:   /**
  84:    * Reads the next byte of data from this message input stream.
  85:    * Returns -1 if the end of the message stream has been reached.
  86:    * @exception IOException if an I/O error occurs
  87:    */
  88:   public int read()
  89:     throws IOException
  90:   {
  91:     if (eof)
  92:       {
  93:         return -1;
  94:       }
  95:     int c;
  96:     if (buf1 != -1)
  97:       {
  98:         c = buf1;
  99:         buf1 = buf2;
 100:         buf2 = -1;
 101:       }
 102:     else
 103:       {
 104:         c = super.read();
 105:       }
 106:     if (c == LF)
 107:       {
 108:         if (buf1 == -1)
 109:           {
 110:             buf1 = super.read();
 111:             if (buf1 == END)
 112:               {
 113:                 buf2 = super.read();
 114:                 if (buf2 == LF)
 115:                   {
 116:                     eof = true;
 117:                     // Allow the final LF to be read
 118:                   }
 119:               }
 120:           }
 121:         else if (buf1 == END)
 122:           {
 123:             if (buf2 == -1)
 124:               {
 125:                 buf2 = super.read();
 126:                 if (buf2 == LF)
 127:                   {
 128:                     eof = true;
 129:                   }
 130:               }
 131:             else if (buf2 == LF)
 132:               {
 133:                 eof = true;
 134:               }
 135:           }
 136:       }
 137:     return c;
 138:   }
 139:   
 140:   /**
 141:    * Reads up to b.length bytes of data from this input stream into
 142:    * an array of bytes.
 143:    * Returns -1 if the end of the stream has been reached.
 144:    * @exception IOException if an I/O error occurs
 145:    */
 146:   public int read(byte[] b)
 147:     throws IOException
 148:   {
 149:     return read(b, 0, b.length);
 150:   }
 151: 
 152:   /**
 153:    * Reads up to len bytes of data from this input stream into an
 154:    * array of bytes, starting at the specified offset.
 155:    * Returns -1 if the end of the stream has been reached.
 156:    * @exception IOException if an I/O error occurs
 157:    */
 158:   public int read(byte[] b, int off, int len)
 159:     throws IOException
 160:   {
 161:     if (eof)
 162:       {
 163:         return -1;
 164:       }
 165:     int c, end = off + len;
 166:     for (int i = off; i < end; i++)
 167:       {
 168:         c = read();
 169:         if (c == -1)
 170:           {
 171:             len = i - off;
 172:             break;
 173:           }
 174:         else
 175:           {
 176:             b[i] = (byte) c;
 177:           }
 178:       }
 179:     return len;
 180:   }
 181:   
 182:   public boolean markSupported()
 183:   {
 184:     return in.markSupported();
 185:   }
 186: 
 187:   public void mark(int readlimit)
 188:   {
 189:     in.mark(readlimit);
 190:     markBuf1 = buf1;
 191:     markBuf2 = buf2;
 192:   }
 193: 
 194:   public void reset()
 195:     throws IOException
 196:   {
 197:     in.reset();
 198:     buf1 = markBuf1;
 199:     buf2 = markBuf2;
 200:   }
 201: 
 202: }