Author: norman
Date: Tue Jan 18 18:50:17 2011
New Revision: 1060532
URL: http://svn.apache.org/viewvc?rev=1060532&view=rev
Log:
switch to "real NIO" for imapserver
Added:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
- copied, changed from r1060047,
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapStreamChannelUpstreamHandler.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapLineHandlerAdapter.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapRequestLineReader.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapSession.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NotEnoughDataException.java
Removed:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/BlockingChannelBufferInputStream.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ChannelOutputStream.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapStreamChannelUpstreamHandler.java
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/StreamHandler.java
Modified:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
Added:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java?rev=1060532&view=auto
==============================================================================
---
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
(added)
+++
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
Tue Jan 18 18:50:17 2011
@@ -0,0 +1,81 @@
+/****************************************************************
+ * 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.imapserver.netty;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+
+import org.apache.james.imap.main.AbstractImapResponseWriter;
+import org.apache.james.imap.message.response.Literal;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBufferOutputStream;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+
+public class ChannelImapResponseWriter extends AbstractImapResponseWriter{
+
+ private Channel channel;
+ public ChannelImapResponseWriter(Channel channel) {
+ this.channel = channel;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.apache.james.imap.main.AbstractImapResponseWriter#write(java.nio.ByteBuffer)
+ */
+ protected void write(ByteBuffer buffer) throws IOException {
+ channel.write(ChannelBuffers.wrappedBuffer(buffer));
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.apache.james.imap.main.AbstractImapResponseWriter#write(org.apache.james.imap.message.response.Literal)
+ */
+ protected void write(Literal literal) throws IOException {
+ ChannelBuffer buf = ChannelBuffers.buffer((int)literal.size());
+ literal.writeTo(Channels.newChannel(new
ChannelBufferOutputStream(buf)));
+ channel.write(buf);
+ }
+
+
+ private final class ChannelWritableByteChannel implements
WritableByteChannel {
+
+ public void close() throws IOException {
+ // do nothing
+ }
+
+ public boolean isOpen() {
+ return channel.isOpen();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
+ */
+ public int write(ByteBuffer src) throws IOException {
+ int size = src.limit();
+ channel.write(ChannelBuffers.wrappedBuffer(src));
+ return size;
+ }
+
+ }
+}
Modified:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java?rev=1060532&r1=1060531&r2=1060532&view=diff
==============================================================================
---
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
(original)
+++
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
Tue Jan 18 18:50:17 2011
@@ -29,7 +29,6 @@ import org.apache.james.imap.api.ImapCon
import org.apache.james.imap.api.process.ImapProcessor;
import org.apache.james.imap.decode.ImapDecoder;
import org.apache.james.imap.encode.ImapEncoder;
-import org.apache.james.imap.main.ImapRequestStreamHandler;
import org.apache.james.protocols.impl.ChannelGroupHandler;
import org.apache.james.protocols.impl.TimeoutHandler;
import org.apache.james.protocols.lib.netty.AbstractConfigurableAsyncServer;
@@ -121,7 +120,8 @@ public class IMAPServer extends Abstract
// Add the text line decoder which limit the max line length,
don't strip the delimiter and use CRLF as delimiter
pipeline.addLast("framer", new
DelimiterBasedFrameDecoder(MAX_LINE_LENGTH, false, Delimiters.lineDelimiter()));
-
+ pipeline.addLast("requestDecoder", new
ImapRequestFrameDecoder(decoder));
+
if (isSSLSocket()) {
// We need to set clientMode to false.
@@ -133,12 +133,11 @@ public class IMAPServer extends Abstract
}
pipeline.addLast("connectionCountHandler",
getConnectionCountHandler());
- final ImapRequestStreamHandler handler = new
ImapRequestStreamHandler(decoder, processor, encoder);
if (isStartTLSSupported()) {
- pipeline.addLast("coreHandler", new
ImapStreamChannelUpstreamHandler(hello, handler, getLogger(), timer,
IMAPServer.this.getTimeout(), compress, getSSLContext(),
getEnabledCipherSuites()));
+ pipeline.addLast("coreHandler", new
ImapChannelUpstreamHandler(hello, processor, encoder, getLogger(), compress,
getSSLContext(), getEnabledCipherSuites()));
} else {
- pipeline.addLast("coreHandler", new
ImapStreamChannelUpstreamHandler(hello, handler, getLogger(), timer,
IMAPServer.this.getTimeout(), compress));
+ pipeline.addLast("coreHandler", new
ImapChannelUpstreamHandler(hello, processor, encoder, getLogger(), compress));
}
return pipeline;
Copied:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
(from r1060047,
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapStreamChannelUpstreamHandler.java)
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java?p2=james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java&p1=james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapStreamChannelUpstreamHandler.java&r1=1060047&r2=1060532&rev=1060532&view=diff
==============================================================================
---
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapStreamChannelUpstreamHandler.java
(original)
+++
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
Tue Jan 18 18:50:17 2011
@@ -20,17 +20,21 @@ package org.apache.james.imapserver.nett
import java.io.FilterOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
-import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import org.apache.commons.logging.Log;
-import org.apache.james.imap.api.ImapConstants;
-import org.apache.james.imap.main.ImapRequestStreamHandler;
-import org.apache.james.imap.main.ImapSessionImpl;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.api.ImapSessionState;
+import org.apache.james.imap.api.process.ImapProcessor;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.encode.ImapEncoder;
+import org.apache.james.imap.encode.ImapResponseComposer;
+import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
+import org.apache.james.imap.main.ResponseEncoder;
+import org.apache.james.protocols.impl.ChannelAttributeSupport;
import org.apache.james.protocols.impl.SessionLog;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
@@ -38,24 +42,21 @@ import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
-import org.jboss.netty.handler.codec.compression.ZlibDecoder;
-import org.jboss.netty.handler.codec.compression.ZlibEncoder;
-import org.jboss.netty.handler.codec.compression.ZlibWrapper;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.ssl.SslHandler;
-import org.jboss.netty.util.Timer;
/**
* {@link StreamHandler} which handles IMAP
*
*
*/
-public class ImapStreamChannelUpstreamHandler extends StreamHandler{
+public class ImapChannelUpstreamHandler extends SimpleChannelUpstreamHandler
implements ChannelAttributeSupport{
private final Log logger;
private final String hello;
- private final ImapRequestStreamHandler handler;
private String[] enabledCipherSuites;
@@ -63,19 +64,20 @@ public class ImapStreamChannelUpstreamHa
private boolean compress;
- private final static String IMAP_SESSION = "IMAP_SESSION";
- private final static String BUFFERED_OUT = "BUFFERED_OUT";
-
- public ImapStreamChannelUpstreamHandler(final String hello, final
ImapRequestStreamHandler handler, final Log logger, final Timer timer, final
long readTimeout, boolean compress) {
- this(hello, handler, logger, timer, readTimeout, compress, null, null);
+ private ImapProcessor processor;
+
+ private ImapEncoder encoder;
+
+ public ImapChannelUpstreamHandler(final String hello, final ImapProcessor
processor, ImapEncoder encoder, final Log logger, boolean compress) {
+ this(hello, processor, encoder, logger, compress, null, null);
}
- public ImapStreamChannelUpstreamHandler(final String hello, final
ImapRequestStreamHandler handler, final Log logger, final Timer timer, final
long readTimeout, boolean compress, SSLContext context, String[]
enabledCipherSuites) {
- super(timer, readTimeout, TimeUnit.SECONDS);
+ public ImapChannelUpstreamHandler(final String hello, final ImapProcessor
processor, ImapEncoder encoder, final Log logger, boolean compress, SSLContext
context, String[] enabledCipherSuites) {
this.logger = logger;
this.hello = hello;
- this.handler = handler;
+ this.processor = processor;
+ this.encoder = encoder;
this.context = context;
this.enabledCipherSuites = enabledCipherSuites;
this.compress = compress;
@@ -84,98 +86,12 @@ public class ImapStreamChannelUpstreamHa
private Log getLogger(Channel channel) {
return new SessionLog(""+channel.getId(), logger);
}
- @Override
- protected void processStreamIo(final ChannelHandlerContext ctx, final
InputStream in, final OutputStream out) {
- final ImapSessionImpl imapSession = (ImapSessionImpl)
getAttachment(ctx).get(IMAP_SESSION);
- Channel channel = ctx.getChannel();
-
- // Store the stream as attachment
- OutputStream bufferedOut = new StartTLSOutputStream(out);
- getAttachment(ctx).put(BUFFERED_OUT, bufferedOut);
-
-
- // handle requests in a loop
- while (channel.isConnected() && handler.handleRequest(in, bufferedOut,
imapSession));
-
- if (imapSession != null) imapSession.logout();
-
- getLogger(ctx.getChannel()).debug("Thread execution complete for
session " + channel.getId());
-
- channel.close();
- }
-
@Override
public void channelBound(final ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
- // create the imap session and store it in the IoSession for later
usage
- ImapSessionImpl imapsession = new ImapSessionImpl() {
-
- @Override
- public boolean startTLS() {
- if (supportStartTLS() == false) return false;
-
-
- OutputStream out =
(OutputStream)getAttachment(ctx).get(KEY_OUT);
- try {
- out.flush();
- } catch (IOException e) {
- getLog().info("Unable to start TLS", e);
- return false;
- }
-
-
- // enable buffering of the stream
-
((StartTLSOutputStream)getAttachment(ctx).get(BUFFERED_OUT)).bufferTillCRLF();
-
- SslHandler filter = new SslHandler(context.createSSLEngine(),
true);
- filter.getEngine().setUseClientMode(false);
- if (enabledCipherSuites != null && enabledCipherSuites.length
> 0) {
-
filter.getEngine().setEnabledCipherSuites(enabledCipherSuites);
- }
- if (ctx.getPipeline().get("zlibDecoder") == null) {
- ctx.getPipeline().addFirst("sslHandler", filter);
- } else {
- ctx.getPipeline().addAfter("zlibDecoder", "sslHandler",
filter);
-
- }
-
- return true;
- }
-
- @Override
- public boolean supportStartTLS() {
- return context != null;
- }
-
- @Override
- public boolean isCompressionSupported() {
- return compress;
- }
-
- @Override
- public boolean startCompression() {
- ctx.getChannel().setReadable(false);
- // enable buffering of the stream
- OutputStream out =
(OutputStream)getAttachment(ctx).get(KEY_OUT);
- try {
- out.flush();
- } catch (IOException e) {
- getLog().info("Unable to start compression", e);
- return false;
- }
- ctx.getPipeline().addFirst("zlibDecoder", new
ZlibDecoder(ZlibWrapper.NONE));
- ctx.getPipeline().addFirst("zlibEncoder", new
ZlibEncoder(ZlibWrapper.NONE, 5));
-
- ctx.getChannel().setReadable(true);
-
- return true;
- }
-
- };
- imapsession.setLog(getLogger(ctx.getChannel()));
-
- getAttachment(ctx).put(IMAP_SESSION, imapsession);
+ ImapSession imapsession = new NettyImapSession(ctx, logger, context,
enabledCipherSuites, compress);
+ attributes.set(ctx.getChannel(), imapsession);
super.channelBound(ctx, e);
}
@@ -194,8 +110,13 @@ public class ImapStreamChannelUpstreamHa
InetSocketAddress address = (InetSocketAddress)
ctx.getChannel().getRemoteAddress();
getLogger(ctx.getChannel()).info("Connection established from " +
address.getHostName() + " (" + address.getAddress().getHostAddress()+ ")");
+ ImapResponseComposer response = new ImapResponseComposerImpl(
+ new ChannelImapResponseWriter(ctx.getChannel()));
+ ctx.setAttachment(response);
+
// write hello to client
-
ctx.getChannel().write(ChannelBuffers.copiedBuffer((ImapConstants.UNTAGGED + "
OK " + hello +" " + new String(ImapConstants.BYTES_LINE_END)).getBytes()));
+ response.hello(hello);
+
//ctx.getChannel().write(ChannelBuffers.copiedBuffer((ImapConstants.UNTAGGED +
" OK " + hello +" " + new String(ImapConstants.BYTES_LINE_END)).getBytes()));
super.channelConnected(ctx, e);
@@ -206,7 +127,7 @@ public class ImapStreamChannelUpstreamHa
getLogger(ctx.getChannel()).debug("Error while processing imap
request" ,e.getCause());
// logout on error not sure if that is the best way to handle it
- final ImapSessionImpl imapSession = (ImapSessionImpl)
getAttachment(ctx).get(IMAP_SESSION);
+ final ImapSession imapSession = (ImapSession)
attributes.get(ctx.getChannel());
if (imapSession != null) imapSession.logout();
// just close the channel now!
@@ -215,6 +136,35 @@ public class ImapStreamChannelUpstreamHa
super.exceptionCaught(ctx, e);
}
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
+ ImapSession session = (ImapSession) attributes.get(ctx.getChannel());
+ ImapResponseComposer response = (ImapResponseComposer)
ctx.getAttachment();
+ ImapMessage message = (ImapMessage) e.getMessage();
+
+
+ final ResponseEncoder responseEncoder = new ResponseEncoder(encoder,
+ response, session);
+ processor.process(message, responseEncoder, session);
+
+ if (session.getState() == ImapSessionState.LOGOUT) {
+ ctx.getChannel().close();
+ }
+ final IOException failure = responseEncoder.getFailure();
+
+ if (failure != null) {
+ final Log logger = session.getLog();
+ logger.info(failure.getMessage());
+ if (logger.isDebugEnabled()) {
+ logger.debug("Failed to write " + message, failure);
+ }
+ throw failure;
+ }
+
+
+ super.messageReceived(ctx, e);
+ }
+
/**
* Because Netty {@link SslHandler} need to NOT encrypt the first response
send to client this {@link FilterOutputStream} is needed. It
* buffer the data till the complete response was written to the stream
(searching for the CRLF).
Added:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapLineHandlerAdapter.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapLineHandlerAdapter.java?rev=1060532&view=auto
==============================================================================
---
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapLineHandlerAdapter.java
(added)
+++
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapLineHandlerAdapter.java
Tue Jan 18 18:50:17 2011
@@ -0,0 +1,42 @@
+/****************************************************************
+ * 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.imapserver.netty;
+
+import org.apache.james.imap.api.process.ImapLineHandler;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.protocols.impl.ChannelAttributeSupport;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+
+public class ImapLineHandlerAdapter extends SimpleChannelUpstreamHandler
implements ChannelAttributeSupport{
+
+ private ImapLineHandler lineHandler;
+
+ public ImapLineHandlerAdapter(ImapLineHandler lineHandler) {
+ this.lineHandler = lineHandler;
+ }
+
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
+ lineHandler.onLine((ImapSession) attributes.get(ctx.getChannel()),
((ChannelBuffer)e.getMessage()).array());
+ }
+
+}
Added:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java?rev=1060532&view=auto
==============================================================================
---
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
(added)
+++
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
Tue Jan 18 18:50:17 2011
@@ -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.imapserver.netty;
+
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.decode.ImapDecoder;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.apache.james.protocols.impl.ChannelAttributeSupport;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.frame.FrameDecoder;
+
+/**
+ * {@link FrameDecoder} which will decode via and {@link ImapDecoder} instance
+ *
+ */
+public class ImapRequestFrameDecoder extends FrameDecoder implements
ChannelAttributeSupport{
+
+ private ImapDecoder decoder;
+
+ public ImapRequestFrameDecoder(ImapDecoder decoder) {
+ this.decoder = decoder;
+ }
+
+ @Override
+ protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buffer) throws Exception {
+ buffer.markReaderIndex();
+
+ // check if we failed before and if we already know how much data we
need to sucess next run
+ Object attachment = ctx.getAttachment();
+ if (attachment != null) {
+ int size = (Integer) attachment;
+ if (size != NotEnoughDataException.UNKNOWN_SIZE && size >
buffer.readableBytes()) {
+ buffer.resetReaderIndex();
+
+ return null;
+ }
+ }
+
+ try {
+ ImapRequestLineReader reader = new
NettyImapRequestLineReader(channel, buffer);
+ ImapMessage message = decoder.decode(reader, (ImapSession)
attributes.get(channel));
+
+ // ok no errors found consume the rest of the line
+ reader.consumeLine();
+
+ ctx.setAttachment(null);
+ return message;
+ } catch (NotEnoughDataException e) {
+ // this exception was thrown because we don't have enough data yet
+ int neededData = e.getDataSize();
+ ctx.setAttachment(neededData);
+ buffer.resetReaderIndex();
+ return null;
+ }
+ }
+
+}
Added:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapRequestLineReader.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapRequestLineReader.java?rev=1060532&view=auto
==============================================================================
---
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapRequestLineReader.java
(added)
+++
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapRequestLineReader.java
Tue Jan 18 18:50:17 2011
@@ -0,0 +1,80 @@
+/****************************************************************
+ * 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.imapserver.netty;
+
+import java.io.InputStream;
+
+import org.apache.james.imap.decode.DecodingException;
+import org.apache.james.imap.decode.ImapRequestLineReader;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBufferInputStream;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+
+public class NettyImapRequestLineReader extends ImapRequestLineReader{
+
+ private ChannelBuffer buffer;
+ private Channel channel;
+ private ChannelBuffer cRequest =
ChannelBuffers.wrappedBuffer("+\r\n".getBytes());
+
+ public NettyImapRequestLineReader(Channel channel, ChannelBuffer buffer) {
+ this.buffer = buffer;
+ this.channel = channel;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.decode.ImapRequestLineReader#nextChar()
+ */
+ public char nextChar() throws DecodingException {
+ if (!nextSeen) {
+ int next = -1;
+
+ try {
+ next = buffer.readByte();
+ } catch (IndexOutOfBoundsException e) {
+ throw new NotEnoughDataException();
+ }
+
+ nextSeen = true;
+ nextChar = (char) next;
+ }
+ return nextChar;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.decode.ImapRequestLineReader#read(int)
+ */
+ public InputStream read(int size) throws DecodingException {
+ if (size > buffer.readableBytes()) {
+ throw new NotEnoughDataException(size);
+ }
+ return new ChannelBufferInputStream(buffer, size);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.apache.james.imap.decode.ImapRequestLineReader#commandContinuationRequest()
+ */
+ protected void commandContinuationRequest() throws DecodingException {
+ channel.write(cRequest);
+ }
+}
Added:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapSession.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapSession.java?rev=1060532&view=auto
==============================================================================
---
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapSession.java
(added)
+++
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NettyImapSession.java
Tue Jan 18 18:50:17 2011
@@ -0,0 +1,238 @@
+/****************************************************************
+ * 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.imapserver.netty;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapSessionState;
+import org.apache.james.imap.api.process.ImapLineHandler;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.api.process.SelectedMailbox;
+import org.apache.james.protocols.impl.SessionLog;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.compression.ZlibDecoder;
+import org.jboss.netty.handler.codec.compression.ZlibEncoder;
+import org.jboss.netty.handler.codec.compression.ZlibWrapper;
+import org.jboss.netty.handler.ssl.SslHandler;
+
+public class NettyImapSession implements ImapSession{
+
+ private ImapSessionState state = ImapSessionState.NON_AUTHENTICATED;
+ private SelectedMailbox selectedMailbox;
+ private Map<String, Object> attributesByKey = new HashMap<String,
Object>();
+ private SSLContext sslContext;
+ private String[] enabledCipherSuites;
+ private boolean compress;
+ private SessionLog log;
+ private ChannelHandlerContext context;
+ private int handlerCount;
+
+ public NettyImapSession(ChannelHandlerContext context, Log log, SSLContext
sslContext, String[] enabledCipherSuites, boolean compress) {
+ this.context = context;
+ this.log = new SessionLog(context.getChannel().getId() + "", log);
+ this.sslContext = sslContext;
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.compress = compress;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#logout()
+ */
+ public void logout() {
+ closeMailbox();
+ state = ImapSessionState.LOGOUT;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#authenticated()
+ */
+ public void authenticated() {
+ this.state = ImapSessionState.AUTHENTICATED;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#deselect()
+ */
+ public void deselect() {
+ this.state = ImapSessionState.AUTHENTICATED;
+ closeMailbox();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.apache.james.imap.api.process.ImapSession#selected(org.apache.james.imap.api.process.SelectedMailbox)
+ */
+ public void selected(SelectedMailbox mailbox) {
+ this.state = ImapSessionState.SELECTED;
+ closeMailbox();
+ this.selectedMailbox = mailbox;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#getSelected()
+ */
+ public SelectedMailbox getSelected() {
+ return this.selectedMailbox;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#getState()
+ */
+ public ImapSessionState getState() {
+ return this.state;
+ }
+
+ private void closeMailbox() {
+ if (selectedMailbox != null) {
+ selectedMailbox.deselect();
+ selectedMailbox = null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.apache.james.imap.api.process.ImapSession#getAttribute(java.lang.String)
+ */
+ public Object getAttribute(String key) {
+ final Object result = attributesByKey .get(key);
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.apache.james.imap.api.process.ImapSession#setAttribute(java.lang.String,
java.lang.Object)
+ */
+ public void setAttribute(String key, Object value) {
+ if (value == null) {
+ attributesByKey.remove(key);
+ } else {
+ attributesByKey.put(key, value);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#startTLS()
+ */
+ public boolean startTLS() {
+ if (supportStartTLS() == false) return false;
+
+
+ /*
+ OutputStream out = (OutputStream)getAttachment(ctx).get(KEY_OUT);
+ try {
+ out.flush();
+ } catch (IOException e) {
+ getLog().info("Unable to start TLS", e);
+ return false;
+ }
+
+
+ // enable buffering of the stream
+
//((StartTLSOutputStream)getAttachment(ctx).get(BUFFERED_OUT)).bufferTillCRLF();
+*/
+ SslHandler filter = new SslHandler(sslContext.createSSLEngine(),
false);
+ filter.getEngine().setUseClientMode(false);
+ if (enabledCipherSuites != null && enabledCipherSuites.length > 0) {
+ filter.getEngine().setEnabledCipherSuites(enabledCipherSuites);
+ }
+ if (context.getPipeline().get("zlibDecoder") == null) {
+ context.getPipeline().addFirst("sslHandler", filter);
+ } else {
+ context.getPipeline().addAfter("zlibDecoder", "sslHandler",
filter);
+
+ }
+
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#supportStartTLS()
+ */
+ public boolean supportStartTLS() {
+ return sslContext != null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.apache.james.imap.api.process.ImapSession#isCompressionSupported()
+ */
+ public boolean isCompressionSupported() {
+ return compress;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#startCompression()
+ */
+ public boolean startCompression() {
+ context.getChannel().setReadable(false);
+ /*
+ // enable buffering of the stream
+ OutputStream out = (OutputStream)getAttachment(ctx).get(KEY_OUT);
+ try {
+ out.flush();
+ } catch (IOException e) {
+ getLog().info("Unable to start compression", e);
+ return false;
+ }
+ */
+ context.getPipeline().addFirst("zlibDecoder", new
ZlibDecoder(ZlibWrapper.NONE));
+ context.getPipeline().addFirst("zlibEncoder", new
ZlibEncoder(ZlibWrapper.NONE, 5));
+
+ context.getChannel().setReadable(true);
+
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
org.apache.james.imap.api.process.ImapSession#pushLineHandler(org.apache.james.imap.api.process.ImapLineHandler)
+ */
+ public void pushLineHandler(ImapLineHandler lineHandler) {
+ context.getPipeline().addBefore("requestDecoder", "lineHandler" +
handlerCount++, new ImapLineHandlerAdapter(lineHandler));
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#popLineHandler()
+ */
+ public void popLineHandler() {
+ context.getPipeline().remove("lineHandler" + --handlerCount);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.james.imap.api.process.ImapSession#getLog()
+ */
+ public Log getLog() {
+ return log;
+ }
+
+}
Added:
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NotEnoughDataException.java
URL:
http://svn.apache.org/viewvc/james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NotEnoughDataException.java?rev=1060532&view=auto
==============================================================================
---
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NotEnoughDataException.java
(added)
+++
james/server/trunk/imapserver/src/main/java/org/apache/james/imapserver/netty/NotEnoughDataException.java
Tue Jan 18 18:50:17 2011
@@ -0,0 +1,37 @@
+/****************************************************************
+ * 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.imapserver.netty;
+
+public class NotEnoughDataException extends RuntimeException{
+
+ public final static int UNKNOWN_SIZE = -1;
+ private int size;
+
+ public NotEnoughDataException(int size) {
+ this.size = size;
+ }
+
+ public NotEnoughDataException() {
+ this(UNKNOWN_SIZE);
+ }
+ public int getDataSize() {
+ return size;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]