001    /*
002     * Copyright 2010 the original author or authors.
003     * 
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package com.hs.mail.imap.message.responder;
017    
018    import java.util.Date;
019    
020    import javax.mail.Flags;
021    
022    import org.apache.commons.lang.ArrayUtils;
023    import org.jboss.netty.channel.Channel;
024    
025    import com.hs.mail.imap.message.request.ImapRequest;
026    import com.hs.mail.imap.message.response.FetchResponse;
027    import com.hs.mail.imap.processor.fetch.Address;
028    import com.hs.mail.imap.processor.fetch.Content;
029    import com.hs.mail.imap.processor.fetch.Envelope;
030    import com.hs.mail.imap.processor.fetch.MimeDescriptor;
031    
032    /**
033     * 
034     * @author Won Chul Doh
035     * @since Mar 8, 2010
036     *
037     */
038    public class FetchResponder extends DefaultImapResponder {
039            
040            public FetchResponder(Channel channel, ImapRequest request) {
041                    super(channel, request);
042            }
043    
044            public void respond(FetchResponse response) {
045                    untagged(response.getMessageNumber() + " " + request.getCommand());
046                    openParen("(");
047                    composeFlags(response);
048                    composeInternalDate(response);
049                    composeSize(response);
050                    composeEnvelope(response);
051                    composeBody(response);
052                    composeBodyStructure(response);
053                    composeUid(response);
054                    composeBodyContent(response);
055                    closeParen(")");
056                    end();
057            }
058    
059            void composeFlags(FetchResponse response) {
060                    Flags flags = response.getFlags();
061                    if (flags != null) {
062                            message("FLAGS");
063                            openParen("(");
064                            flags(flags);
065                            closeParen(")");
066                    }
067            }
068            
069            void composeInternalDate(FetchResponse response) {
070                    Date internalDate = response.getInternalDate();
071                    if (internalDate != null) {
072                            message("INTERNALDATE");
073                            quote(encodeDateTime(internalDate));
074                    }
075            }
076            
077            void composeSize(FetchResponse response) {
078                    Long size = response.getSize();
079                    if (size != null) {
080                            message("RFC822.SIZE");
081                            message(size.toString());
082                    }
083            }
084            
085            void composeUid(FetchResponse response) {
086                    Long uid = response.getUid();
087                    if (uid != null) {
088                            message("UID");
089                            message(uid.toString());
090                    }
091            }
092            
093            void composeEnvelope(Envelope envelope, boolean prefixWithName) {
094                    if (envelope != null) {
095                            if (prefixWithName) {
096                                    message("ENVELOPE");
097                            }
098                            openParen("(");
099                            nillableQuote(envelope.getDate());
100                            nillableQuote(envelope.getSubject());
101                            address(envelope.getFrom());
102                            address(envelope.getSender());
103                            address(envelope.getReplyTo());
104                            address(envelope.getTo());
105                            address(envelope.getCc());
106                            address(envelope.getBcc());
107                            nillableQuote(envelope.getInReplyTo());
108                            nillableQuote(envelope.getMessageId());
109                            closeParen(")");
110                    }
111            }
112            
113            void composeEnvelope(FetchResponse response) {
114                    Envelope envelope = response.getEnvelope();
115                    composeEnvelope(envelope, true);
116            }
117            
118            void composeBody(FetchResponse response) {
119                    MimeDescriptor body = response.getBody();
120                    if (body != null) {
121                            message("BODY");
122                            composeStructure(body, false, false);
123                    }
124            }
125            
126            void composeBodyStructure(FetchResponse response) {
127                    MimeDescriptor bodyStructure = response.getBodyStructure();
128                    if (bodyStructure != null) {
129                            message("BODYSTRUCTURE");
130                            composeStructure(bodyStructure, true, false);
131                    }
132            }
133            
134            void composeStructure(MimeDescriptor descriptor, boolean includeExtensions,
135                            boolean isInnerPart) {
136                    String mediaType;
137                    String subType;
138                    if ((mediaType = descriptor.getType()) == null) {
139                            mediaType = "text";
140                            subType = "plain";
141                    } else {
142                            subType = descriptor.getSubType();
143                    }
144                    composeStructure(descriptor, mediaType, subType, includeExtensions,
145                                    isInnerPart);
146            }
147            
148            void composeStructure(MimeDescriptor descriptor, String mediaType,
149                            String subType, boolean includeExtensions, boolean isInnerPart) {
150                    openParen("(");
151                    if ("multipart".equalsIgnoreCase(mediaType)) {
152                            composeMultipart(descriptor, mediaType, subType, includeExtensions);
153                    } else if ("message".equalsIgnoreCase(mediaType)
154                                    && "rfc822".equalsIgnoreCase(subType)) {
155                            composeRfc822(descriptor, mediaType, subType, includeExtensions);
156                    } else {
157                            composeBasic(descriptor, mediaType, subType, includeExtensions);
158                    }
159                    closeParen(")");
160            }
161    
162            void composeMultipart(MimeDescriptor descriptor, String mediaType,
163                            String subType, boolean includeExtensions) {
164                    for (MimeDescriptor part : descriptor.getParts()) {
165                            composeStructure(part, includeExtensions, true);
166                    }
167                    quoteUpper(subType);
168                    if (includeExtensions) {
169                            nillableQuotes(descriptor.getParameters());
170                            composeDisposition(descriptor);
171                            nillableQuotes(descriptor.getLanguages());
172                            nillableQuote(descriptor.getLocation());
173                    }
174            }
175            
176            void composeRfc822(MimeDescriptor descriptor, String mediaType,
177                            String subType, boolean includeExtensions) {
178                    composeBodyFields(descriptor, mediaType, subType);
179                    composeEnvelope(descriptor.getEnvelope(), false);
180                    composeStructure(descriptor.getEmbeddedMessageDescriptor(),
181                                    includeExtensions, true);
182                    message(descriptor.getLines());
183                    if (includeExtensions) {
184                            encodeOnePartBodyExtensions(descriptor);
185                    }
186            }
187            
188            void composeBasic(MimeDescriptor descriptor, String mediaType,
189                            String subType, boolean includeExtensions) {
190                    composeBodyFields(descriptor, mediaType, subType);
191                    if ("text".equalsIgnoreCase(mediaType)) {
192                            message(descriptor.getLines());
193                    }
194                    if (includeExtensions) {
195                            encodeOnePartBodyExtensions(descriptor);
196                    }
197            }
198            
199            void encodeOnePartBodyExtensions(MimeDescriptor descriptor) {
200                    nillableQuote(descriptor.getMd5());
201                    composeDisposition(descriptor);
202                    nillableQuotes(descriptor.getLanguages());
203                    nillableQuote(descriptor.getLocation());
204            }
205    
206            void composeBodyFields(MimeDescriptor descriptor, String mediaType,
207                            String subType) {
208                    quoteUpper(mediaType);
209                    quoteUpper(subType);
210                    nillableQuotes(descriptor.getParameters());
211                    nillableQuote(descriptor.getId());
212                    nillableQuote(descriptor.getDescription());
213                    quoteUpper(descriptor.getEncoding());
214                    message(descriptor.getBodyOctets());
215            }
216            
217            void composeDisposition(MimeDescriptor descriptor) {
218                    String disposition = descriptor.getDisposition();
219                    if (disposition == null) {
220                            nil();
221                    } else {
222                            openParen("(");
223                            quote(disposition);
224                            nillableQuotes(descriptor.getDispositionParams());
225                            closeParen(")");
226                    }
227            }
228            
229            void composeBodyContent(FetchResponse response) {
230                    Content content = response.getContent();
231                    if (content != null) {
232                            message(content.getName());
233                            literal(content);
234                    }
235            }
236    
237            void address(Address[] addresses) {
238                    if (ArrayUtils.isEmpty(addresses)) {
239                            nil();
240                    } else {
241                            openParen("(");
242                            for (int i = 0; i < addresses.length; i++) {
243                                    skipNextSpace();
244                                    openParen("(");
245                                    nillableQuote(addresses[i].getPersonalName());
246                                    nillableQuote(addresses[i].getAtDomainList());
247                                    nillableQuote(addresses[i].getMailboxName());
248                                    nillableQuote(addresses[i].getHostName());
249                                    closeParen(")");
250                            }
251                            closeParen(")");
252                    }
253            }
254            
255    }