1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.james.smtpserver;
21
22 import org.apache.avalon.framework.activity.Initializable;
23 import org.apache.avalon.framework.configuration.Configurable;
24 import org.apache.avalon.framework.configuration.Configuration;
25 import org.apache.avalon.framework.configuration.ConfigurationException;
26 import org.apache.avalon.framework.configuration.DefaultConfiguration;
27 import org.apache.avalon.framework.container.ContainerUtil;
28 import org.apache.avalon.framework.logger.AbstractLogEnabled;
29 import org.apache.avalon.framework.service.ServiceException;
30 import org.apache.avalon.framework.service.ServiceManager;
31 import org.apache.avalon.framework.service.Serviceable;
32 import org.apache.james.smtpserver.core.CoreCmdHandlerLoader;
33 import org.apache.james.smtpserver.core.SendMailHandler;
34 import org.apache.james.smtpserver.core.UnknownCmdHandler;
35 import org.apache.james.smtpserver.core.filter.CoreFilterCmdHandlerLoader;
36
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.Enumeration;
40 import java.util.HashMap;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Locale;
44 import java.util.Map;
45 import java.util.Properties;
46
47
48
49
50
51 public class SMTPHandlerChain extends AbstractLogEnabled implements Configurable, Serviceable, Initializable {
52
53 private HashMap commandHandlerMap = new HashMap();
54 private ArrayList messageHandlers = new ArrayList();
55 private ArrayList connectHandlers = new ArrayList();
56
57 private final CommandHandler unknownHandler = new UnknownCmdHandler();
58 private ServiceManager serviceManager;
59
60 private final static String[] mandatoryCommands = { "MAIL" , "RCPT", "DATA"};
61
62 public void service(ServiceManager arg0) throws ServiceException {
63 serviceManager = arg0;
64 }
65
66
67
68
69
70
71
72 public void configure(Configuration configuration)
73 throws ConfigurationException {
74 addToMap(UnknownCmdHandler.UNKNOWN_COMMAND, unknownHandler);
75 if (configuration == null
76 || configuration.getChildren("handler") == null
77 || configuration.getChildren("handler").length == 0) {
78 configuration = new DefaultConfiguration("handlerchain");
79 Properties cmds = new Properties();
80 cmds.setProperty("Default CoreCmdFilterHandlerLoader",
81 CoreFilterCmdHandlerLoader.class.getName());
82 cmds.setProperty("Default CoreCmdHandlerLoader", CoreCmdHandlerLoader.class
83 .getName());
84 cmds.setProperty("Default SendMailHandler", SendMailHandler.class
85 .getName());
86 Enumeration e = cmds.keys();
87 while (e.hasMoreElements()) {
88 String cmdName = (String) e.nextElement();
89 String className = cmds.getProperty(cmdName);
90 ((DefaultConfiguration) configuration).addChild(addHandler(
91 cmdName, className));
92 }
93 }
94 if (configuration != null) {
95 Configuration[] children = configuration.getChildren("handler");
96 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
97
98
99 loadClass(classLoader, CoreFilterCmdHandlerLoader.class.getName(),
100 addHandler(null, CoreFilterCmdHandlerLoader.class.getName()));
101
102
103 if (children != null) {
104 for (int i = 0; i < children.length; i++) {
105 String className = children[i].getAttribute("class");
106 if (className != null) {
107
108
109 if (!className.equals(CoreFilterCmdHandlerLoader.class
110 .getName())
111 && !className.equals(CoreCmdHandlerLoader.class
112 .getName())
113 && !className.equals(SendMailHandler.class
114 .getName())) {
115
116
117 loadClass(classLoader, className, children[i]);
118 }
119 }
120 }
121
122
123 loadClass(classLoader, CoreCmdHandlerLoader.class.getName(),
124 addHandler(null, CoreCmdHandlerLoader.class.getName()));
125 loadClass(classLoader, SendMailHandler.class.getName(),
126 addHandler(null, SendMailHandler.class.getName()));
127 }
128 }
129
130
131
132
133 if (commandHandlerMap.size() < 2) {
134 if (getLogger().isErrorEnabled()) {
135 getLogger().error("No commandhandlers configured");
136 }
137 throw new ConfigurationException("No commandhandlers configured");
138 } else {
139 boolean found = true;
140 for (int i = 0; i < mandatoryCommands.length; i++) {
141 if (!commandHandlerMap.containsKey(mandatoryCommands[i])) {
142 if (getLogger().isErrorEnabled()) {
143 getLogger().error(
144 "No commandhandlers configured for the command:"
145 + mandatoryCommands[i]);
146 }
147 found = false;
148 break;
149 }
150 }
151
152 if (!found) {
153 throw new ConfigurationException(
154 "No commandhandlers configured for mandatory commands");
155 }
156
157 if (messageHandlers.size() == 0) {
158 if (getLogger().isErrorEnabled()) {
159 getLogger()
160 .error(
161 "No messageHandler configured. Check that SendMailHandler is configured in the SMTPHandlerChain");
162 }
163 throw new ConfigurationException("No messageHandler configured");
164 }
165
166 }
167
168 }
169
170
171
172
173 public void initialize() throws Exception {
174 Iterator h = commandHandlerMap.keySet().iterator();
175
176 while(h.hasNext()) {
177 List handlers = (List) commandHandlerMap.get(h.next());
178 Iterator h2 = handlers.iterator();
179 while (h2.hasNext()) {
180 ContainerUtil.initialize(h2.next());
181 }
182 }
183 }
184
185
186
187
188
189
190
191
192
193 private void loadClass(ClassLoader classLoader, String className,
194 Configuration config) throws ConfigurationException {
195 try {
196 Object handler = classLoader.loadClass(className).newInstance();
197
198
199 ContainerUtil.enableLogging(handler, getLogger());
200
201
202 ContainerUtil.service(handler, serviceManager);
203
204
205 ContainerUtil.configure(handler, config);
206
207
208 if (handler instanceof ConnectHandler) {
209 connectHandlers.add(handler);
210 if (getLogger().isInfoEnabled()) {
211 getLogger().info("Added ConnectHandler: " + className);
212 }
213 }
214
215
216
217 if (handler instanceof CommandsHandler) {
218 Map c = ((CommandsHandler) handler).getCommands();
219
220 Iterator cmdKeys = c.keySet().iterator();
221
222 while (cmdKeys.hasNext()) {
223 String commandName = cmdKeys.next().toString();
224 String cName = c.get(commandName).toString();
225
226 DefaultConfiguration cmdConf = new DefaultConfiguration(
227 "handler");
228 cmdConf.setAttribute("command", commandName);
229 cmdConf.setAttribute("class", cName);
230
231 loadClass(classLoader, cName, cmdConf);
232 }
233
234 }
235
236
237
238 if (handler instanceof CommandHandler) {
239 String commandName = config.getAttribute("command");
240 String cmds[] = commandName.split(",");
241 Collection implCmds = ((CommandHandler) handler).getImplCommands();
242
243 for (int i = 0; i < cmds.length; i++) {
244 commandName = cmds[i].trim().toUpperCase(Locale.US);
245
246
247 if (implCmds.contains(commandName)) {
248 addToMap(commandName, (CommandHandler) handler);
249 if (getLogger().isInfoEnabled()) {
250 getLogger().info(
251 "Added Commandhandler: " + className);
252 }
253 } else {
254
255 throw new ConfigurationException("Commandhandler "
256 + className + " not implement the command "
257 + commandName);
258 }
259
260 }
261
262 }
263
264
265 if (handler instanceof MessageHandler) {
266 messageHandlers.add(handler);
267 if (getLogger().isInfoEnabled()) {
268 getLogger().info("Added MessageHandler: " + className);
269 }
270 }
271 } catch (ClassNotFoundException ex) {
272 if (getLogger().isErrorEnabled()) {
273 getLogger().error("Failed to add Commandhandler: " + className,
274 ex);
275 }
276 throw new ConfigurationException("Failed to add Commandhandler: "
277 + className, ex);
278 } catch (IllegalAccessException ex) {
279 if (getLogger().isErrorEnabled()) {
280 getLogger().error("Failed to add Commandhandler: " + className,
281 ex);
282 }
283 throw new ConfigurationException("Failed to add Commandhandler: "
284 + className, ex);
285 } catch (InstantiationException ex) {
286 if (getLogger().isErrorEnabled()) {
287 getLogger().error("Failed to add Commandhandler: " + className,
288 ex);
289 }
290 throw new ConfigurationException("Failed to add Commandhandler: "
291 + className, ex);
292 } catch (ServiceException e) {
293 if (getLogger().isErrorEnabled()) {
294 getLogger().error(
295 "Failed to service Commandhandler: " + className, e);
296 }
297 throw new ConfigurationException("Failed to add Commandhandler: "
298 + className, e);
299 }
300 }
301
302
303
304
305
306
307
308
309 private DefaultConfiguration addHandler(String cmdName, String className) {
310 DefaultConfiguration cmdConf = new DefaultConfiguration("handler");
311 cmdConf.setAttribute("command",cmdName);
312 cmdConf.setAttribute("class",className);
313 return cmdConf;
314 }
315
316
317
318
319
320
321
322 private void addToMap(String commandName, CommandHandler cmdHandler) {
323 ArrayList handlers = (ArrayList)commandHandlerMap.get(commandName);
324 if(handlers == null) {
325 handlers = new ArrayList();
326 commandHandlerMap.put(commandName, handlers);
327 }
328 handlers.add(cmdHandler);
329 }
330
331
332
333
334
335
336
337 List getCommandHandlers(String command) {
338 if (command == null) {
339 return null;
340 }
341 if (getLogger().isDebugEnabled()) {
342 getLogger().debug("Lookup command handler for command: " + command);
343 }
344 List handlers = (List)commandHandlerMap.get(command);
345 if(handlers == null) {
346 handlers = (List)commandHandlerMap.get(UnknownCmdHandler.UNKNOWN_COMMAND);
347 }
348
349 return handlers;
350 }
351
352
353
354
355
356
357 List getMessageHandlers() {
358 return messageHandlers;
359 }
360
361
362
363
364
365
366 List getConnectHandlers() {
367 return connectHandlers;
368 }
369
370 }