001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.javamail.store.imap.connection;
019 import java.util.ArrayList;
020 import java.util.List;
021
022 import javax.mail.MessagingException;
023
024 /**
025 * Util class to represent a composite FETCH response from an IMAP server. The
026 * response may have information about multiple message dataItems.
027 *
028 * @version $Rev: 594520 $ $Date: 2007-11-13 07:57:39 -0500 (Tue, 13 Nov 2007) $
029 */
030 public class IMAPFetchResponse extends IMAPUntaggedResponse {
031 // parsed sections within the FETCH response structure
032 protected List dataItems = new ArrayList();
033 // the message number to which this applies
034 public int sequenceNumber;
035
036 public IMAPFetchResponse(int sequenceNumber, byte[] data, IMAPResponseTokenizer source) throws MessagingException {
037 super("FETCH", data);
038
039 this.sequenceNumber = sequenceNumber;
040
041 // fetch responses are a list, even if there is just a single member.
042 source.checkLeftParen();
043
044 // loop until we find the list end.
045 while (source.notListEnd()) {
046 // the response names are coded as ATOMS. The BODY one's use a special
047 // syntax, so we need to use the expanded delimiter set to pull this out.
048 String itemName = source.readAtom(true).toUpperCase();
049
050 if (itemName.equals("ENVELOPE")) {
051 dataItems.add(new IMAPEnvelope(source));
052 }
053 else if (itemName.equals("BODYSTRUCTURE")) {
054 dataItems.add(new IMAPBodyStructure(source));
055 }
056 else if (itemName.equals("FLAGS")) {
057 dataItems.add(new IMAPFlags(source));
058 }
059 else if (itemName.equals("INTERNALDATE")) {
060 dataItems.add(new IMAPInternalDate(source));
061 }
062 else if (itemName.equals("UID")) {
063 dataItems.add(new IMAPUid(sequenceNumber, source));
064 }
065 else if (itemName.equals("RFC822")) {
066 // all of the RFC822 items are of form
067 // "RFC822.name". We used the expanded parse above because
068 // the BODY names include some complicated bits. If we got one
069 // of the RFC822 sections, then parse the rest of the name using
070 // the old rules, which will pull in the rest of the name from the period.
071 itemName = source.readAtom(false).toUpperCase();
072 if (itemName.equals(".SIZE")) {
073 dataItems.add(new IMAPMessageSize(source));
074 }
075 else if (itemName.equals(".HEADER")) {
076 dataItems.add(new IMAPInternetHeader(source.readByteArray()));
077 }
078 else if (itemName.equals(".TEXT")) {
079 dataItems.add(new IMAPMessageText(source.readByteArray()));
080 }
081 }
082 // this is just the body alone. Specific body segments
083 // have a more complex naming structure. Believe it or
084 // not,
085 else if (itemName.equals("BODY")) {
086 // time to go parse out the section information from the
087 // name.
088 IMAPBodySection section = new IMAPBodySection(source);
089
090 switch (section.section) {
091 case IMAPBodySection.BODY:
092 // a "full body cast". Just grab the binary data
093 dataItems.add(new IMAPBody(section, source.readByteArray()));
094 break;
095
096 case IMAPBodySection.HEADERS:
097 case IMAPBodySection.HEADERSUBSET:
098 case IMAPBodySection.MIME:
099 // these 3 are all variations of a header request
100 dataItems.add(new IMAPInternetHeader(section, source.readByteArray()));
101 break;
102
103 case IMAPBodySection.TEXT:
104 // just the text portion of the body
105 // a "full body cast". Just grab the binary data
106 dataItems.add(new IMAPMessageText(section, source.readByteArray()));
107 break;
108 }
109 }
110 }
111 // swallow the terminating right paren
112 source.checkRightParen();
113 }
114
115 /**
116 * Retrieve the sequence number for the FETCH item.
117 *
118 * @return The message sequence number this FETCH applies to.
119 */
120 public int getSequenceNumber() {
121 return sequenceNumber;
122 }
123
124 /**
125 * Get the section count.
126 *
127 * @return The number of sections in the response.
128 */
129 public int getCount() {
130 return dataItems.size();
131 }
132
133 /**
134 * Get the complete set of response dataItems.
135 *
136 * @return The List of IMAPFetchResponse values.
137 */
138 public List getDataItems() {
139 return dataItems;
140 }
141
142
143 /**
144 * Fetch a particular response type from the response dataItems.
145 *
146 * @param type The target FETCH type.
147 *
148 * @return The first IMAPFetchDataItem item that matches the response type.
149 */
150 public IMAPFetchDataItem getDataItem(int type) {
151 for (int i = 0; i < dataItems.size(); i ++) {
152 IMAPFetchDataItem item = (IMAPFetchDataItem)dataItems.get(i);
153 if (item.isType(type)) {
154 return item;
155 }
156 }
157 return null;
158 }
159
160 }
161