View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  
21  
22  package org.apache.james.pop3server;
23  
24  import org.apache.avalon.framework.configuration.Configurable;
25  import org.apache.avalon.framework.configuration.Configuration;
26  import org.apache.avalon.framework.configuration.ConfigurationException;
27  import org.apache.avalon.framework.configuration.DefaultConfiguration;
28  import org.apache.avalon.framework.container.ContainerUtil;
29  import org.apache.avalon.framework.logger.AbstractLogEnabled;
30  import org.apache.avalon.framework.service.ServiceException;
31  import org.apache.avalon.framework.service.ServiceManager;
32  import org.apache.avalon.framework.service.Serviceable;
33  
34  import java.util.ArrayList;
35  import java.util.Enumeration;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Locale;
39  import java.util.Properties;
40  
41  /**
42    * The POP3HandlerChain is per service object providing access
43    * ConnectHandlers, Commandhandlers and message handlers
44    */
45  public class POP3HandlerChain extends AbstractLogEnabled implements Configurable, Serviceable {
46  
47      private HashMap commandHandlerMap = new HashMap();
48      private ArrayList messageHandlers = new ArrayList();
49      private ArrayList connectHandlers = new ArrayList();
50  
51      private final CommandHandler unknownHandler = new UnknownCmdHandler();
52      private ServiceManager serviceManager;
53  
54      private final static String[] mandatoryCommands = { "USER" , "PASS", "LIST"};
55  
56      public void service(ServiceManager serviceManager) throws ServiceException {
57          this.serviceManager = serviceManager;
58      }
59  
60  
61      /**
62       * loads the various handlers from the configuration
63       * @param configuration configuration under handlerchain node
64       */
65      public void configure(Configuration configuration) throws  ConfigurationException {
66          addToMap(UnknownCmdHandler.UNKNOWN_COMMAND, unknownHandler);
67          if(configuration == null || configuration.getChildren("handler") == null || configuration.getChildren("handler").length == 0) {
68              configuration = new DefaultConfiguration("handlerchain");
69              Properties cmds = new Properties();
70              cmds.setProperty("USER",UserCmdHandler.class.getName());
71              cmds.setProperty("PASS",PassCmdHandler.class.getName());
72              cmds.setProperty("LIST",ListCmdHandler.class.getName());
73              cmds.setProperty("UIDL",UidlCmdHandler.class.getName());
74              cmds.setProperty("RSET",RsetCmdHandler.class.getName());
75              cmds.setProperty("DELE",DeleCmdHandler.class.getName());
76              cmds.setProperty("NOOP",NoopCmdHandler.class.getName());
77              cmds.setProperty("RETR",RetrCmdHandler.class.getName());
78              cmds.setProperty("TOP" ,TopCmdHandler.class.getName());
79              cmds.setProperty("STAT",StatCmdHandler.class.getName());
80              cmds.setProperty("QUIT",QuitCmdHandler.class.getName());
81              Enumeration e = cmds.keys();
82              while (e.hasMoreElements()) {
83                  String cmdName = (String) e.nextElement();
84                  String className = cmds.getProperty(cmdName);
85                  DefaultConfiguration cmdConf = new DefaultConfiguration("handler");
86                  cmdConf.setAttribute("command",cmdName);
87                  cmdConf.setAttribute("class",className);
88                  ((DefaultConfiguration) configuration).addChild(cmdConf);
89              }
90          }
91          if(configuration != null) {
92              Configuration[] children = configuration.getChildren("handler");
93              if ( children != null ) {
94                  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
95                  for ( int i = 0 ; i < children.length ; i++ ) {
96                      String className = children[i].getAttribute("class");
97                      if(className != null) {
98                          //load the handler
99                          try {
100                             Object handler = classLoader.loadClass(className).newInstance();
101 
102                             //enable logging
103                             ContainerUtil.enableLogging(handler, getLogger());
104 
105                             //servicing the handler
106                             ContainerUtil.service(handler,serviceManager);
107 
108                             //configure the handler
109                             ContainerUtil.configure(handler,children[i]);
110 
111                             //if it is a connect handler add it to list of connect handlers
112                             if(handler instanceof ConnectHandler) {
113                                 connectHandlers.add((ConnectHandler)handler);
114                                 if (getLogger().isInfoEnabled()) {
115                                     getLogger().info("Added ConnectHandler: " + className);
116                                 }
117                             }
118 
119                             //if it is a command handler add it to the map with key as command name
120                             if(handler instanceof CommandHandler) {
121                                 String commandName = children[i].getAttribute("command");
122                                 commandName = commandName.toUpperCase(Locale.US);
123                                 addToMap(commandName, (CommandHandler)handler);
124                                 if (getLogger().isInfoEnabled()) {
125                                     getLogger().info("Added Commandhandler: " + className);
126                                 }
127 
128                             }
129 
130                         } catch (ClassNotFoundException ex) {
131                            if (getLogger().isErrorEnabled()) {
132                                getLogger().error("Failed to add Commandhandler: " + className,ex);
133                            }
134                         } catch (IllegalAccessException ex) {
135                            if (getLogger().isErrorEnabled()) {
136                                getLogger().error("Failed to add Commandhandler: " + className,ex);
137                            }
138                         } catch (InstantiationException ex) {
139                            if (getLogger().isErrorEnabled()) {
140                                getLogger().error("Failed to add Commandhandler: " + className,ex);
141                            }
142                         } catch (ServiceException e) {
143                             if (getLogger().isErrorEnabled()) {
144                                 getLogger().error("Failed to service Commandhandler: " + className,e);
145                             }
146                         }
147                     }
148                 }
149             }
150         }
151 
152         //the size must be greater than 1 because we added UnknownCmdHandler to the map
153         if(commandHandlerMap.size() < 2) {
154             if (getLogger().isErrorEnabled()) {
155                 getLogger().error("No commandhandlers configured");
156             }
157             throw new ConfigurationException("No commandhandlers configured");
158         } else {
159             boolean found = true;
160             for (int i = 0; i < mandatoryCommands.length; i++) {
161                 if(!commandHandlerMap.containsKey(mandatoryCommands[i])) {
162                     if (getLogger().isErrorEnabled()) {
163                         getLogger().error("No commandhandlers configured for the command:" + mandatoryCommands[i]);
164                     }
165                     found = false;
166                     break;
167                 }
168             }
169 
170             if(!found) {
171                 throw new ConfigurationException("No commandhandlers configured for mandatory commands");
172             }
173             
174         }
175     }
176 
177     /**
178      * Add it to map (key as command name, value is an array list of commandhandlers)
179      *
180      * @param commandName the command name which will be key
181      * @param cmdHandler The commandhandler object
182      */
183     private void addToMap(String commandName, CommandHandler cmdHandler) {
184         ArrayList handlers = (ArrayList)commandHandlerMap.get(commandName);
185         if(handlers == null) {
186             handlers = new ArrayList();
187             commandHandlerMap.put(commandName, handlers);
188         }
189         handlers.add(cmdHandler);
190     }
191 
192     /**
193      * Returns all the configured commandhandlers for the specified command
194      *
195      * @param command the command name which will be key
196      * @return List of commandhandlers
197      */
198     List getCommandHandlers(String command) {
199         if (command == null) {
200             return null;
201         }
202         if (getLogger().isDebugEnabled()) {
203             getLogger().debug("Lookup command handler for command: " + command);
204         }
205         List handlers =  (List)commandHandlerMap.get(command);
206         if(handlers == null) {
207             handlers = (List)commandHandlerMap.get(UnknownCmdHandler.UNKNOWN_COMMAND);
208         }
209 
210         return handlers;
211     }
212 
213     /**
214      * Returns all the configured message handlers
215      *
216      * @return List of message handlers
217      */
218     List getMessageHandlers() {
219         return messageHandlers;
220     }
221 
222     /**
223      * Returns all the configured connect handlers
224      *
225      * @return List of connect handlers
226      */
227     List getConnectHandlers() {
228         return connectHandlers;
229     }
230 
231 }