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