You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/05/09 02:25:04 UTC

[james-project] 06/07: [REFACTORING] Reaorder declarations in ImapRequestLineReader

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 3be6fc4e03246371832a6c8afd93e7fe609ae890
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri May 6 11:21:22 2022 +0700

    [REFACTORING] Reaorder declarations in ImapRequestLineReader
    
     - Nested class/interfaces first
     - Then constant
     - Then static methods
     - Then fields
     - Then abstract methods
     - Then regular methods
---
 .../james/imap/decode/ImapRequestLineReader.java   | 490 ++++++++++-----------
 1 file changed, 243 insertions(+), 247 deletions(-)

diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java
index 9f96244d1b..6672549531 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java
@@ -57,19 +57,258 @@ import org.apache.james.mailbox.MessageUid;
  * lookahead=1 on the underlying character stream. TODO need to look at encoding
  */
 public abstract class ImapRequestLineReader {
+    /**
+     * 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);
+    }
 
-    private static final int QUOTED_BUFFER_INITIAL_CAPACITY = 64;
+    /**
+     * Verifies subsequent characters match a specified string
+     */
+    public static class StringMatcherCharacterValidator implements CharacterValidator {
+        public static StringMatcherCharacterValidator ignoreCase(String expectedString) {
+            return new StringMatcherCharacterValidator(expectedString);
+        }
 
-    protected boolean nextSeen = false;
+        static boolean asciiEqualsIgnoringCase(Character c1, Character c2) {
+            return Character.toUpperCase(c1) == Character.toUpperCase(c2);
+        }
 
-    protected char nextChar; // unknown
+        private final String expectedString;
+        private int position = 0;
+
+        private StringMatcherCharacterValidator(String expectedString) {
+            this.expectedString = expectedString;
+        }
+
+        /**
+         * Verifies whether the next character is valid or not.
+         *
+         * This call will mutate StringValidator internal state, making it progress to following character validation.
+         */
+        @Override
+        public boolean isValid(char chr) {
+            if (position >= expectedString.length()) {
+                return false;
+            } else {
+                return asciiEqualsIgnoringCase(chr, expectedString.charAt(position++));
+            }
+        }
+    }
+
+    public static class NoopCharValidator implements CharacterValidator {
+        public static CharacterValidator INSTANCE = new NoopCharValidator();
+
+        @Override
+        public boolean isValid(char chr) {
+            return true;
+        }
+    }
+
+    public static class AtomCharValidator implements CharacterValidator {
+        public static CharacterValidator INSTANCE = new AtomCharValidator();
+
+        @Override
+        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 AtomCharValidator {
+        public static CharacterValidator INSTANCE = new TagCharValidator();
+
+        @Override
+        public boolean isValid(char chr) {
+            if (chr == '+') {
+                return false;
+            }
+            return super.isValid(chr);
+        }
+    }
+
+    public static class MessageSetCharValidator implements CharacterValidator {
+        public static CharacterValidator INSTANCE = new MessageSetCharValidator();
+
+        @Override
+        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();
+                return charBuffer.toString();
+
+            } 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(boolean endOfInput) throws DecodingException {
+            buffer.flip();
+            return decodeMoreBytesToCharacterBuffer(endOfInput);
+        }
+
+        private CoderResult decodeMoreBytesToCharacterBuffer(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);
+        }
+    }
 
+    private static final int QUOTED_BUFFER_INITIAL_CAPACITY = 64;
 
     public static int cap(char next) {
         return next > 'Z' ? next ^ 32 : next;
     }
-    
+
+    public static boolean isCHAR(char chr) {
+        return (chr >= 0x01 && chr <= 0x7f);
+    }
+
+    public static boolean isListWildcard(char chr) {
+        return (chr == '*' || chr == '%');
+    }
+
+    public static boolean isQuotedSpecial(char chr) {
+        return (chr == '"' || chr == '\\');
+    }
+
+    protected char nextChar; // unknown
+    protected boolean nextSeen = false;
+
+    /**
+     * Reads the next character in the current line. This method will continue
+     * to return the same character until the {@link #consume()} method is
+     * called.
+     *
+     * @return The next character TODO: character encoding is variable and
+     *         cannot be determine at the token level; this char is not accurate
+     *         reported; should be an octet
+     * @throws DecodingException
+     *             If the end-of-stream is reached.
+     */
+    public abstract char nextChar() throws DecodingException;
+
+    /**
+     * Reads and consumes a number of characters from the underlying reader,
+     * filling the char array provided. TODO: remove unnecessary copying of
+     * bits; line reader should maintain an internal ByteBuffer;
+     *
+     * @param size
+     *            count of characters to read and consume
+     * @param extraCRLF
+     *            <code>true</code> if extra CRLF is wanted, <code>false</code> else
+     * @throws DecodingException
+     *             If a char can't be read into each array element.
+     */
+    public abstract Literal read(int size, boolean extraCRLF) throws IOException;
+
+    /**
+     * Sends a server command continuation request '+' back to the client,
+     * requesting more data to be sent.
+     */
+    protected abstract void commandContinuationRequest() throws DecodingException;
+
     /**
      * Reads the next regular, non-space character in the current line. Spaces
      * are skipped over, but end-of-line characters will cause a
@@ -108,19 +347,6 @@ public abstract class ImapRequestLineReader {
         return Optional.of(next);
     }
 
-    /**
-     * Reads the next character in the current line. This method will continue
-     * to return the same character until the {@link #consume()} method is
-     * called.
-     * 
-     * @return The next character TODO: character encoding is variable and
-     *         cannot be determine at the token level; this char is not accurate
-     *         reported; should be an octet
-     * @throws DecodingException
-     *             If the end-of-stream is reached.
-     */
-    public abstract char nextChar() throws DecodingException;
-
     /**
      * Moves the request line reader to end of the line, checking that no
      * non-space character are found.
@@ -168,26 +394,6 @@ public abstract class ImapRequestLineReader {
         return current;
     }
 
-    /**
-     * Reads and consumes a number of characters from the underlying reader,
-     * filling the char array provided. TODO: remove unnecessary copying of
-     * bits; line reader should maintain an internal ByteBuffer;
-     * 
-     * @param size
-     *            count of characters to read and consume
-     * @param extraCRLF
-     *            <code>true</code> if extra CRLF is wanted, <code>false</code> else
-     * @throws DecodingException
-     *             If a char can't be read into each array element.
-     */
-    public abstract Literal read(int size, boolean extraCRLF) throws IOException;
-
-    /**
-     * Sends a server command continuation request '+' back to the client,
-     * requesting more data to be sent.
-     */
-    protected abstract void commandContinuationRequest() throws DecodingException;
-
     /**
      * Consume the rest of the line
      */
@@ -624,18 +830,6 @@ public abstract class ImapRequestLineReader {
         return number;
     }
 
-    public static boolean isCHAR(char chr) {
-        return (chr >= 0x01 && chr <= 0x7f);
-    }
-
-    public static boolean isListWildcard(char chr) {
-        return (chr == '*' || chr == '%');
-    }
-
-    public static boolean isQuotedSpecial(char chr) {
-        return (chr == '"' || chr == '\\');
-    }
-
     /**
      * Reads a "message set" argument, and parses into an IdSet.
      */
@@ -828,202 +1022,4 @@ public abstract class ImapRequestLineReader {
         }
     }
 
-    /**
-     * 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);
-    }
-
-    /**
-     * Verifies subsequent characters match a specified string
-     */
-    public static class StringMatcherCharacterValidator implements CharacterValidator {
-        public static StringMatcherCharacterValidator ignoreCase(String expectedString) {
-            return new StringMatcherCharacterValidator(expectedString);
-        }
-
-        static boolean asciiEqualsIgnoringCase(Character c1, Character c2) {
-            return Character.toUpperCase(c1) == Character.toUpperCase(c2);
-        }
-
-        private final String expectedString;
-        private int position = 0;
-
-        private StringMatcherCharacterValidator(String expectedString) {
-            this.expectedString = expectedString;
-        }
-
-        /**
-         * Verifies whether the next character is valid or not.
-         *
-         * This call will mutate StringValidator internal state, making it progress to following character validation.
-         */
-        @Override
-        public boolean isValid(char chr) {
-            if (position >= expectedString.length()) {
-                return false;
-            } else {
-                return asciiEqualsIgnoringCase(chr, expectedString.charAt(position++));
-            }
-        }
-    }
-
-    public static class NoopCharValidator implements CharacterValidator {
-        public static CharacterValidator INSTANCE = new NoopCharValidator();
-
-        @Override
-        public boolean isValid(char chr) {
-            return true;
-        }
-    }
-
-    public static class AtomCharValidator implements CharacterValidator {
-        public static CharacterValidator INSTANCE = new AtomCharValidator();
-
-        @Override
-        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 AtomCharValidator {
-        public static CharacterValidator INSTANCE = new TagCharValidator();
-
-        @Override
-        public boolean isValid(char chr) {
-            if (chr == '+') {
-                return false;
-            }
-            return super.isValid(chr);
-        }
-    }
-
-    public static class MessageSetCharValidator implements CharacterValidator {
-        public static CharacterValidator INSTANCE = new MessageSetCharValidator();
-
-        @Override
-        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();
-                return charBuffer.toString();
-
-            } 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(boolean endOfInput) throws DecodingException {
-            buffer.flip();
-            return decodeMoreBytesToCharacterBuffer(endOfInput);
-        }
-
-        private CoderResult decodeMoreBytesToCharacterBuffer(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);
-        }
-    }
-
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org