Source Code Cross Referenced for MimeMessageWrapper.java in  » Web-Mail » james-2.3.1 » org » apache » james » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Mail » james 2.3.1 » org.apache.james.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.activity.Disposable;
021:        import org.apache.avalon.framework.container.ContainerUtil;
022:        import org.apache.james.util.InternetPrintWriter;
023:        import org.apache.james.util.io.IOUtil;
024:
025:        import javax.activation.DataHandler;
026:        import javax.mail.MessagingException;
027:        import javax.mail.Session;
028:        import javax.mail.internet.InternetHeaders;
029:        import javax.mail.internet.MimeMessage;
030:        import javax.mail.util.SharedByteArrayInputStream;
031:
032:        import java.io.BufferedWriter;
033:        import java.io.ByteArrayOutputStream;
034:        import java.io.IOException;
035:        import java.io.InputStream;
036:        import java.io.InputStreamReader;
037:        import java.io.LineNumberReader;
038:        import java.io.OutputStream;
039:        import java.io.OutputStreamWriter;
040:        import java.io.PrintWriter;
041:        import java.util.Enumeration;
042:
043:        /**
044:         * This object wraps a MimeMessage, only loading the underlying MimeMessage
045:         * object when needed.  Also tracks if changes were made to reduce
046:         * unnecessary saves.
047:         */
048:        public class MimeMessageWrapper extends MimeMessage implements 
049:                Disposable {
050:
051:            /**
052:             * Can provide an input stream to the data
053:             */
054:            protected MimeMessageSource source = null;
055:
056:            /**
057:             * This is false until we parse the message 
058:             */
059:            protected boolean messageParsed = false;
060:
061:            /**
062:             * This is false until we parse the message 
063:             */
064:            protected boolean headersModified = false;
065:
066:            /**
067:             * This is false until we parse the message 
068:             */
069:            protected boolean bodyModified = false;
070:
071:            /**
072:             * Keep a reference to the sourceIn so we can close it
073:             * only when we dispose the message.
074:             */
075:            private InputStream sourceIn;
076:
077:            private MimeMessageWrapper(Session session)
078:                    throws MessagingException {
079:                super (session);
080:                this .headers = null;
081:                this .modified = false;
082:                this .headersModified = false;
083:                this .bodyModified = false;
084:            }
085:
086:            /**
087:             * A constructor that instantiates a MimeMessageWrapper based on
088:             * a MimeMessageSource
089:             *
090:             * @param source the MimeMessageSource
091:             * @throws MessagingException 
092:             */
093:            public MimeMessageWrapper(Session session, MimeMessageSource source)
094:                    throws MessagingException {
095:                this (session);
096:                this .source = source;
097:            }
098:
099:            /**
100:             * A constructor that instantiates a MimeMessageWrapper based on
101:             * a MimeMessageSource
102:             *
103:             * @param source the MimeMessageSource
104:             * @throws MessagingException 
105:             * @throws MessagingException 
106:             */
107:            public MimeMessageWrapper(MimeMessageSource source)
108:                    throws MessagingException {
109:                this (Session.getDefaultInstance(System.getProperties()), source);
110:            }
111:
112:            public MimeMessageWrapper(MimeMessage original)
113:                    throws MessagingException {
114:                this (Session.getDefaultInstance(System.getProperties()));
115:                flags = original.getFlags();
116:
117:                // if the original is an unmodified MimeMessageWrapped we clone the headers and
118:                // take its source.
119:                /* Temporary commented out because of JAMES-474
120:                if (original instanceof MimeMessageWrapper && !((MimeMessageWrapper) original).bodyModified) {
121:                    source = ((MimeMessageWrapper) original).source;
122:                    // this probably speed up things
123:                    if (((MimeMessageWrapper) original).headers != null) {
124:                        ByteArrayOutputStream temp = new ByteArrayOutputStream();
125:                        InternetHeaders ih = ((MimeMessageWrapper) original).headers;
126:                        MimeMessageUtil.writeHeadersTo(ih.getAllHeaderLines(),temp);
127:                        headers = createInternetHeaders(new ByteArrayInputStream(temp.toByteArray()));
128:                        headersModified = ((MimeMessageWrapper) original).headersModified;
129:                    }
130:                }
131:                 */
132:
133:                if (source == null) {
134:                    ByteArrayOutputStream bos;
135:                    int size = original.getSize();
136:                    if (size > 0)
137:                        bos = new ByteArrayOutputStream(size);
138:                    else
139:                        bos = new ByteArrayOutputStream();
140:                    try {
141:                        original.writeTo(bos);
142:                        bos.close();
143:                        SharedByteArrayInputStream bis = new SharedByteArrayInputStream(
144:                                bos.toByteArray());
145:                        parse(bis);
146:                        bis.close();
147:                        saved = true;
148:                    } catch (IOException ex) {
149:                        // should never happen, but just in case...
150:                        throw new MessagingException(
151:                                "IOException while copying message", ex);
152:                    }
153:                }
154:            }
155:
156:            /**
157:             * Returns the source ID of the MimeMessageSource that is supplying this
158:             * with data.
159:             * @see MimeMessageSource
160:             */
161:            public synchronized String getSourceId() {
162:                return source != null ? source.getSourceId() : null;
163:            }
164:
165:            /**
166:             * Load the message headers from the internal source.
167:             *
168:             * @throws MessagingException if an error is encountered while
169:             *                            loading the headers
170:             */
171:            protected synchronized void loadHeaders() throws MessagingException {
172:                if (headers != null) {
173:                    //Another thread has already loaded these headers
174:                    return;
175:                } else if (source != null) {
176:                    try {
177:                        InputStream in = source.getInputStream();
178:                        try {
179:                            headers = createInternetHeaders(in);
180:                        } finally {
181:                            IOUtil.shutdownStream(in);
182:                        }
183:                    } catch (IOException ioe) {
184:                        throw new MessagingException(
185:                                "Unable to parse headers from stream: "
186:                                        + ioe.getMessage(), ioe);
187:                    }
188:                } else {
189:                    throw new MessagingException(
190:                            "loadHeaders called for a message with no source, contentStream or stream");
191:                }
192:            }
193:
194:            /**
195:             * Load the complete MimeMessage from the internal source.
196:             *
197:             * @throws MessagingException if an error is encountered while
198:             *                            loading the message
199:             */
200:            protected synchronized void loadMessage() throws MessagingException {
201:                if (messageParsed) {
202:                    //Another thread has already loaded this message
203:                    return;
204:                } else if (source != null) {
205:                    sourceIn = null;
206:                    try {
207:                        sourceIn = source.getInputStream();
208:
209:                        parse(sourceIn);
210:                        // TODO is it ok?
211:                        saved = true;
212:
213:                    } catch (IOException ioe) {
214:                        IOUtil.shutdownStream(sourceIn);
215:                        sourceIn = null;
216:                        throw new MessagingException("Unable to parse stream: "
217:                                + ioe.getMessage(), ioe);
218:                    }
219:                } else {
220:                    throw new MessagingException(
221:                            "loadHeaders called for an unparsed message with no source");
222:                }
223:            }
224:
225:            /**
226:             * Get whether the message has been modified.
227:             *
228:             * @return whether the message has been modified
229:             */
230:            public synchronized boolean isModified() {
231:                return headersModified || bodyModified || modified;
232:            }
233:
234:            /**
235:             * Rewritten for optimization purposes
236:             */
237:            public synchronized void writeTo(OutputStream os)
238:                    throws IOException, MessagingException {
239:                if (source != null && !isModified()) {
240:                    // We do not want to instantiate the message... just read from source
241:                    // and write to this outputstream
242:                    InputStream in = source.getInputStream();
243:                    try {
244:                        MimeMessageUtil.copyStream(in, os);
245:                    } finally {
246:                        IOUtil.shutdownStream(in);
247:                    }
248:                } else {
249:                    writeTo(os, os);
250:                }
251:            }
252:
253:            /**
254:             * Rewritten for optimization purposes
255:             */
256:            public void writeTo(OutputStream os, String[] ignoreList)
257:                    throws IOException, MessagingException {
258:                writeTo(os, os, ignoreList);
259:            }
260:
261:            /**
262:             * Write
263:             */
264:            public void writeTo(OutputStream headerOs, OutputStream bodyOs)
265:                    throws IOException, MessagingException {
266:                writeTo(headerOs, bodyOs, new String[0]);
267:            }
268:
269:            public synchronized void writeTo(OutputStream headerOs,
270:                    OutputStream bodyOs, String[] ignoreList)
271:                    throws IOException, MessagingException {
272:                if (source != null && !isModified()) {
273:                    //We do not want to instantiate the message... just read from source
274:                    //  and write to this outputstream
275:
276:                    //First handle the headers
277:                    InputStream in = source.getInputStream();
278:                    try {
279:                        InternetHeaders headers = new InternetHeaders(in);
280:                        PrintWriter pos = new InternetPrintWriter(
281:                                new BufferedWriter(new OutputStreamWriter(
282:                                        headerOs), 512), true);
283:                        for (Enumeration e = headers
284:                                .getNonMatchingHeaderLines(ignoreList); e
285:                                .hasMoreElements();) {
286:                            String header = (String) e.nextElement();
287:                            pos.println(header);
288:                        }
289:                        pos.println();
290:                        pos.flush();
291:                        MimeMessageUtil.copyStream(in, bodyOs);
292:                    } finally {
293:                        IOUtil.shutdownStream(in);
294:                    }
295:                } else {
296:                    MimeMessageUtil.writeToInternal(this , headerOs, bodyOs,
297:                            ignoreList);
298:                }
299:            }
300:
301:            /**
302:             * This is the MimeMessage implementation - this should return ONLY the
303:             * body, not the entire message (should not count headers).  Will have
304:             * to parse the message.
305:             */
306:            public int getSize() throws MessagingException {
307:                if (!messageParsed) {
308:                    loadMessage();
309:                }
310:                return super .getSize();
311:            }
312:
313:            /**
314:             * Corrects JavaMail 1.1 version which always returns -1.
315:             * Only corrected for content less than 5000 bytes,
316:             * to avoid memory hogging.
317:             */
318:            public int getLineCount() throws MessagingException {
319:                InputStream in = null;
320:                try {
321:                    in = getContentStream();
322:                } catch (Exception e) {
323:                    return -1;
324:                }
325:                if (in == null) {
326:                    return -1;
327:                }
328:                //Wrap input stream in LineNumberReader
329:                //Not sure what encoding to use really...
330:                try {
331:                    LineNumberReader counter;
332:                    if (getEncoding() != null) {
333:                        counter = new LineNumberReader(new InputStreamReader(
334:                                in, getEncoding()));
335:                    } else {
336:                        counter = new LineNumberReader(
337:                                new InputStreamReader(in));
338:                    }
339:                    //Read through all the data
340:                    char[] block = new char[4096];
341:                    while (counter.read(block) > -1) {
342:                        //Just keep reading
343:                    }
344:                    return counter.getLineNumber();
345:                } catch (IOException ioe) {
346:                    return -1;
347:                } finally {
348:                    IOUtil.shutdownStream(in);
349:                }
350:            }
351:
352:            /**
353:             * Returns size of message, ie headers and content
354:             */
355:            public long getMessageSize() throws MessagingException {
356:                if (source != null && !isModified()) {
357:                    try {
358:                        return source.getMessageSize();
359:                    } catch (IOException ioe) {
360:                        throw new MessagingException(
361:                                "Error retrieving message size", ioe);
362:                    }
363:                } else {
364:                    return MimeMessageUtil.calculateMessageSize(this );
365:                }
366:            }
367:
368:            /**
369:             * We override all the "headers" access methods to be sure that we
370:             * loaded the headers 
371:             */
372:
373:            public String[] getHeader(String name) throws MessagingException {
374:                if (headers == null) {
375:                    loadHeaders();
376:                }
377:                return headers.getHeader(name);
378:            }
379:
380:            public String getHeader(String name, String delimiter)
381:                    throws MessagingException {
382:                if (headers == null) {
383:                    loadHeaders();
384:                }
385:                return headers.getHeader(name, delimiter);
386:            }
387:
388:            public Enumeration getAllHeaders() throws MessagingException {
389:                if (headers == null) {
390:                    loadHeaders();
391:                }
392:                return headers.getAllHeaders();
393:            }
394:
395:            public Enumeration getMatchingHeaders(String[] names)
396:                    throws MessagingException {
397:                if (headers == null) {
398:                    loadHeaders();
399:                }
400:                return headers.getMatchingHeaders(names);
401:            }
402:
403:            public Enumeration getNonMatchingHeaders(String[] names)
404:                    throws MessagingException {
405:                if (headers == null) {
406:                    loadHeaders();
407:                }
408:                return headers.getNonMatchingHeaders(names);
409:            }
410:
411:            public Enumeration getAllHeaderLines() throws MessagingException {
412:                if (headers == null) {
413:                    loadHeaders();
414:                }
415:                return headers.getAllHeaderLines();
416:            }
417:
418:            public Enumeration getMatchingHeaderLines(String[] names)
419:                    throws MessagingException {
420:                if (headers == null) {
421:                    loadHeaders();
422:                }
423:                return headers.getMatchingHeaderLines(names);
424:            }
425:
426:            public Enumeration getNonMatchingHeaderLines(String[] names)
427:                    throws MessagingException {
428:                if (headers == null) {
429:                    loadHeaders();
430:                }
431:                return headers.getNonMatchingHeaderLines(names);
432:            }
433:
434:            private synchronized void checkModifyHeaders()
435:                    throws MessagingException {
436:                // Disable only-header loading optimizations for JAMES-559
437:                if (!messageParsed) {
438:                    loadMessage();
439:                }
440:                // End JAMES-559
441:                if (headers == null) {
442:                    loadHeaders();
443:                }
444:                modified = true;
445:                saved = false;
446:                headersModified = true;
447:            }
448:
449:            public void setHeader(String name, String value)
450:                    throws MessagingException {
451:                checkModifyHeaders();
452:                super .setHeader(name, value);
453:            }
454:
455:            public void addHeader(String name, String value)
456:                    throws MessagingException {
457:                checkModifyHeaders();
458:                super .addHeader(name, value);
459:            }
460:
461:            public void removeHeader(String name) throws MessagingException {
462:                checkModifyHeaders();
463:                super .removeHeader(name);
464:            }
465:
466:            public void addHeaderLine(String line) throws MessagingException {
467:                checkModifyHeaders();
468:                super .addHeaderLine(line);
469:            }
470:
471:            /**
472:             * The message is changed when working with headers and when altering the content.
473:             * Every method that alter the content will fallback to this one.
474:             * 
475:             * @see javax.mail.Part#setDataHandler(javax.activation.DataHandler)
476:             */
477:            public synchronized void setDataHandler(DataHandler arg0)
478:                    throws MessagingException {
479:                modified = true;
480:                saved = false;
481:                bodyModified = true;
482:                super .setDataHandler(arg0);
483:            }
484:
485:            /**
486:             * @see org.apache.avalon.framework.activity.Disposable#dispose()
487:             */
488:            public void dispose() {
489:                if (sourceIn != null) {
490:                    IOUtil.shutdownStream(sourceIn);
491:                }
492:                if (source != null) {
493:                    ContainerUtil.dispose(source);
494:                }
495:            }
496:
497:            /**
498:             * @see javax.mail.internet.MimeMessage#parse(java.io.InputStream)
499:             */
500:            protected synchronized void parse(InputStream is)
501:                    throws MessagingException {
502:                // the super implementation calls
503:                // headers = createInternetHeaders(is);
504:                super .parse(is);
505:                messageParsed = true;
506:            }
507:
508:            /**
509:             * If we already parsed the headers then we simply return the updated ones.
510:             * Otherwise we parse
511:             * 
512:             * @see javax.mail.internet.MimeMessage#createInternetHeaders(java.io.InputStream)
513:             */
514:            protected synchronized InternetHeaders createInternetHeaders(
515:                    InputStream is) throws MessagingException {
516:                /* This code is no more needed: see JAMES-570 and new tests
517:                   
518:                 * InternetHeaders can be a bit awkward to work with due to
519:                 * its own internal handling of header order.  This hack may
520:                 * not always be necessary, but for now we are trying to
521:                 * ensure that there is a Return-Path header, even if just a
522:                 * placeholder, so that later, e.g., in LocalDelivery, when we
523:                 * call setHeader, it will remove any other Return-Path
524:                 * headers, and ensure that ours is on the top. addHeader
525:                 * handles header order, but not setHeader. This may change in
526:                 * future JavaMail.  But if there are other Return-Path header
527:                 * values, let's drop our placeholder.
528:
529:                MailHeaders newHeaders = new MailHeaders(new ByteArrayInputStream((RFC2822Headers.RETURN_PATH + ": placeholder").getBytes()));
530:                newHeaders.setHeader(RFC2822Headers.RETURN_PATH, null);
531:                newHeaders.load(is);
532:                String[] returnPathHeaders = newHeaders.getHeader(RFC2822Headers.RETURN_PATH);
533:                if (returnPathHeaders.length > 1) newHeaders.setHeader(RFC2822Headers.RETURN_PATH, returnPathHeaders[1]);
534:                 */
535:
536:                // Keep this: skip the headers from the stream
537:                // we could put that code in the else and simple write an "header" skipping
538:                // reader for the others.
539:                MailHeaders newHeaders = new MailHeaders(is);
540:
541:                if (headers != null) {
542:                    return headers;
543:                } else {
544:                    return newHeaders;
545:                }
546:            }
547:
548:            /**
549:             * @see javax.mail.internet.MimeMessage#getContentStream()
550:             */
551:            protected InputStream getContentStream() throws MessagingException {
552:                if (!messageParsed) {
553:                    loadMessage();
554:                }
555:                return super .getContentStream();
556:            }
557:
558:            /**
559:             * @see javax.mail.internet.MimeMessage#getRawInputStream()
560:             */
561:            public InputStream getRawInputStream() throws MessagingException {
562:                if (!messageParsed && !isModified() && source != null) {
563:                    InputStream is;
564:                    try {
565:                        is = source.getInputStream();
566:                        // skip the headers.
567:                        new MailHeaders(is);
568:                        return is;
569:                    } catch (IOException e) {
570:                        throw new MessagingException(
571:                                "Unable to read the stream: " + e.getMessage(),
572:                                e);
573:                    }
574:                } else
575:                    return super.getRawInputStream();
576:            }
577:
578:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.