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