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
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
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
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
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
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
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 }