KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mail > providers > mbox > MboxOutputStream


1 /*
2  * MboxOutputStream.java
3  * Copyright (C) 1999 dog <dog@dog.net.uk>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * You also have permission to link it with the Sun Microsystems, Inc.
11  * JavaMail(tm) extension and run that combination.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  * You may retrieve the latest version of this library from
23  * http://www.dog.net.uk/knife/
24  *
25  * Contributor(s): nil
26  */

27
28 package gnu.mail.providers.mbox;
29
30 import java.io.*;
31
32 /**
33  * A filter stream that can escape mbox From_ lines in message content.
34  * This will only work reliably for messages with <1024 bytes in each line.
35  *
36  * @author dog@dog.net.uk
37  * @version 2.0
38  */

39 class MboxOutputStream
40   extends FilterOutputStream
41 {
42
43   private static byte KET = 62;
44
45   /**
46    * The buffer where the current line is stored.
47    */

48   protected byte buf[];
49
50   /**
51    * The number of valid bytes in the buffer.
52    */

53   protected int count = 0;
54
55   /**
56    * Constructs an mbox From_-escaping output stream with a buffer size of
57    * 1024 bytes.
58    */

59   public MboxOutputStream(OutputStream out)
60   {
61     this(out, 1024);
62   }
63
64   /**
65    * Constructs an mbox From_-escaping output stream with the specified
66    * buffer size.
67    * @param len the buffer size
68    */

69   public MboxOutputStream(OutputStream out, int len)
70   {
71     super(out);
72     buf = new byte[len];
73   }
74
75   /**
76    * Flush the internal buffer.
77    */

78   protected void validateAndFlushBuffer()
79     throws IOException
80   {
81     if (count > 0)
82     {
83       boolean done = false;
84       for (int i=0; i<count-5 && !done; i++)
85       {
86         if (buf[i]=='F' &&
87             buf[i+1]=='r' &&
88             buf[i+2]=='o' &&
89             buf[i+3]=='m' &&
90             buf[i+4]==' ')
91         {
92           byte[] b2 = new byte[buf.length+1];
93           System.arraycopy(buf, 0, b2, 0, buf.length);
94           b2[i] = KET;
95           System.arraycopy(buf, i, b2, i+1, buf.length-i);
96           buf = b2;
97           count++;
98           done = true;
99         }
100         else if (buf[i]!=KET && buf[i]!='\n')
101         {
102           done = true;
103         }
104       }
105       out.write(buf, 0, count);
106       count = 0;
107     }
108   }
109
110   /**
111    * Writes the specified byte to this output stream.
112    */

113   public synchronized void write(int b)
114     throws IOException
115   {
116     if (b=='\r')
117       return;
118     if (count>buf.length)
119       validateAndFlushBuffer();
120     buf[count++] = (byte)b;
121     if (b=='\n')
122       validateAndFlushBuffer();
123   }
124
125   /**
126    * Writes <code>len</code> bytes from the specified byte array
127    * starting at offset <code>off</code> to this output stream.
128    */

129   public synchronized void write(byte b[], int off, int len)
130     throws IOException
131   {
132     // strip any CRs in the byte array
133
for (int i=off; i<off+len; i++)
134     {
135       if (b[i]=='\r')
136       {
137         byte[] b2 = new byte[b.length-1];
138         System.arraycopy(b, off, b2, off, len-1);
139         System.arraycopy(b, i+1, b2, i, len-(i-off)-1);
140         b = b2;
141         len--;
142         i--;
143       }
144     }
145     // validate and flush a line at a time
146
for (int i=off; i<off+len; i++)
147     {
148       if (b[i]=='\n' || i-off>buf.length)
149       {
150         int cl = (i-off>buf.length) ? buf.length : i-off;
151         System.arraycopy(b, off, buf, count, cl);
152         count += cl;
153         validateAndFlushBuffer();
154         len = len-(i-off);
155         byte[] b2 = new byte[b.length];
156         System.arraycopy(b, i, b2, off, len);
157         b = b2;
158         i = off;
159       }
160     }
161     System.arraycopy(b, off, buf, count, len);
162     count += len;
163   }
164
165   /**
166    * Flushes this output stream.
167    */

168   public synchronized void flush()
169     throws IOException
170   {
171     validateAndFlushBuffer();
172     out.flush();
173   }
174   
175 }
176
Popular Tags