You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by Norman Maurer <no...@apache.org> on 2010/08/30 18:20:04 UTC
Re: svn commit: r990364 [2/5] - in /james/imap/trunk: ./ decode/
decode/src/ message/ message/src/main/java/org/apache/james/imap/decode/
message/src/main/java/org/apache/james/imap/decode/base/ message/src/main/java/org/apache/james/imap/decode/main
Hi Eric,
these changes seems to mess up with how svn should be used.. maybe its
the stupid eclipse plugin who knows ;) Could you revert the changes
and better use svn cp so we don't loose all the history ?
Thx,
Norman
2010/8/28 <er...@apache.org>:
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/AbstractImapCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/AbstractImapCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/AbstractImapCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/AbstractImapCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,774 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.base;
> +
> +import java.io.ByteArrayOutputStream;
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.nio.ByteBuffer;
> +import java.nio.CharBuffer;
> +import java.nio.charset.CharacterCodingException;
> +import java.nio.charset.Charset;
> +import java.nio.charset.CharsetDecoder;
> +import java.nio.charset.CoderResult;
> +import java.nio.charset.CodingErrorAction;
> +import java.nio.charset.MalformedInputException;
> +import java.nio.charset.UnmappableCharacterException;
> +import java.util.ArrayList;
> +import java.util.Date;
> +
> +import javax.mail.Flags;
> +
> +import org.apache.commons.io.IOUtils;
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.api.display.HumanReadableText;
> +import org.apache.james.imap.api.message.IdRange;
> +import org.apache.james.imap.api.message.request.DayMonthYear;
> +import org.apache.james.imap.api.message.response.StatusResponseFactory;
> +import org.apache.james.imap.decode.DecoderUtils;
> +import org.apache.james.imap.decode.ImapCommandParser;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.MessagingImapCommandParser;
> +import org.apache.james.imap.decode.DecodingException;
> +
> +/**
> + * <p>
> + * <strong>Note:</strong>
> + * </p>
> + *
> + * @version $Revision: 109034 $
> + */
> +public abstract class AbstractImapCommandParser implements ImapCommandParser, MessagingImapCommandParser {
> + private static final int QUOTED_BUFFER_INITIAL_CAPACITY = 64;
> +
> + private static final Charset US_ASCII = Charset.forName("US-ASCII");
> +
> + private final ImapCommand command;
> +
> + private ImapMessageFactory messageFactory;
> +
> + private StatusResponseFactory statusResponseFactory;
> +
> + public AbstractImapCommandParser(final ImapCommand command) {
> + super();
> + this.command = command;
> + }
> +
> + public ImapCommand getCommand() {
> + return command;
> + }
> +
> +
> + /**
> + * @see org.apache.james.imap.decode.MessagingImapCommandParser#getMessageFactory()
> + */
> + public ImapMessageFactory getMessageFactory() {
> + return messageFactory;
> + }
> +
> + /**
> + * @see org.apache.james.imap.decode.MessagingImapCommandParser#setMessageFactory(org.apache.james.imap.api.ImapMessageFactory)
> + */
> + public void setMessageFactory(ImapMessageFactory messageFactory) {
> + this.messageFactory = messageFactory;
> + }
> +
> + public final StatusResponseFactory getStatusResponseFactory() {
> + return statusResponseFactory;
> + }
> +
> + public final void setStatusResponseFactory(
> + StatusResponseFactory statusResponseFactory) {
> + this.statusResponseFactory = statusResponseFactory;
> + }
> +
> + /**
> + * Parses a request into a command message for later processing.
> + *
> + * @param request
> + * <code>ImapRequestLineReader</code>, not null
> + * @return <code>ImapCommandMessage</code>, not null
> + */
> + public final ImapMessage parse(ImapRequestLineReader request, String tag, Log logger) {
> + ImapMessage result;
> + try {
> +
> + ImapMessage message = decode(command, request, tag, logger);
> + result = message;
> +
> + } catch (DecodingException e) {
> + logger.debug("Cannot parse protocol ", e);
> + e.printStackTrace();
> + result = messageFactory.taggedBad(tag, command, e.getKey());
> + }
> + return result;
> + }
> +
> + /**
> + * Parses a request into a command message for later processing.
> + * @param command
> + * <code>ImapCommand</code> to be parsed, not null
> + * @param request
> + * <code>ImapRequestLineReader</code>, not null
> + * @param tag command tag, not null
> + * @param logger TODO
> + * @param logger TODO
> + * @return <code>ImapCommandMessage</code>, not null
> + * @throws DecodingException
> + * if the request cannot be parsed
> + */
> + protected abstract ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException;
> +
> + /**
> + * Reads an argument of type "atom" from the request.
> + */
> + public static String atom(ImapRequestLineReader request)
> + throws DecodingException {
> + return consumeWord(request, new ATOM_CHARValidator());
> + }
> +
> + /**
> + * Reads a command "tag" from the request.
> + */
> + public static String tag(ImapRequestLineReader request)
> + throws DecodingException {
> + CharacterValidator validator = new TagCharValidator();
> + return consumeWord(request, validator);
> + }
> +
> + /**
> + * Reads an argument of type "astring" from the request.
> + */
> + public String astring(ImapRequestLineReader request)
> + throws DecodingException {
> + return astring(request, null);
> + }
> +
> + /**
> + * Reads an argument of type "astring" from the request.
> + */
> + public String astring(ImapRequestLineReader request, Charset charset)
> + throws DecodingException {
> + char next = request.nextWordChar();
> + switch (next) {
> + case '"':
> + return consumeQuoted(request, charset);
> + case '{':
> + return consumeLiteral(request, charset);
> + default:
> + return atom(request);
> + }
> + }
> +
> + /**
> + * Reads an argument of type "nstring" from the request.
> + */
> + public String nstring(ImapRequestLineReader request)
> + throws DecodingException {
> + char next = request.nextWordChar();
> + switch (next) {
> + case '"':
> + return consumeQuoted(request);
> + case '{':
> + return consumeLiteral(request, null);
> + default:
> + String value = atom(request);
> + if ("NIL".equals(value)) {
> + return null;
> + } else {
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS,
> + "Invalid nstring value: valid values are '\"...\"', '{12} CRLF *CHAR8', and 'NIL'.");
> + }
> + }
> + }
> +
> + /**
> + * Reads a "mailbox" argument from the request. Not implemented *exactly* as
> + * per spec, since a quoted or literal "inbox" still yeilds "INBOX" (ie
> + * still case-insensitive if quoted or literal). I think this makes sense.
> + *
> + * mailbox ::= "INBOX" / astring ;; INBOX is case-insensitive. All case
> + * variants of ;; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX ;; not
> + * as an astring.
> + */
> + public String mailbox(ImapRequestLineReader request)
> + throws DecodingException {
> + String mailbox = astring(request);
> + if (mailbox.equalsIgnoreCase(ImapConstants.INBOX_NAME)) {
> + return ImapConstants.INBOX_NAME;
> + } else {
> + return mailbox;
> + }
> + }
> +
> + /**
> + * Reads one <code>date</code> argument from the request.
> + *
> + * @param request
> + * <code>ImapRequestLineReader</code>, not null
> + * @return <code>DayMonthYear</code>, not null
> + * @throws DecodingException
> + */
> + public DayMonthYear date(ImapRequestLineReader request)
> + throws DecodingException {
> +
> + final char one = request.consume();
> + final char two = request.consume();
> + final int day;
> + if (two == '-') {
> + day = DecoderUtils.decodeFixedDay(' ', one);
> + } else {
> + day = DecoderUtils.decodeFixedDay(one, two);
> + nextIsDash(request);
> + }
> +
> + final char monthFirstChar = request.consume();
> + final char monthSecondChar = request.consume();
> + final char monthThirdChar = request.consume();
> + final int month = DecoderUtils.decodeMonth(monthFirstChar,
> + monthSecondChar, monthThirdChar) + 1;
> + nextIsDash(request);
> + final char milleniumChar = request.consume();
> + final char centuryChar = request.consume();
> + final char decadeChar = request.consume();
> + final char yearChar = request.consume();
> + final int year = DecoderUtils.decodeYear(milleniumChar, centuryChar,
> + decadeChar, yearChar);
> + final DayMonthYear result = new DayMonthYear(day, month, year);
> + return result;
> + }
> +
> + private void nextIsDash(ImapRequestLineReader request)
> + throws DecodingException {
> + final char next = request.consume();
> + if (next != '-') {
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Expected dash but was " + next);
> + }
> + }
> +
> + /**
> + * Reads a "date-time" argument from the request.
> + */
> + public Date dateTime(ImapRequestLineReader request)
> + throws DecodingException {
> + char next = request.nextWordChar();
> + String dateString;
> + if (next == '"') {
> + dateString = consumeQuoted(request);
> + } else {
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "DateTime values must be quoted.");
> + }
> +
> + return DecoderUtils.decodeDateTime(dateString);
> + }
> +
> + /**
> + * Reads the next "word from the request, comprising all characters up to
> + * the next SPACE. Characters are tested by the supplied CharacterValidator,
> + * and an exception is thrown if invalid characters are encountered.
> + */
> + protected static String consumeWord(ImapRequestLineReader request,
> + CharacterValidator validator) throws DecodingException {
> + StringBuffer atom = new StringBuffer();
> +
> + char next = request.nextWordChar();
> + while (!isWhitespace(next)) {
> + if (validator.isValid(next)) {
> + atom.append(next);
> + request.consume();
> + } else {
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Invalid character: '" + next + "'");
> + }
> + next = request.nextChar();
> + }
> + return atom.toString();
> + }
> +
> + private static boolean isWhitespace(char next) {
> + return (next == ' ' || next == '\n' || next == '\r' || next == '\t');
> + }
> +
> + /**
> + * Reads an argument of type "literal" from the request, in the format: "{"
> + * charCount "}" CRLF *CHAR8 Note before calling, the request should be
> + * positioned so that nextChar is '{'. Leading whitespace is not skipped in
> + * this method.
> + *
> + * @param charset ,
> + * or null for <code>US-ASCII</code>
> + */
> + protected String consumeLiteral(final ImapRequestLineReader request,
> + final Charset charset) throws DecodingException {
> + if (charset == null) {
> + return consumeLiteral(request, US_ASCII);
> + } else {
> + ByteArrayOutputStream out = new ByteArrayOutputStream();
> + try {
> + IOUtils.copy(consumeLiteral(request),out);
> + } catch (IOException e) {
> + throw new DecodingException(HumanReadableText.BAD_IO_ENCODING, "Bad character encoding", e);
> + }
> + final byte[] bytes = out.toByteArray();
> + final ByteBuffer buffer = ByteBuffer.wrap(bytes);
> + return decode(charset, buffer);
> + }
> + }
> +
> + protected InputStream consumeLiteral(final ImapRequestLineReader request) throws DecodingException {
> + // The 1st character must be '{'
> + consumeChar(request, '{');
> +
> + StringBuffer digits = new StringBuffer();
> + char next = request.nextChar();
> + while (next != '}' && next != '+') {
> + digits.append(next);
> + request.consume();
> + next = request.nextChar();
> + }
> +
> + // If the number is *not* suffixed with a '+', we *are* using a
> + // synchronized literal,
> + // and we need to send command continuation request before reading
> + // data.
> + boolean synchronizedLiteral = true;
> + // '+' indicates a non-synchronized literal (no command continuation
> + // request)
> + if (next == '+') {
> + synchronizedLiteral = false;
> + consumeChar(request, '+');
> + }
> +
> + // Consume the '}' and the newline
> + consumeChar(request, '}');
> + consumeCRLF(request);
> +
> + if (synchronizedLiteral) {
> + request.commandContinuationRequest();
> + }
> +
> + final int size = Integer.parseInt(digits.toString());
> + return request.read(size);
> + }
> +
> + private String decode(final Charset charset, final ByteBuffer buffer)
> + throws DecodingException {
> + try {
> + final String result = charset.newDecoder().onMalformedInput(
> + CodingErrorAction.REPORT).onUnmappableCharacter(
> + CodingErrorAction.REPORT).decode(buffer).toString();
> + return result;
> +
> + } catch (IllegalStateException e) {
> + throw new DecodingException(HumanReadableText.BAD_IO_ENCODING, "Bad character encoding", e);
> + } catch (MalformedInputException e) {
> + throw new DecodingException(HumanReadableText.BAD_IO_ENCODING, "Bad character encoding", e);
> + } catch (UnmappableCharacterException e) {
> + throw new DecodingException(HumanReadableText.BAD_IO_ENCODING, "Bad character encoding", e);
> + } catch (CharacterCodingException e) {
> + throw new DecodingException(HumanReadableText.BAD_IO_ENCODING, "Bad character encoding", e);
> + }
> + }
> +
> + /**
> + * Consumes a CRLF from the request.
> + * TODO: This is too liberal, the spec insists on \r\n for new lines.
> + *
> + * @param request
> + * @throws DecodingException
> + */
> + private void consumeCRLF(ImapRequestLineReader request)
> + throws DecodingException {
> + char next = request.nextChar();
> + if (next != '\n') {
> + consumeChar(request, '\r');
> + }
> + consumeChar(request, '\n');
> + }
> +
> + /**
> + * Consumes the next character in the request, checking that it matches the
> + * expected one. This method should be used when the
> + */
> + protected void consumeChar(ImapRequestLineReader request, char expected)
> + throws DecodingException {
> + char consumed = request.consume();
> + if (consumed != expected) {
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS,
> + "Expected:'" + expected + "' found:'" + consumed + "'");
> + }
> + }
> +
> + /**
> + * Reads a quoted string value from the request.
> + */
> + protected String consumeQuoted(ImapRequestLineReader request)
> + throws DecodingException {
> + return consumeQuoted(request, null);
> + }
> +
> + /**
> + * Reads a quoted string value from the request.
> + */
> + protected String consumeQuoted(ImapRequestLineReader request,
> + Charset charset) throws DecodingException {
> + if (charset == null) {
> + return consumeQuoted(request, US_ASCII);
> + } else {
> + // The 1st character must be '"'
> + consumeChar(request, '"');
> + final QuotedStringDecoder decoder = new QuotedStringDecoder(charset);
> + final String result = decoder.decode(request);
> + consumeChar(request, '"');
> + return result;
> + }
> + }
> +
> + /**
> + * Reads a "flags" argument from the request.
> + */
> + public Flags flagList(ImapRequestLineReader request)
> + throws DecodingException {
> + Flags flags = new Flags();
> + request.nextWordChar();
> + consumeChar(request, '(');
> + CharacterValidator validator = new NoopCharValidator();
> + String nextWord = consumeWord(request, validator);
> + while (!nextWord.endsWith(")")) {
> + DecoderUtils.setFlag(nextWord, flags);
> + nextWord = consumeWord(request, validator);
> + }
> + // Got the closing ")", may be attached to a word.
> + if (nextWord.length() > 1) {
> + int parenIndex = nextWord.indexOf(')');
> + if (parenIndex > 0) {
> + final String nextFlag = nextWord.substring(0, parenIndex);
> + DecoderUtils.setFlag(nextFlag, flags);
> + }
> + }
> +
> + return flags;
> + }
> +
> + /**
> + * Reads an argument of type "number" from the request.
> + */
> + public long number(ImapRequestLineReader request) throws DecodingException {
> + return readDigits(request, 0, 0, true);
> + }
> +
> + private long readDigits(final ImapRequestLineReader request, int add,
> + final long total, final boolean first) throws DecodingException {
> + final char next;
> + if (first) {
> + next = request.nextWordChar();
> + } else {
> + request.consume();
> + next = request.nextChar();
> + }
> + final long currentTotal = (10 * total) + add;
> + switch (next) {
> + case '0':
> + return readDigits(request, 0, currentTotal, false);
> + case '1':
> + return readDigits(request, 1, currentTotal, false);
> + case '2':
> + return readDigits(request, 2, currentTotal, false);
> + case '3':
> + return readDigits(request, 3, currentTotal, false);
> + case '4':
> + return readDigits(request, 4, currentTotal, false);
> + case '5':
> + return readDigits(request, 5, currentTotal, false);
> + case '6':
> + return readDigits(request, 6, currentTotal, false);
> + case '7':
> + return readDigits(request, 7, currentTotal, false);
> + case '8':
> + return readDigits(request, 8, currentTotal, false);
> + case '9':
> + return readDigits(request, 9, currentTotal, false);
> + case '.':
> + case ' ':
> + case '>':
> + case '\r':
> + case '\n':
> + case '\t':
> + return currentTotal;
> + default:
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Expected a digit but was " + next);
> + }
> + }
> +
> + /**
> + * Reads an argument of type "nznumber" (a non-zero number) (NOTE this isn't
> + * strictly as per the spec, since the spec disallows numbers such as "0123"
> + * as nzNumbers (although it's ok as a "number". I think the spec is a bit
> + * shonky.)
> + */
> + public long nzNumber(ImapRequestLineReader request)
> + throws DecodingException {
> + long number = number(request);
> + if (number == 0) {
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Zero value not permitted.");
> + }
> + return number;
> + }
> +
> + private static boolean isCHAR(char chr) {
> + return (chr >= 0x01 && chr <= 0x7f);
> + }
> +
> + protected static boolean isListWildcard(char chr) {
> + return (chr == '*' || chr == '%');
> + }
> +
> + private static boolean isQuotedSpecial(char chr) {
> + return (chr == '"' || chr == '\\');
> + }
> +
> + /**
> + * Consumes the request up to and including the eno-of-line.
> + *
> + * @param request
> + * The request
> + * @throws DecodingException
> + * If characters are encountered before the endLine.
> + */
> + public void endLine(ImapRequestLineReader request) throws DecodingException {
> + request.eol();
> + }
> +
> + /**
> + * Reads a "message set" argument, and parses into an IdSet. Currently only
> + * supports a single range of values.
> + */
> + public IdRange[] parseIdRange(ImapRequestLineReader request)
> + throws DecodingException {
> + CharacterValidator validator = new MessageSetCharValidator();
> + String nextWord = consumeWord(request, validator);
> +
> + int commaPos = nextWord.indexOf(',');
> + if (commaPos == -1) {
> + return new IdRange[] { parseRange(nextWord) };
> + }
> +
> + ArrayList<IdRange> rangeList = new ArrayList<IdRange>();
> + int pos = 0;
> + while (commaPos != -1) {
> + String range = nextWord.substring(pos, commaPos);
> + IdRange set = parseRange(range);
> + rangeList.add(set);
> +
> + pos = commaPos + 1;
> + commaPos = nextWord.indexOf(',', pos);
> + }
> + String range = nextWord.substring(pos);
> + rangeList.add(parseRange(range));
> + return (IdRange[]) rangeList.toArray(new IdRange[rangeList.size()]);
> + }
> +
> + private IdRange parseRange(String range) throws DecodingException {
> + int pos = range.indexOf(':');
> + try {
> + if (pos == -1) {
> + long value = parseLong(range);
> + return new IdRange(value);
> + } else {
> + long lowVal = parseLong(range.substring(0, pos));
> + long highVal = parseLong(range.substring(pos + 1));
> + return new IdRange(lowVal, highVal);
> + }
> + } catch (NumberFormatException e) {
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Invalid message set.", e);
> + }
> + }
> +
> + private long parseLong(String value) {
> + if (value.length() == 1 && value.charAt(0) == '*') {
> + return Long.MAX_VALUE;
> + }
> + return Long.parseLong(value);
> + }
> +
> + /**
> + * Provides the ability to ensure characters are part of a permitted set.
> + */
> + public interface CharacterValidator {
> + /**
> + * Validates the supplied character.
> + *
> + * @param chr
> + * The character to validate.
> + * @return <code>true</code> if chr is valid, <code>false</code> if
> + * not.
> + */
> + boolean isValid(char chr);
> + }
> +
> + public static class NoopCharValidator implements CharacterValidator {
> + public boolean isValid(char chr) {
> + return true;
> + }
> + }
> +
> + public static class ATOM_CHARValidator implements CharacterValidator {
> + public boolean isValid(char chr) {
> + return (isCHAR(chr) && !isAtomSpecial(chr) && !isListWildcard(chr) && !isQuotedSpecial(chr));
> + }
> +
> + private boolean isAtomSpecial(char chr) {
> + return (chr == '(' || chr == ')' || chr == '{' || chr == ' ' || chr == Character.CONTROL);
> + }
> + }
> +
> + public static class TagCharValidator extends ATOM_CHARValidator {
> + public boolean isValid(char chr) {
> + if (chr == '+')
> + return false;
> + return super.isValid(chr);
> + }
> + }
> +
> + public static class MessageSetCharValidator implements CharacterValidator {
> + public boolean isValid(char chr) {
> + return (isDigit(chr) || chr == ':' || chr == '*' || chr == ',');
> + }
> +
> + private boolean isDigit(char chr) {
> + return '0' <= chr && chr <= '9';
> + }
> + }
> +
> + /**
> + * Decodes contents of a quoted string. Charset aware. One shot, not thread
> + * safe.
> + */
> + private static class QuotedStringDecoder {
> + /** Decoder suitable for charset */
> + private final CharsetDecoder decoder;
> +
> + /** byte buffer will be filled then flushed to character buffer */
> + private final ByteBuffer buffer;
> +
> + /** character buffer may be dynamically resized */
> + CharBuffer charBuffer;
> +
> + public QuotedStringDecoder(Charset charset) {
> + decoder = charset.newDecoder();
> + buffer = ByteBuffer.allocate(QUOTED_BUFFER_INITIAL_CAPACITY);
> + charBuffer = CharBuffer.allocate(QUOTED_BUFFER_INITIAL_CAPACITY);
> + }
> +
> + public String decode(ImapRequestLineReader request)
> + throws DecodingException {
> + try {
> + decoder.reset();
> + char next = request.nextChar();
> + while (next != '"') {
> + // fill up byte buffer before decoding
> + if (!buffer.hasRemaining()) {
> + decodeByteBufferToCharacterBuffer(false);
> + }
> + if (next == '\\') {
> + request.consume();
> + next = request.nextChar();
> + if (!isQuotedSpecial(next)) {
> + throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS,
> + "Invalid escaped character in quote: '"
> + + next + "'");
> + }
> + }
> + // TODO: nextChar does not report accurate chars so safe to
> + // cast to byte
> + buffer.put((byte) next);
> + request.consume();
> + next = request.nextChar();
> + }
> + completeDecoding();
> + final String result = charBuffer.toString();
> + return result;
> +
> + } catch (IllegalStateException e) {
> + throw new DecodingException(HumanReadableText.BAD_IO_ENCODING, "Bad character encoding", e);
> + }
> + }
> +
> + private void completeDecoding() throws DecodingException {
> + decodeByteBufferToCharacterBuffer(true);
> + flush();
> + charBuffer.flip();
> + }
> +
> + private void flush() throws DecodingException {
> + final CoderResult coderResult = decoder.flush(charBuffer);
> + if (coderResult.isOverflow()) {
> + upsizeCharBuffer();
> + flush();
> + } else if (coderResult.isError()) {
> + throw new DecodingException(HumanReadableText.BAD_IO_ENCODING, "Bad character encoding");
> + }
> + }
> +
> + /**
> + * Decodes contents of the byte buffer to the character buffer. The
> + * character buffer will be replaced by a larger one if required.
> + *
> + * @param endOfInput
> + * is the input ended
> + */
> + private CoderResult decodeByteBufferToCharacterBuffer(
> + final boolean endOfInput) throws DecodingException {
> + buffer.flip();
> + return decodeMoreBytesToCharacterBuffer(endOfInput);
> + }
> +
> + private CoderResult decodeMoreBytesToCharacterBuffer(
> + final boolean endOfInput) throws DecodingException {
> + final CoderResult coderResult = decoder.decode(buffer, charBuffer,
> + endOfInput);
> + if (coderResult.isOverflow()) {
> + upsizeCharBuffer();
> + return decodeMoreBytesToCharacterBuffer(endOfInput);
> + } else if (coderResult.isError()) {
> + throw new DecodingException(HumanReadableText.BAD_IO_ENCODING, "Bad character encoding");
> + } else if (coderResult.isUnderflow()) {
> + buffer.clear();
> + }
> + return coderResult;
> + }
> +
> + /**
> + * Increases the size of the character buffer.
> + */
> + private void upsizeCharBuffer() {
> + final int oldCapacity = charBuffer.capacity();
> + CharBuffer oldBuffer = charBuffer;
> + charBuffer = CharBuffer.allocate(oldCapacity
> + + QUOTED_BUFFER_INITIAL_CAPACITY);
> + oldBuffer.flip();
> + charBuffer.put(oldBuffer);
> + }
> + }
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/EolInputStream.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/EolInputStream.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/EolInputStream.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/EolInputStream.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,77 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.base;
> +
> +import java.io.FileInputStream;
> +import java.io.FilterInputStream;
> +import java.io.IOException;
> +import java.io.InputStream;
> +
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +
> +/**
> + * {@link FileInputStream} which call the eol() method of the {@link ImapRequestLineReader} when the end
> + * of the wrapped {@link InputStream} is reached
> + *
> + *
> + */
> +public class EolInputStream extends FilterInputStream{
> +
> + private ImapRequestLineReader reader;
> + private boolean eolCalled = false;
> +
> + public EolInputStream(ImapRequestLineReader reader, InputStream in) {
> + super(in);
> + this.reader = reader;
> + }
> +
> + @Override
> + public int read() throws IOException {
> + int i = in.read();
> + eol(i);
> + return i;
> + }
> +
> + @Override
> + public int read(byte[] b, int off, int len) throws IOException {
> + int i = in.read(b, off, len);
> + eol(i);
> + return i;
> + }
> +
> + @Override
> + public int read(byte[] b) throws IOException {
> + int i = in.read(b);
> + eol(i);
> + return i;
> + }
> +
> + private void eol(int i ) throws IOException{
> + if (i == -1 && eolCalled == false) {
> + reader.eol();
> + eolCalled = true;
> + }
> + }
> +
> + @Override
> + public int available() throws IOException {
> + return in.available();
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/FixedLengthInputStream.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/FixedLengthInputStream.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/FixedLengthInputStream.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/base/FixedLengthInputStream.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,101 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.base;
> +
> +import java.io.FilterInputStream;
> +import java.io.IOException;
> +import java.io.InputStream;
> +
> +/**
> + *
> + * An input stream which reads a fixed number of bytes from the underlying input
> + * stream. Once the number of bytes has been read, the FixedLengthInputStream
> + * will act as thought the end of stream has been reached, even if more bytes
> + * are present in the underlying input stream.
> + */
> +public class FixedLengthInputStream extends FilterInputStream {
> + private long pos = 0;
> +
> + private long length;
> +
> + public FixedLengthInputStream(InputStream in, long length) {
> + super(in);
> + this.length = length;
> + }
> +
> + public int read() throws IOException {
> + if (pos >= length) {
> + return -1;
> + }
> + pos++;
> + return super.read();
> + }
> +
> + public int read(byte b[]) throws IOException {
> +
> + return read(b, 0, b.length);
> + }
> +
> + public int read(byte b[], int off, int len) throws IOException {
> +
> +
> + if (pos >= length) {
> + return -1;
> + }
> +
> + if (pos + len >= length) {
> + int readLimit = (int) length - (int) pos;
> + pos = length;
> +
> + return super.read(b, off, readLimit);
> + }
> +
> +
> + int i = super.read(b, off, len);
> + pos += i;
> + return i;
> +
> + }
> +
> + public long skip(long n) throws IOException {
> + throw new IOException("Not implemented");
> + // return super.skip( n );
> + }
> +
> + public int available() throws IOException {
> + return (int) (length - pos);
> + }
> +
> + public void close() throws IOException {
> + // Don't do anything to the underlying stream.
> + }
> +
> + public void mark(int readlimit) {
> + // Don't do anything.
> + }
> +
> + public synchronized void reset() throws IOException {
> + throw new IOException("mark not supported");
> + }
> +
> + public boolean markSupported() {
> + return false;
> + }
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/main/DefaultImapDecoder.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/main/DefaultImapDecoder.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/main/DefaultImapDecoder.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/main/DefaultImapDecoder.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,123 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.main;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.api.ImapSessionState;
> +import org.apache.james.imap.api.display.HumanReadableText;
> +import org.apache.james.imap.api.process.ImapSession;
> +import org.apache.james.imap.decode.ImapCommandParser;
> +import org.apache.james.imap.decode.ImapCommandParserFactory;
> +import org.apache.james.imap.decode.ImapDecoder;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + * {@link ImapDecoder} implementation which parse the data via lookup the right {@link ImapCommandParser} via an {@link ImapCommandParserFactory}. The
> + * response will get generated via the {@link ImapMessageFactory}.
> + *
> + */
> +public class DefaultImapDecoder implements ImapDecoder {
> +
> + private final ImapMessageFactory messageFactory;
> +
> + private final ImapCommandParserFactory imapCommands;
> +
> + public DefaultImapDecoder(final ImapMessageFactory messageFactory,
> + final ImapCommandParserFactory imapCommands) {
> + this.messageFactory = messageFactory;
> + this.imapCommands = imapCommands;
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.ImapDecoder#decode(org.apache.james.imap.decode.ImapRequestLineReader, org.apache.james.imap.api.process.ImapSession)
> + */
> + public ImapMessage decode(ImapRequestLineReader request, ImapSession session) {
> + ImapMessage message;
> + final Log logger = session.getLog();
> +
> + try {
> + final String tag = AbstractImapCommandParser.tag(request);
> + message = decodeCommandTagged(request, logger, tag, session);
> + } catch (DecodingException e) {
> + logger.debug("Cannot parse tag", e);
> +
> + // When the tag cannot be read, there is something seriously wrong.
> + // It is probably not possible to recover
> + // and (since this may indicate an attack) wiser not to try
> + message = messageFactory.bye(HumanReadableText.ILLEGAL_TAG);
> + session.logout();
> + }
> + return message;
> + }
> +
> +
> + private ImapMessage decodeCommandTagged(
> + final ImapRequestLineReader request, final Log logger,
> + final String tag, final ImapSession session) {
> + ImapMessage message;
> + if (logger.isDebugEnabled()) {
> + logger.debug("Got <tag>: " + tag);
> + }
> + try {
> + final String commandName = AbstractImapCommandParser.atom(request);
> + message = decodeCommandNamed(request, tag, commandName, logger,
> + session);
> + } catch (DecodingException e) {
> + logger.debug("Error during initial request parsing", e);
> + message = unknownCommand(tag, session);
> + }
> + return message;
> + }
> +
> + private ImapMessage unknownCommand(final String tag,
> + final ImapSession session) {
> + ImapMessage message;
> + if (session.getState() == ImapSessionState.NON_AUTHENTICATED) {
> + message = messageFactory
> + .bye(HumanReadableText.BYE_UNKNOWN_COMMAND);
> + session.logout();
> + } else {
> + message = messageFactory.taggedBad(tag, null,
> + HumanReadableText.UNKNOWN_COMMAND);
> + }
> + return message;
> + }
> +
> + private ImapMessage decodeCommandNamed(final ImapRequestLineReader request,
> + final String tag, String commandName, final Log logger,
> + final ImapSession session) {
> + ImapMessage message;
> + if (logger.isDebugEnabled()) {
> + logger.debug("Got <command>: " + commandName);
> + }
> + final ImapCommandParser command = imapCommands.getParser(commandName);
> + if (command == null) {
> + logger.info("Missing command implementation.");
> + message = unknownCommand(tag, session);
> + } else {
> + message = command.parse(request, tag, logger);
> + }
> + return message;
> + }
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractUidCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractUidCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractUidCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AbstractUidCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,51 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +abstract class AbstractUidCommandParser extends AbstractImapCommandParser {
> +
> + public AbstractUidCommandParser(final ImapCommand command) {
> + super(command);
> + }
> +
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + final ImapMessage result = decode(command, request, tag, false, logger);
> + return result;
> + }
> +
> + public ImapMessage decode(ImapRequestLineReader request, String tag,
> + boolean useUids, Log logger) throws DecodingException {
> + final ImapCommand command = getCommand();
> + final ImapMessage result = decode(command, request, tag, useUids, logger);
> + return result;
> + }
> +
> + protected abstract ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, boolean useUids, Log logger)
> + throws DecodingException;
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,98 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import java.util.Date;
> +
> +import javax.mail.Flags;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +import org.apache.james.imap.decode.base.EolInputStream;
> +
> +/**
> + * Parses APPEND command
> + *
> + */
> +public class AppendCommandParser extends AbstractImapCommandParser {
> +
> + public AppendCommandParser() {
> + super(ImapCommand.authenticatedStateCommand(ImapConstants.APPEND_COMMAND_NAME));
> + }
> +
> + /**
> + * If the next character in the request is a '(', tries to read a
> + * "flag_list" argument from the request. If not, returns a MessageFlags
> + * with no flags set.
> + */
> + public Flags optionalAppendFlags(ImapRequestLineReader request)
> + throws DecodingException {
> + char next = request.nextWordChar();
> + if (next == '(') {
> + return flagList(request);
> + } else {
> + return null;
> + }
> + }
> +
> + /**
> + * If the next character in the request is a '"', tries to read a DateTime
> + * argument. If not, returns null.
> + */
> + public Date optionalDateTime(ImapRequestLineReader request)
> + throws DecodingException {
> + char next = request.nextWordChar();
> + if (next == '"') {
> + return dateTime(request);
> + } else {
> + return null;
> + }
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + String mailboxName = mailbox(request);
> + Flags flags = optionalAppendFlags(request);
> + if (flags == null) {
> + flags = new Flags();
> + }
> + Date datetime = optionalDateTime(request);
> + if (datetime == null) {
> + datetime = new Date();
> + }
> + request.nextWordChar();
> +
> + // Use a EolInputStream so it will call eol when the message was read
> + final EolInputStream message = new EolInputStream(request, consumeLiteral(request));
> + final ImapMessageFactory factory = getMessageFactory();
> + final ImapMessage result = factory.createAppendMessage(command,
> + mailboxName, flags, datetime, message, tag);
> + return result;
> + }
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AuthenticateCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AuthenticateCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AuthenticateCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/AuthenticateCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,55 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + *
> + * Parses AUTHENTICATE commands
> + *
> + */
> +public class AuthenticateCommandParser extends AbstractImapCommandParser {
> +
> + public AuthenticateCommandParser() {
> + super(ImapCommand.nonAuthenticatedStateCommand(ImapConstants.AUTHENTICATE_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + String authType = astring(request);
> + endLine(request);
> + final ImapMessageFactory factory = getMessageFactory();
> + final ImapMessage result = factory.createAuthenticateMessage(command,
> + authType, tag);
> + return result;
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CapabilityCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CapabilityCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CapabilityCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CapabilityCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,53 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + * Parses CAPABILITY commands
> + *
> + */
> +public class CapabilityCommandParser extends AbstractImapCommandParser {
> +
> + public CapabilityCommandParser() {
> + super(ImapCommand.anyStateCommand(ImapConstants.CAPABILITY_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + endLine(request);
> + final ImapMessageFactory factory = getMessageFactory();
> + final ImapMessage result = factory
> + .createCapabilityMessage(command, tag);
> + return result;
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CheckCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CheckCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CheckCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CheckCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,51 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + * Parses CHECK commands
> + *
> + */
> +public class CheckCommandParser extends AbstractImapCommandParser {
> +
> + public CheckCommandParser() {
> + super(ImapCommand.selectedStateCommand(ImapConstants.CHECK_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + endLine(request);
> + final ImapMessage result = getMessageFactory().createCheckMessage(
> + command, tag);
> + return result;
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CloseCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CloseCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CloseCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CloseCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,53 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + *
> + * Parse CLOSE commands
> + *
> + */
> +class CloseCommandParser extends AbstractImapCommandParser {
> +
> + public CloseCommandParser() {
> + super(ImapCommand.selectedStateCommand(ImapConstants.CLOSE_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + endLine(request);
> + final ImapMessageFactory factory = getMessageFactory();
> + final ImapMessage result = factory.createCloseMessage(command, tag);
> + return result;
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,54 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.api.message.IdRange;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +
> +/**
> + * Parse COPY commands
> + *
> + */
> +public class CopyCommandParser extends AbstractUidCommandParser {
> +
> + public CopyCommandParser() {
> + super(ImapCommand.selectedStateCommand(ImapConstants.COPY_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.parser.AbstractUidCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, boolean, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, boolean useUids, Log logger)
> + throws DecodingException {
> + IdRange[] idSet = parseIdRange(request);
> + String mailboxName = mailbox(request);
> + endLine(request);
> + final ImapMessage result = getMessageFactory().createCopyMessage(
> + command, idSet, mailboxName, useUids, tag);
> + return result;
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CreateCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CreateCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CreateCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/CreateCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,54 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + * Parse CREATE commands
> + *
> + */
> +public class CreateCommandParser extends AbstractImapCommandParser {
> +
> + public CreateCommandParser() {
> + super(ImapCommand.authenticatedStateCommand(ImapConstants.CREATE_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + String mailboxName = mailbox(request);
> + endLine(request);
> + final ImapMessageFactory factory = getMessageFactory();
> + final ImapMessage result = factory.createCreateMessage(command,
> + mailboxName, tag);
> + return result;
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/DeleteCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/DeleteCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/DeleteCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/DeleteCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,54 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + * Parse DELETE commands
> + *
> + */
> +public class DeleteCommandParser extends AbstractImapCommandParser {
> +
> + public DeleteCommandParser() {
> + super(ImapCommand.authenticatedStateCommand(ImapConstants.DELETE_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + String mailboxName = mailbox(request);
> + endLine(request);
> + final ImapMessageFactory factory = getMessageFactory();
> + final ImapMessage result = factory.createDeleteMessage(command,
> + mailboxName, tag);
> + return result;
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,52 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + * Parse EXAMINE commands
> + *
> + */
> +public class ExamineCommandParser extends AbstractImapCommandParser {
> +
> + public ExamineCommandParser() {
> + super(ImapCommand.authenticatedStateCommand(ImapConstants.EXAMINE_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + final String mailboxName = mailbox(request);
> + endLine(request);
> + final ImapMessage result = getMessageFactory().createExamineMessage(
> + command, mailboxName, tag);
> + return result;
> + }
> +
> +}
>
> Added: james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java
> URL: http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java?rev=990364&view=auto
> ==============================================================================
> --- james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java (added)
> +++ james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java Sat Aug 28 13:55:56 2010
> @@ -0,0 +1,52 @@
> +/****************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one *
> + * or more contributor license agreements. See the NOTICE file *
> + * distributed with this work for additional information *
> + * regarding copyright ownership. The ASF licenses this file *
> + * to you 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.imap.decode.parser;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.james.imap.api.ImapMessageFactory;
> +import org.apache.james.imap.api.ImapCommand;
> +import org.apache.james.imap.api.ImapConstants;
> +import org.apache.james.imap.api.ImapMessage;
> +import org.apache.james.imap.decode.ImapRequestLineReader;
> +import org.apache.james.imap.decode.DecodingException;
> +import org.apache.james.imap.decode.base.AbstractImapCommandParser;
> +
> +/**
> + * Parse EXPUNGE commands
> + *
> + */
> +public class ExpungeCommandParser extends AbstractImapCommandParser {
> +
> + public ExpungeCommandParser() {
> + super(ImapCommand.selectedStateCommand(ImapConstants.EXPUNGE_COMMAND_NAME));
> + }
> +
> + /*
> + * (non-Javadoc)
> + * @see org.apache.james.imap.decode.base.AbstractImapCommandParser#decode(org.apache.james.imap.api.ImapCommand, org.apache.james.imap.decode.ImapRequestLineReader, java.lang.String, org.apache.commons.logging.Log)
> + */
> + protected ImapMessage decode(ImapCommand command,
> + ImapRequestLineReader request, String tag, Log logger) throws DecodingException {
> + endLine(request);
> + final ImapMessageFactory factory = getMessageFactory();
> + final ImapMessage result = factory.createExpungeMessage(command, tag);
> + return result;
> + }
> +
> +}
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
> For additional commands, e-mail: server-dev-help@james.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org