Just a minor comment from a quick review. The synchronized(session) should be removed.. You use an AtomicBoolean so you should be safe here..
Will have a deeper look later Bye, Nomrna 2010/12/15 <nik...@apache.org>: > Author: niklas > Date: Wed Dec 15 16:00:25 2010 > New Revision: 1049622 > > URL: http://svn.apache.org/viewvc?rev=1049622&view=rev > Log: > Added initial support for IDLE (IMAP-239). > > Added: > > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ContinuationReader.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/IdleRequest.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/response/ContinuationResponse.java > > james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/IdleProcessor.java > Modified: > > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapConstants.java > > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java > > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseWriter.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/main/ChannelImapResponseWriter.java > > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java > > james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/MockImapResponseWriter.java > > james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/base/ByteImapResponseWriter.java > > james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/DefaultProcessorChain.java > > Added: > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ContinuationReader.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ContinuationReader.java?rev=1049622&view=auto > ============================================================================== > --- > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ContinuationReader.java > (added) > +++ > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ContinuationReader.java > Wed Dec 15 16:00:25 2010 > @@ -0,0 +1,27 @@ > +/**************************************************************** > + * 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.api; > + > +import java.io.IOException; > + > +public interface ContinuationReader { > + > + public String readContinuation() throws IOException; > + > +} > > Modified: > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapConstants.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapConstants.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapConstants.java > (original) > +++ > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapConstants.java > Wed Dec 15 16:00:25 2010 > @@ -31,6 +31,8 @@ public interface ImapConstants { > > public static final String UNTAGGED = "*"; > > + public static final String CONTINUATION = "+"; > + > public static final String SP = " "; > > public static final String NIL = "NIL"; > @@ -105,6 +107,8 @@ public interface ImapConstants { > > public static final String SUPPORTS_STARTTLS = "STARTTLS"; > > + public static final String SUPPORTS_IDLE = "IDLE"; > + > public static final char HIERARCHY_DELIMITER_CHAR = '.'; > > public static final char NAMESPACE_PREFIX_CHAR = '#'; > @@ -183,6 +187,8 @@ public interface ImapConstants { > > public static final String NOOP_COMMAND_NAME = "NOOP"; > > + public static final String IDLE_COMMAND_NAME = "IDLE"; > + > public static final String LSUB_COMMAND_NAME = "LSUB"; > > public static final String LOGOUT_COMMAND_NAME = "LOGOUT"; > > Modified: > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java > (original) > +++ > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/ImapMessageFactory.java > Wed Dec 15 16:00:25 2010 > @@ -68,6 +68,9 @@ public interface ImapMessageFactory { > public ImapMessage createNoopMessage(final ImapCommand command, > final String tag); > > + public ImapMessage createIdleMessage(final ImapCommand command, > + final ContinuationReader reader, final String tag); > + > public ImapMessage createCloseMessage(final ImapCommand command, > final String tag); > > > Modified: > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java > (original) > +++ > james/imap/trunk/api/src/main/java/org/apache/james/imap/api/display/HumanReadableText.java > Wed Dec 15 16:00:25 2010 > @@ -196,6 +196,9 @@ public class HumanReadableText { > public static final HumanReadableText BYE_UNKNOWN_COMMAND = new > HumanReadableText( > "org.apache.james.imap.BYE_UNKNOWN_COMMAND", "Unknown command."); > > + public static final HumanReadableText IDLING = new HumanReadableText( > + "org.apache.james.imap.IDLING", "Idling"); > + > private final String defaultValue; > > private final String key; > > Modified: > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java > (original) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/ImapRequestLineReader.java > Wed Dec 15 16:00:25 2010 > @@ -19,8 +19,10 @@ > > package org.apache.james.imap.decode; > > +import java.io.IOException; > import java.io.InputStream; > > +import org.apache.james.imap.api.ContinuationReader; > import org.apache.james.imap.api.display.HumanReadableText; > > /** > @@ -30,7 +32,7 @@ import org.apache.james.imap.api.display > * > * @version $Revision: 109034 $ > */ > -public abstract class ImapRequestLineReader { > +public abstract class ImapRequestLineReader implements ContinuationReader { > > > protected boolean nextSeen = false; > @@ -154,4 +156,22 @@ public abstract class ImapRequestLineRea > } > consume(); > } > + > + public String readContinuation() throws IOException { > + // Consume the '\n' from the previous line. > + consume(); > + > + StringBuilder sb = new StringBuilder(); > + char next = nextChar(); > + while (next != '\r') { > + sb.append(next); > + consume(); > + next = nextChar(); > + } > + consume(); > + > + // NOTE: This code leaves the '\n' as next char. This seems to be > what is expected by the code which parses commands. > + > + return sb.toString(); > + } > } > > Added: > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java?rev=1049622&view=auto > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java > (added) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java > Wed Dec 15 16:00:25 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 IDLE commands > + * > + */ > +public class IdleCommandParser extends AbstractImapCommandParser { > + > + public IdleCommandParser() { > + > super(ImapCommand.selectedStateCommand(ImapConstants.IDLE_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().createIdleMessage(command, request, tag); > + return result; > + } > + > +} > > Modified: > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java > (original) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java > Wed Dec 15 16:00:25 2010 > @@ -104,7 +104,7 @@ public class ImapParserFactory implement > // _imapCommands.put( "MYRIGHTS", MyRightsCommand.class ); > > // Commands only valid in SELECTED state. > - // CHECK, CLOSE, EXPUNGE, SEARCH, FETCH, STORE, COPY, and UID > + // CHECK, CLOSE, EXPUNGE, SEARCH, FETCH, STORE, COPY, UID and IDLE > _imapCommands.put(ImapConstants.CHECK_COMMAND_NAME, > CheckCommandParser.class); > _imapCommands.put(ImapConstants.CLOSE_COMMAND_NAME, > @@ -121,6 +121,8 @@ public class ImapParserFactory implement > StoreCommandParser.class); > _imapCommands.put(ImapConstants.UID_COMMAND_NAME, > UidCommandParser.class); > + _imapCommands.put(ImapConstants.IDLE_COMMAND_NAME, > + IdleCommandParser.class); > _imapCommands.put(ImapConstants.STARTTLS, > StartTLSCommandParser.class); > } > > > Added: > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java?rev=1049622&view=auto > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java > (added) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java > Wed Dec 15 16:00:25 2010 > @@ -0,0 +1,60 @@ > +/**************************************************************** > + * 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.encode; > + > +import java.io.IOException; > +import java.util.ArrayList; > +import java.util.Locale; > + > +import org.apache.james.imap.api.ImapMessage; > +import org.apache.james.imap.api.display.HumanReadableText; > +import org.apache.james.imap.api.display.Locales; > +import org.apache.james.imap.api.display.Localizer; > +import org.apache.james.imap.api.process.ImapSession; > +import org.apache.james.imap.encode.base.AbstractChainedImapEncoder; > +import org.apache.james.imap.message.response.ContinuationResponse; > + > +public class ContinuationResponseEncoder extends AbstractChainedImapEncoder { > + > + private final Localizer localizer; > + > + public ContinuationResponseEncoder(ImapEncoder next, final Localizer > localizer) { > + super(next); > + this.localizer = localizer; > + } > + > + protected void doEncode(ImapMessage acceptableMessage, > + ImapResponseComposer composer, ImapSession session) throws > IOException { > + > + ContinuationResponse response = (ContinuationResponse) > acceptableMessage; > + final String message = response.getData() != null ? > response.getData() : asString(response.getTextKey(), session); > + composer.continuationResponse(message); > + } > + > + private String asString(HumanReadableText text, ImapSession session) { > + // TODO: calculate locales > + return localizer.localize(text, new Locales(new ArrayList<Locale>(), > null)); > + } > + > + protected boolean isAcceptable(ImapMessage message) { > + return (message instanceof ContinuationResponse); > + } > + > +} > > Modified: > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java > (original) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseComposer.java > Wed Dec 15 16:00:25 2010 > @@ -293,4 +293,13 @@ public interface ImapResponseComposer { > * @throws IOException > */ > public ImapResponseComposer capabilities(List<String> capabilities) > throws IOException; > + > + /** > + * Writes a continuation response. > + * > + * @param message > + * message for display, not null > + */ > + public abstract void continuationResponse(String message) throws > IOException; > + > } > \ No newline at end of file > > Modified: > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseWriter.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseWriter.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseWriter.java > (original) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/ImapResponseWriter.java > Wed Dec 15 16:00:25 2010 > @@ -47,6 +47,14 @@ public interface ImapResponseWriter { > void tag(String tag) throws IOException; > > /** > + * Starts a continuation response. > + * > + * @param message > + * the message, not null > + */ > + void continuation(String message) throws IOException; > + > + /** > * Writes a command name. > * > * @param commandName > > Modified: > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java > (original) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/encode/base/ImapResponseComposerImpl.java > Wed Dec 15 16:00:25 2010 > @@ -90,6 +90,15 @@ public class ImapResponseComposerImpl im > > /** > * @throws IOException > + * @see > org.apache.james.imap.encode.ImapResponseComposer#continuationResponse(String) > + */ > + public void continuationResponse(String message) throws IOException { > + writer.continuation(message); > + end(); > + } > + > + /** > + * @throws IOException > * @see > org.apache.james.imap.encode.ImapResponseComposer#flagsResponse(javax.mail.Flags) > */ > public void flagsResponse(Flags flags) throws IOException { > > 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=1049622&r1=1049621&r2=1049622&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 > Wed Dec 15 16:00:25 2010 > @@ -21,6 +21,7 @@ package org.apache.james.imap.encode.mai > > import org.apache.james.imap.api.display.Localizer; > import org.apache.james.imap.encode.CapabilityResponseEncoder; > +import org.apache.james.imap.encode.ContinuationResponseEncoder; > import org.apache.james.imap.encode.ExistsResponseEncoder; > import org.apache.james.imap.encode.ExpungeResponseEncoder; > import org.apache.james.imap.encode.FetchResponseEncoder; > @@ -73,7 +74,9 @@ public class DefaultImapEncoderFactory i > listResponseEncoder); > final CapabilityResponseEncoder capabilityResponseEncoder = new > CapabilityResponseEncoder( > flagsResponseEncoder); > - return capabilityResponseEncoder; > + final ContinuationResponseEncoder continuationResponseEncoder = new > ContinuationResponseEncoder( > + capabilityResponseEncoder, localizer); > + return continuationResponseEncoder; > } > > private final Localizer localizer; > > Modified: > james/imap/trunk/message/src/main/java/org/apache/james/imap/main/ChannelImapResponseWriter.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/main/ChannelImapResponseWriter.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/main/ChannelImapResponseWriter.java > (original) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/main/ChannelImapResponseWriter.java > Wed Dec 15 16:00:25 2010 > @@ -253,4 +253,8 @@ public class ChannelImapResponseWriter i > public void quoteUpperCaseAscii(String message) throws IOException { > upperCaseAscii(message, true); > } > + > + public void continuation(String message) throws IOException { > + writeASCII(CONTINUATION + SP + message); > + } > } > > Modified: > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java > (original) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/BaseImap4Rev1MessageFactory.java > Wed Dec 15 16:00:25 2010 > @@ -23,6 +23,7 @@ import java.util.Date; > > import javax.mail.Flags; > > +import org.apache.james.imap.api.ContinuationReader; > import org.apache.james.imap.api.ImapMessageFactory; > import org.apache.james.imap.api.ImapCommand; > import org.apache.james.imap.api.ImapMessage; > @@ -85,6 +86,14 @@ public class BaseImap4Rev1MessageFactory > > /* > * (non-Javadoc) > + * @see > org.apache.james.imap.api.ImapMessageFactory#createNoopMessage(org.apache.james.imap.api.ImapCommand, > java.lang.String) > + */ > + public ImapMessage createIdleMessage(ImapCommand command, > ContinuationReader reader, String tag) { > + return new IdleRequest(command, reader, tag); > + } > + > + /* > + * (non-Javadoc) > * @see > org.apache.james.imap.api.ImapMessageFactory#createCloseMessage(org.apache.james.imap.api.ImapCommand, > java.lang.String) > */ > public ImapMessage createCloseMessage(ImapCommand command, String tag) { > > Added: > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/IdleRequest.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/IdleRequest.java?rev=1049622&view=auto > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/IdleRequest.java > (added) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/request/IdleRequest.java > Wed Dec 15 16:00:25 2010 > @@ -0,0 +1,36 @@ > +/**************************************************************** > + * 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.message.request; > + > +import org.apache.james.imap.api.ContinuationReader; > +import org.apache.james.imap.api.ImapCommand; > + > +public class IdleRequest extends AbstractImapRequest { > + > + private final ContinuationReader reader; > + > + public IdleRequest(ImapCommand command, ContinuationReader reader, > String tag) { > + super(tag, command); > + this.reader = reader; > + } > + > + public ContinuationReader getContinuationReader() { > + return reader; > + } > +} > > Added: > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/response/ContinuationResponse.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/main/java/org/apache/james/imap/message/response/ContinuationResponse.java?rev=1049622&view=auto > ============================================================================== > --- > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/response/ContinuationResponse.java > (added) > +++ > james/imap/trunk/message/src/main/java/org/apache/james/imap/message/response/ContinuationResponse.java > Wed Dec 15 16:00:25 2010 > @@ -0,0 +1,50 @@ > +/**************************************************************** > + * 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.message.response; > + > +import org.apache.james.imap.api.display.HumanReadableText; > +import org.apache.james.imap.api.message.response.ImapResponseMessage; > + > +public class ContinuationResponse implements ImapResponseMessage { > + > + private final String data; > + > + private final HumanReadableText textKey; > + > + public ContinuationResponse(final String data) { > + super(); > + this.data = data; > + this.textKey = null; > + } > + > + public ContinuationResponse(final HumanReadableText textKey) { > + super(); > + this.data = null; > + this.textKey = textKey; > + } > + > + public String getData() { > + return data; > + } > + > + public HumanReadableText getTextKey() { > + return textKey; > + } > +} > > Modified: > james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/MockImapResponseWriter.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/MockImapResponseWriter.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/MockImapResponseWriter.java > (original) > +++ > james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/MockImapResponseWriter.java > Wed Dec 15 16:00:25 2010 > @@ -279,6 +279,17 @@ public class MockImapResponseWriter impl > > } > > + public static class ContinuationOperation { > + public boolean equals(Object obj) { > + return obj instanceof ContinuationOperation; > + } > + > + public int hashCode() { > + return 3; > + } > + > + } > + > public void closeParen() { > operations.add(new BracketOperation(false, false)); > } > @@ -442,4 +453,8 @@ public class MockImapResponseWriter impl > > public void space() { > } > + > + public void continuation(String message) { > + operations.add(new ContinuationOperation()); > + } > } > > Modified: > james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/base/ByteImapResponseWriter.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/base/ByteImapResponseWriter.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/base/ByteImapResponseWriter.java > (original) > +++ > james/imap/trunk/message/src/test/java/org/apache/james/imap/encode/base/ByteImapResponseWriter.java > Wed Dec 15 16:00:25 2010 > @@ -204,4 +204,8 @@ public class ByteImapResponseWriter impl > public void quoteUpperCaseAscii(String message) { > upperCaseAscii(message, true); > } > + > + public void continuation(String message) throws IOException { > + writer.print(CONTINUATION + SP + message); > + } > } > > Modified: > james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/DefaultProcessorChain.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/DefaultProcessorChain.java?rev=1049622&r1=1049621&r2=1049622&view=diff > ============================================================================== > --- > james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/DefaultProcessorChain.java > (original) > +++ > james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/DefaultProcessorChain.java > Wed Dec 15 16:00:25 2010 > @@ -84,8 +84,10 @@ public class DefaultProcessorChain { > appendProcessor, mailboxManager, statusResponseFactory); > final NoopProcessor noopProcessor = new NoopProcessor(storeProcessor, > mailboxManager, statusResponseFactory); > + final IdleProcessor idleProcessor = new IdleProcessor(noopProcessor, > + mailboxManager, statusResponseFactory); > final StatusProcessor statusProcessor = new StatusProcessor( > - noopProcessor, mailboxManager, statusResponseFactory); > + idleProcessor, mailboxManager, statusResponseFactory); > final LSubProcessor lsubProcessor = new LSubProcessor(statusProcessor, > mailboxManager, subscriptionManager, statusResponseFactory); > final ListProcessor listProcessor = new ListProcessor(lsubProcessor, > @@ -97,6 +99,7 @@ public class DefaultProcessorChain { > final NamespaceProcessor namespaceProcessor = new NamespaceProcessor( > selectProcessor, mailboxManager, statusResponseFactory); > > + capabilityProcessor.addProcessor(idleProcessor); > capabilityProcessor.addProcessor(namespaceProcessor); > > final ImapProcessor fetchProcessor = new > FetchProcessor(namespaceProcessor, > > Added: > james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/IdleProcessor.java > URL: > http://svn.apache.org/viewvc/james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/IdleProcessor.java?rev=1049622&view=auto > ============================================================================== > --- > james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/IdleProcessor.java > (added) > +++ > james/imap/trunk/processor/src/main/java/org/apache/james/imap/processor/IdleProcessor.java > Wed Dec 15 16:00:25 2010 > @@ -0,0 +1,134 @@ > +/**************************************************************** > + * 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.processor; > + > +import static org.apache.james.imap.api.ImapConstants.SUPPORTS_IDLE; > + > +import java.io.IOException; > +import java.util.Arrays; > +import java.util.List; > +import java.util.concurrent.atomic.AtomicBoolean; > + > +import org.apache.james.imap.api.ContinuationReader; > +import org.apache.james.imap.api.ImapCommand; > +import org.apache.james.imap.api.ImapMessage; > +import org.apache.james.imap.api.display.HumanReadableText; > +import org.apache.james.imap.api.message.request.ImapRequest; > +import org.apache.james.imap.api.message.response.StatusResponse; > +import org.apache.james.imap.api.message.response.StatusResponseFactory; > +import org.apache.james.imap.api.process.ImapProcessor; > +import org.apache.james.imap.api.process.ImapSession; > +import org.apache.james.imap.message.request.IdleRequest; > +import org.apache.james.imap.message.response.ContinuationResponse; > +import org.apache.james.imap.processor.base.ImapSessionUtils; > +import org.apache.james.mailbox.MailboxException; > +import org.apache.james.mailbox.MailboxListener; > +import org.apache.james.mailbox.MailboxManager; > +import org.apache.james.mailbox.MailboxSession; > + > +public class IdleProcessor extends AbstractMailboxProcessor implements > CapabilityImplementingProcessor { > + > + private final StatusResponseFactory factory; > + > + public IdleProcessor(final ImapProcessor next, final MailboxManager > mailboxManager, > + final StatusResponseFactory factory) { > + super(next, mailboxManager, factory); > + > + this.factory = factory; > + } > + > + protected boolean isAcceptable(ImapMessage message) { > + return (message instanceof IdleRequest); > + } > + > + protected void doProcess(ImapRequest message, ImapSession session, > + String tag, ImapCommand command, Responder responder) { > + > + try { > + IdleRequest request = (IdleRequest) message; > + ContinuationReader reader = request.getContinuationReader(); > + > + responder.respond(new > ContinuationResponse(HumanReadableText.IDLING)); > + unsolicitedResponses(session, responder, false); > + > + MailboxManager mailboxManager = getMailboxManager(); > + MailboxSession mailboxSession = > ImapSessionUtils.getMailboxSession(session); > + AtomicBoolean closed = new AtomicBoolean(false); > + > + String line = null; > + try { > + mailboxManager.addListener(session.getSelected().getPath(), > + new IdleMailboxListener(closed, session, responder), > mailboxSession); > + > + line = reader.readContinuation(); > + } finally { > + synchronized (session) { > + closed.set(true); > + } > + } > + if (!"DONE".equals(line.toUpperCase())) { > + StatusResponse response = factory.taggedBad(tag, command, > + HumanReadableText.INVALID_COMMAND); > + responder.respond(response); > + } else { > + okComplete(command, tag, responder); > + } > + } catch (IOException e) { > + // TODO: What should we do here? > + no(command, tag, responder, > HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING); > + } catch (MailboxException e) { > + // TODO: What should we do here? > + no(command, tag, responder, > HumanReadableText.GENERIC_FAILURE_DURING_PROCESSING); > + } > + } > + > + public List<String> getImplementedCapabilities(ImapSession session) { > + return Arrays.asList(SUPPORTS_IDLE); > + } > + > + private class IdleMailboxListener implements MailboxListener { > + > + private final AtomicBoolean closed; > + private final ImapSession session; > + private final Responder responder; > + > + public IdleMailboxListener(AtomicBoolean closed, ImapSession > session, Responder responder) { > + this.closed = closed; > + this.session = session; > + this.responder = responder; > + } > + > + public void event(Event event) { > + synchronized (session) { > + if (isClosed()) { > + return; > + } > + if (event instanceof Added || event instanceof Expunged || > event instanceof FlagsUpdated) { > + unsolicitedResponses(session, responder, false); > + } > + } > + } > + > + public boolean isClosed() { > + return closed.get(); > + } > + > + } > +} > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org > For additional commands, e-mail: server-dev-h...@james.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org