View Javadoc

1   /************************************************************************
2    * Copyright (c) 2000-2006 The Apache Software Foundation.             *
3    * All rights reserved.                                                *
4    * ------------------------------------------------------------------- *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you *
6    * may not use this file except in compliance with the License. You    *
7    * may obtain a copy of 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,   *
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
14   * implied.  See the License for the specific language governing       *
15   * permissions and limitations under the License.                      *
16   ***********************************************************************/
17  
18  package org.apache.james.nntpserver.repository;
19  
20  import org.apache.james.core.MailHeaders;
21  import org.apache.james.nntpserver.NNTPException;
22  import org.apache.james.util.io.IOUtil;
23  
24  import javax.mail.internet.InternetHeaders;
25  import java.io.BufferedReader;
26  import java.io.File;
27  import java.io.FileInputStream;
28  import java.io.FileReader;
29  import java.io.IOException;
30  import java.io.OutputStream;
31  
32  /*** 
33   * Please see NNTPArticle for comments
34   */
35  class NNTPArticleImpl implements NNTPArticle {
36  
37      /***
38       * The file that stores the article data
39       */
40      private final File articleFile;
41  
42      /***
43       * The newsgroup containing this article.
44       */
45      private final NNTPGroup group;
46  
47      /***
48       * The sole constructor for this class.
49       *
50       * @param group the news group containing this article
51       * @param f the file that stores the article data
52       */
53      NNTPArticleImpl(NNTPGroup group, File f) {
54          articleFile = f;
55          this.group = group;
56      }
57  
58      /***
59       * @see org.apache.james.nntpserver.repository.NNTPArticle#getGroup()
60       */
61      public NNTPGroup getGroup() {
62          return group;
63      }
64  
65      /***
66       * @see org.apache.james.nntpserver.repository.NNTPArticle#getArticleNumber()
67       */
68      public int getArticleNumber() {
69          return Integer.parseInt(articleFile.getName());
70      }
71  
72      /***
73       * @see org.apache.james.nntpserver.repository.NNTPArticle#getUniqueID()
74       */
75      public String getUniqueID() {
76          FileInputStream fin = null;
77          try {
78              fin = new FileInputStream(articleFile);
79              InternetHeaders headers = new InternetHeaders(fin);
80              String[] idheader = headers.getHeader("Message-Id");
81              fin.close();
82              return ( idheader.length > 0 ) ? idheader[0] : null;
83          } catch(Exception ex) {
84              throw new NNTPException(ex);
85          } finally {
86              IOUtil.shutdownStream(fin);
87          }
88      }
89  
90      /***
91       * @see org.apache.james.nntpserver.repository.NNTPArticle#writeArticle(OutputStream)
92       */
93      public void writeArticle(OutputStream out) {
94          FileInputStream fileStream = null;
95          try {
96              fileStream = new FileInputStream(articleFile);
97              byte[] readBuffer = new byte[1024];
98              int read = 0;
99              while ((read = fileStream.read(readBuffer)) > 0) {
100                 out.write(readBuffer, 0, read);
101             }
102         } catch(IOException ex) { 
103             throw new NNTPException(ex);
104         } finally {
105             if (fileStream != null) {
106                 try {
107                     fileStream.close();
108                 } catch (IOException ioe) {
109                     // Ignored
110                 }
111             }
112         }
113     }
114 
115     /***
116      * @see org.apache.james.nntpserver.repository.NNTPArticle#writeHead(OutputStream)
117      */
118     public void writeHead(OutputStream out) {
119         FileInputStream fileStream = null;
120         try {
121             fileStream = new FileInputStream(articleFile);
122             MailHeaders headers = new MailHeaders(fileStream);
123             byte[] headerBuffer = headers.toByteArray();
124             int headerBufferLength = headerBuffer.length;
125             // Write the headers excluding the final CRLF pair
126             if (headerBufferLength > 2) {
127                 out.write(headerBuffer, 0, (headerBufferLength - 2));
128             }
129         } catch(Exception ex) { 
130             throw new NNTPException(ex);
131         } finally {
132             if (fileStream != null) {
133                 try {
134                     fileStream.close();
135                 } catch (IOException ioe) {
136                     // Ignored
137                 }
138             }
139         }
140     }
141 
142     /***
143      * @see org.apache.james.nntpserver.repository.NNTPArticle#writeBody(OutputStream)
144      */
145     public void writeBody(OutputStream out) {
146         FileInputStream fileStream = null;
147         try {
148             fileStream = new FileInputStream(articleFile);
149             MailHeaders headers = new MailHeaders(fileStream);
150             byte[] readBuffer = new byte[1024];
151             int read = 0;
152             while ((read = fileStream.read(readBuffer)) > 0) {
153                 out.write(readBuffer, 0, read);
154             }
155         } catch(Exception ex) {
156             throw new NNTPException(ex);
157         } finally {
158             if (fileStream != null) {
159                 try {
160                     fileStream.close();
161                 } catch (IOException ioe) {
162                     // Ignored
163                 }
164             }
165         }
166     }
167 
168     /***
169      * @see org.apache.james.nntpserver.repository.NNTPArticle#writeOverview(OutputStream)
170      */
171     public void writeOverview(OutputStream out) {
172         FileInputStream fileStream = null;
173         try {
174             fileStream = new FileInputStream(articleFile);
175             InternetHeaders hdr = new InternetHeaders(fileStream);
176             String subject = hdr.getHeader("Subject",null);
177             String author = hdr.getHeader("From",null);
178             String date = hdr.getHeader("Date",null);
179             String msgId = hdr.getHeader("Message-Id",null);
180             String references = hdr.getHeader("References",null);
181             long byteCount = articleFile.length();
182 
183             // get line count, if not set, count the lines
184             String lineCount = hdr.getHeader("Lines",null);
185             if (lineCount == null) {
186                 BufferedReader rdr = new BufferedReader(new FileReader(fileStream.getFD()));
187                 int lines = 0;
188                 while (rdr.readLine() != null) {
189                     lines++;
190                 }
191 
192                 lineCount = Integer.toString(lines);
193                 rdr.close();
194             }
195 
196             StringBuffer line=new StringBuffer(256)
197                 .append(getArticleNumber())    .append("\t")
198                 .append(cleanHeader(subject))    .append("\t")
199                 .append(cleanHeader(author))     .append("\t")
200                 .append(cleanHeader(date))       .append("\t")
201                 .append(cleanHeader(msgId))      .append("\t")
202                 .append(cleanHeader(references)) .append("\t")
203                 .append(byteCount)               .append("\t")
204                 .append(lineCount).append("\r\n");
205             String lineString = line.toString();
206             out.write(lineString.getBytes("ASCII"));
207         } catch(Exception ex) {
208             throw new NNTPException(ex);
209         } finally {
210             if (fileStream != null) {
211                 try {
212                     fileStream.close();
213                 } catch (IOException ioe) {
214                     // Ignored
215                 }
216             }
217         }
218     }
219 
220     /***
221      * @see org.apache.james.nntpserver.repository.NNTPArticle#getHeader(String)
222      */
223     public String getHeader(String header) {
224         try {
225             FileInputStream fin = new FileInputStream(articleFile);
226             InternetHeaders hdr = new InternetHeaders(fin);
227             fin.close();
228             return hdr.getHeader(header,null);
229         } catch(Exception ex) {
230             throw new NNTPException(ex);
231         }
232     }
233 
234     /***
235      * Strips out newlines and tabs, converting them to spaces.
236      * rfc2980: 2.8 XOVER requires newline and tab to be converted to spaces
237      *
238      * @param the input String
239      *
240      * @return the cleaned string
241      */
242     private String cleanHeader(String field) {
243         if ( field == null )
244             field = "";
245         StringBuffer sb = new StringBuffer(field);
246         for( int i=0 ; i<sb.length() ; i++ ) {
247             char c = sb.charAt(i);
248             if( (c=='\n') || (c=='\t') || (c=='\r')) {
249                 sb.setCharAt(i, ' ');
250             }
251         }
252         return sb.toString();
253     }
254 }