0001: /****************************************************************
0002: * Licensed to the Apache Software Foundation (ASF) under one *
0003: * or more contributor license agreements. See the NOTICE file *
0004: * distributed with this work for additional information *
0005: * regarding copyright ownership. The ASF licenses this file *
0006: * to you under the Apache License, Version 2.0 (the *
0007: * "License"); you may not use this file except in compliance *
0008: * with the License. You may obtain a copy of the License at *
0009: * *
0010: * http://www.apache.org/licenses/LICENSE-2.0 *
0011: * *
0012: * Unless required by applicable law or agreed to in writing, *
0013: * software distributed under the License is distributed on an *
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
0015: * KIND, either express or implied. See the License for the *
0016: * specific language governing permissions and limitations *
0017: * under the License. *
0018: ****************************************************************/package org.apache.james.remotemanager;
0019:
0020: import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
0021: import org.apache.avalon.excalibur.pool.Poolable;
0022: import org.apache.avalon.framework.container.ContainerUtil;
0023: import org.apache.avalon.framework.logger.AbstractLogEnabled;
0024: import org.apache.james.Constants;
0025: import org.apache.james.services.JamesUser;
0026: import org.apache.james.services.User;
0027: import org.apache.james.services.UsersRepository;
0028: import org.apache.james.util.watchdog.Watchdog;
0029: import org.apache.james.util.watchdog.WatchdogTarget;
0030: import org.apache.mailet.MailAddress;
0031:
0032: import javax.mail.internet.ParseException;
0033: import java.io.BufferedReader;
0034: import java.io.BufferedWriter;
0035: import java.io.IOException;
0036: import java.io.InputStreamReader;
0037: import java.io.OutputStreamWriter;
0038: import java.io.PrintWriter;
0039: import java.net.Socket;
0040: import java.util.Iterator;
0041: import java.util.Locale;
0042:
0043: /**
0044: * Provides a really rude network interface to administer James.
0045: * Allow to add accounts.
0046: * TODO: -improve protocol
0047: * -much more...
0048: *
0049: * @version $Revision: 440727 $
0050: *
0051: */
0052: public class RemoteManagerHandler extends AbstractLogEnabled implements
0053: ConnectionHandler, Poolable {
0054:
0055: /**
0056: * The text string for the MEMSTAT command
0057: */
0058: private static final String COMMAND_MEMSTAT = "MEMSTAT";
0059:
0060: /**
0061: * The text string for the ADDUSER command
0062: */
0063: private static final String COMMAND_ADDUSER = "ADDUSER";
0064:
0065: /**
0066: * The text string for the SETPASSWORD command
0067: */
0068: private static final String COMMAND_SETPASSWORD = "SETPASSWORD";
0069:
0070: /**
0071: * The text string for the DELUSER command
0072: */
0073: private static final String COMMAND_DELUSER = "DELUSER";
0074:
0075: /**
0076: * The text string for the LISTUSERS command
0077: */
0078: private static final String COMMAND_LISTUSERS = "LISTUSERS";
0079:
0080: /**
0081: * The text string for the COUNTUSERS command
0082: */
0083: private static final String COMMAND_COUNTUSERS = "COUNTUSERS";
0084:
0085: /**
0086: * The text string for the VERIFY command
0087: */
0088: private static final String COMMAND_VERIFY = "VERIFY";
0089:
0090: /**
0091: * The text string for the HELP command
0092: */
0093: private static final String COMMAND_HELP = "HELP";
0094:
0095: /**
0096: * The text string for the SETFORWARDING command
0097: */
0098: private static final String COMMAND_SETFORWARDING = "SETFORWARDING";
0099:
0100: /**
0101: * The text string for the SHOWFORWARDING command
0102: */
0103: private static final String COMMAND_SHOWFORWARDING = "SHOWFORWARDING";
0104:
0105: /**
0106: * The text string for the UNSETFORWARDING command
0107: */
0108: private static final String COMMAND_UNSETFORWARDING = "UNSETFORWARDING";
0109:
0110: /**
0111: * The text string for the SETALIAS command
0112: */
0113: private static final String COMMAND_SETALIAS = "SETALIAS";
0114:
0115: /**
0116: * The text string for the SHOWALIAS command
0117: */
0118: private static final String COMMAND_SHOWALIAS = "SHOWALIAS";
0119:
0120: /**
0121: * The text string for the UNSETALIAS command
0122: */
0123: private static final String COMMAND_UNSETALIAS = "UNSETALIAS";
0124:
0125: /**
0126: * The text string for the USER command
0127: */
0128: private static final String COMMAND_USER = "USER";
0129:
0130: /**
0131: * The text string for the QUIT command
0132: */
0133: private static final String COMMAND_QUIT = "QUIT";
0134:
0135: /**
0136: * The text string for the SHUTDOWN command
0137: */
0138: private static final String COMMAND_SHUTDOWN = "SHUTDOWN";
0139:
0140: /**
0141: * The per-service configuration data that applies to all handlers
0142: */
0143: private RemoteManagerHandlerConfigurationData theConfigData;
0144:
0145: /**
0146: * The current UsersRepository being managed/viewed/modified
0147: */
0148: private UsersRepository users;
0149:
0150: /**
0151: * The reader associated with incoming commands.
0152: */
0153: private BufferedReader in;
0154:
0155: /**
0156: * The writer to which outgoing messages are written.
0157: */
0158: private PrintWriter out;
0159:
0160: /**
0161: * The thread executing this handler
0162: */
0163: private Thread handlerThread;
0164:
0165: /**
0166: * The TCP/IP socket over which the RemoteManager interaction
0167: * is occurring
0168: */
0169: private Socket socket;
0170:
0171: /**
0172: * The watchdog being used by this handler to deal with idle timeouts.
0173: */
0174: private Watchdog theWatchdog;
0175:
0176: /**
0177: * The watchdog target that idles out this handler.
0178: */
0179: private WatchdogTarget theWatchdogTarget = new RemoteManagerWatchdogTarget();
0180:
0181: /**
0182: * Set the configuration data for the handler.
0183: *
0184: * @param theData the configuration data
0185: */
0186: void setConfigurationData(
0187: RemoteManagerHandlerConfigurationData theData) {
0188: theConfigData = theData;
0189:
0190: // Reset the users repository to the default.
0191: users = theConfigData.getUsersRepository();
0192: }
0193:
0194: /**
0195: * Set the Watchdog for use by this handler.
0196: *
0197: * @param theWatchdog the watchdog
0198: */
0199: void setWatchdog(Watchdog theWatchdog) {
0200: this .theWatchdog = theWatchdog;
0201: }
0202:
0203: /**
0204: * Gets the Watchdog Target that should be used by Watchdogs managing
0205: * this connection.
0206: *
0207: * @return the WatchdogTarget
0208: */
0209: WatchdogTarget getWatchdogTarget() {
0210: return theWatchdogTarget;
0211: }
0212:
0213: /**
0214: * Idle out this connection
0215: */
0216: void idleClose() {
0217: if (getLogger() != null) {
0218: getLogger().error(
0219: "Remote Manager Connection has idled out.");
0220: }
0221: try {
0222: if (socket != null) {
0223: socket.close();
0224: }
0225: } catch (Exception e) {
0226: // ignored
0227: } finally {
0228: socket = null;
0229: }
0230:
0231: synchronized (this ) {
0232: // Interrupt the thread to recover from internal hangs
0233: if (handlerThread != null) {
0234: handlerThread.interrupt();
0235: handlerThread = null;
0236: }
0237: }
0238: }
0239:
0240: /**
0241: * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket)
0242: */
0243: public void handleConnection(final Socket connection)
0244: throws IOException {
0245:
0246: socket = connection;
0247: String remoteIP = socket.getInetAddress().getHostAddress();
0248: String remoteHost = socket.getInetAddress().getHostName();
0249:
0250: synchronized (this ) {
0251: handlerThread = Thread.currentThread();
0252: }
0253:
0254: try {
0255: in = new BufferedReader(new InputStreamReader(socket
0256: .getInputStream(), "ASCII"), 512);
0257: out = new PrintWriter(new BufferedWriter(
0258: new OutputStreamWriter(socket.getOutputStream()),
0259: 512), false);
0260: if (getLogger().isInfoEnabled()) {
0261: StringBuffer infoBuffer = new StringBuffer(128).append(
0262: "Access from ").append(remoteHost).append("(")
0263: .append(remoteIP).append(")");
0264: getLogger().info(infoBuffer.toString());
0265: }
0266: writeLoggedResponse("JAMES Remote Administration Tool "
0267: + Constants.SOFTWARE_VERSION);
0268: writeLoggedResponse("Please enter your login and password");
0269: String login = null;
0270: String password = null;
0271: do {
0272: if (login != null) {
0273: final String message = "Login failed for " + login;
0274: writeLoggedFlushedResponse(message);
0275: }
0276: writeLoggedFlushedResponse("Login id:");
0277: login = in.readLine().trim();
0278: writeLoggedFlushedResponse("Password:");
0279: password = in.readLine().trim();
0280: } while (!password.equals(theConfigData
0281: .getAdministrativeAccountData().get(login))
0282: || password.length() == 0);
0283:
0284: StringBuffer messageBuffer = new StringBuffer(64).append(
0285: "Welcome ").append(login).append(
0286: ". HELP for a list of commands");
0287: out.println(messageBuffer.toString());
0288: out.flush();
0289: if (getLogger().isInfoEnabled()) {
0290: StringBuffer infoBuffer = new StringBuffer(128).append(
0291: "Login for ").append(login).append(
0292: " successful");
0293: getLogger().info(infoBuffer.toString());
0294: }
0295:
0296: try {
0297: out.print(theConfigData.getPrompt());
0298: out.flush();
0299: theWatchdog.start();
0300: while (parseCommand(in.readLine())) {
0301: theWatchdog.reset();
0302: out.print(theConfigData.getPrompt());
0303: out.flush();
0304: }
0305: theWatchdog.stop();
0306: } catch (IOException ioe) {
0307: //We can cleanly ignore this as it's probably a socket timeout
0308: } catch (Throwable thr) {
0309: System.out.println("Exception: " + thr.getMessage());
0310: getLogger()
0311: .error(
0312: "Encountered exception in handling the remote manager connection.",
0313: thr);
0314: }
0315: StringBuffer infoBuffer = new StringBuffer(64).append(
0316: "Logout for ").append(login).append(".");
0317: getLogger().info(infoBuffer.toString());
0318:
0319: } catch (final IOException e) {
0320: out.println("Error. Closing connection");
0321: out.flush();
0322: if (getLogger().isErrorEnabled()) {
0323: StringBuffer exceptionBuffer = new StringBuffer(128)
0324: .append("Exception during connection from ")
0325: .append(remoteHost).append(" (").append(
0326: remoteIP).append("): ").append(
0327: e.getMessage());
0328: getLogger().error(exceptionBuffer.toString());
0329: }
0330: } finally {
0331: resetHandler();
0332: }
0333: }
0334:
0335: /**
0336: * Resets the handler data to a basic state.
0337: */
0338: private void resetHandler() {
0339:
0340: // Clear the Watchdog
0341: if (theWatchdog != null) {
0342: ContainerUtil.dispose(theWatchdog);
0343: theWatchdog = null;
0344: }
0345:
0346: in = null;
0347: out = null;
0348: try {
0349: if (socket != null) {
0350: socket.close();
0351: }
0352: } catch (IOException e) {
0353: if (getLogger().isErrorEnabled()) {
0354: getLogger().error(
0355: "Exception closing socket: " + e.getMessage());
0356: }
0357: } finally {
0358: socket = null;
0359: }
0360:
0361: synchronized (this ) {
0362: handlerThread = null;
0363: }
0364:
0365: // Reset user repository
0366: users = theConfigData.getUsersRepository();
0367:
0368: // Clear config data
0369: theConfigData = null;
0370: }
0371:
0372: /**
0373: * <p>This method parses and processes RemoteManager commands read off the
0374: * wire in handleConnection. It returns true if expecting additional
0375: * commands, false otherwise.</p>
0376: *
0377: * @param command the raw command string passed in over the socket
0378: *
0379: * @return whether additional commands are expected.
0380: */
0381: private boolean parseCommand(String rawCommand) {
0382: if (rawCommand == null) {
0383: return false;
0384: }
0385: String command = rawCommand.trim();
0386: String argument = null;
0387: int breakIndex = command.indexOf(" ");
0388: if (breakIndex > 0) {
0389: argument = command.substring(breakIndex + 1);
0390: command = command.substring(0, breakIndex);
0391: }
0392: command = command.toUpperCase(Locale.US);
0393: if (command.equals(COMMAND_ADDUSER)) {
0394: doADDUSER(argument);
0395: } else if (command.equals(COMMAND_SETPASSWORD)) {
0396: return doSETPASSWORD(argument);
0397: } else if (command.equals(COMMAND_DELUSER)) {
0398: return doDELUSER(argument);
0399: } else if (command.equals(COMMAND_LISTUSERS)) {
0400: return doLISTUSERS(argument);
0401: } else if (command.equals(COMMAND_COUNTUSERS)) {
0402: return doCOUNTUSERS(argument);
0403: } else if (command.equals(COMMAND_VERIFY)) {
0404: return doVERIFY(argument);
0405: } else if (command.equals(COMMAND_HELP)) {
0406: return doHELP(argument);
0407: } else if (command.equals(COMMAND_SETALIAS)) {
0408: return doSETALIAS(argument);
0409: } else if (command.equals(COMMAND_SETFORWARDING)) {
0410: return doSETFORWARDING(argument);
0411: } else if (command.equals(COMMAND_SHOWALIAS)) {
0412: return doSHOWALIAS(argument);
0413: } else if (command.equals(COMMAND_SHOWFORWARDING)) {
0414: return doSHOWFORWARDING(argument);
0415: } else if (command.equals(COMMAND_UNSETALIAS)) {
0416: return doUNSETALIAS(argument);
0417: } else if (command.equals(COMMAND_UNSETFORWARDING)) {
0418: return doUNSETFORWARDING(argument);
0419: } else if (command.equals(COMMAND_USER)) {
0420: return doUSER(argument);
0421: } else if (command.equals(COMMAND_MEMSTAT)) {
0422: return doMEMSTAT(argument);
0423: } else if (command.equals(COMMAND_QUIT)) {
0424: return doQUIT(argument);
0425: } else if (command.equals(COMMAND_SHUTDOWN)) {
0426: return doSHUTDOWN(argument);
0427: } else {
0428: return doUnknownCommand(rawCommand);
0429: }
0430: return true;
0431: }
0432:
0433: /**
0434: * Handler method called upon receipt of an MEMSTAT command.
0435: * Returns whether further commands should be read off the wire.
0436: *
0437: * @param argument the argument passed in with the command
0438: */
0439: private boolean doMEMSTAT(String argument) {
0440: writeLoggedFlushedResponse("Current memory statistics:");
0441: writeLoggedFlushedResponse("\tFree Memory: "
0442: + Runtime.getRuntime().freeMemory());
0443: writeLoggedFlushedResponse("\tTotal Memory: "
0444: + Runtime.getRuntime().totalMemory());
0445: writeLoggedFlushedResponse("\tMax Memory: "
0446: + Runtime.getRuntime().maxMemory());
0447:
0448: if ("-gc".equalsIgnoreCase(argument)) {
0449: System.gc();
0450: writeLoggedFlushedResponse("And after System.gc():");
0451: writeLoggedFlushedResponse("\tFree Memory: "
0452: + Runtime.getRuntime().freeMemory());
0453: writeLoggedFlushedResponse("\tTotal Memory: "
0454: + Runtime.getRuntime().totalMemory());
0455: writeLoggedFlushedResponse("\tMax Memory: "
0456: + Runtime.getRuntime().maxMemory());
0457: }
0458:
0459: return true;
0460: }
0461:
0462: /**
0463: * Handler method called upon receipt of an ADDUSER command.
0464: * Returns whether further commands should be read off the wire.
0465: *
0466: * @param argument the argument passed in with the command
0467: */
0468: private boolean doADDUSER(String argument) {
0469: int breakIndex = -1;
0470: if ((argument == null) || (argument.equals(""))
0471: || ((breakIndex = argument.indexOf(" ")) < 0)) {
0472: writeLoggedFlushedResponse("Usage: adduser [username] [password]");
0473: return true;
0474: }
0475: String username = argument.substring(0, breakIndex);
0476: String passwd = argument.substring(breakIndex + 1);
0477: if (username.equals("") || passwd.equals("")) {
0478: writeLoggedFlushedResponse("Usage: adduser [username] [password]");
0479: return true;
0480: }
0481:
0482: boolean success = false;
0483: if (users.contains(username)) {
0484: StringBuffer responseBuffer = new StringBuffer(64).append(
0485: "User ").append(username).append(" already exists");
0486: String response = responseBuffer.toString();
0487: writeLoggedResponse(response);
0488: } else {
0489: success = users.addUser(username, passwd);
0490: }
0491: if (success) {
0492: StringBuffer responseBuffer = new StringBuffer(64).append(
0493: "User ").append(username).append(" added");
0494: String response = responseBuffer.toString();
0495: out.println(response);
0496: getLogger().info(response);
0497: } else {
0498: out.println("Error adding user " + username);
0499: getLogger().error("Error adding user " + username);
0500: }
0501: out.flush();
0502: return true;
0503: }
0504:
0505: /**
0506: * Handler method called upon receipt of an SETPASSWORD command.
0507: * Returns whether further commands should be read off the wire.
0508: *
0509: * @param argument the argument passed in with the command
0510: */
0511: private boolean doSETPASSWORD(String argument) {
0512:
0513: int breakIndex = -1;
0514: if ((argument == null) || (argument.equals(""))
0515: || ((breakIndex = argument.indexOf(" ")) < 0)) {
0516: writeLoggedFlushedResponse("Usage: setpassword [username] [password]");
0517: return true;
0518: }
0519: String username = argument.substring(0, breakIndex);
0520: String passwd = argument.substring(breakIndex + 1);
0521:
0522: if (username.equals("") || passwd.equals("")) {
0523: writeLoggedFlushedResponse("Usage: adduser [username] [password]");
0524: return true;
0525: }
0526: User user = users.getUserByName(username);
0527: if (user == null) {
0528: writeLoggedFlushedResponse("No such user " + username);
0529: return true;
0530: }
0531: boolean success = user.setPassword(passwd);
0532: if (success) {
0533: users.updateUser(user);
0534: StringBuffer responseBuffer = new StringBuffer(64).append(
0535: "Password for ").append(username).append(" reset");
0536: String response = responseBuffer.toString();
0537: out.println(response);
0538: getLogger().info(response);
0539: } else {
0540: out.println("Error resetting password");
0541: getLogger().error("Error resetting password");
0542: }
0543: out.flush();
0544: return true;
0545: }
0546:
0547: /**
0548: * Handler method called upon receipt of an DELUSER command.
0549: * Returns whether further commands should be read off the wire.
0550: *
0551: * @param argument the argument passed in with the command
0552: */
0553: private boolean doDELUSER(String argument) {
0554: String user = argument;
0555: if ((user == null) || (user.equals(""))) {
0556: writeLoggedFlushedResponse("Usage: deluser [username]");
0557: return true;
0558: }
0559: if (users.contains(user)) {
0560: try {
0561: users.removeUser(user);
0562: StringBuffer responseBuffer = new StringBuffer(64)
0563: .append("User ").append(user)
0564: .append(" deleted");
0565: String response = responseBuffer.toString();
0566: out.println(response);
0567: getLogger().info(response);
0568: } catch (Exception e) {
0569: StringBuffer exceptionBuffer = new StringBuffer(128)
0570: .append("Error deleting user ").append(user)
0571: .append(" : ").append(e.getMessage());
0572: String exception = exceptionBuffer.toString();
0573: out.println(exception);
0574: getLogger().error(exception);
0575: }
0576: } else {
0577: StringBuffer responseBuffer = new StringBuffer(64).append(
0578: "User ").append(user).append(" doesn't exist");
0579: String response = responseBuffer.toString();
0580: out.println(response);
0581: }
0582: out.flush();
0583: return true;
0584: }
0585:
0586: /**
0587: * Handler method called upon receipt of an LISTUSERS command.
0588: * Returns whether further commands should be read off the wire.
0589: *
0590: * @param argument the argument passed in with the command
0591: */
0592: private boolean doLISTUSERS(String argument) {
0593: writeLoggedResponse("Existing accounts " + users.countUsers());
0594: for (Iterator it = users.list(); it.hasNext();) {
0595: writeLoggedResponse("user: " + (String) it.next());
0596: }
0597: out.flush();
0598: return true;
0599: }
0600:
0601: /**
0602: * Handler method called upon receipt of an COUNTUSERS command.
0603: * Returns whether further commands should be read off the wire.
0604: *
0605: * @param argument the argument passed in with the command
0606: */
0607: private boolean doCOUNTUSERS(String argument) {
0608: writeLoggedFlushedResponse("Existing accounts "
0609: + users.countUsers());
0610: return true;
0611: }
0612:
0613: /**
0614: * Handler method called upon receipt of an VERIFY command.
0615: * Returns whether further commands should be read off the wire.
0616: *
0617: * @param argument the argument passed in with the command
0618: */
0619: private boolean doVERIFY(String argument) {
0620: String user = argument;
0621: if (user == null || user.equals("")) {
0622: writeLoggedFlushedResponse("Usage: verify [username]");
0623: return true;
0624: }
0625: if (users.contains(user)) {
0626: StringBuffer responseBuffer = new StringBuffer(64).append(
0627: "User ").append(user).append(" exists");
0628: String response = responseBuffer.toString();
0629: writeLoggedResponse(response);
0630: } else {
0631: StringBuffer responseBuffer = new StringBuffer(64).append(
0632: "User ").append(user).append(" does not exist");
0633: String response = responseBuffer.toString();
0634: writeLoggedResponse(response);
0635: }
0636: out.flush();
0637: return true;
0638: }
0639:
0640: /**
0641: * Handler method called upon receipt of an HELP command.
0642: * Returns whether further commands should be read off the wire.
0643: *
0644: * @param argument the argument passed in with the command
0645: */
0646: private boolean doHELP(String argument) {
0647: out.println("Currently implemented commands:");
0648: out
0649: .println("help display this help");
0650: out
0651: .println("listusers display existing accounts");
0652: out
0653: .println("countusers display the number of existing accounts");
0654: out
0655: .println("adduser [username] [password] add a new user");
0656: out
0657: .println("verify [username] verify if specified user exist");
0658: out
0659: .println("deluser [username] delete existing user");
0660: out
0661: .println("setpassword [username] [password] sets a user's password");
0662: out
0663: .println("setalias [user] [alias] locally forwards all email for 'user' to 'alias'");
0664: out
0665: .println("showalias [username] shows a user's current email alias");
0666: out
0667: .println("unsetalias [user] unsets an alias for 'user'");
0668: out
0669: .println("setforwarding [username] [emailaddress] forwards a user's email to another email address");
0670: out
0671: .println("showforwarding [username] shows a user's current email forwarding");
0672: out
0673: .println("unsetforwarding [username] removes a forward");
0674: out
0675: .println("user [repositoryname] change to another user repository");
0676: out
0677: .println("shutdown kills the current JVM (convenient when James is run as a daemon)");
0678: out
0679: .println("quit close connection");
0680: out.flush();
0681: return true;
0682: }
0683:
0684: /**
0685: * Handler method called upon receipt of an SETALIAS command.
0686: * Returns whether further commands should be read off the wire.
0687: *
0688: * @param argument the argument passed in with the command
0689: */
0690: private boolean doSETALIAS(String argument) {
0691: int breakIndex = -1;
0692: if ((argument == null) || (argument.equals(""))
0693: || ((breakIndex = argument.indexOf(" ")) < 0)) {
0694: writeLoggedFlushedResponse("Usage: setalias [username] [emailaddress]");
0695: return true;
0696: }
0697: String username = argument.substring(0, breakIndex);
0698: String alias = argument.substring(breakIndex + 1);
0699: if (username.equals("") || alias.equals("")) {
0700: writeLoggedFlushedResponse("Usage: setalias [username] [alias]");
0701: return true;
0702: }
0703:
0704: User baseuser = users.getUserByName(username);
0705: if (baseuser == null) {
0706: writeLoggedFlushedResponse("No such user " + username);
0707: return true;
0708: }
0709: if (!(baseuser instanceof JamesUser)) {
0710: writeLoggedFlushedResponse("Can't set alias for this user type.");
0711: return true;
0712: }
0713:
0714: JamesUser user = (JamesUser) baseuser;
0715: JamesUser aliasUser = (JamesUser) users.getUserByName(alias);
0716: if (aliasUser == null) {
0717: writeLoggedFlushedResponse("Alias unknown to server - create that user first.");
0718: return true;
0719: }
0720:
0721: boolean success = user.setAlias(alias);
0722: if (success) {
0723: user.setAliasing(true);
0724: users.updateUser(user);
0725: StringBuffer responseBuffer = new StringBuffer(64).append(
0726: "Alias for ").append(username).append(" set to:")
0727: .append(alias);
0728: String response = responseBuffer.toString();
0729: out.println(response);
0730: getLogger().info(response);
0731: } else {
0732: out.println("Error setting alias");
0733: getLogger().error("Error setting alias");
0734: }
0735: out.flush();
0736: return true;
0737: }
0738:
0739: /**
0740: * Handler method called upon receipt of an SETFORWARDING command.
0741: * Returns whether further commands should be read off the wire.
0742: *
0743: * @param argument the argument passed in with the command
0744: */
0745: private boolean doSETFORWARDING(String argument) {
0746: int breakIndex = -1;
0747: if ((argument == null) || (argument.equals(""))
0748: || ((breakIndex = argument.indexOf(" ")) < 0)) {
0749: writeLoggedFlushedResponse("Usage: setforwarding [username] [emailaddress]");
0750: return true;
0751: }
0752: String username = argument.substring(0, breakIndex);
0753: String forward = argument.substring(breakIndex + 1);
0754: if (username.equals("") || forward.equals("")) {
0755: writeLoggedFlushedResponse("Usage: setforwarding [username] [emailaddress]");
0756: return true;
0757: }
0758: // Verify user exists
0759: User baseuser = users.getUserByName(username);
0760: if (baseuser == null) {
0761: writeLoggedFlushedResponse("No such user " + username);
0762: return true;
0763: } else if (!(baseuser instanceof JamesUser)) {
0764: writeLoggedFlushedResponse("Can't set forwarding for this user type.");
0765: return true;
0766: }
0767: JamesUser user = (JamesUser) baseuser;
0768: // Verify acceptable email address
0769: MailAddress forwardAddr;
0770: try {
0771: forwardAddr = new MailAddress(forward);
0772: } catch (ParseException pe) {
0773: writeLoggedResponse("Parse exception with that email address: "
0774: + pe.getMessage());
0775: writeLoggedFlushedResponse("Forwarding address not added for "
0776: + username);
0777: return true;
0778: }
0779:
0780: boolean success = user.setForwardingDestination(forwardAddr);
0781: if (success) {
0782: user.setForwarding(true);
0783: users.updateUser(user);
0784: StringBuffer responseBuffer = new StringBuffer(64).append(
0785: "Forwarding destination for ").append(username)
0786: .append(" set to:").append(forwardAddr.toString());
0787: String response = responseBuffer.toString();
0788: out.println(response);
0789: getLogger().info(response);
0790: } else {
0791: out.println("Error setting forwarding");
0792: getLogger().error("Error setting forwarding");
0793: }
0794: out.flush();
0795: return true;
0796: }
0797:
0798: /**
0799: * Handler method called upon receipt of an SHOWALIAS command.
0800: * Returns whether further commands should be read off the wire.
0801: *
0802: * @param argument the user name
0803: */
0804: private boolean doSHOWALIAS(String username) {
0805: if (username == null || username.equals("")) {
0806: writeLoggedFlushedResponse("Usage: showalias [username]");
0807: return true;
0808: }
0809:
0810: User baseuser = users.getUserByName(username);
0811: if (baseuser == null) {
0812: writeLoggedFlushedResponse("No such user " + username);
0813: return true;
0814: } else if (!(baseuser instanceof JamesUser)) {
0815: writeLoggedFlushedResponse("Can't show aliases for this user type.");
0816: return true;
0817: }
0818:
0819: JamesUser user = (JamesUser) baseuser;
0820: if (user == null) {
0821: writeLoggedFlushedResponse("No such user " + username);
0822: return true;
0823: }
0824:
0825: if (!user.getAliasing()) {
0826: writeLoggedFlushedResponse("User " + username
0827: + " does not currently have an alias");
0828: return true;
0829: }
0830:
0831: String alias = user.getAlias();
0832:
0833: if (alias == null || alias.equals("")) { // defensive programming -- neither should occur
0834: String errmsg = "For user "
0835: + username
0836: + ", the system indicates that aliasing is set but no alias was found";
0837: out.println(errmsg);
0838: getLogger().error(errmsg);
0839: return true;
0840: }
0841:
0842: writeLoggedFlushedResponse("Current alias for " + username
0843: + " is: " + alias);
0844: return true;
0845: }
0846:
0847: /**
0848: * Handler method called upon receipt of an SHOWFORWARDING command.
0849: * Returns whether further commands should be read off the wire.
0850: *
0851: * @param argument the user name
0852: */
0853: private boolean doSHOWFORWARDING(String username) {
0854: if (username == null || username.equals("")) {
0855: writeLoggedFlushedResponse("Usage: showforwarding [username]");
0856: return true;
0857: }
0858:
0859: // Verify user exists
0860: User baseuser = users.getUserByName(username);
0861: if (baseuser == null) {
0862: writeLoggedFlushedResponse("No such user " + username);
0863: return true;
0864: } else if (!(baseuser instanceof JamesUser)) {
0865: writeLoggedFlushedResponse("Can't set forwarding for this user type.");
0866: return true;
0867: }
0868: JamesUser user = (JamesUser) baseuser;
0869: if (user == null) {
0870: writeLoggedFlushedResponse("No such user " + username);
0871: return true;
0872: }
0873:
0874: if (!user.getForwarding()) {
0875: writeLoggedFlushedResponse("User " + username
0876: + " is not currently being forwarded");
0877: return true;
0878: }
0879:
0880: MailAddress fwdAddr = user.getForwardingDestination();
0881:
0882: if (fwdAddr == null) { // defensive programming -- should not occur
0883: String errmsg = "For user "
0884: + username
0885: + ", the system indicates that forwarding is set but no forwarding destination was found";
0886: out.println(errmsg);
0887: getLogger().error(errmsg);
0888: return true;
0889: }
0890:
0891: writeLoggedFlushedResponse("Current forwarding destination for "
0892: + username + " is: " + fwdAddr);
0893: return true;
0894: }
0895:
0896: /**
0897: * Handler method called upon receipt of an UNSETALIAS command.
0898: * Returns whether further commands should be read off the wire.
0899: *
0900: * @param argument the argument passed in with the command
0901: */
0902: private boolean doUNSETALIAS(String argument) {
0903: if ((argument == null) || (argument.equals(""))) {
0904: writeLoggedFlushedResponse("Usage: unsetalias [username]");
0905: return true;
0906: }
0907: String username = argument;
0908: JamesUser user = (JamesUser) users.getUserByName(username);
0909: if (user == null) {
0910: writeLoggedResponse("No such user " + username);
0911: } else if (user.getAliasing()) {
0912: user.setAliasing(false);
0913: users.updateUser(user);
0914: StringBuffer responseBuffer = new StringBuffer(64).append(
0915: "Alias for ").append(username).append(" unset");
0916: String response = responseBuffer.toString();
0917: out.println(response);
0918: getLogger().info(response);
0919: } else {
0920: writeLoggedResponse("Aliasing not active for" + username);
0921: }
0922: out.flush();
0923: return true;
0924: }
0925:
0926: /**
0927: * Handler method called upon receipt of an UNSETFORWARDING command.
0928: * Returns whether further commands should be read off the wire.
0929: *
0930: * @param argument the argument passed in with the command
0931: */
0932: private boolean doUNSETFORWARDING(String argument) {
0933: if ((argument == null) || (argument.equals(""))) {
0934: writeLoggedFlushedResponse("Usage: unsetforwarding [username]");
0935: return true;
0936: }
0937: String username = argument;
0938: JamesUser user = (JamesUser) users.getUserByName(username);
0939: if (user == null) {
0940: writeLoggedFlushedResponse("No such user " + username);
0941: } else if (user.getForwarding()) {
0942: user.setForwarding(false);
0943: users.updateUser(user);
0944: StringBuffer responseBuffer = new StringBuffer(64).append(
0945: "Forward for ").append(username).append(" unset");
0946: String response = responseBuffer.toString();
0947: out.println(response);
0948: out.flush();
0949: getLogger().info(response);
0950: } else {
0951: writeLoggedFlushedResponse("Forwarding not active for"
0952: + username);
0953: }
0954: return true;
0955: }
0956:
0957: /**
0958: * Handler method called upon receipt of a USER command.
0959: * Returns whether further commands should be read off the wire.
0960: *
0961: * @param argument the argument passed in with the command
0962: */
0963: private boolean doUSER(String argument) {
0964: if (argument == null || argument.equals("")) {
0965: writeLoggedFlushedResponse("Usage: user [repositoryName]");
0966: return true;
0967: }
0968: String repositoryName = argument.toLowerCase(Locale.US);
0969: UsersRepository repos = theConfigData.getUserStore()
0970: .getRepository(repositoryName);
0971: if (repos == null) {
0972: writeLoggedFlushedResponse("No such repository: "
0973: + repositoryName);
0974: } else {
0975: users = repos;
0976: StringBuffer responseBuffer = new StringBuffer(64).append(
0977: "Changed to repository '").append(repositoryName)
0978: .append("'.");
0979: writeLoggedFlushedResponse(responseBuffer.toString());
0980: }
0981: return true;
0982: }
0983:
0984: /**
0985: * Handler method called upon receipt of a QUIT command.
0986: * Returns whether further commands should be read off the wire.
0987: *
0988: * @param argument the argument passed in with the command
0989: */
0990: private boolean doQUIT(String argument) {
0991: writeLoggedFlushedResponse("Bye");
0992: return false;
0993: }
0994:
0995: /**
0996: * Handler method called upon receipt of a SHUTDOWN command.
0997: * Returns whether further commands should be read off the wire.
0998: *
0999: * @param argument the argument passed in with the command
1000: */
1001: private boolean doSHUTDOWN(String argument) {
1002: writeLoggedFlushedResponse("Shutting down, bye bye");
1003: System.exit(0);
1004: return false;
1005: }
1006:
1007: /**
1008: * Handler method called upon receipt of an unrecognized command.
1009: * Returns whether further commands should be read off the wire.
1010: *
1011: * @param argument the unknown command
1012: */
1013: private boolean doUnknownCommand(String argument) {
1014: writeLoggedFlushedResponse("Unknown command " + argument);
1015: return true;
1016: }
1017:
1018: /**
1019: * This method logs at a "DEBUG" level the response string that
1020: * was sent to the RemoteManager client. The method is provided largely
1021: * as syntactic sugar to neaten up the code base. It is declared
1022: * private and final to encourage compiler inlining.
1023: *
1024: * @param responseString the response string sent to the client
1025: */
1026: private final void logResponseString(String responseString) {
1027: if (getLogger().isDebugEnabled()) {
1028: getLogger().debug("Sent: " + responseString);
1029: }
1030: }
1031:
1032: /**
1033: * Write and flush a response string. The response is also logged.
1034: * Should be used for the last line of a multi-line response or
1035: * for a single line response.
1036: *
1037: * @param responseString the response string sent to the client
1038: */
1039: final void writeLoggedFlushedResponse(String responseString) {
1040: out.println(responseString);
1041: out.flush();
1042: logResponseString(responseString);
1043: }
1044:
1045: /**
1046: * Write a response string. The response is also logged.
1047: * Used for multi-line responses.
1048: *
1049: * @param responseString the response string sent to the client
1050: */
1051: final void writeLoggedResponse(String responseString) {
1052: out.println(responseString);
1053: logResponseString(responseString);
1054: }
1055:
1056: /**
1057: * A private inner class which serves as an adaptor
1058: * between the WatchdogTarget interface and this
1059: * handler class.
1060: */
1061: private class RemoteManagerWatchdogTarget implements WatchdogTarget {
1062:
1063: /**
1064: * @see org.apache.james.util.watchdog.WatchdogTarget#execute()
1065: */
1066: public void execute() {
1067: RemoteManagerHandler.this.idleClose();
1068: }
1069: }
1070: }
|