📄 fetchcommand.java
字号:
/*********************************************************************** * Copyright (c) 2000-2004 The Apache Software Foundation. * * All rights reserved. * * ------------------------------------------------------------------- * * Licensed under the Apache License, Version 2.0 (the "License"); you * * may not use this file except in compliance with the License. You * * may obtain a copy of the License at: * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * * implied. See the License for the specific language governing * * permissions and limitations under the License. * ***********************************************************************/package org.apache.james.imapserver.commands;import org.apache.excalibur.util.StringUtil;import org.apache.james.core.MimeMessageWrapper;import org.apache.james.imapserver.ImapRequestLineReader;import org.apache.james.imapserver.ImapResponse;import org.apache.james.imapserver.ImapSession;import org.apache.james.imapserver.ProtocolException;import org.apache.james.imapserver.store.MailboxException;import org.apache.james.imapserver.store.MessageFlags;import org.apache.james.imapserver.store.SimpleImapMessage;import org.apache.james.imapserver.store.ImapMailbox;import javax.mail.MessagingException;import javax.mail.internet.MimeMessage;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.ArrayList;import java.util.Collections;import java.util.Enumeration;import java.util.Iterator;import java.util.List;import java.util.Collection;/** * Handles processeing for the FETCH imap command. * * * @version $Revision: 1.1.2.3 $ */class FetchCommand extends SelectedStateCommand implements UidEnabledCommand{ public static final String NAME = "FETCH"; public static final String ARGS = "<message-set> <fetch-profile>"; private FetchCommandParser parser = new FetchCommandParser(); /** @see CommandTemplate#doProcess */ protected void doProcess( ImapRequestLineReader request, ImapResponse response, ImapSession session ) throws ProtocolException, MailboxException { doProcess( request, response, session, false ); } public void doProcess( ImapRequestLineReader request, ImapResponse response, ImapSession session, boolean useUids ) throws ProtocolException, MailboxException { IdSet idSet = parser.set( request ); FetchRequest fetch = parser.fetchRequest( request ); parser.endLine( request ); ImapMailbox mailbox = session.getSelected(); long[] uids = mailbox.getMessageUids(); for ( int i = 0; i < uids.length; i++ ) { long uid = uids[i]; int msn = mailbox.getMsn( uid ); if ( ( useUids && idSet.includes( uid ) ) || ( !useUids && idSet.includes( msn ) ) ) { SimpleImapMessage imapMessage = mailbox.getMessage( uid ); String msgData = outputMessage( fetch, imapMessage ); response.fetchResponse( msn, msgData ); } } session.unsolicitedResponses( response ); response.commandComplete( this ); } private String outputMessage( FetchRequest fetch, SimpleImapMessage message ) throws MailboxException, ProtocolException { StringBuffer response = new StringBuffer(); List elements = fetch.getElements(); for ( int i = 0; i < elements.size(); i++ ) { FetchElement fetchElement = ( FetchElement ) elements.get( i ); if ( i > 0 ) { response.append( SP ); } response.append( fetchElement.getResponseName() ); response.append( SP ); if ( fetchElement == FetchElement.FLAGS ) { MessageFlags flags = message.getFlags(); response.append( flags.format() ); } else if ( fetchElement == FetchElement.INTERNALDATE ) { // TODO format properly String internalDate = message.getAttributes().getInternalDateAsString(); response.append( "\"" ); response.append( internalDate ); response.append ( "\"" ); } else if ( fetchElement == FetchElement.RFC822_SIZE ) { response.append( message.getAttributes().getSize() ); } else if ( fetchElement == FetchElement.ENVELOPE ) { response.append( message.getAttributes().getEnvelope() ); } else if ( fetchElement == FetchElement.BODY ) { response.append( message.getAttributes().getBodyStructure( false ) ); } else if ( fetchElement == FetchElement.BODYSTRUCTURE ) { response.append( message.getAttributes().getBodyStructure( true ) ); } else if ( fetchElement == FetchElement.UID ) { response.append( message.getUid() ); } // Various mechanisms for returning message body. else if ( fetchElement instanceof BodyFetchElement ) { BodyFetchElement bodyFetchElement = (BodyFetchElement)fetchElement; String sectionSpecifier = bodyFetchElement.getParameters(); boolean peek = bodyFetchElement.isPeek(); MimeMessage mimeMessage = message.getMimeMessage(); try { handleBodyFetch( mimeMessage, sectionSpecifier, response ); } catch ( MessagingException e ) { // TODO chain exceptions throw new MailboxException( e.getMessage() ); } if ( ! peek ) { message.getFlags().setSeen( true ); // TODO need to store this change. } } else { throw new ProtocolException( "Invalid fetch attribute" ); } } return response.toString(); } private void handleBodyFetch( MimeMessage mimeMessage, String sectionSpecifier, StringBuffer response ) throws ProtocolException, MessagingException { if ( sectionSpecifier.length() == 0 ) { // TODO - need to use an InputStream from the response here. ByteArrayOutputStream bout = new ByteArrayOutputStream(); try { mimeMessage.writeTo(bout); } catch ( IOException e ) { throw new ProtocolException( "Error reading message source" ); } byte[] bytes = bout.toByteArray(); addLiteral( bytes, response ); } else if ( sectionSpecifier.equalsIgnoreCase( "HEADER" ) ) { Enumeration enum = mimeMessage.getAllHeaderLines(); addHeaders( enum, response ); } else if ( sectionSpecifier.startsWith( "HEADER.FIELDS.NOT " ) ) { String[] excludeNames = extractHeaderList( sectionSpecifier, "HEADER.FIELDS.NOT ".length() ); Enumeration enum = mimeMessage.getNonMatchingHeaderLines( excludeNames ); addHeaders( enum, response ); } else if ( sectionSpecifier.startsWith( "HEADER.FIELDS " ) ) { String[] includeNames = extractHeaderList( sectionSpecifier, "HEADER.FIELDS ".length() ); Enumeration enum = mimeMessage.getMatchingHeaderLines( includeNames ); addHeaders( enum, response ); } else if ( sectionSpecifier.equalsIgnoreCase( "MIME" ) ) { // TODO implement throw new ProtocolException( "MIME not yet implemented." ); } else if ( sectionSpecifier.equalsIgnoreCase( "TEXT" ) ) { // TODO - need to use an InputStream from the response here. // TODO - this is a hack. To get just the body content, I'm using a null // input stream to take the headers. Need to have a way of ignoring headers. ByteArrayOutputStream headerOut = new ByteArrayOutputStream(); ByteArrayOutputStream bodyOut = new ByteArrayOutputStream(); try { MimeMessageWrapper.writeTo( mimeMessage, headerOut, bodyOut ); byte[] bytes = bodyOut.toByteArray(); addLiteral( bytes, response ); } catch ( IOException e ) { throw new ProtocolException( "Error reading message source" ); } } else { // Should be a part specifier followed by a section specifier. // See if there's a leading part specifier. // If so, get the number, get the part, and call this recursively. int dotPos = sectionSpecifier.indexOf( '.' ); if ( dotPos == -1 ) { throw new ProtocolException( "Malformed fetch attribute: " + sectionSpecifier ); } int partNumber = Integer.parseInt( sectionSpecifier.substring( 0, dotPos ) ); String partSectionSpecifier = sectionSpecifier.substring( dotPos + 1 ); // TODO - get the MimePart of the mimeMessage, and call this method // with the new partSectionSpecifier.// MimeMessage part;// handleBodyFetch( part, partSectionSpecifier, response ); throw new ProtocolException( "Mime parts not yet implemented for fetch." ); } } private void addLiteral( byte[] bytes, StringBuffer response ) { response.append('{' ); response.append( bytes.length + 1 ); response.append( '}' ); response.append( "\r\n" ); for ( int i = 0; i < bytes.length; i++ ) { byte b = bytes[i]; response.append((char)b); } } // TODO should do this at parse time. private String[] extractHeaderList( String headerList, int prefixLen ) { // Remove the trailing and leading ')(' String tmp = headerList.substring( prefixLen + 1, headerList.length() - 1 ); String[] headerNames = StringUtil.split( tmp, " " ); return headerNames; } private void addHeaders( Enumeration enum, StringBuffer response ) { List lines = new ArrayList(); int count = 0; while (enum.hasMoreElements()) { String line = (String)enum.nextElement(); count += line.length() + 2; lines.add(line); } response.append( '{' ); response.append( count + 2 ); response.append( '}' ); response.append("\r\n"); Iterator lit = lines.iterator(); while (lit.hasNext()) { String line = (String)lit.next(); response.append( line ); response.append( "\r\n" ); } response.append("\r\n"); } /** @see ImapCommand#getName */ public String getName() { return NAME; } /** @see CommandTemplate#getArgSyntax */ public String getArgSyntax() { return ARGS; } private class FetchCommandParser extends CommandParser { public FetchRequest fetchRequest( ImapRequestLineReader request ) throws ProtocolException { FetchRequest fetch = new FetchRequest(); CharacterValidator validator = new NoopCharValidator(); char next = nextNonSpaceChar( request ); consumeChar( request, '(' );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -