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.core;
019:
020: import org.apache.avalon.framework.container.ContainerUtil;
021: import org.apache.mailet.RFC2822Headers;
022:
023: import javax.mail.MessagingException;
024: import javax.mail.internet.MimeMessage;
025: import javax.mail.util.SharedByteArrayInputStream;
026:
027: import java.io.BufferedReader;
028: import java.io.ByteArrayOutputStream;
029: import java.io.IOException;
030: import java.io.InputStream;
031: import java.io.InputStreamReader;
032: import java.util.Enumeration;
033:
034: /**
035: * Test the subject folding issue.
036: */
037: public class MimeMessageWrapperTest extends MimeMessageFromStreamTest {
038:
039: private final class TestableMimeMessageWrapper extends
040: MimeMessageWrapper {
041:
042: boolean messageLoadable = true;
043: boolean headersLoadable = true;
044:
045: private TestableMimeMessageWrapper(MimeMessageSource source)
046: throws MessagingException {
047: super (source);
048: }
049:
050: public boolean messageParsed() {
051: return messageParsed;
052: }
053:
054: public MailHeaders getInnerHeaders() {
055: return (MailHeaders) headers;
056: }
057:
058: public boolean isHeadersLoadable() {
059: return headersLoadable;
060: }
061:
062: public void setHeadersLoadable(boolean headersLoadable) {
063: this .headersLoadable = headersLoadable;
064: }
065:
066: public boolean isMessageLoadable() {
067: return messageLoadable;
068: }
069:
070: public void setMessageLoadable(boolean messageLoadable) {
071: this .messageLoadable = messageLoadable;
072: }
073:
074: protected synchronized void loadHeaders()
075: throws MessagingException {
076: if (headersLoadable) {
077: super .loadHeaders();
078: } else {
079: throw new IllegalStateException(
080: "headersLoadable disabled");
081: }
082: }
083:
084: protected synchronized MailHeaders loadHeaders(InputStream is)
085: throws MessagingException {
086: if (headersLoadable) {
087: return (MailHeaders) super .createInternetHeaders(is);
088: } else {
089: throw new IllegalStateException(
090: "headersLoadable disabled");
091: }
092: }
093:
094: protected synchronized void loadMessage()
095: throws MessagingException {
096: if (messageLoadable) {
097: super .loadMessage();
098: } else {
099: throw new IllegalStateException(
100: "messageLoadable disabled");
101: }
102: }
103:
104: }
105:
106: TestableMimeMessageWrapper mw = null;
107: String content = "Subject: foo\r\nContent-Transfer-Encoding2: plain";
108: String sep = "\r\n\r\n";
109: String body = "bar\r\n";
110:
111: protected MimeMessage getMessageFromSources(String sources)
112: throws Exception {
113: MimeMessageInputStreamSource mmis = null;
114: try {
115: mmis = new MimeMessageInputStreamSource("test",
116: new SharedByteArrayInputStream(sources.getBytes()));
117: } catch (MessagingException e) {
118: }
119: return new TestableMimeMessageWrapper(mmis);
120: }
121:
122: protected void setUp() throws Exception {
123: mw = (TestableMimeMessageWrapper) getMessageFromSources(content
124: + sep + body);
125: }
126:
127: protected void tearDown() throws Exception {
128: ContainerUtil.dispose(mw);
129: }
130:
131: public void testDeferredMessageLoading() throws MessagingException,
132: IOException {
133: assertEquals("foo", mw.getSubject());
134: assertFalse(mw.messageParsed());
135: assertEquals("bar\r\n", mw.getContent());
136: assertTrue(mw.messageParsed());
137: assertFalse(mw.isModified());
138: }
139:
140: /** this is commented out due optimisation reverts (JAMES-559)
141: public void testDeferredMessageLoadingWhileWriting() throws MessagingException, IOException {
142: mw.setMessageLoadable(false);
143: assertEquals("foo",mw.getSubject());
144: assertFalse(mw.isModified());
145: mw.setSubject("newSubject");
146: assertEquals("newSubject",mw.getSubject());
147: assertFalse(mw.messageParsed());
148: assertTrue(mw.isModified());
149: mw.setMessageLoadable(true);
150: }
151: */
152:
153: public void testDeferredHeaderLoading() throws MessagingException,
154: IOException {
155: mw.setHeadersLoadable(false);
156: try {
157: assertEquals("foo", mw.getSubject());
158: fail("subject should not be loadable here, headers loading is disabled");
159: } catch (IllegalStateException e) {
160:
161: }
162: }
163:
164: /**
165: * See JAMES-474
166: * MimeMessageWrapper(MimeMessage) should clone the original message.
167: */
168: public void testMessageCloned() throws MessagingException,
169: IOException, InterruptedException {
170: MimeMessageWrapper mmw = new MimeMessageWrapper(mw);
171: ContainerUtil.dispose(mw);
172: mw = null;
173: System.gc();
174: Thread.sleep(200);
175: mmw.writeTo(System.out);
176: }
177:
178: /*
179: * Class under test for String getSubject()
180: */
181: public void testGetSubjectFolding() {
182: try {
183: StringBuffer res = new StringBuffer();
184: BufferedReader r = new BufferedReader(
185: new InputStreamReader(mw.getInputStream()));
186: String line;
187: while (r.ready()) {
188: line = r.readLine();
189: res.append(line + "\r\n");
190: }
191: r.close();
192: assertEquals(body, res.toString());
193: } catch (MessagingException e) {
194: // TODO Auto-generated catch block
195: e.printStackTrace();
196: } catch (IOException e) {
197: // TODO Auto-generated catch block
198: e.printStackTrace();
199: }
200: }
201:
202: /*
203: * Class under test for String getSubject()
204: */
205: public void testAddHeaderAndSave() {
206: try {
207: mw.addHeader("X-Test", "X-Value");
208:
209: assertEquals("X-Value", mw.getHeader("X-Test")[0]);
210:
211: mw.saveChanges();
212:
213: ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
214: mw.writeTo(rawMessage);
215:
216: assertEquals("X-Value", mw.getHeader("X-Test")[0]);
217:
218: String res = rawMessage.toString();
219:
220: boolean found = res.indexOf("X-Test: X-Value") > 0;
221: assertEquals(true, found);
222:
223: } catch (MessagingException e) {
224: // TODO Auto-generated catch block
225: e.printStackTrace();
226: } catch (IOException e) {
227: // TODO Auto-generated catch block
228: e.printStackTrace();
229: }
230: }
231:
232: public void testReplaceReturnPathOnBadMessage() throws Exception {
233: MimeMessage message = getMessageWithBadReturnPath();
234: message.setHeader(RFC2822Headers.RETURN_PATH, "<test@test.de>");
235: Enumeration e = message
236: .getMatchingHeaderLines(new String[] { "Return-Path" });
237: assertEquals("Return-Path: <test@test.de>", e.nextElement());
238: assertFalse(e.hasMoreElements());
239: Enumeration h = message.getAllHeaderLines();
240: assertEquals("Return-Path: <test@test.de>", h.nextElement());
241: assertFalse(h.nextElement().toString().startsWith(
242: "Return-Path:"));
243: }
244:
245: public void testAddReturnPathOnBadMessage() throws Exception {
246: MimeMessage message = getMessageWithBadReturnPath();
247: message.addHeader(RFC2822Headers.RETURN_PATH, "<test@test.de>");
248: // test that we have now 2 return-paths
249: Enumeration e = message
250: .getMatchingHeaderLines(new String[] { "Return-Path" });
251: assertEquals("Return-Path: <test@test.de>", e.nextElement());
252: assertEquals("Return-Path: <mybadreturn@example.com>", e
253: .nextElement());
254: // test that return-path is the first line
255: Enumeration h = message.getAllHeaderLines();
256: assertEquals("Return-Path: <test@test.de>", h.nextElement());
257: }
258:
259: }
|