Author: btellier Date: Thu Dec 17 14:53:00 2015 New Revision: 1720566 URL: http://svn.apache.org/viewvc?rev=1720566&view=rev Log: JAMES-1618 Write a ManageSieve server
Added: james/project/trunk/server/protocols/protocols-managesieve/ james/project/trunk/server/protocols/protocols-managesieve/pom.xml james/project/trunk/server/protocols/protocols-managesieve/src/ james/project/trunk/server/protocols/protocols-managesieve/src/main/ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServer.java james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServerFactory.java Modified: james/project/trunk/server/pom.xml Modified: james/project/trunk/server/pom.xml URL: http://svn.apache.org/viewvc/james/project/trunk/server/pom.xml?rev=1720566&r1=1720565&r2=1720566&view=diff ============================================================================== --- james/project/trunk/server/pom.xml (original) +++ james/project/trunk/server/pom.xml Thu Dec 17 14:53:00 2015 @@ -94,6 +94,7 @@ <module>protocols/jmap-integration-testing</module> <module>protocols/protocols-library</module> <module>protocols/protocols-lmtp</module> + <module>protocols/protocols-managesieve</module> <module>protocols/protocols-pop3</module> <module>protocols/protocols-smtp</module> Added: james/project/trunk/server/protocols/protocols-managesieve/pom.xml URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/protocols-managesieve/pom.xml?rev=1720566&view=auto ============================================================================== --- james/project/trunk/server/protocols/protocols-managesieve/pom.xml (added) +++ james/project/trunk/server/protocols/protocols-managesieve/pom.xml Thu Dec 17 14:53:00 2015 @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>james-server</artifactId> + <groupId>org.apache.james</groupId> + <version>3.0.0-beta5-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>james-server-protocols-managesieve</artifactId> + + <dependencies> + <dependency> + <groupId>org.apache.james</groupId> + <artifactId>james-server-protocols-library</artifactId> + </dependency> + <dependency> + <groupId>org.apache.james</groupId> + <artifactId>james-server-filesystem-api</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.james.protocols</groupId> + <artifactId>protocols-managesieve</artifactId> + <version>${protocols.version}</version> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + <dependency> + <groupId>org.apache.james.protocols</groupId> + <artifactId>protocols-netty</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>commons-configuration</groupId> + <artifactId>commons-configuration</artifactId> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty</artifactId> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-annotation_1.1_spec</artifactId> + </dependency> + <dependency> + <groupId>javax.inject</groupId> + <artifactId>javax.inject</artifactId> + </dependency> + </dependencies> + + +</project> \ No newline at end of file Added: james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java?rev=1720566&view=auto ============================================================================== --- james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java (added) +++ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java Thu Dec 17 14:53:00 2015 @@ -0,0 +1,43 @@ +/**************************************************************** + * 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.managesieveserver.netty; + +import org.jboss.netty.channel.Channel; +import org.jboss.netty.handler.stream.ChunkedStream; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +public class ChannelManageSieveResponseWriter { + private final Channel channel; + + public ChannelManageSieveResponseWriter(Channel channel) { + this.channel = channel; + } + + public void write(String response) throws IOException { + if (channel.isConnected()) { + InputStream in = new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8)); + channel.write(new ChunkedStream(in)); + } + } +} Added: james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java?rev=1720566&view=auto ============================================================================== --- james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java (added) +++ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java Thu Dec 17 14:53:00 2015 @@ -0,0 +1,102 @@ +/**************************************************************** + * 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.managesieveserver.netty; + +import org.apache.james.managesieve.api.Session; +import org.apache.james.managesieve.transcode.ManageSieveProcessor; +import org.apache.james.managesieve.util.SettableSession; +import org.apache.james.protocols.api.logger.ProtocolLoggerAdapter; +import org.apache.james.protocols.api.logger.ProtocolSessionLogger; +import org.apache.james.protocols.lib.Slf4jLoggerAdapter; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFutureListener; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelLocal; +import org.jboss.netty.channel.ChannelStateEvent; +import org.jboss.netty.channel.ExceptionEvent; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelUpstreamHandler; +import org.jboss.netty.handler.codec.frame.TooLongFrameException; +import org.slf4j.Logger; + +import java.net.InetSocketAddress; + +public class ManageSieveChannelUpstreamHandler extends SimpleChannelUpstreamHandler { + + private final Logger logger; + private final ChannelLocal<Session> attributes; + private final ManageSieveProcessor manageSieveProcessor; + + public ManageSieveChannelUpstreamHandler(ManageSieveProcessor manageSieveProcessor, Logger logger) { + this.logger = logger; + this.attributes = new ChannelLocal<Session>(); + this.manageSieveProcessor = manageSieveProcessor; + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + String request = (String) e.getMessage(); + Session manageSieveSession = attributes.get(ctx.getChannel()); + String responseString = manageSieveProcessor.handleRequest(manageSieveSession, request); + ((ChannelManageSieveResponseWriter)ctx.getAttachment()).write(responseString); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { + getLogger(ctx.getChannel()).warn("Error while processing imap request: " + e.getCause().getClass().getName() + " - " + e.getCause().getMessage()); + getLogger(ctx.getChannel()).debug("Error while processing imap request", e.getCause()); + + if (e.getCause() instanceof TooLongFrameException) { + // Max line length exceeded + // + // See also JAMES-1190 + ((ChannelManageSieveResponseWriter)ctx.getAttachment()).write("NO Maximum command line length exceeded"); + } else { + // logout on error not sure if that is the best way to handle it + attributes.remove(ctx.getChannel()); + + // Make sure we close the channel after all the buffers were flushed out + Channel channel = ctx.getChannel(); + if (channel.isConnected()) { + channel.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); + } + } + } + + @Override + public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { + attributes.set(ctx.getChannel(), new SettableSession()); + ctx.setAttachment(new ChannelManageSieveResponseWriter(ctx.getChannel())); + super.channelBound(ctx, e); + } + + @Override + public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { + InetSocketAddress address = (InetSocketAddress) ctx.getChannel().getRemoteAddress(); + getLogger(ctx.getChannel()).info("Connection closed for " + address.getAddress().getHostAddress()); + attributes.remove(ctx.getChannel()); + super.channelClosed(ctx, e); + } + + private Logger getLogger(Channel channel) { + return new Slf4jLoggerAdapter(new ProtocolSessionLogger("" + channel.getId(), new ProtocolLoggerAdapter(logger))); + } +} Added: james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServer.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServer.java?rev=1720566&view=auto ============================================================================== --- james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServer.java (added) +++ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServer.java Thu Dec 17 14:53:00 2015 @@ -0,0 +1,131 @@ +/**************************************************************** + * 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.managesieveserver.netty; + +import org.apache.james.managesieve.transcode.ManageSieveProcessor; +import org.apache.james.protocols.api.Encryption; +import org.apache.james.protocols.lib.netty.AbstractConfigurableAsyncServer; +import org.apache.james.protocols.netty.ChannelGroupHandler; +import org.apache.james.protocols.netty.ConnectionLimitUpstreamHandler; +import org.apache.james.protocols.netty.ConnectionPerIpLimitUpstreamHandler; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.ChannelUpstreamHandler; +import org.jboss.netty.channel.group.ChannelGroup; +import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder; +import org.jboss.netty.handler.codec.frame.Delimiters; +import org.jboss.netty.handler.codec.string.StringDecoder; +import org.jboss.netty.handler.codec.string.StringEncoder; +import org.jboss.netty.handler.execution.ExecutionHandler; +import org.jboss.netty.handler.ssl.SslHandler; +import org.jboss.netty.handler.stream.ChunkedWriteHandler; +import org.jboss.netty.util.CharsetUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLEngine; + +import static org.jboss.netty.channel.Channels.pipeline; + +public class ManageSieveServer extends AbstractConfigurableAsyncServer { + + private static final Logger LOGGER = LoggerFactory.getLogger(ManageSieveServer.class); + + final static String SSL_HANDLER = "sslHandler"; + final static String FRAMER = "framer"; + final static String CORE_HANDLER = "coreHandler"; + final static String GROUP_HANDLER = "groupHandler"; + final static String CONNECTION_LIMIT_HANDLER = "connectionLimitHandler"; + final static String CONNECTION_LIMIT_PER_IP_HANDLER = "connectionPerIpLimitHandler"; + final static String CONNECTION_COUNT_HANDLER = "connectionCountHandler"; + final static String CHUNK_WRITE_HANDLER = "chunkWriteHandler"; + final static String EXECUTION_HANDLER = "executionHandler"; + + + private int maxLineLength; + private ManageSieveProcessor manageSieveProcessor; + + public ManageSieveServer(int maxLineLength, ManageSieveProcessor manageSieveProcessor) { + this.maxLineLength = maxLineLength; + this.manageSieveProcessor = manageSieveProcessor; + } + + @Override + protected int getDefaultPort() { + return 4190; + } + + @Override + protected String getDefaultJMXName() { + return "managesieveserver"; + } + + @Override + protected ChannelUpstreamHandler createCoreHandler() { + return new ManageSieveChannelUpstreamHandler(manageSieveProcessor, LOGGER); + } + + @Override + protected ChannelPipelineFactory createPipelineFactory(final ChannelGroup group) { + + return new ChannelPipelineFactory() { + + private final ChannelGroupHandler groupHandler = new ChannelGroupHandler(group); + + public ChannelPipeline getPipeline() throws Exception { + ChannelPipeline pipeline = pipeline(); + Encryption secure = getEncryption(); + if (secure != null && !secure.isStartTLS()) { + // We need to set clientMode to false. + // See https://issues.apache.org/jira/browse/JAMES-1025 + SSLEngine engine = secure.getContext().createSSLEngine(); + engine.setUseClientMode(false); + pipeline.addFirst(SSL_HANDLER, new SslHandler(engine)); + + } + pipeline.addLast(GROUP_HANDLER, groupHandler); + pipeline.addLast(CONNECTION_LIMIT_HANDLER, new ConnectionLimitUpstreamHandler(ManageSieveServer.this.connectionLimit)); + pipeline.addLast(CONNECTION_LIMIT_PER_IP_HANDLER, new ConnectionPerIpLimitUpstreamHandler(ManageSieveServer.this.connPerIP)); + // Add the text line decoder which limit the max line length, + // don't strip the delimiter and use CRLF as delimiter + // Use a SwitchableDelimiterBasedFrameDecoder, see JAMES-1436 + pipeline.addLast(FRAMER, new DelimiterBasedFrameDecoder(maxLineLength, false, Delimiters.lineDelimiter())); + pipeline.addLast(CONNECTION_COUNT_HANDLER, getConnectionCountHandler()); + pipeline.addLast(CHUNK_WRITE_HANDLER, new ChunkedWriteHandler()); + + ExecutionHandler ehandler = getExecutionHandler(); + if (ehandler != null) { + pipeline.addLast(EXECUTION_HANDLER, ehandler); + + } + pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8)); + pipeline.addLast(CORE_HANDLER, createCoreHandler()); + pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8)); + return pipeline; + } + + }; + } + + @Override + public String getServiceType() { + return "Manage Sieve Service"; + } +} Added: james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServerFactory.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServerFactory.java?rev=1720566&view=auto ============================================================================== --- james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServerFactory.java (added) +++ james/project/trunk/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveServerFactory.java Thu Dec 17 14:53:00 2015 @@ -0,0 +1,76 @@ +/**************************************************************** + * 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.managesieveserver.netty; + +import org.apache.commons.configuration.HierarchicalConfiguration; +import org.apache.james.filesystem.api.FileSystem; +import org.apache.james.managesieve.transcode.ManageSieveProcessor; +import org.apache.james.protocols.lib.netty.AbstractConfigurableAsyncServer; +import org.apache.james.protocols.lib.netty.AbstractServerFactory; +import org.apache.james.sieverepository.api.SieveRepository; +import org.apache.james.user.api.UsersRepository; +import org.slf4j.Logger; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; + +public class ManageSieveServerFactory extends AbstractServerFactory { + + private SieveRepository sieveRepository; + private UsersRepository usersRepository; + private FileSystem fileSystem; + private ManageSieveProcessor manageSieveProcessor; + + public ManageSieveServerFactory() { + this.manageSieveProcessor = new ManageSieveProcessor(); + } + + @Inject + public void setSieveRepository(SieveRepository sieveRepository) { + this.sieveRepository = sieveRepository; + } + + @Inject + public void setUsersRepository(UsersRepository usersRepository) { + this.usersRepository = usersRepository; + } + + @Inject + public void setFileSystem(FileSystem fileSystem) { + this.fileSystem = fileSystem; + } + + @Override + protected List<AbstractConfigurableAsyncServer> createServers(Logger log, HierarchicalConfiguration config) throws Exception { + List<AbstractConfigurableAsyncServer> servers = new ArrayList<AbstractConfigurableAsyncServer>(); + List<HierarchicalConfiguration> configs = config.configurationsAt("managesieveserver"); + + for (HierarchicalConfiguration serverConfig: configs) { + ManageSieveServer server = new ManageSieveServer(8000, manageSieveProcessor); + server.setLog(log); + server.setFileSystem(fileSystem); + server.configure(serverConfig); + servers.add(server); + } + + return servers; + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org