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.remotemanager;
23  
24  import java.io.IOException;
25  import java.lang.reflect.Method;
26  import java.net.Socket;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Collection;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.Locale;
33  import java.util.Map;
34  
35  import javax.mail.internet.ParseException;
36  
37  import org.apache.james.Constants;
38  import org.apache.james.api.user.JamesUser;
39  import org.apache.james.api.user.User;
40  import org.apache.james.api.user.UsersRepository;
41  import org.apache.james.api.vut.management.VirtualUserTableManagementException;
42  import org.apache.james.management.BayesianAnalyzerManagementException;
43  import org.apache.james.management.DomainListManagementException;
44  import org.apache.james.management.ProcessorManagementService;
45  import org.apache.james.management.SpoolFilter;
46  import org.apache.james.socket.ProtocolHandler;
47  import org.apache.james.socket.ProtocolHandlerHelper;
48  import org.apache.mailet.MailAddress;
49  
50  
51  /**
52   * Provides a console-based administration interface covering most of the management 
53   * functionality found in the classes from package org.apache.james.management
54   * 
55   * TODO: -improve protocol
56   *       -much more...
57   *
58   * @version $Revision: 726391 $
59   *
60   */
61  public class RemoteManagerHandler implements ProtocolHandler {
62  
63      private ProtocolHandlerHelper helper;
64      
65      private static final Class[] WORKER_METHOD_PARAMETERSET = new Class[] {String.class};
66  
67      private static final List COMMANDLIST = Arrays.asList(new String[] { 
68          "MEMSTAT",
69          "ADDUSER",
70          "SETPASSWORD",
71          "DELUSER",
72          "LISTUSERS",
73          "COUNTUSERS",
74          "VERIFY",
75          "HELP",
76          "SETFORWARDING",
77          "SHOWFORWARDING",
78          "UNSETFORWARDING",
79          "SETALIAS",
80          "SHOWALIAS",
81          "UNSETALIAS",
82          "USER",
83          "LISTSPOOL",
84          "FLUSHSPOOL",
85          "DELETESPOOL",
86          "MOVEMAILS",
87          "ADDHAM",
88          "ADDSPAM",
89          "EXPORTBAYESIANDATA",
90          "IMPORTBAYESIANDATA",
91          "RESETBAYESIANDATA",
92          "LISTPROCESSORS",
93          "LISTMAILETS",
94          "LISTMATCHERS",
95          "SHOWMAILETINFO",
96          "SHOWMATCHERINFO",
97          "ADDMAPPING",
98          "REMOVEMAPPING",
99          "LISTMAPPING",
100         "LISTALLMAPPINGS",
101         "ADDDOMAIN",
102         "REMOVEDOMAIN",
103         "LISTDOMAINS",
104         "QUIT",
105         "SHUTDOWN"
106     });
107 
108     /**
109      * The per-service configuration data that applies to all handlers
110      */
111     private RemoteManagerHandlerConfigurationData theConfigData;
112 
113     /**
114      * The current UsersRepository being managed/viewed/modified
115      */
116     private UsersRepository users;
117     
118     private CommandRegistry commandRegistry;
119     
120     private final static String HEADER_IDENTIFIER = "header=";
121     private final static String REGEX_IDENTIFIER = "regex=";
122     private final static String KEY_IDENTIFIER = "key=";
123 
124     private final static String ADD_MAPPING_ACTION = "ADD_MAPPING";
125     private final static String REMOVE_MAPPING_ACTION = "REMOVE_MAPPING";
126 
127     
128     /**
129      * Set the configuration data for the handler.
130      *
131      * @param theData the configuration data
132      */
133     public void setConfigurationData(Object theData) {
134         if (theData instanceof RemoteManagerHandlerConfigurationData) {
135             theConfigData = (RemoteManagerHandlerConfigurationData) theData;
136 
137             // Reset the users repository to the default.
138             users = theConfigData.getUsersRepository();
139             
140             Command[] commands = theConfigData.getCommands();
141             commandRegistry = new CommandRegistry(commands);
142         } else {
143             throw new IllegalArgumentException("Configuration object does not implement RemoteManagerHandlerConfigurationData");
144         }
145     }
146 
147     /**
148      * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
149      */
150     public void handleProtocol() throws IOException {
151         helper.writeLoggedResponse("JAMES Remote Administration Tool " + Constants.SOFTWARE_VERSION );
152         helper.writeLoggedResponse("Please enter your login and password");
153         String login = null;
154         String password = null;
155         do {
156             if (login != null) {
157                 final String message = "Login failed for " + login;
158                 helper.writeLoggedFlushedResponse(message);
159             }
160             helper.writeLoggedFlushedResponse("Login id:");
161             login = helper.getInputReader().readLine().trim();
162             helper.writeLoggedFlushedResponse("Password:");
163             password = helper.getInputReader().readLine().trim();
164         } while (!password.equals(theConfigData.getAdministrativeAccountData().get(login)) || password.length() == 0);
165 
166         StringBuffer messageBuffer =
167             new StringBuffer(64)
168                     .append("Welcome ")
169                     .append(login)
170                     .append(". HELP for a list of commands");
171         helper.getOutputWriter().println( messageBuffer.toString() );
172         helper.getOutputWriter().flush();
173         if (helper.getAvalonLogger().isInfoEnabled()) {
174             StringBuffer infoBuffer =
175                 new StringBuffer(128)
176                         .append("Login for ")
177                         .append(login)
178                         .append(" successful");
179             helper.getAvalonLogger().info(infoBuffer.toString());
180         }
181 
182         try {
183             helper.getOutputWriter().print(theConfigData.getPrompt());
184             helper.getOutputWriter().flush();
185             helper.getWatchdog().start();
186             while (parseCommand(helper.getInputReader().readLine())) {
187                 helper.getWatchdog().reset();
188                 helper.getOutputWriter().print(theConfigData.getPrompt());
189                 helper.getOutputWriter().flush();
190             }
191             helper.getWatchdog().stop();
192         } catch (IOException ioe) {
193             //We can cleanly ignore this as it's probably a socket timeout
194         } catch (Throwable thr) {
195             System.out.println("Exception: " + thr.getMessage());
196             helper.getAvalonLogger().error("Encountered exception in handling the remote manager connection.", thr);
197         }
198         StringBuffer infoBuffer =
199             new StringBuffer(64)
200                     .append("Logout for ")
201                     .append(login)
202                     .append(".");
203         helper.getAvalonLogger().info(infoBuffer.toString());
204 
205     }
206 
207     /**
208      * @see org.apache.james.socket.AbstractJamesHandler#errorHandler(java.lang.RuntimeException)
209      */
210     public void errorHandler(RuntimeException e) {
211         helper.getOutputWriter().println("Unexpected Error: "+e.getMessage());
212         helper.getOutputWriter().flush();
213         if (helper.getAvalonLogger().isErrorEnabled()) {
214             StringBuffer exceptionBuffer =
215                 new StringBuffer(128)
216                         .append("Exception during connection from ")
217                         .append(helper.getRemoteHost())
218                         .append(" (")
219                         .append(helper.getRemoteIP())
220                         .append("): ")
221                         .append(e.getMessage());
222             helper.getAvalonLogger().error(exceptionBuffer.toString(),e);
223         }
224     }
225 
226     /**
227      * Resets the handler data to a basic state.
228      */
229     public void resetHandler() {
230         // Reset user repository
231         users = theConfigData.getUsersRepository();
232 
233         // Clear config data
234         theConfigData = null;
235     }
236 
237     /**
238      * <p>This method parses and processes RemoteManager commands read off the
239      * wire in handleConnection.  It returns true if expecting additional
240      * commands, false otherwise.</p>
241      *
242      * @param rawCommand the raw command string passed in over the socket
243      *
244      * @return whether additional commands are expected.
245      */
246     private boolean parseCommand( String rawCommand ) {
247         if (rawCommand == null) {
248             return false;
249         }
250         String command = rawCommand.trim();
251         String argument = null;
252         int breakIndex = command.indexOf(" ");
253         if (breakIndex > 0) {
254             argument = command.substring(breakIndex + 1);
255             command = command.substring(0, breakIndex);
256         }
257         command = command.toUpperCase(Locale.US);
258         
259         if (!COMMANDLIST.contains(command)) {
260             final boolean result = commandRegistry.execute(command, argument, helper.getOutputWriter());
261             helper.getOutputWriter().flush();
262             return result;
263         }
264         
265         try {
266             Method method = getClass().getDeclaredMethod("do"+command, WORKER_METHOD_PARAMETERSET);
267             Boolean returnFlag = (Boolean)method.invoke(this, new Object[] {argument});
268             return returnFlag.booleanValue();
269         } catch (SecurityException e) {
270             helper.writeLoggedFlushedResponse("could not determine executioner of command " + command);
271         } catch (NoSuchMethodException e) {
272             return doUnknownCommand(rawCommand);
273         } catch (Exception e) {
274             e.printStackTrace();
275             helper.writeLoggedFlushedResponse("could not execute command " + command);
276         }
277         return false;
278    }
279 
280     /**
281      * Handler method called upon receipt of an MEMSTAT command.
282      * Returns whether further commands should be read off the wire.
283      *
284      * @param argument the argument passed in with the command
285      */
286     private boolean doMEMSTAT(String argument) {
287         helper.writeLoggedFlushedResponse("Current memory statistics:");
288         helper.writeLoggedFlushedResponse("\tFree Memory: " + Runtime.getRuntime().freeMemory());
289         helper.writeLoggedFlushedResponse("\tTotal Memory: " + Runtime.getRuntime().totalMemory());
290         helper.writeLoggedFlushedResponse("\tMax Memory: " + Runtime.getRuntime().maxMemory());
291 
292         if ("-gc".equalsIgnoreCase(argument)) {
293             System.gc();
294             helper.writeLoggedFlushedResponse("And after System.gc():");
295             helper.writeLoggedFlushedResponse("\tFree Memory: " + Runtime.getRuntime().freeMemory());
296             helper.writeLoggedFlushedResponse("\tTotal Memory: " + Runtime.getRuntime().totalMemory());
297             helper.writeLoggedFlushedResponse("\tMax Memory: " + Runtime.getRuntime().maxMemory());
298         }
299 
300         return true;
301     }
302     
303     /**
304      * Handler method called upon receipt of an ADDUSER command.
305      * Returns whether further commands should be read off the wire.
306      *
307      * @param argument the argument passed in with the command
308      */
309     private boolean doADDUSER(String argument) {
310         int breakIndex = -1;
311         if ((argument == null) ||
312             (argument.equals("")) ||
313             ((breakIndex = argument.indexOf(" ")) < 0)) {
314             helper.writeLoggedFlushedResponse("Usage: adduser [username] [password]");
315             return true;
316         }
317         String username = argument.substring(0,breakIndex);
318         String passwd = argument.substring(breakIndex + 1);
319         if (username.equals("") || passwd.equals("")) {
320             helper.writeLoggedFlushedResponse("Usage: adduser [username] [password]");
321             return true;
322         }
323 
324         boolean success = false;
325         if (users.contains(username)) {
326             StringBuffer responseBuffer =
327                 new StringBuffer(64)
328                         .append("User ")
329                         .append(username)
330                         .append(" already exists");
331             String response = responseBuffer.toString();
332             helper.writeLoggedResponse(response);
333         } else {
334             if((username.indexOf("@") < 0) == false) {
335                 if(theConfigData.getMailServer().supportVirtualHosting() == false) {
336                     helper.getOutputWriter().println("Virtualhosting not supported");
337                     helper.getOutputWriter().flush();
338                     return true;
339                 }
340                 String domain = username.split("@")[1];
341                 if (theConfigData.getDomainListManagement().containsDomain(domain) == false) {
342                     helper.getOutputWriter().println("Domain not exists: " + domain);
343                     helper.getOutputWriter().flush();
344                     return true;
345                 }
346             }
347             success = users.addUser(username, passwd);
348         }
349         if ( success ) {
350             StringBuffer responseBuffer =
351                 new StringBuffer(64)
352                         .append("User ")
353                         .append(username)
354                         .append(" added");
355             String response = responseBuffer.toString();
356             helper.getOutputWriter().println(response);
357             helper.getAvalonLogger().info(response);
358         } else {
359             helper.getOutputWriter().println("Error adding user " + username);
360             helper.getAvalonLogger().error("Error adding user " + username);
361         }
362         helper.getOutputWriter().flush();
363         return true;
364     }
365 
366     /**
367      * Handler method called upon receipt of an SETPASSWORD command.
368      * Returns whether further commands should be read off the wire.
369      *
370      * @param argument the argument passed in with the command
371      */
372     private boolean doSETPASSWORD(String argument) {
373 
374         int breakIndex = -1;
375         if ((argument == null) ||
376             (argument.equals("")) ||
377             ((breakIndex = argument.indexOf(" ")) < 0)) {
378             helper.writeLoggedFlushedResponse("Usage: setpassword [username] [password]");
379             return true;
380         }
381         String username = argument.substring(0,breakIndex);
382         String passwd = argument.substring(breakIndex + 1);
383 
384         if (username.equals("") || passwd.equals("")) {
385             helper.writeLoggedFlushedResponse("Usage: adduser [username] [password]");
386             return true;
387         }
388         User user = users.getUserByName(username);
389         if (user == null) {
390             helper.writeLoggedFlushedResponse("No such user " + username);
391             return true;
392         }
393         boolean success = user.setPassword(passwd);
394         if (success) {
395             users.updateUser(user);
396             StringBuffer responseBuffer =
397                 new StringBuffer(64)
398                         .append("Password for ")
399                         .append(username)
400                         .append(" reset");
401             String response = responseBuffer.toString();
402             helper.getOutputWriter().println(response);
403             helper.getAvalonLogger().info(response);
404         } else {
405             helper.getOutputWriter().println("Error resetting password");
406             helper.getAvalonLogger().error("Error resetting password");
407         }
408         helper.getOutputWriter().flush();
409         return true;
410     }
411 
412     /**
413      * Handler method called upon receipt of an DELUSER command.
414      * Returns whether further commands should be read off the wire.
415      *
416      * @param argument the argument passed in with the command
417      */
418     private boolean doDELUSER(String argument) {
419         String user = argument;
420         if ((user == null) || (user.equals(""))) {
421             helper.writeLoggedFlushedResponse("Usage: deluser [username]");
422             return true;
423         }
424         if (users.contains(user)) {
425             try {
426                 users.removeUser(user);
427                 StringBuffer responseBuffer =
428                                              new StringBuffer(64)
429                                              .append("User ")
430                                              .append(user)
431                                              .append(" deleted");
432                 String response = responseBuffer.toString();
433                 helper.getOutputWriter().println(response);
434                 helper.getAvalonLogger().info(response);
435             } catch (Exception e) {
436                 StringBuffer exceptionBuffer =
437                                               new StringBuffer(128)
438                                               .append("Error deleting user ")
439                                               .append(user)
440                                               .append(" : ")
441                                               .append(e.getMessage());
442                 String exception = exceptionBuffer.toString();
443                 helper.getOutputWriter().println(exception);
444                 helper.getAvalonLogger().error(exception);
445             }
446         } else {
447             StringBuffer responseBuffer =
448                                          new StringBuffer(64)
449                                          .append("User ")
450                                          .append(user)
451                                          .append(" doesn't exist");
452             String response = responseBuffer.toString();
453             helper.getOutputWriter().println(response);
454         }
455         helper.getOutputWriter().flush();
456         return true;
457     }
458 
459     /**
460      * Handler method called upon receipt of an LISTUSERS command.
461      * Returns whether further commands should be read off the wire.
462      *
463      * @param argument the argument passed in with the command
464      */
465     private boolean doLISTUSERS(String argument) {
466         if (argument == null) {
467             helper.writeLoggedResponse("Existing accounts " + users.countUsers());
468             for (Iterator it = users.list(); it.hasNext();) {
469                helper.writeLoggedResponse("user: " + (String) it.next());
470             }
471             helper.getOutputWriter().flush();
472             return true;
473         } else {
474             if(theConfigData.getMailServer().supportVirtualHosting() == false) {
475                 helper.getOutputWriter().println("Virtualhosting not supported");
476                 helper.getOutputWriter().flush();
477                 return true;
478             }
479         
480             ArrayList userList = getDomainUserList(argument);
481             helper.writeLoggedResponse("Existing accounts from domain " + argument + " " + userList.size());
482             for (int i = 0; i <userList.size(); i++) {
483                 helper.writeLoggedResponse("user: " + userList.get(i));
484             }
485             helper.getOutputWriter().flush();
486             return true;
487         }
488     }
489 
490     /**
491      * Handler method called upon receipt of an COUNTUSERS command.
492      * Returns whether further commands should be read off the wire.
493      *
494      * @param argument the argument passed in with the command
495      */
496     private boolean doCOUNTUSERS(String argument) {
497         if (argument == null) {
498             helper.writeLoggedFlushedResponse("Existing accounts " + users.countUsers());
499             return true;
500         } else {
501             if(theConfigData.getMailServer().supportVirtualHosting() == false) {
502                 helper.getOutputWriter().println("Virtualhosting not supported");
503                 helper.getOutputWriter().flush();
504                 return true;
505            }
506             
507            helper.writeLoggedFlushedResponse("Existing accounts for domain " + argument + " " + getDomainUserList(argument).size());
508            return true;
509         }
510     }
511 
512     /**
513      * Handler method called upon receipt of an VERIFY command.
514      * Returns whether further commands should be read off the wire.
515      *
516      * @param argument the argument passed in with the command
517      */
518     private boolean doVERIFY(String argument) {
519         String user = argument;
520         if (user == null || user.equals("")) {
521             helper.writeLoggedFlushedResponse("Usage: verify [username]");
522             return true;
523         }
524         if (users.contains(user)) {
525             StringBuffer responseBuffer =
526                 new StringBuffer(64)
527                         .append("User ")
528                         .append(user)
529                         .append(" exists");
530             String response = responseBuffer.toString();
531             helper.writeLoggedResponse(response);
532         } else {
533             StringBuffer responseBuffer =
534                 new StringBuffer(64)
535                         .append("User ")
536                         .append(user)
537                         .append(" does not exist");
538             String response = responseBuffer.toString();
539             helper.writeLoggedResponse(response);
540         }
541         helper.getOutputWriter().flush();
542         return true;
543     }
544 
545     /**
546      * Handler method called upon receipt of a HELP command.
547      * Returns whether further commands should be read off the wire.
548      *
549      * @param argument the argument passed in with the command
550      */
551     private boolean doHELP(String argument) {
552         helper.getOutputWriter().println("Currently implemented commands:");
553         helper.getOutputWriter().println("help                                                                    display this help");
554         helper.getOutputWriter().println("listusers                                                               display existing accounts");
555         helper.getOutputWriter().println("countusers                                                              display the number of existing accounts");
556         helper.getOutputWriter().println("adduser [username] [password]                                           add a new user");
557         helper.getOutputWriter().println("verify [username]                                                       verify if specified user exist");
558         helper.getOutputWriter().println("deluser [username]                                                      delete existing user");
559         helper.getOutputWriter().println("setpassword [username] [password]                                       sets a user's password");
560         helper.getOutputWriter().println("setalias [user] [alias]                                                 locally forwards all email for 'user' to 'alias'");
561         helper.getOutputWriter().println("showalias [username]                                                    shows a user's current email alias");
562         helper.getOutputWriter().println("unsetalias [user]                                                       unsets an alias for 'user'");
563         helper.getOutputWriter().println("setforwarding [username] [emailaddress]                                 forwards a user's email to another email address");
564         helper.getOutputWriter().println("showforwarding [username]                                               shows a user's current email forwarding");
565         helper.getOutputWriter().println("unsetforwarding [username]                                              removes a forward");
566         helper.getOutputWriter().println("user [repositoryname]                                                   change to another user repository");
567         helper.getOutputWriter().println("addmapping ([table=virtualusertablename]) [user@domain] [mapping]       add mapping for the given emailaddress");
568         helper.getOutputWriter().println("removemapping ([table=virtualusertablename]) [user@domain] [mapping]    remove mapping for the given emailaddress");
569         helper.getOutputWriter().println("listmapping ([table=virtualusertablename]) [user@domain]                list all mappings for the given emailaddress");
570         helper.getOutputWriter().println("listallmappings ([table=virtualusertablename])                          list all mappings");
571         helper.getOutputWriter().println("adddomain [domainname]                                                  add domain to local domains");
572         helper.getOutputWriter().println("removedomain [domainname]                                               remove domain from local domains");
573         helper.getOutputWriter().println("listdomains                                                             list local domains");
574         helper.getOutputWriter().println("listspool [spoolrepositoryname] ([header=name] [regex=value])           list all mails which reside in the spool and have an error state");
575         helper.getOutputWriter().println("flushspool [spoolrepositoryname] ([key] | [header=name] [regex=value])  try to resend the mail assing to the given key. If no key is given all mails get resend");
576         helper.getOutputWriter().println("deletespool [spoolrepositoryname] ([key] | [header=name] [regex=value]) delete the mail assigned to the given key. If no key is given all mails get deleted");
577         helper.getOutputWriter().println("movemails [srcSpoolrepositoryname] [dstSpoolrepositoryname] ([header=headername] [regex=regexValue])");
578         helper.getOutputWriter().println("    [srcstate=sourcestate] [dststate=destinationstate]                  move mails from the source repository to the destination repository.");
579         helper.getOutputWriter().println("listprocessors [processorname]                                          list names of all processors");
580         helper.getOutputWriter().println("listmailets [processorname]                                             list names of all mailets for specified processor");
581         helper.getOutputWriter().println("listmatchers [processorname]                                            list names of all mailets for specified processor");
582         helper.getOutputWriter().println("showmailetinfo [processorname] [#index]                                 shows configuration for mailet of specified processor at given index");
583         helper.getOutputWriter().println("showmatcherinfo [processorname] [#index]                                shows configuration for matcher of specified processor at given index");
584         helper.getOutputWriter().println("addham dir/mbox [directory/mbox]                                        feed the BayesianAnalysisFeeder with the content of the directory or mbox file as HAM");
585         helper.getOutputWriter().println("addspam dir/mbox [directory/mbox]                                       feed the BayesianAnalysisFeeder with the content of the directory or mbox file as SPAM");
586         helper.getOutputWriter().println("exportbayesiandata [file]                                               export the BayesianAnalysis data to a xml file");
587         helper.getOutputWriter().println("resetbayesiandata                                                       reset trained BayesianAnalysis data");
588         helper.getOutputWriter().println("memstat ([-gc])                                                         shows memory usage. When called with -gc the garbage collector get called");
589         helper.getOutputWriter().println("shutdown                                                                kills the current JVM (convenient when James is run as a daemon)");
590         helper.getOutputWriter().println("quit                                                                    close connection");
591         helper.getOutputWriter().flush();
592         return true;
593 
594     }
595 
596     /**
597      * Handler method called upon receipt of an SETALIAS command.
598      * Returns whether further commands should be read off the wire.
599      *
600      * @param argument the argument passed in with the command
601      */
602     private boolean doSETALIAS(String argument) {
603         int breakIndex = -1;
604         if ((argument == null) ||
605             (argument.equals("")) ||
606             ((breakIndex = argument.indexOf(" ")) < 0)) {
607             helper.writeLoggedFlushedResponse("Usage: setalias [username] [emailaddress]");
608             return true;
609         }
610         String username = argument.substring(0,breakIndex);
611         String alias = argument.substring(breakIndex + 1);
612         if (username.equals("") || alias.equals("")) {
613             helper.writeLoggedFlushedResponse("Usage: setalias [username] [alias]");
614             return true;
615         }
616 
617         User baseuser = users.getUserByName(username);
618         if (baseuser == null) {
619             helper.writeLoggedFlushedResponse("No such user " + username);
620             return true;
621         }
622         if (! (baseuser instanceof JamesUser ) ) {
623             helper.writeLoggedFlushedResponse("Can't set alias for this user type.");
624             return true;
625         }
626 
627         JamesUser user = (JamesUser) baseuser;
628         JamesUser aliasUser = (JamesUser) users.getUserByName(alias);
629         if (aliasUser == null) {
630             helper.writeLoggedFlushedResponse("Alias unknown to server - create that user first.");
631             return true;
632         }
633 
634         boolean success = user.setAlias(alias);
635         if (success) {
636             user.setAliasing(true);
637             users.updateUser(user);
638             StringBuffer responseBuffer =
639                 new StringBuffer(64)
640                         .append("Alias for ")
641                         .append(username)
642                         .append(" set to:")
643                         .append(alias);
644             String response = responseBuffer.toString();
645             helper.getOutputWriter().println(response);
646             helper.getAvalonLogger().info(response);
647         } else {
648             helper.getOutputWriter().println("Error setting alias");
649             helper.getAvalonLogger().error("Error setting alias");
650         }
651         helper.getOutputWriter().flush();
652         return true;
653     }
654 
655     /**
656      * Handler method called upon receipt of an SETFORWARDING command.
657      * Returns whether further commands should be read off the wire.
658      *
659      * @param argument the argument passed in with the command
660      */
661     private boolean doSETFORWARDING(String argument) {
662         int breakIndex = -1;
663         if ((argument == null) ||
664             (argument.equals("")) ||
665             ((breakIndex = argument.indexOf(" ")) < 0)) {
666             helper.writeLoggedFlushedResponse("Usage: setforwarding [username] [emailaddress]");
667             return true;
668         }
669         String username = argument.substring(0,breakIndex);
670         String forward = argument.substring(breakIndex + 1);
671         if (username.equals("") || forward.equals("")) {
672            helper.writeLoggedFlushedResponse("Usage: setforwarding [username] [emailaddress]");
673            return true;
674         }
675         // Verify user exists
676         User baseuser = users.getUserByName(username);
677         if (baseuser == null) {
678             helper.writeLoggedFlushedResponse("No such user " + username);
679             return true;
680         } else if (! (baseuser instanceof JamesUser ) ) {
681             helper.writeLoggedFlushedResponse("Can't set forwarding for this user type.");
682             return true;
683         }
684         JamesUser user = (JamesUser)baseuser;
685         // Verify acceptable email address
686         MailAddress forwardAddr;
687         try {
688              forwardAddr = new MailAddress(forward);
689         } catch(ParseException pe) {
690             helper.writeLoggedResponse("Parse exception with that email address: " + pe.getMessage());
691             helper.writeLoggedFlushedResponse("Forwarding address not added for " + username);
692             return true;
693         }
694 
695         boolean success = user.setForwardingDestination(forwardAddr);
696         if (success) {
697             user.setForwarding(true);
698             users.updateUser(user);
699             StringBuffer responseBuffer =
700                 new StringBuffer(64)
701                         .append("Forwarding destination for ")
702                         .append(username)
703                         .append(" set to:")
704                         .append(forwardAddr.toString());
705             String response = responseBuffer.toString();
706             helper.getOutputWriter().println(response);
707             helper.getAvalonLogger().info(response);
708         } else {
709             helper.getOutputWriter().println("Error setting forwarding");
710             helper.getAvalonLogger().error("Error setting forwarding");
711         }
712         helper.getOutputWriter().flush();
713         return true;
714     }
715 
716     /**
717      * Handler method called upon receipt of an SHOWALIAS command.
718      * Returns whether further commands should be read off the wire.
719      *
720      * @param username the user name
721      */
722     private boolean doSHOWALIAS(String username) {
723         if ( username == null || username.equals("") ) {
724             helper.writeLoggedFlushedResponse("Usage: showalias [username]");
725             return true;
726         }
727 
728 
729         User baseuser = users.getUserByName(username);
730         if (baseuser == null) {
731             helper.writeLoggedFlushedResponse("No such user " + username);
732             return true;
733         } else if (! (baseuser instanceof JamesUser ) ) {
734             helper.writeLoggedFlushedResponse("Can't show aliases for this user type.");
735             return true;
736         }
737 
738         JamesUser user = (JamesUser)baseuser;
739         if ( user == null ) {
740             helper.writeLoggedFlushedResponse("No such user " + username);
741             return true;
742         }
743 
744         if ( !user.getAliasing() ) {
745             helper.writeLoggedFlushedResponse("User " + username + " does not currently have an alias");
746             return true;
747         }
748 
749         String alias = user.getAlias();
750 
751         if ( alias == null || alias.equals("") ) {    //  defensive programming -- neither should occur
752             String errmsg = "For user " + username + ", the system indicates that aliasing is set but no alias was found";
753             helper.getOutputWriter().println(errmsg);
754             helper.getAvalonLogger().error(errmsg);
755             return true;
756         }
757 
758         helper.writeLoggedFlushedResponse("Current alias for " + username + " is: " + alias);
759         return true;
760     }
761 
762     /**
763      * Handler method called upon receipt of an SHOWFORWARDING command.
764      * Returns whether further commands should be read off the wire.
765      *
766      * @param username the user name
767      */
768     private boolean doSHOWFORWARDING(String username) {
769         if ( username == null || username.equals("") ) {
770             helper.writeLoggedFlushedResponse("Usage: showforwarding [username]");
771             return true;
772         }
773 
774         // Verify user exists
775         User baseuser = users.getUserByName(username);
776         if (baseuser == null) {
777             helper.writeLoggedFlushedResponse("No such user " + username);
778             return true;
779         } else if (! (baseuser instanceof JamesUser ) ) {
780             helper.writeLoggedFlushedResponse("Can't set forwarding for this user type.");
781             return true;
782         }
783         JamesUser user = (JamesUser)baseuser;
784         if ( user == null ) {
785             helper.writeLoggedFlushedResponse("No such user " + username);
786             return true;
787         }
788 
789         if ( !user.getForwarding() ) {
790             helper.writeLoggedFlushedResponse("User " + username + " is not currently being forwarded");
791             return true;
792         }
793 
794         MailAddress fwdAddr = user.getForwardingDestination();
795 
796         if ( fwdAddr == null ) {    //  defensive programming -- should not occur
797             String errmsg = "For user " + username + ", the system indicates that forwarding is set but no forwarding destination was found";
798             helper.getOutputWriter().println(errmsg);
799             helper.getAvalonLogger().error(errmsg);
800             return true;
801         }
802 
803         helper.writeLoggedFlushedResponse("Current forwarding destination for " + username + " is: " + fwdAddr);
804         return true;
805     }
806 
807     /**
808      * Handler method called upon receipt of an UNSETALIAS command.
809      * Returns whether further commands should be read off the wire.
810      *
811      * @param argument the argument passed in with the command
812      */
813     private boolean doUNSETALIAS(String argument) {
814         if ((argument == null) || (argument.equals(""))) {
815             helper.writeLoggedFlushedResponse("Usage: unsetalias [username]");
816             return true;
817         }
818         String username = argument;
819         JamesUser user = (JamesUser) users.getUserByName(username);
820         if (user == null) {
821             helper.writeLoggedResponse("No such user " + username);
822         } else if (user.getAliasing()){
823             user.setAliasing(false);
824             users.updateUser(user);
825             StringBuffer responseBuffer =
826                 new StringBuffer(64)
827                         .append("Alias for ")
828                         .append(username)
829                         .append(" unset");
830             String response = responseBuffer.toString();
831             helper.getOutputWriter().println(response);
832             helper.getAvalonLogger().info(response);
833         } else {
834             helper.writeLoggedResponse("Aliasing not active for" + username);
835         }
836         helper.getOutputWriter().flush();
837         return true;
838     }
839 
840     /**
841      * Handler method called upon receipt of an UNSETFORWARDING command.
842      * Returns whether further commands should be read off the wire.
843      *
844      * @param argument the argument passed in with the command
845      */
846     private boolean doUNSETFORWARDING(String argument) {
847         if ((argument == null) || (argument.equals(""))) {
848             helper.writeLoggedFlushedResponse("Usage: unsetforwarding [username]");
849             return true;
850         }
851         String username = argument;
852         JamesUser user = (JamesUser) users.getUserByName(username);
853         if (user == null) {
854             helper.writeLoggedFlushedResponse("No such user " + username);
855         } else if (user.getForwarding()){
856             user.setForwarding(false);
857             users.updateUser(user);
858             StringBuffer responseBuffer =
859                 new StringBuffer(64)
860                         .append("Forward for ")
861                         .append(username)
862                         .append(" unset");
863             String response = responseBuffer.toString();
864             helper.getOutputWriter().println(response);
865             helper.getOutputWriter().flush();
866             helper.getAvalonLogger().info(response);
867         } else {
868             helper.writeLoggedFlushedResponse("Forwarding not active for" + username);
869         }
870         return true;
871     }
872 
873     /**
874      * Handler method called upon receipt of a USER command.
875      * Returns whether further commands should be read off the wire.
876      *
877      * @param argument the argument passed in with the command
878      */
879     private boolean doUSER(String argument) {
880         if (argument == null || argument.equals("")) {
881             helper.writeLoggedFlushedResponse("Usage: user [repositoryName]");
882             return true;
883         }
884         String repositoryName = argument.toLowerCase(Locale.US);
885         UsersRepository repos = theConfigData.getUserStore().getRepository(repositoryName);
886         if ( repos == null ) {
887             helper.writeLoggedFlushedResponse("No such repository: " + repositoryName);
888         } else {
889             users = repos;
890             StringBuffer responseBuffer =
891                 new StringBuffer(64)
892                         .append("Changed to repository '")
893                         .append(repositoryName)
894                         .append("'.");
895             helper.writeLoggedFlushedResponse(responseBuffer.toString());
896         }
897         return true;
898     }
899 
900     /**
901      * Handler method called upon receipt of a LISTSPOOL command. Returns
902      * whether further commands should be read off the wire.
903      * 
904      * @param argument
905      *            the argument passed in with the command
906      */
907     private boolean doLISTSPOOL(String argument) {
908 
909     int count = 0;
910         String[] args = null;
911         String headername = null;
912         String regex = null;
913         
914         if (argument != null) args = argument.split(" ");
915 
916         // check if the command was called correct
917         if ((argument == null) || (argument.trim().equals("")) || args.length < 1 || args.length > 3 || (args.length > 1 && !args[1].startsWith(HEADER_IDENTIFIER)) || (args.length > 2 && !args[2].startsWith(REGEX_IDENTIFIER))) {
918             helper.writeLoggedFlushedResponse("Usage: LISTSPOOL [spoolrepositoryname] ([header=headername] [regex=regexValue])");
919             return true;
920         }
921 
922         String url = args[0];
923         
924         if (args.length > 1) { 
925             headername = args[1].substring(HEADER_IDENTIFIER.length());
926             regex = args[2].substring(REGEX_IDENTIFIER.length());
927         }
928         
929         try {
930             List spoolItems;
931             
932             if (headername == null || regex == null) {
933                 spoolItems = theConfigData.getSpoolManagement().getSpoolItems(url, SpoolFilter.ERRORMAIL_FILTER);
934             } else {
935                 spoolItems = theConfigData.getSpoolManagement().getSpoolItems(url, new SpoolFilter(SpoolFilter.ERROR_STATE,headername,regex));
936             }
937             
938             count = spoolItems.size();
939             if (count > 0) helper.getOutputWriter().println("Messages in spool:");
940             for (Iterator iterator = spoolItems.iterator(); iterator.hasNext();) {
941                 String item = (String) iterator.next();
942                 helper.getOutputWriter().println(item);
943                 helper.getOutputWriter().flush();
944             }
945             helper.getOutputWriter().println("Number of spooled mails: " + count);
946             helper.getOutputWriter().flush();
947         } catch (Exception e) {
948             helper.getOutputWriter().println("Error opening the spoolrepository " + e.getMessage());
949             helper.getOutputWriter().flush();
950             helper.getAvalonLogger().error(
951                     "Error opening the spoolrepository " + e.getMessage());
952         }
953         return true;
954     }
955 
956     /**
957      * Handler method called upon receipt of a LISTSPOOL command.
958      * Returns whether further commands should be read off the wire.
959      *
960      * @param argument the argument passed in with the command
961      */
962     private boolean doFLUSHSPOOL(String argument) {
963         int count = 0;
964         String[] args = null;
965 
966         if (argument != null)
967             args = argument.split(" ");
968 
969         // check if the command was called correct
970         if ((argument == null || argument.trim().equals(""))
971                 || (args.length < 1 || args.length > 3 || (!args[1].startsWith(KEY_IDENTIFIER) && (args.length > 1  
972                 && !args[1].startsWith(HEADER_IDENTIFIER))) || (args.length == 3 && !args[2].startsWith(REGEX_IDENTIFIER)))) {
973             helper.writeLoggedFlushedResponse("Usage: FLUSHSPOOL [spoolrepositoryname] ([key=mKey] | [header=headername] [regex=regexValue] )");
974             return true;
975         }
976 
977         String url = args[0];
978         String key = null;
979         String header = null;
980         String regex = null;
981         
982         if (args[1].startsWith(KEY_IDENTIFIER)) {
983             key = args[1].substring(KEY_IDENTIFIER.length()); 
984         } else {
985             header = args[1].substring(HEADER_IDENTIFIER.length());
986             regex = args[2].substring(REGEX_IDENTIFIER.length()); 
987         }
988         
989         try {
990             if (key != null) {
991                 count = theConfigData.getSpoolManagement().resendSpoolItems(url, key, null, SpoolFilter.ERRORMAIL_FILTER);
992             } else {
993                 count = theConfigData.getSpoolManagement().resendSpoolItems(url, key, null, new SpoolFilter(SpoolFilter.ERROR_STATE,header,regex));
994             }
995             helper.getOutputWriter().println("Number of flushed mails: " + count);
996             helper.getOutputWriter().flush();
997 
998         } catch (Exception e) {
999             helper.getOutputWriter()
1000                     .println("Error accessing the spoolrepository "
1001                             + e.getMessage());
1002             helper.getOutputWriter().flush();
1003             helper.getAvalonLogger().error(
1004                     "Error accessing the spoolrepository " + e.getMessage());
1005         }
1006         return true;
1007     }
1008 
1009     /**
1010      * Handler method called upon receipt of a DELETESPOOL command. Returns
1011      * whether further commands should be read off the wire.
1012      * 
1013      * @param argument
1014      *            the argument passed in with the command
1015      */
1016     private boolean doDELETESPOOL(String argument) {
1017         String[] args = null;
1018 
1019         if (argument != null)
1020             args = argument.split(" ");
1021 
1022         // check if the command was called correct
1023         if ((argument == null || argument.trim().equals(""))
1024                 || (args.length < 1 || args.length > 3 || (args.length > 1 && (!args[1].startsWith(KEY_IDENTIFIER) 
1025                 && !args[1].startsWith(HEADER_IDENTIFIER))) || (args.length == 3 && !args[2].startsWith(REGEX_IDENTIFIER)))) {
1026             helper.writeLoggedFlushedResponse("Usage: DELETESPOOL [spoolrepositoryname] ([key=mKey] | [header=headername] [regex=regexValue])");
1027             return true;
1028         }
1029 
1030         String url = args[0];
1031         String key = null;
1032         String header = null;
1033         String regex = null;
1034 
1035         if (args[1].startsWith(KEY_IDENTIFIER)) {
1036             key = args[1].substring(KEY_IDENTIFIER.length()); 
1037         } else {
1038             header = args[1].substring(HEADER_IDENTIFIER.length());
1039             regex = args[2].substring(REGEX_IDENTIFIER.length()); 
1040         }
1041 
1042         try {
1043             ArrayList lockingFailures = new ArrayList();
1044             int count = 0;
1045             
1046             if (key != null) {
1047                 count = theConfigData.getSpoolManagement().removeSpoolItems(url, key, lockingFailures, SpoolFilter.ERRORMAIL_FILTER);
1048             } else {
1049                 count = theConfigData.getSpoolManagement().removeSpoolItems(url, key, lockingFailures, new SpoolFilter(SpoolFilter.ERROR_STATE,header,regex));
1050             }
1051             
1052             for (Iterator iterator = lockingFailures.iterator(); iterator.hasNext();) {
1053                 String lockFailureKey = (String) iterator.next();
1054                 helper.getOutputWriter().println("Error locking the mail with key:  " + lockFailureKey);
1055             }
1056             helper.getOutputWriter().flush();
1057 
1058             helper.getOutputWriter().println("Number of deleted mails: " + count);
1059             helper.getOutputWriter().flush();
1060 
1061         } catch (Exception e) {
1062             helper.getOutputWriter().println("Error opening the spoolrepository " + e.getMessage());
1063             helper.getOutputWriter().flush();
1064             helper.getAvalonLogger().error("Error opeing the spoolrepository " + e.getMessage());
1065         }
1066         return true;
1067     }
1068 
1069 
1070     /**
1071      * Handler method called upon receipt of a MOVEMAILS command. Returns
1072      * whether further commands should be read off the wire.
1073      * 
1074      * @param argument
1075      *            the argument passed in with the command
1076      */
1077     private boolean doMOVEMAILS(String argument) {
1078         String[] args = null;
1079 
1080         if (argument != null)
1081             args = argument.split(" ");
1082 
1083         // check if the command was called correct
1084         if ((argument == null || argument.trim().equals(""))
1085                 || (args.length < 2 || args.length > 6)) {
1086             helper.writeLoggedFlushedResponse("Usage: MOVEMAILS [srcSpoolrepositoryname] [dstSpoolrepositoryname] ([header=headername] [regex=regexValue]) [srcstate=sourcestate] [dststate=destinationstate]");
1087             return true;
1088         }
1089 
1090         String srcUrl = args[0];
1091         String dstUrl = args[1];
1092         
1093         String dstState = null;
1094         String srcState = null;
1095         String header = null;
1096         String regex = null;
1097 
1098         for (int i = 2; i < args.length; i++) {
1099             if (args[i].startsWith(HEADER_IDENTIFIER)) {
1100                 header = args[i].substring(HEADER_IDENTIFIER.length());
1101             } else if (args[i].startsWith(REGEX_IDENTIFIER)) {
1102                 header = args[i].substring(REGEX_IDENTIFIER.length());
1103             } else if (args[i].startsWith("srcstate=")) {
1104                 header = args[i].substring("srcstate=".length());
1105             } else if (args[i].startsWith("dststate=")) {
1106                 header = args[i].substring("dststate=".length());
1107             } else {
1108                 helper.writeLoggedResponse("Unexpected parameter "+args[i]);
1109                 helper.writeLoggedFlushedResponse("Usage: MOVEMAILS [srcSpoolrepositoryname] [dstSpoolrepositoryname] ([header=headername] [regex=regexValue]) [srcstate=sourcestate] [dststate=destinationstate]");
1110                 return true;
1111             }
1112         }
1113         
1114         if ((header != null && regex == null) || (header == null && regex != null)) {
1115             if (regex == null) {
1116                 helper.writeLoggedResponse("Bad parameters: used header without regex");
1117             } else {
1118                 helper.writeLoggedResponse("Bad parameters: used regex without header");
1119             }
1120             helper.writeLoggedFlushedResponse("Usage: MOVEMAILS [srcSpoolrepositoryname] [dstSpoolrepositoryname] ([header=headername] [regex=regexValue]) [srcstate=sourcestate] [dststate=destinationstate]");
1121             return true;
1122         }
1123 
1124         try {
1125             int count = theConfigData.getSpoolManagement().moveSpoolItems(srcUrl, dstUrl, dstState, new SpoolFilter(srcState,header,regex));
1126             
1127             helper.getOutputWriter().println("Number of moved mails: " + count);
1128             helper.getOutputWriter().flush();
1129 
1130         } catch (Exception e) {
1131             helper.getOutputWriter().println("Error opening the spoolrepository " + e.getMessage());
1132             helper.getOutputWriter().flush();
1133             helper.getAvalonLogger().error("Error opeing the spoolrepository " + e.getMessage());
1134         }
1135         return true;
1136     }
1137 
1138     /**
1139      * Handler method called upon receipt of a QUIT command. Returns whether
1140      * further commands should be read off the wire.
1141      * 
1142      * @param argument
1143      *            the argument passed in with the command
1144      */
1145     private boolean doQUIT(String argument) {
1146         helper.writeLoggedFlushedResponse("Bye");
1147         return false;
1148     }
1149 
1150     /**
1151      * Handler method called upon receipt of a SHUTDOWN command. Returns whether
1152      * further commands should be read off the wire.
1153      * 
1154      * @param argument
1155      *            the argument passed in with the command
1156      */
1157     private boolean doSHUTDOWN(String argument) {
1158         helper.writeLoggedFlushedResponse("Shutting down, bye bye");
1159         System.exit(0);
1160         return false;
1161     }
1162 
1163     /**
1164      * Handler method called upon receipt of an unrecognized command. Returns
1165      * whether further commands should be read off the wire.
1166      * 
1167      * @param argument
1168      *            the unknown command
1169      */
1170     private boolean doUnknownCommand(String argument) {
1171         helper.writeLoggedFlushedResponse("Unknown command " + argument);
1172         return true;
1173     }
1174     
1175     /**
1176      * Handler method called upon receipt of a ADDHAM command. Returns
1177      * whether further commands should be read off the wire.
1178      * 
1179      * @param argument
1180      *            the argument passed in with the command
1181      */
1182     private boolean doADDHAM(String argument) {
1183         String [] args = null;
1184         int count = 0;
1185         
1186         if (argument != null) {
1187             args = argument.split(" "); 
1188         }
1189         
1190         // check if the command was called correct
1191         if (argument == null || argument.trim().equals("") || (args != null && args.length != 2)) {
1192             helper.writeLoggedFlushedResponse("Usage: ADDHAM DIR/MBOX [dir/mbox]");
1193             return true;
1194         }
1195 
1196         try {
1197             
1198             // stop watchdog cause feeding can take some time
1199             helper.getWatchdog().stop();  
1200             
1201             if (args[0].equalsIgnoreCase("DIR")) {
1202                 count = theConfigData.getBayesianAnalyzerManagement().addHamFromDir(args[1]);
1203             } else if (args[0].equalsIgnoreCase("MBOX")) {
1204                 count = theConfigData.getBayesianAnalyzerManagement().addHamFromMbox(args[1]);
1205             } else {
1206                 helper.writeLoggedFlushedResponse("Usage: ADDHAM DIR/MBOX [dir/mbox]");
1207                 return true;
1208             }
1209             helper.getOutputWriter().println("Feed the BayesianAnalysis with " + count + " HAM");
1210             helper.getOutputWriter().flush();
1211         
1212         } catch (BayesianAnalyzerManagementException e) {
1213             helper.getAvalonLogger().error("Error on feeding BayesianAnalysis: " + e);
1214             helper.getOutputWriter().println("Error on feeding BayesianAnalysis: " + e);
1215             helper.getOutputWriter().flush();
1216             return true;
1217         } finally {
1218             helper.getWatchdog().start();
1219         }
1220     
1221         return true;
1222     }
1223     
1224     /**
1225      * Handler method called upon receipt of a ADDSPAM command. Returns
1226      * whether further commands should be read off the wire.
1227      * 
1228      * @param argument
1229      *            the argument passed in with the command
1230      */
1231     private boolean doADDSPAM(String argument) {
1232         String [] args = null;
1233         int count = 0;
1234         
1235         if (argument != null) {
1236             args = argument.split(" "); 
1237         }
1238         // check if the command was called correct
1239         if (argument == null || argument.trim().equals("") || (args != null && args.length != 2)) {
1240             helper.writeLoggedFlushedResponse("Usage: ADDSPAM DIR/MBOX [dir/mbox]");
1241             return true;
1242         }
1243 
1244         try {
1245             
1246             // stop watchdog cause feeding can take some time
1247             helper.getWatchdog().stop();
1248             
1249             if (args[0].equalsIgnoreCase("DIR")) {
1250                 count = theConfigData.getBayesianAnalyzerManagement().addSpamFromDir(args[1]);
1251             } else if (args[0].equalsIgnoreCase("MBOX")) {
1252                 count = theConfigData.getBayesianAnalyzerManagement().addSpamFromMbox(args[1]);
1253             } else {
1254                 helper.writeLoggedFlushedResponse("Usage: ADDHAM DIR/MBOX [dir/mbox]");
1255                 return true;
1256             }
1257             helper.getOutputWriter().println("Feed the BayesianAnalysis with " + count + " SPAM");
1258             helper.getOutputWriter().flush();
1259             
1260         } catch (BayesianAnalyzerManagementException e) {
1261             helper.getAvalonLogger().error("Error on feeding BayesianAnalysis: " + e);
1262             helper.getOutputWriter().println("Error on feeding BayesianAnalysis: " + e);
1263             helper.getOutputWriter().flush();
1264             return true;
1265         } finally {
1266             helper.getWatchdog().start();
1267         }
1268     
1269         return true;
1270     }
1271     
1272    
1273     
1274     private boolean doEXPORTBAYESIANDATA(String argument) {
1275         // check if the command was called correct
1276         if (argument == null || argument.trim().equals("")) {
1277             helper.writeLoggedFlushedResponse("Usage: EXPORTBAYESIANALYZERDATA [dir]");
1278             return true;
1279         }
1280 
1281         try {
1282             
1283             // stop watchdog cause feeding can take some time
1284             helper.getWatchdog().stop();
1285             
1286             theConfigData.getBayesianAnalyzerManagement().exportData(argument);
1287             helper.getOutputWriter().println("Exported the BayesianAnalysis data");
1288             helper.getOutputWriter().flush();
1289 
1290         } catch (BayesianAnalyzerManagementException e) {
1291             helper.getAvalonLogger().error("Error on exporting BayesianAnalysis data: " + e);
1292             helper.getOutputWriter().println("Error on exporting BayesianAnalysis data: " + e);
1293             helper.getOutputWriter().flush();
1294             return true;
1295         } finally {
1296             helper.getWatchdog().start();
1297         }
1298     
1299         // check if any exception was thrown
1300         return true;
1301     }
1302     
1303     private boolean doIMPORTBAYESIANDATA(String argument) {
1304         // check if the command was called correct
1305         if (argument == null || argument.trim().equals("")) {
1306             helper.writeLoggedFlushedResponse("Usage: IMPORTBAYESIANALYZERDATA [dir]");
1307             return true;
1308         }
1309 
1310         try {
1311             
1312             // stop watchdog cause feeding can take some time
1313             helper.getWatchdog().stop();
1314             
1315             theConfigData.getBayesianAnalyzerManagement().importData(argument);
1316             helper.getOutputWriter().println("Imported the BayesianAnalysis data");
1317             helper.getOutputWriter().flush();
1318 
1319         } catch (BayesianAnalyzerManagementException e) {
1320             helper.getAvalonLogger().error("Error on importing BayesianAnalysis data: " + e);
1321             helper.getOutputWriter().println("Error on importing BayesianAnalysis data: " + e);
1322             helper.getOutputWriter().flush();
1323             return true;
1324         } finally {
1325             helper.getWatchdog().start();
1326         }
1327     
1328         return true;
1329     }
1330     
1331     private boolean doRESETBAYESIANDATA(String argument) {
1332 
1333         try {           
1334             // stop watchdog cause feeding can take some time
1335             helper.getWatchdog().stop();
1336             
1337             theConfigData.getBayesianAnalyzerManagement().resetData();
1338             helper.getOutputWriter().println("Reseted the BayesianAnalysis data");
1339             helper.getOutputWriter().flush();
1340 
1341         } catch (BayesianAnalyzerManagementException e) {
1342             helper.getAvalonLogger().error("Error on reseting BayesianAnalysis data: " + e);
1343             helper.getOutputWriter().println("Error on reseting BayesianAnalysis data: " + e);
1344             helper.getOutputWriter().flush();
1345             return true;
1346         } finally {
1347             helper.getWatchdog().start();
1348         }
1349     
1350         return true;
1351     }
1352 
1353     private boolean doLISTPROCESSORS(String argument) {
1354         String[] processorNames = theConfigData.getProcessorManagement().getProcessorNames();
1355         helper.writeLoggedResponse("Existing processors: " + processorNames.length);
1356         for (int i = 0; i < processorNames.length; i++) {
1357             helper.writeLoggedResponse("\t" + processorNames[i]);
1358          }
1359         return true;
1360     }
1361 
1362     private boolean processorExists(String name) {
1363         name = name.toLowerCase(Locale.US);
1364         List processorList = Arrays.asList(theConfigData.getProcessorManagement().getProcessorNames());
1365         return processorList.contains(name);
1366     }
1367     
1368     private boolean doLISTMAILETS(String argument) {
1369         ProcessorManagementService processorManagement = theConfigData.getProcessorManagement();
1370         if (argument == null || !processorExists(argument)) {
1371             helper.writeLoggedFlushedResponse("Usage: LISTMAILETS [processor]");
1372             helper.writeLoggedFlushedResponse("The list of valid processor names can be retrieved using command LISTPROCESSORS");
1373             return true;
1374         }
1375         String[] mailetNames = processorManagement.getMailetNames(argument);
1376         helper.writeLoggedResponse("Existing mailets in processor: " + mailetNames.length);
1377         for (int i = 0; i < mailetNames.length; i++) {
1378             helper.writeLoggedResponse((i+1) + ". " + mailetNames[i]);
1379          }
1380         return true;
1381     }
1382 
1383     private boolean doLISTMATCHERS(String argument) {
1384         ProcessorManagementService processorManagement = theConfigData.getProcessorManagement();
1385         if (argument == null || !processorExists(argument)) {
1386             helper.writeLoggedFlushedResponse("Usage: LISTMATCHERS [processor]");
1387             helper.writeLoggedFlushedResponse("The list of valid processor names can be retrieved using command LISTPROCESSORS");
1388             return true;
1389         }
1390         String[] matcherNames = processorManagement.getMatcherNames(argument);
1391         helper.writeLoggedResponse("Existing matchers in processor: " + matcherNames.length);
1392         for (int i = 0; i < matcherNames.length; i++) {
1393             helper.writeLoggedResponse((i+1) + ". " + matcherNames[i]);
1394          }
1395         return true;
1396     }
1397 
1398     private Object[] extractMailetInfoParameters(String argument, String commandHelp) {
1399         String[] argList = argument.split(" ");
1400         boolean argListOK = argument != null && argList != null && argList.length == 2;
1401         if (!argListOK) {
1402             helper.writeLoggedFlushedResponse("Usage: SHOW" + commandHelp + "INFO [processor] [#index]");
1403             return null;
1404         }
1405         String processorName = argList[0];
1406         if (!processorExists(processorName)) {
1407             helper.writeLoggedFlushedResponse("The list of valid processor names can be retrieved using command LISTPROCESSORS");
1408             return null;
1409         }
1410         int index = -1;
1411         try {
1412             index = Integer.parseInt(argList[1]) - 1;
1413         } catch (NumberFormatException e) {
1414             // fall thru with -1
1415         }
1416         if (index < 0) {
1417             helper.writeLoggedFlushedResponse("The index parameter must be a positive number");
1418             return null;
1419         }
1420         
1421         return new Object[] {processorName, new Integer(index)};
1422     }
1423 
1424     private boolean doSHOWMAILETINFO(String argument) {
1425         ProcessorManagementService processorManagement = theConfigData.getProcessorManagement();
1426         Object[] parameters = extractMailetInfoParameters(argument, "MAILET");
1427         if (parameters == null) return true;
1428         
1429         // extract parsed parameters
1430         String processorName = (String) parameters[0];
1431         int index = ((Integer)parameters[1]).intValue();
1432         
1433         String[] mailetParameters = null; 
1434         try {
1435             mailetParameters = processorManagement.getMailetParameters(processorName, index);
1436         } catch (RuntimeException e) {
1437             // fall thru with NULL
1438         }
1439         if (mailetParameters == null) {
1440             helper.writeLoggedFlushedResponse("The index is not referring to an existing mailet");
1441             return true;
1442         }
1443         helper.writeLoggedResponse("Mailet parameters: " + mailetParameters.length);
1444         for (int i = 0; i < mailetParameters.length; i++) {
1445             String parameter = (String) mailetParameters[i];
1446             helper.writeLoggedResponse("\t" + parameter);
1447          }
1448         return true;
1449     }
1450 
1451     private boolean doSHOWMATCHERINFO(String argument) {
1452         ProcessorManagementService processorManagement = theConfigData.getProcessorManagement();
1453         Object[] parameters = extractMailetInfoParameters(argument, "MATCHER");
1454         if (parameters == null) return true;
1455         
1456         // extract parsed parameters
1457         String processorName = (String) parameters[0];
1458         int index = ((Integer)parameters[1]).intValue();
1459         
1460         String[] matcherParameters = null; 
1461         try {
1462             matcherParameters = processorManagement.getMatcherParameters(processorName, index);
1463         } catch (RuntimeException e) {
1464             // fall thru with NULL
1465         }
1466         if (matcherParameters == null) {
1467             helper.writeLoggedFlushedResponse("The index is not referring to an existing matcher");
1468             return true;
1469         }
1470         helper.writeLoggedResponse("Matcher parameters: " + matcherParameters.length);
1471         for (int i = 0; i < matcherParameters.length; i++) {
1472             String parameter = (String) matcherParameters[i];
1473             helper.writeLoggedResponse("\t" + parameter);
1474          }
1475         return true;
1476     }
1477     
1478     private boolean doADDMAPPING(String argument) {
1479         String[] args = null;
1480         
1481         if (argument != null)
1482             args = argument.split(" ");
1483 
1484         // check if the command was called correct
1485         if (argument == null || argument.trim().equals("") || args.length < 2 || args.length > 3) {
1486             helper.writeLoggedFlushedResponse("Usage: ADDMAPPING [table=table] user@domain mapping");
1487             return true;
1488         }
1489         try {
1490             helper.getOutputWriter().println("Adding mapping successful: " + mappingAction(args,ADD_MAPPING_ACTION));
1491             helper.getOutputWriter().flush();
1492         } catch (VirtualUserTableManagementException e) {
1493             helper.getAvalonLogger().error("Error on adding mapping: " + e);
1494             helper.getOutputWriter().println("Error on adding mapping: " + e);
1495             helper.getOutputWriter().flush();
1496         } catch (IllegalArgumentException e) {
1497             helper.getAvalonLogger().error("Error on adding mapping: " + e);
1498             helper.getOutputWriter().println("Error on adding mapping: " + e);
1499             helper.getOutputWriter().flush();
1500         }
1501         return true;
1502     }
1503     
1504     private boolean doREMOVEMAPPING(String argument) {
1505         String[] args = null;
1506         
1507         if (argument != null)
1508             args = argument.split(" ");
1509 
1510         // check if the command was called correct
1511         if (argument == null || argument.trim().equals("") || args.length < 2 || args.length > 3) {
1512             helper.writeLoggedFlushedResponse("Usage: REMOVEMAPPING [table=table] user@domain mapping");
1513             return true;
1514         }
1515         try {
1516             helper.getOutputWriter().println("Removing mapping successful: " + mappingAction(args,REMOVE_MAPPING_ACTION));
1517             helper.getOutputWriter().flush();
1518         } catch (VirtualUserTableManagementException e) {
1519             helper.getAvalonLogger().error("Error on  removing mapping: " + e);
1520             helper.getOutputWriter().println("Error on removing mapping: " + e);
1521             helper.getOutputWriter().flush();
1522         } catch (IllegalArgumentException e) {
1523             helper.getAvalonLogger().error("Error on removing mapping: " + e);
1524             helper.getOutputWriter().println("Error on removing mapping: " + e);
1525             helper.getOutputWriter().flush();
1526         }
1527         return true;
1528     }
1529 
1530     private boolean doLISTMAPPING(String argument) {
1531         String[] args = null;
1532         String table = null;
1533         String user = null;
1534         String domain = null;
1535 
1536         if (argument != null)
1537             args = argument.split(" ");
1538 
1539         // check if the command was called correct
1540         if (argument == null || argument.trim().equals("") || args.length < 1 || args.length > 2) {
1541             helper.writeLoggedFlushedResponse("Usage: LISTMAPPING [table=table] user@domain");
1542             return true;
1543         }
1544 
1545         if (args[0].startsWith("table=")) {
1546             table = args[0].substring("table=".length());
1547             if (args[1].indexOf("@") > 0) {
1548                 user = getMappingValue(args[1].split("@")[0]);
1549                 domain = getMappingValue(args[1].split("@")[1]);
1550             } else {
1551             helper.writeLoggedFlushedResponse("Usage: LISTMAPPING [table=table] user@domain");
1552                 return true;
1553             }
1554         } else {
1555             if (args[0].indexOf("@") > 0) {
1556                 user = getMappingValue(args[0].split("@")[0]);
1557                 domain = getMappingValue(args[0].split("@")[1]);
1558             } else {
1559             helper.writeLoggedFlushedResponse("Usage: LISTMAPPING [table=table] user@domain");
1560                 return true;
1561             }
1562         }
1563         
1564         try {
1565             Collection mappings = theConfigData.getVirtualUserTableManagement().getUserDomainMappings(table, user, domain);
1566             if (mappings == null) {
1567                 helper.getOutputWriter().println("No mappings found");
1568                 helper.getOutputWriter().flush();
1569             } else {
1570                 helper.getOutputWriter().println("Mappings:");
1571                 
1572                 Iterator m = mappings.iterator();
1573                 while(m.hasNext()) {
1574                     helper.getOutputWriter().println(m.next());
1575                 }
1576                 helper.getOutputWriter().flush();
1577             }
1578         } catch (VirtualUserTableManagementException e) {
1579             helper.getAvalonLogger().error("Error on listing mapping: " + e);
1580             helper.getOutputWriter().println("Error on listing mapping: " + e);
1581             helper.getOutputWriter().flush();
1582         } catch (IllegalArgumentException e) {
1583             helper.getAvalonLogger().error("Error on listing mapping: " + e);
1584             helper.getOutputWriter().println("Error on listing mapping: " + e);
1585             helper.getOutputWriter().flush();
1586         }
1587         return true;
1588     }
1589     
1590     private boolean doLISTALLMAPPINGS(String argument) {
1591         String[] args = null;
1592         String table = null;
1593 
1594         if (argument != null)
1595             args = argument.split(" ");
1596 
1597         // check if the command was called correct
1598         if (args != null && args.length > 1) {
1599             helper.writeLoggedFlushedResponse("Usage: LISTALLMAPPINGS [table=table]");
1600             return true;
1601         }
1602 
1603         if (args != null && args[0].startsWith("table=")) {
1604             table = args[0].substring("table=".length());
1605        
1606         } 
1607         
1608         try {
1609             Map mappings = theConfigData.getVirtualUserTableManagement().getAllMappings(table);
1610             if (mappings == null) {
1611                 helper.getOutputWriter().println("No mappings found");
1612                 helper.getOutputWriter().flush();
1613             } else {
1614                 helper.getOutputWriter().println("Mappings:");
1615                 
1616                 Iterator m = mappings.keySet().iterator();
1617                 while(m.hasNext()) {
1618                     String key = m.next().toString();
1619                     helper.getOutputWriter().println(key + "  -> " + mappings.get(key));
1620                 }
1621                 helper.getOutputWriter().flush();
1622             }
1623         } catch (VirtualUserTableManagementException e) {
1624             helper.getAvalonLogger().error("Error on listing all mapping: " + e);
1625             helper.getOutputWriter().println("Error on listing all mapping: " + e);
1626             helper.getOutputWriter().flush();
1627         } catch (IllegalArgumentException e) {
1628             helper.getAvalonLogger().error("Error on listing all mapping: " + e);
1629             helper.getOutputWriter().println("Error on listing all mapping: " + e);
1630             helper.getOutputWriter().flush();
1631         }
1632         return true;
1633     }
1634     
1635     private String getMappingValue(String raw) {
1636         if (raw.equals("*")) {
1637             return null;
1638         } else {
1639             return raw;
1640         }
1641     }
1642     
1643     private boolean mappingAction(String[] args, String action) throws IllegalArgumentException, VirtualUserTableManagementException{ 
1644         String table = null;
1645         String user = null;
1646         String domain = null;
1647         String mapping = null;
1648     
1649         if (args[0].startsWith("table=")) {
1650             table = args[0].substring("table=".length());
1651             if (args[1].indexOf("@") > 0) {
1652                 user = getMappingValue(args[1].split("@")[0]);
1653                 domain = getMappingValue(args[1].split("@")[1]);
1654             } else {
1655                 throw new IllegalArgumentException("Invalid usage.");
1656             }
1657             mapping = args[2];
1658         } else {
1659             if (args[0].indexOf("@") > 0) {
1660                 user = getMappingValue(args[0].split("@")[0]);
1661                 domain = getMappingValue(args[0].split("@")[1]);
1662             } else {
1663                 throw new IllegalArgumentException("Invalid usage.");
1664             }
1665             mapping = args[1];
1666         }
1667         
1668         if (action.equals(ADD_MAPPING_ACTION)) {
1669             return theConfigData.getVirtualUserTableManagement().addMapping(table, user, domain, mapping);
1670         } else if (action.equals(REMOVE_MAPPING_ACTION)){
1671             return theConfigData.getVirtualUserTableManagement().removeMapping(table, user, domain, mapping);
1672         } else {
1673             throw new IllegalArgumentException("Invalid action: " + action);
1674         }   
1675     }
1676     
1677     private boolean doLISTDOMAINS(String argument) {
1678         Collection domains = theConfigData.getDomainListManagement().getDomains();
1679         if (domains == null) {
1680             helper.getOutputWriter().println("No domains found");
1681             helper.getOutputWriter().flush();
1682         } else {
1683             helper.getOutputWriter().println("Domains:");
1684                 
1685             Iterator d = domains.iterator();
1686             while(d.hasNext()) {
1687                 helper.getOutputWriter().println(d.next());
1688             }
1689             helper.getOutputWriter().flush();
1690         }   
1691         return true;
1692     }
1693 
1694     private boolean doADDDOMAIN(String argument) {
1695 
1696         // check if the command was called correct
1697         if (argument == null) {
1698             helper.writeLoggedFlushedResponse("Usage: ADDDOMAIN domain");
1699             return true;
1700         }
1701         
1702         try {
1703             if(theConfigData.getDomainListManagement().addDomain(argument)) {
1704                 helper.getOutputWriter().println("Adding domain " + argument + " successful");
1705                 helper.getOutputWriter().flush();
1706             } else {
1707                 helper.getOutputWriter().println("Adding domain " + argument + " fail");
1708                 helper.getOutputWriter().flush();
1709             }
1710         } catch (DomainListManagementException e) {
1711             helper.getAvalonLogger().error("Error on adding domain: " + e);
1712             helper.getOutputWriter().println("Error on adding domain: " + e);
1713             helper.getOutputWriter().flush();
1714         }
1715         return true;
1716     }
1717     
1718     private boolean doREMOVEDOMAIN(String argument) {
1719         // check if the command was called correct
1720         if (argument == null) {
1721             helper.writeLoggedFlushedResponse("Usage: REMOVEDOMAIN domain");
1722             return true;
1723         }
1724         
1725         try {
1726             if(theConfigData.getDomainListManagement().removeDomain(argument)) {
1727                 helper.getOutputWriter().println("Removing domain " + argument + " successful");
1728                 helper.getOutputWriter().flush();
1729             } else {
1730                 helper.getOutputWriter().println("Removing domain " + argument + " fail");
1731                 helper.getOutputWriter().flush();
1732             }
1733         } catch (DomainListManagementException e) {
1734             helper.getAvalonLogger().error("Error on removing domain: " + e);
1735             helper.getOutputWriter().println("Error on removing domain: " + e);
1736             helper.getOutputWriter().flush();
1737         }
1738         return true;
1739     }
1740     
1741     /**
1742      * Return an ArrayList which contains all usernames for the given domain
1743      * 
1744      * @param domain the domain
1745      * @return ArrayList which contains the users
1746      */
1747     private ArrayList getDomainUserList(String domain) {
1748         ArrayList userList = new ArrayList();
1749         
1750         for (Iterator it = users.list(); it.hasNext();) {
1751            String user = (String) it.next();
1752            if (user.endsWith(domain)) {
1753                userList.add(user);
1754            }
1755         }
1756         
1757         return userList;
1758     }
1759 
1760 
1761     public void setProtocolHandlerHelper(ProtocolHandlerHelper phh) {
1762         this.helper = phh;
1763     }
1764 }