Author: rdonkin
Date: Mon May 18 10:53:01 2009
New Revision: 775895

URL: http://svn.apache.org/viewvc?rev=775895&view=rev
Log:
IMAP-91 Add configuration parameter to default encoder factory to enable a 
workaround for broken clients. https://issues.apache.org/jira/browse/IMAP-91

Added:
    
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java
      - copied, changed from r775865, 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java
Modified:
    
james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
    
james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java
    
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java
    
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java

Modified: 
james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java?rev=775895&r1=775894&r2=775895&view=diff
==============================================================================
--- 
james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
 (original)
+++ 
james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
 Mon May 18 10:53:01 2009
@@ -40,8 +40,18 @@
 
 public class FetchResponseEncoder extends AbstractChainedImapEncoder {
 
-    public FetchResponseEncoder(final ImapEncoder next) {
+    /** Disables all optional BODYSTRUCTURE extensions */
+    private final boolean neverAddBodyStructureExtensions;
+    
+    /**
+     * Constructs an encoder for FETCH messages.
+     * @param next not null
+     * @param neverAddBodyStructureExtensions true to activate a workaround 
for broken clients who
+     * cannot parse BODYSTRUCTURE extensions, false to fully support RFC3501
+     */
+    public FetchResponseEncoder(final ImapEncoder next, final boolean 
neverAddBodyStructureExtensions) {
         super(next);
+        this.neverAddBodyStructureExtensions = neverAddBodyStructureExtensions;
     }
 
     public boolean isAcceptable(final ImapMessage message) {
@@ -104,12 +114,17 @@
             final Structure structure, final boolean includeExtensions,
             final String mediaType, final String subType, boolean isInnerPart, 
ImapSession session)
             throws IOException {
+        //
+        // Workaround for broken clients
+        // See IMAP-91
+        //
+        final boolean includeOptionalExtensions = includeExtensions && 
!neverAddBodyStructureExtensions;
         if (isInnerPart) {
             composer.skipNextSpace();
         }
         if (ImapConstants.MIME_TYPE_MULTIPART.equalsIgnoreCase(mediaType)) {
 
-            encodeMultipart(composer, structure, subType, includeExtensions, 
session);
+            encodeMultipart(composer, structure, subType, 
includeOptionalExtensions, session);
 
         } else {
             if (ImapConstants.MIME_TYPE_MESSAGE.equalsIgnoreCase(mediaType)
@@ -117,9 +132,9 @@
                             .equalsIgnoreCase(subType)) {
 
                 encodeRfc822Message(composer, structure, mediaType, subType,
-                        includeExtensions, session);
+                        includeOptionalExtensions, session);
             } else {
-                encodeBasic(composer, structure, includeExtensions, mediaType,
+                encodeBasic(composer, structure, includeOptionalExtensions, 
mediaType,
                         subType, session);
             }
         }

Modified: 
james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java?rev=775895&r1=775894&r2=775895&view=diff
==============================================================================
--- 
james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java
 (original)
+++ 
james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java
 Mon May 18 10:53:01 2009
@@ -41,7 +41,14 @@
  */
 public class DefaultImapEncoderFactory implements ImapEncoderFactory {
 
-    public static final ImapEncoder createDefaultEncoder(final Localizer 
localizer) {
+    /**
+     * Builds the default encoder
+     * @param localizer not null
+     * @param neverAddBodyStructureExtensions true to activate a workaround 
for broken clients who
+     * cannot parse BODYSTRUCTURE extensions, false to fully support RFC3501
+     * @return not null
+     */
+    public static final ImapEncoder createDefaultEncoder(final Localizer 
localizer, final boolean neverAddBodyStructureExtensions) {
         final EndImapEncoder endImapEncoder = new EndImapEncoder();
         final NamespaceResponseEncoder namespaceEncoder = new 
NamespaceResponseEncoder(endImapEncoder);
         final StatusResponseEncoder statusResponseEncoder = new 
StatusResponseEncoder(
@@ -49,7 +56,7 @@
         final RecentResponseEncoder recentResponseEncoder = new 
RecentResponseEncoder(
                 statusResponseEncoder);
         final FetchResponseEncoder fetchResponseEncoder = new 
FetchResponseEncoder(
-                recentResponseEncoder);
+                recentResponseEncoder, neverAddBodyStructureExtensions);
         final ExpungeResponseEncoder expungeResponseEncoder = new 
ExpungeResponseEncoder(
                 fetchResponseEncoder);
         final ExistsResponseEncoder existsResponseEncoder = new 
ExistsResponseEncoder(
@@ -70,18 +77,26 @@
     }
 
     private final Localizer localizer;
+    private final boolean neverAddBodyStructureExtensions;
     
     public DefaultImapEncoderFactory() {
-        this(new DefaultLocalizer());
+        this(new DefaultLocalizer(), false);
     }
     
-    public DefaultImapEncoderFactory(final Localizer localizer) {
+    /**
+     * Constructs the default factory for encoders
+     * @param localizer not null
+     * @param neverAddBodyStructureExtensions true to activate a workaround 
for broken clients who
+     * cannot parse BODYSTRUCTURE extensions, false to fully support RFC3501
+     */
+    public DefaultImapEncoderFactory(final Localizer localizer, boolean 
neverAddBodyStructureExtensions) {
         super();
         this.localizer = localizer;
+        this.neverAddBodyStructureExtensions = neverAddBodyStructureExtensions;
     }
 
     public ImapEncoder buildImapEncoder() {
-        return createDefaultEncoder(localizer);
+        return createDefaultEncoder(localizer, 
neverAddBodyStructureExtensions);
     }
 
 }

Modified: 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java?rev=775895&r1=775894&r2=775895&view=diff
==============================================================================
--- 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java
 (original)
+++ 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java
 Mon May 18 10:53:01 2009
@@ -103,7 +103,7 @@
         message = new FetchResponse(MSN, null, null, null, null, envelope, 
null, null, null);
         composer = mock(ImapResponseComposer.class);
         mockNextEncoder = mock(ImapEncoder.class);
-        encoder = new FetchResponseEncoder(mockNextEncoder);
+        encoder = new FetchResponseEncoder(mockNextEncoder, false);
         stubCommand = ImapCommand.anyStateCommand("COMMAND");
         flags = new Flags(Flags.Flag.DELETED);
     }

Copied: 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java
 (from r775865, 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java)
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java?p2=james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java&p1=james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java&r1=775865&r2=775895&rev=775895&view=diff
==============================================================================
--- 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java
 (original)
+++ 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java
 Mon May 18 10:53:01 2009
@@ -19,6 +19,11 @@
 
 package org.apache.james.imap.encode;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import javax.mail.Flags;
 
 import org.apache.james.imap.api.ImapCommand;
@@ -31,12 +36,13 @@
 import org.jmock.Sequence;
 import org.jmock.integration.junit3.MockObjectTestCase;
 
-public class FetchResponseEncoderTest extends MockObjectTestCase {
+public class FetchResponseEncoderNoExtensionsTest extends MockObjectTestCase {
 
     Flags flags;
 
     ImapResponseComposer composer;
 
+    FetchResponse.Structure stubStructure;
 
     ImapEncoder mockNextEncoder;
 
@@ -48,9 +54,10 @@
         super.setUp();
         composer = mock(ImapResponseComposer.class);
         mockNextEncoder = mock(ImapEncoder.class);
-        encoder = new FetchResponseEncoder(mockNextEncoder);
+        encoder = new FetchResponseEncoder(mockNextEncoder, true);
         stubCommand = ImapCommand.anyStateCommand("COMMAND");
         flags = new Flags(Flags.Flag.DELETED);
+        stubStructure = mock(FetchResponse.Structure.class);
     }
 
     protected void tearDown() throws Exception {
@@ -104,4 +111,47 @@
         }});
         encoder.doEncode(message, composer, new FakeImapSession());
     }
+    
+    public void testShouldNotAddExtensionsWithEncodingBodyStructure() throws 
Exception {
+        FetchResponse message = new FetchResponse(100, flags, new Long(72),
+                null, null, null, null, stubStructure, null);
+        final Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put("CHARSET", "US-ASCII");
+        final List<String> parameterList= new ArrayList<String>();
+        parameterList.add("CHARSET");
+        parameterList.add("US-ASCII");
+        
+        checking(new Expectations() {{
+            final long octets = 2279L;
+            final long lines = 48L;
+            allowing(stubStructure).getMediaType(); will(returnValue("TEXT"));
+            allowing(stubStructure).getSubType(); will(returnValue("HTML"));
+            allowing(stubStructure).getOctets();will(returnValue(octets));
+            allowing(stubStructure).getLines();will(returnValue(lines));
+            allowing(stubStructure).getParameters(); 
will(returnValue(parameterList));
+            allowing(stubStructure).getEncoding(); will(returnValue("7BIT"));
+            ignoring(stubStructure);
+            
+            final Sequence sequence = sequence("composition");
+            oneOf(composer).openFetchResponse(with(equal(100L))); 
inSequence(sequence);
+            oneOf(composer).flags(with(equal(flags))); inSequence(sequence);
+            
oneOf(composer).message(with(equal("BODYSTRUCTURE")));inSequence(sequence);
+            
oneOf(composer).openParen();will(returnValue(composer));inSequence(sequence);
+            
oneOf(composer).quoteUpperCaseAscii("TEXT");will(returnValue(composer));inSequence(sequence);
+            
oneOf(composer).quoteUpperCaseAscii("HTML");will(returnValue(composer));inSequence(sequence);
+            
oneOf(composer).nillableQuotes(parameterList);will(returnValue(composer));inSequence(sequence);
+            
oneOf(composer).nillableQuote("");will(returnValue(composer));inSequence(sequence);
+            
oneOf(composer).nillableQuote("");will(returnValue(composer));inSequence(sequence);
+            
oneOf(composer).quoteUpperCaseAscii("7BIT");will(returnValue(composer));inSequence(sequence);
+            oneOf(composer).message(octets);inSequence(sequence);
+            oneOf(composer).message(lines);inSequence(sequence);
+            oneOf(composer).closeParen();inSequence(sequence);
+            oneOf(composer).message(with(equal("UID"))); inSequence(sequence);
+            oneOf(composer).message(with(equal(72L))); inSequence(sequence);
+            oneOf(composer).closeFetchResponse(); inSequence(sequence);
+           ;
+        }});
+        final FakeImapSession fakeImapSession = new FakeImapSession();
+        encoder.doEncode(message, composer, fakeImapSession);
+    }
 }

Modified: 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java
URL: 
http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java?rev=775895&r1=775894&r2=775895&view=diff
==============================================================================
--- 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java
 (original)
+++ 
james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java
 Mon May 18 10:53:01 2009
@@ -48,7 +48,7 @@
         super.setUp();
         composer = mock(ImapResponseComposer.class);
         mockNextEncoder = mock(ImapEncoder.class);
-        encoder = new FetchResponseEncoder(mockNextEncoder);
+        encoder = new FetchResponseEncoder(mockNextEncoder, false);
         stubCommand = ImapCommand.anyStateCommand("COMMAND");
         flags = new Flags(Flags.Flag.DELETED);
     }



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to