001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019 package org.apache.james.protocols.smtp;
020
021 import java.util.ArrayList;
022 import java.util.Collections;
023 import java.util.List;
024
025 import org.apache.james.protocols.api.handler.AbstractProtocolHandlerChain;
026 import org.apache.james.protocols.api.handler.ProtocolHandlerChain;
027 import org.apache.james.protocols.api.handler.WiringException;
028 import org.apache.james.protocols.smtp.core.DataCmdHandler;
029 import org.apache.james.protocols.smtp.core.DataLineMessageHookHandler;
030 import org.apache.james.protocols.smtp.core.ExpnCmdHandler;
031 import org.apache.james.protocols.smtp.core.HeloCmdHandler;
032 import org.apache.james.protocols.smtp.core.HelpCmdHandler;
033 import org.apache.james.protocols.smtp.core.MailCmdHandler;
034 import org.apache.james.protocols.smtp.core.NoopCmdHandler;
035 import org.apache.james.protocols.smtp.core.PostmasterAbuseRcptHook;
036 import org.apache.james.protocols.smtp.core.QuitCmdHandler;
037 import org.apache.james.protocols.smtp.core.RcptCmdHandler;
038 import org.apache.james.protocols.smtp.core.ReceivedDataLineFilter;
039 import org.apache.james.protocols.smtp.core.RsetCmdHandler;
040 import org.apache.james.protocols.smtp.core.SMTPCommandDispatcherLineHandler;
041 import org.apache.james.protocols.smtp.core.VrfyCmdHandler;
042 import org.apache.james.protocols.smtp.core.WelcomeMessageHandler;
043 import org.apache.james.protocols.smtp.core.esmtp.AuthCmdHandler;
044 import org.apache.james.protocols.smtp.core.esmtp.EhloCmdHandler;
045 import org.apache.james.protocols.smtp.core.esmtp.MailSizeEsmtpExtension;
046 import org.apache.james.protocols.smtp.core.esmtp.StartTlsCmdHandler;
047 import org.apache.james.protocols.smtp.hook.AuthHook;
048 import org.apache.james.protocols.smtp.hook.Hook;
049 import org.apache.james.protocols.smtp.hook.MessageHook;
050
051 /**
052 * This {@link ProtocolHandlerChain} implementation add all needed handlers to
053 * the chain to act as full blown SMTPServer. By default messages will just get
054 * rejected after the DATA command.
055 *
056 * If you want to accept the messagejust add a {@link MessageHook}
057 * implementation to the chain and handle the queuing
058 *
059 *
060 *
061 */
062 public class SMTPProtocolHandlerChain extends AbstractProtocolHandlerChain {
063 private final List<Object> defaultHandlers = new ArrayList<Object>();
064 private final List<Hook> hooks = new ArrayList<Hook>();
065 private final List<Object> handlers = new ArrayList<Object>();
066 private boolean authHandler = false;
067
068 public SMTPProtocolHandlerChain() throws WiringException {
069 defaultHandlers.addAll(initDefaultHandlers());
070 copy();
071
072 wireExtensibleHandlers();
073 }
074
075 protected List<Object> initDefaultHandlers() {
076 List<Object> defaultHandlers = new ArrayList<Object>();
077 defaultHandlers.add(new SMTPCommandDispatcherLineHandler());
078 defaultHandlers.add(new ExpnCmdHandler());
079 defaultHandlers.add(new EhloCmdHandler());
080 defaultHandlers.add(new HeloCmdHandler());
081 defaultHandlers.add(new HelpCmdHandler());
082 defaultHandlers.add(new MailCmdHandler());
083 defaultHandlers.add(new NoopCmdHandler());
084 defaultHandlers.add(new QuitCmdHandler());
085 defaultHandlers.add(new RcptCmdHandler());
086 defaultHandlers.add(new RsetCmdHandler());
087 defaultHandlers.add(new VrfyCmdHandler());
088 defaultHandlers.add(new DataCmdHandler());
089 defaultHandlers.add(new MailSizeEsmtpExtension());
090 defaultHandlers.add(new WelcomeMessageHandler());
091 defaultHandlers.add(new PostmasterAbuseRcptHook());
092 defaultHandlers.add(new ReceivedDataLineFilter());
093 defaultHandlers.add(new DataLineMessageHookHandler());
094 defaultHandlers.add(new StartTlsCmdHandler());
095 return defaultHandlers;
096 }
097
098
099 /**
100 * Add the hook to the chain
101 *
102 * @param hook
103 * @throws WiringException
104 */
105 public final synchronized void addHook(Hook hook) throws WiringException {
106 if (hook instanceof AuthHook && !authHandler) {
107 defaultHandlers.add(new AuthCmdHandler());
108 authHandler = true;
109 }
110 addHook(hooks.size(), hook);
111 }
112
113 /**
114 * Add the hook to the chain on the given index
115 *
116 * @param index
117 * @param hook
118 * @throws WiringException
119 */
120 public final synchronized void addHook(int index, Hook hook) throws WiringException {
121 hooks.add(index, hook);
122 copy();
123 wireExtensibleHandlers();
124
125 }
126
127 /**
128 * Remove the Hook found on the given index from the chain
129 *
130 * @param index
131 * @return hook
132 * @throws WiringException
133 */
134 public final synchronized Hook removeHook(int index) throws WiringException {
135 Hook hook = hooks.remove(index);
136 handlers.remove(hook);
137 wireExtensibleHandlers();
138 return hook;
139
140 }
141
142 /**
143 * Return the index of the given hook
144 *
145 * @param hook
146 * @return index
147 */
148 public synchronized int getIndexOfHook(Hook hook) {
149 return hooks.indexOf(hook);
150 }
151
152 /**
153 * @see
154 * org.apache.james.protocols.api.handler.AbstractProtocolHandlerChain#getHandlers()
155 */
156 @Override
157 protected synchronized List<Object> getHandlers() {
158 return Collections.unmodifiableList(handlers);
159 }
160
161 /**
162 * Copy the lists
163 */
164 private void copy() {
165 handlers.clear();
166 handlers.addAll(defaultHandlers);
167 handlers.addAll(hooks);
168 }
169 }