You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2010/01/17 19:19:57 UTC

svn commit: r900176 - in /james/server/trunk: imapserver-function/ imapserver-function/src/main/java/org/apache/james/imapserver/mina/ spring-deployment/src/main/config/james/

Author: norman
Date: Sun Jan 17 18:19:56 2010
New Revision: 900176

URL: http://svn.apache.org/viewvc?rev=900176&view=rev
Log:
Add Async ImapServer which use MINA (JAMES-952)

Added:
    james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/
    james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/AsyncImapServer.java
    james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/ImapIoHandler.java
Modified:
    james/server/trunk/imapserver-function/pom.xml
    james/server/trunk/spring-deployment/src/main/config/james/spring-beans.xml

Modified: james/server/trunk/imapserver-function/pom.xml
URL: http://svn.apache.org/viewvc/james/server/trunk/imapserver-function/pom.xml?rev=900176&r1=900175&r2=900176&view=diff
==============================================================================
--- james/server/trunk/imapserver-function/pom.xml (original)
+++ james/server/trunk/imapserver-function/pom.xml Sun Jan 17 18:19:56 2010
@@ -69,6 +69,12 @@
        <artifactId>geronimo-annotation_1.0_spec</artifactId>
     </dependency>
     
+    
+    <dependency>
+      <groupId>org.apache.james</groupId>
+      <artifactId>james-server-mina-socket-library</artifactId>
+    </dependency>
+    
     <dependency>
       <groupId>org.apache.james</groupId>
       <artifactId>james-server-socket-shared-library</artifactId>
@@ -125,6 +131,11 @@
     </dependency>
         
     <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
     	<groupId>junit</groupId>
     	<artifactId>junit</artifactId>
     </dependency>

Added: james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/AsyncImapServer.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/AsyncImapServer.java?rev=900176&view=auto
==============================================================================
--- james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/AsyncImapServer.java (added)
+++ james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/AsyncImapServer.java Sun Jan 17 18:19:56 2010
@@ -0,0 +1,205 @@
+/****************************************************************
+ * 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.mina;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Date;
+
+import javax.annotation.Resource;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.james.imap.api.ImapConstants;
+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.mailbox.Mailbox;
+import org.apache.james.imap.mailbox.MailboxManager;
+import org.apache.james.imap.mailbox.MailboxSession;
+import org.apache.james.imap.main.ImapRequestHandler;
+import org.apache.james.socket.mina.AbstractAsyncServer;
+import org.apache.jsieve.mailet.Poster;
+import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
+import org.apache.mina.core.service.IoHandler;
+
+/**
+ * Async ImapServer which use MINA for socket handling
+ *
+ */
+public class AsyncImapServer extends AbstractAsyncServer implements ImapConstants, Poster{
+
+    private static final String softwaretype = "JAMES "+VERSION+" Server "; //+ Constants.SOFTWARE_VERSION;
+
+    private String hello;
+    private ImapProcessor processor;
+    private ImapEncoder encoder;
+
+    private ImapDecoder decoder;
+
+    private MailboxManager mailboxManager;
+
+    @Resource(name="imapDecoder")
+    public void setImapDecoder(ImapDecoder decoder) {
+        this.decoder = decoder;
+    }
+    
+    @Resource(name="imapEncoder")
+    public void setImapEncoder(ImapEncoder encoder) {
+        this.encoder = encoder;
+    }
+    
+    @Resource(name="imapProcessor")
+    public void setImapProcessor(ImapProcessor processor) {
+        this.processor = processor;
+    }
+   
+    @Resource(name="mailboxmanager")
+    public void setMailboxManager(MailboxManager mailboxManager) {
+        this.mailboxManager = mailboxManager;
+    }
+    
+    @Override
+    public void doConfigure( final HierarchicalConfiguration configuration ) throws ConfigurationException {
+        super.doConfigure(configuration);
+        hello  = softwaretype + " Server " + getHelloName() + " is ready.";
+    }
+    
+    
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.socket.mina.AbstractAsyncServer#getDefaultPort()
+     */
+    public int getDefaultPort() {
+        return 143;
+    }
+
+ 
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.socket.mina.AbstractAsyncServer#getServiceType()
+     */
+    public String getServiceType() {
+        return "IMAP Service";
+    }
+    
+    @Override
+    protected IoHandler createIoHandler() {
+        final ImapRequestHandler handler = new ImapRequestHandler(decoder, processor, encoder);
+        return new ImapIoHandler(hello, handler, getLogger());
+    }
+
+    @Override
+    protected DefaultIoFilterChainBuilder createIoFilterChainBuilder() {
+        
+        // just return an empty filterchain because we need no special protocol filter etc
+        return new DefaultIoFilterChainBuilder();
+    }
+
+    /**
+     * @see org.apache.jsieve.mailet.Poster#post(java.lang.String, javax.mail.internet.MimeMessage)
+     */
+    public void post(String url, MimeMessage mail)throws MessagingException {
+        final int endOfScheme = url.indexOf(':');
+        if (endOfScheme < 0) {
+            throw new MessagingException("Malformed URI");
+        } else {
+            final String scheme = url.substring(0, endOfScheme);
+            if ("mailbox".equals(scheme)) {
+                final int startOfUser = endOfScheme + 3;
+                final int endOfUser = url.indexOf('@', startOfUser);
+                if (endOfUser < 0) {
+                    // TODO: when user missing, append to a default location
+                    throw new MessagingException("Shared mailbox is not supported");
+                } else {
+                    String user = url.substring(startOfUser, endOfUser);
+                    final int startOfHost = endOfUser + 1;
+                    final int endOfHost  = url.indexOf('/', startOfHost);
+                    final String host = url.substring(startOfHost, endOfHost);
+                    //if (!"localhost".equals(host)) {
+                    if (getMailServer().isLocalServer(host) == false) {
+                        //TODO: possible support for clustering?
+                        throw new MessagingException("Only local mailboxes are supported");
+                    } else {
+                        final String urlPath;
+                        final int length = url.length();
+                        if (endOfHost + 1 == length) {
+                            urlPath = "INBOX";
+                        } else {
+                            urlPath = url.substring(endOfHost, length);
+                        }
+                        
+                        // check if we should use the full emailaddress as username
+                        if (getMailServer().supportVirtualHosting()) {
+                            user = user + "@" + host;
+                        } 
+                        
+                        final MailboxSession session = mailboxManager.createSystemSession(user, getLogger());
+                        // This allows Sieve scripts to use a standard delimiter regardless of mailbox implementation
+                        final String mailbox = urlPath.replace('/', session.getPersonalSpace().getDeliminator());
+                        postToMailbox(user, mail, mailbox, session, mailboxManager);
+                    }
+                }
+            } else {
+                // TODO: add support for more protocols
+                // TODO: for example mailto: for forwarding over SMTP
+                // TODO: for example xmpp: for forwarding over Jabber
+                throw new MessagingException("Unsupported protocol");
+            }
+        }
+    }
+    
+    public void postToMailbox(String username, MimeMessage mail, String destination, final MailboxSession session, final MailboxManager mailboxManager) throws MessagingException {
+        if (destination == null || "".equals(destination)) {
+            destination = "INBOX";
+        }
+        final String name = mailboxManager.resolve(username, destination);
+        try
+        {
+            if ("INBOX".equalsIgnoreCase(destination) && !(mailboxManager.mailboxExists(name, session))) {
+                mailboxManager.createMailbox(name, session);
+            }
+            final Mailbox mailbox = mailboxManager.getMailbox(name, session);
+            
+            if (mailbox == null) {
+                final String error = "Mailbox for user " + username
+                        + " was not found on this server.";
+                throw new MessagingException(error);
+            }
+
+            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            mail.writeTo(baos);
+            mailbox.appendMessage(baos.toByteArray() , new Date(), session, true, null);
+        }
+        catch (IOException e)
+        {
+            throw new MessagingException("Failed to write mail message", e);
+        }
+        finally 
+        {
+            session.close();   
+            mailboxManager.logout(session, true);
+        }
+    }
+
+
+}

Added: james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/ImapIoHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/ImapIoHandler.java?rev=900176&view=auto
==============================================================================
--- james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/ImapIoHandler.java (added)
+++ james/server/trunk/imapserver-function/src/main/java/org/apache/james/imapserver/mina/ImapIoHandler.java Sun Jan 17 18:19:56 2010
@@ -0,0 +1,104 @@
+/****************************************************************
+ * 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.mina;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.encode.ImapResponseComposer;
+import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
+import org.apache.james.imap.main.ImapRequestHandler;
+import org.apache.james.imap.main.ImapSessionImpl;
+import org.apache.mina.core.buffer.IoBuffer;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.handler.stream.StreamIoHandler;
+
+/**
+ * IoHandler which process Imap commands
+ *
+ */
+public class ImapIoHandler extends StreamIoHandler{
+
+    private Log logger;
+
+    private String hello;
+
+    private ImapRequestHandler handler;
+
+    private final static String IMAP_SESSION = "IMAP_SESSION"; 
+    public ImapIoHandler(String hello, ImapRequestHandler handler, Log logger) {
+        this.logger = logger;
+        this.hello = hello;
+        this.handler = handler;
+        
+    }
+
+    @Override
+    public void exceptionCaught(IoSession session, Throwable cause) {
+        cause.printStackTrace();
+        super.exceptionCaught(session, cause);
+    }
+
+    @Override
+    public void sessionCreated(IoSession session) throws Exception {
+        
+        // create the imap session and store it in the IoSession for later usage
+        final ImapSessionImpl imapsession = new ImapSessionImpl();
+        imapsession.setLog(logger);
+        
+        session.setAttribute(IMAP_SESSION, imapsession);
+        
+        super.sessionCreated(session);
+    }
+    
+
+    @Override
+    public void sessionOpened(IoSession session) {
+        // write hello to client
+        session.write(IoBuffer.wrap((ImapConstants.UNTAGGED + " OK " + hello +" " + new String(ImapConstants.BYTES_LINE_END)).getBytes()));
+        
+        super.sessionOpened(session);
+    }
+
+    @Override
+    protected void processStreamIo(final IoSession session, final InputStream in, final OutputStream out) {  
+        
+        // it would prolly make sense to use a thread pool...
+        new Thread(new Runnable() {
+        
+
+        public void run() {
+            final ImapSessionImpl imapSession = (ImapSessionImpl) session.getAttribute(IMAP_SESSION);            
+
+            // handle requests in a loop
+            while(handler.handleRequest( in, out, imapSession ));
+            if (imapSession != null) imapSession.logout();
+            session.close(false);
+        }
+
+        }).start();
+
+    }
+
+}

Modified: james/server/trunk/spring-deployment/src/main/config/james/spring-beans.xml
URL: http://svn.apache.org/viewvc/james/server/trunk/spring-deployment/src/main/config/james/spring-beans.xml?rev=900176&r1=900175&r2=900176&view=diff
==============================================================================
--- james/server/trunk/spring-deployment/src/main/config/james/spring-beans.xml (original)
+++ james/server/trunk/spring-deployment/src/main/config/james/spring-beans.xml Sun Jan 17 18:19:56 2010
@@ -305,6 +305,12 @@
 	<!--
 	<bean id="domainlist" class="org.apache.james.vut.XMLVirtualUserTable"/>
 	-->
+	<!--  
+    <bean id="imapserver" name="org.apache.jsieve.mailet.Poster" class="org.apache.james.imapserver.mina.AsyncImapServer">
+		<property name="imapDecoder" ref="imapDecoder"/>
+		<property name="imapEncoder" ref="imapEncoder"/>	
+	</bean>
+	-->
 
 	<!-- IMAP server Beans -->
 	<bean id="imapserver.protocolhandlerfactory" name="org.apache.jsieve.mailet.Poster" class="org.apache.james.imapserver.ImapServerProtocolHandlerFactory">



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