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