View Javadoc

1   /**
2    *
3    * Copyright 2003-2005 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You 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 implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.geronimo.javamail.store.pop3.message;
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.Enumeration;
25  
26  import javax.mail.Flags;
27  import javax.mail.Folder;
28  import javax.mail.IllegalWriteException;
29  import javax.mail.MessagingException;
30  import javax.mail.Session;
31  import javax.mail.event.MessageChangedEvent;
32  import javax.mail.internet.InternetHeaders;
33  import javax.mail.internet.MimeMessage;
34  
35  import org.apache.geronimo.javamail.store.pop3.POP3CommandFactory;
36  import org.apache.geronimo.javamail.store.pop3.POP3Connection;
37  import org.apache.geronimo.javamail.store.pop3.POP3Folder;
38  import org.apache.geronimo.javamail.store.pop3.POP3Response;
39  import org.apache.geronimo.javamail.store.pop3.response.POP3ListResponse;
40  import org.apache.geronimo.javamail.store.pop3.response.POP3ResponseFactory;
41  
42  /**
43   * POP3 implementation of javax.mail.internet.MimeMessage
44   * 
45   * Only the most basic information is given and Message objects created here is
46   * a light-weight reference to the actual Message As per the JavaMail spec items
47   * from the actual message will get filled up on demand
48   * 
49   * If some other items are obtained from the server as a result of one call,
50   * then the other details are also processed and filled in. For ex if RETR is
51   * called then header information will also be processed in addition to the
52   * content
53   * 
54   * @version $Rev: 432884 $ $Date: 2006-08-19 14:53:20 -0700 (Sat, 19 Aug 2006) $
55   */
56  public class POP3Message extends MimeMessage {
57  
58      private POP3Connection pop3Con;
59  
60      private int msgSize = -1;
61  
62      private int headerSize = -1;
63  
64      // We can't use header bcos it's already initialize to
65      // to an empty InternetHeader
66      private InputStream rawHeaders;
67  
68      // used to force loading of headers again
69      private boolean loadHeaders = true;
70  
71      // to get accessed to the debug setting and log
72      private Session session;
73  
74      protected POP3Message(Folder folder, int msgnum, Session session, POP3Connection pop3Con) {
75          super(folder, msgnum);
76          this.pop3Con = pop3Con;
77          this.session = session;
78      }
79  
80      /**
81       * @see javax.mail.internet.MimeMessage#getContentStream()
82       */
83      protected InputStream getContentStream() throws MessagingException {
84          POP3Response msgResponse = null;
85          try {
86              msgResponse = pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_RETR(msgnum));
87          } catch (Exception e) {
88              e.printStackTrace();
89          }
90          loadHeaders = true;
91          loadHeaders(msgResponse.getData());
92          loadContent(msgResponse.getData());
93  
94          return contentStream;
95      }
96  
97      public void setFlags(Flags newFlags, boolean set) throws MessagingException {
98          Flags oldFlags = (Flags) flags.clone();
99          super.setFlags(newFlags, set);
100 
101         if (!flags.equals(oldFlags)) {
102             ((POP3Folder) folder).notifyMessageChangedListeners(MessageChangedEvent.FLAGS_CHANGED, this);
103         }
104     }
105 
106     protected void loadHeaders(InputStream in) throws MessagingException {
107         if (loadHeaders || rawHeaders == null) {
108             rawHeaders = in;
109             headers = new InternetHeaders(rawHeaders);
110             loadHeaders = false;
111         }
112     }
113 
114     protected void loadContent(InputStream stream) throws MessagingException {
115         ByteArrayOutputStream out = new ByteArrayOutputStream();
116         try {
117             int byteRead = stream.read();
118             int lastByte = -1;
119             for (; byteRead > 0;) {
120                 if (byteRead == ' ' && lastByte == '\n') {
121                     break;
122                 }
123                 lastByte = byteRead;
124                 byteRead = stream.read();
125             }
126 
127             for (; stream.available() > 0;) {
128                 out.write(stream.read());
129             }
130 
131             contentStream = new ByteArrayInputStream(out.toByteArray());
132             msgSize = contentStream.available();
133 
134         } catch (IOException e) {
135 
136             throw new MessagingException("Error loading content info", e);
137         }
138     }
139 
140     public int getSize() throws MessagingException {
141         if (msgSize >= 0) {
142             return msgSize;
143         }
144         try {
145 
146             if (msgSize < 0) {
147                 if (rawHeaders == null) {
148                     loadHeaders();
149                 }
150                 POP3ListResponse res = (POP3ListResponse) POP3ResponseFactory.getListResponse(pop3Con
151                         .sendCommand(POP3CommandFactory.getCOMMAND_LIST(msgnum)));
152                 msgSize = res.getSize() - headerSize;
153             }
154             return msgSize;
155         } catch (MessagingException ex) {
156             throw new MessagingException("error getting size", ex);
157         }
158     }
159 
160     /**
161      * notice that we pass zero as the no of lines from the message,as it
162      * doesn't serv any purpose to get only a certain number of lines.
163      * 
164      * However this maybe important if a mail client only shows 3 or 4 lines of
165      * the message in the list and then when the user clicks they would load the
166      * message on demand.
167      * 
168      */
169     protected void loadHeaders() throws MessagingException {
170         POP3Response msgResponse = null;
171         try {
172 
173             msgResponse = pop3Con.sendCommand(POP3CommandFactory.getCOMMAND_TOP(msgnum, 0));
174         } catch (Exception e) {
175             e.printStackTrace();
176         }
177         loadHeaders(msgResponse.getData());
178     }
179 
180     /***************************************************************************
181      * Following is a set of methods that deal with headers I have tried to use
182      * the bare minimum
183      * 
184      * Used sun's POP3 impl & JavaMail API as a guide in decided which methods
185      * are important.
186      **************************************************************************/
187 
188     public String[] getHeader(String name) throws MessagingException {
189         if (rawHeaders == null)
190             loadHeaders();
191         return headers.getHeader(name);
192     }
193 
194     public String getHeader(String name, String delimiter) throws MessagingException {
195         if (headers == null)
196             loadHeaders();
197         return headers.getHeader(name, delimiter);
198     }
199 
200     public Enumeration getAllHeaders() throws MessagingException {
201         if (headers == null)
202             loadHeaders();
203         return headers.getAllHeaders();
204     }
205 
206     public Enumeration getMatchingHeaders(String[] names) throws MessagingException {
207         if (headers == null)
208             loadHeaders();
209         return headers.getMatchingHeaders(names);
210     }
211 
212     public Enumeration getNonMatchingHeaders(String[] names) throws MessagingException {
213         if (headers == null)
214             loadHeaders();
215         return headers.getNonMatchingHeaders(names);
216     }
217 
218     public Enumeration getAllHeaderLines() throws MessagingException {
219         if (headers == null)
220             loadHeaders();
221         return headers.getAllHeaderLines();
222     }
223 
224     public Enumeration getMatchingHeaderLines(String[] names) throws MessagingException {
225         if (headers == null)
226             loadHeaders();
227         return headers.getMatchingHeaderLines(names);
228     }
229 
230     public Enumeration getNonMatchingHeaderLines(String[] names) throws MessagingException {
231         if (headers == null)
232             loadHeaders();
233         return headers.getNonMatchingHeaderLines(names);
234     }
235 
236     // the following are overrides for header modification methods. These
237     // messages are read only,
238     // so the headers cannot be modified.
239     public void addHeader(String name, String value) throws MessagingException {
240         throw new IllegalWriteException("POP3 messages are read-only");
241     }
242 
243     public void setHeader(String name, String value) throws MessagingException {
244         throw new IllegalWriteException("POP3 messages are read-only");
245     }
246 
247     public void removeHeader(String name) throws MessagingException {
248         throw new IllegalWriteException("POP3 messages are read-only");
249     }
250 
251     public void addHeaderLine(String line) throws MessagingException {
252         throw new IllegalWriteException("POP3 messages are read-only");
253     }
254 
255     /**
256      * We cannot modify these messages
257      */
258     public void saveChanges() throws MessagingException {
259         throw new IllegalWriteException("POP3 messages are read-only");
260     }
261 }