001: /****************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one *
003: * or more contributor license agreements. See the NOTICE file *
004: * distributed with this work for additional information *
005: * regarding copyright ownership. The ASF licenses this file *
006: * to you under the Apache License, Version 2.0 (the *
007: * "License"); you may not use this file except in compliance *
008: * with the License. You may obtain a copy of the License at *
009: * *
010: * http://www.apache.org/licenses/LICENSE-2.0 *
011: * *
012: * Unless required by applicable law or agreed to in writing, *
013: * software distributed under the License is distributed on an *
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015: * KIND, either express or implied. See the License for the *
016: * specific language governing permissions and limitations *
017: * under the License. *
018: ****************************************************************/package org.apache.james.nntpserver.repository;
019:
020: import org.apache.james.core.MailHeaders;
021: import org.apache.james.nntpserver.NNTPException;
022: import org.apache.james.util.io.IOUtil;
023:
024: import javax.mail.internet.InternetHeaders;
025: import java.io.BufferedReader;
026: import java.io.File;
027: import java.io.FileInputStream;
028: import java.io.FileReader;
029: import java.io.IOException;
030: import java.io.OutputStream;
031:
032: /**
033: * Please see NNTPArticle for comments
034: */
035: class NNTPArticleImpl implements NNTPArticle {
036:
037: /**
038: * The file that stores the article data
039: */
040: private final File articleFile;
041:
042: /**
043: * The newsgroup containing this article.
044: */
045: private final NNTPGroup group;
046:
047: /**
048: * The sole constructor for this class.
049: *
050: * @param group the news group containing this article
051: * @param f the file that stores the article data
052: */
053: NNTPArticleImpl(NNTPGroup group, File f) {
054: articleFile = f;
055: this .group = group;
056: }
057:
058: /**
059: * @see org.apache.james.nntpserver.repository.NNTPArticle#getGroup()
060: */
061: public NNTPGroup getGroup() {
062: return group;
063: }
064:
065: /**
066: * @see org.apache.james.nntpserver.repository.NNTPArticle#getArticleNumber()
067: */
068: public int getArticleNumber() {
069: return Integer.parseInt(articleFile.getName());
070: }
071:
072: /**
073: * @see org.apache.james.nntpserver.repository.NNTPArticle#getUniqueID()
074: */
075: public String getUniqueID() {
076: FileInputStream fin = null;
077: try {
078: fin = new FileInputStream(articleFile);
079: InternetHeaders headers = new InternetHeaders(fin);
080: String[] idheader = headers.getHeader("Message-Id");
081: fin.close();
082: return (idheader.length > 0) ? idheader[0] : null;
083: } catch (Exception ex) {
084: throw new NNTPException(ex);
085: } finally {
086: IOUtil.shutdownStream(fin);
087: }
088: }
089:
090: /**
091: * @see org.apache.james.nntpserver.repository.NNTPArticle#writeArticle(OutputStream)
092: */
093: public void writeArticle(OutputStream out) {
094: FileInputStream fileStream = null;
095: try {
096: fileStream = new FileInputStream(articleFile);
097: byte[] readBuffer = new byte[1024];
098: int read = 0;
099: 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(
187: fileStream.getFD()));
188: int lines = 0;
189: while (rdr.readLine() != null) {
190: lines++;
191: }
192:
193: lineCount = Integer.toString(lines);
194: rdr.close();
195: }
196:
197: StringBuffer line = new StringBuffer(256).append(
198: getArticleNumber()).append("\t").append(
199: cleanHeader(subject)).append("\t").append(
200: cleanHeader(author)).append("\t").append(
201: cleanHeader(date)).append("\t").append(
202: cleanHeader(msgId)).append("\t").append(
203: cleanHeader(references)).append("\t").append(
204: byteCount).append("\t").append(lineCount).append(
205: "\r\n");
206: String lineString = line.toString();
207: out.write(lineString.getBytes("ASCII"));
208: } catch (Exception ex) {
209: throw new NNTPException(ex);
210: } finally {
211: if (fileStream != null) {
212: try {
213: fileStream.close();
214: } catch (IOException ioe) {
215: // Ignored
216: }
217: }
218: }
219: }
220:
221: /**
222: * @see org.apache.james.nntpserver.repository.NNTPArticle#getHeader(String)
223: */
224: public String getHeader(String header) {
225: try {
226: FileInputStream fin = new FileInputStream(articleFile);
227: InternetHeaders hdr = new InternetHeaders(fin);
228: fin.close();
229: return hdr.getHeader(header, null);
230: } catch (Exception ex) {
231: throw new NNTPException(ex);
232: }
233: }
234:
235: /**
236: * Strips out newlines and tabs, converting them to spaces.
237: * rfc2980: 2.8 XOVER requires newline and tab to be converted to spaces
238: *
239: * @param the input String
240: *
241: * @return the cleaned string
242: */
243: private String cleanHeader(String field) {
244: if (field == null)
245: field = "";
246: StringBuffer sb = new StringBuffer(field);
247: for (int i = 0; i < sb.length(); i++) {
248: char c = sb.charAt(i);
249: if ((c == '\n') || (c == '\t') || (c == '\r')) {
250: sb.setCharAt(i, ' ');
251: }
252: }
253: return sb.toString();
254: }
255: }
|