View Javadoc

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