package org.mailster.smtp.core.commands;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import org.apache.mina.core.session.IoSession;
import org.mailster.smtp.core.SMTPConnectionHandler;
import org.mailster.smtp.core.SMTPContext;
import org.mailster.smtp.core.commands.impl.AuthCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class manages execution of a SMTP command.
*
* @author Jon Stevens
* @author Edouard De Oliveira <doe_wanted@yahoo.fr>
*/
public class CommandHandler
{
private Map<String, Command> commandMap = new HashMap<String, Command>();
private static final Logger LOG = LoggerFactory.getLogger(CommandHandler.class);
/**
* Populates a default set of commands based with the BuiltinCommandRegistry commands.
*/
public CommandHandler()
{
for(BuiltinCommandRegistry entry : BuiltinCommandRegistry.values())
{
addCommand(entry.getCommand());
}
}
/**
* Adds a new command to the map.
* @param cmd the command to add
*/
public void addCommand(Command cmd)
{
LOG.debug("Added command {}", cmd.getName());
if (cmd instanceof AbstractCommand)
((AbstractCommand) cmd).setCommandHandler(this);
this.commandMap.put(cmd.getName(), cmd);
}
/**
* Does the map contain the named command?
* @param cmd
* @return true if the command exists
*/
public boolean containsCommand(String cmd)
{
return this.commandMap.containsKey(cmd);
}
/**
* Calls the execute method on a command.
*
* @param ctx
* @param cmdString
* @throws SocketTimeoutException
* @throws IOException
*/
public void handleCommand(String cmdString, IoSession session, SMTPContext ctx)
throws IOException
{
try
{
Command cmd = getCommandFromString(cmdString);
cmd.execute(cmdString, session, ctx);
}
catch (CommandException e)
{
SMTPConnectionHandler.sendResponse(session, "500 " + e.getMessage());
}
}
/**
* Executes an auth command.
*
* @param ctx
* @param commandString
* @throws SocketTimeoutException
* @throws IOException
*/
public void handleAuthChallenge(String commandString, IoSession session, SMTPContext ctx)
throws SocketTimeoutException, IOException
{
Command cmd = this.commandMap.get(AuthCommand.VERB);
cmd.execute(commandString, session, ctx);
}
/**
* Given a string, find the Command object.
*
* @param cmdString
* @return The command object.
* @throws UnknownCommandException
* @throws InvalidCommandNameException
*/
public Command getCommandFromString(String cmdString)
throws UnknownCommandException, InvalidCommandNameException
{
String verb = toVerb(cmdString);
Command cmd = this.commandMap.get(verb);
if (cmd == null)
throw new UnknownCommandException("Command not implemented");
return cmd;
}
/** */
private String toVerb(String cmd) throws InvalidCommandNameException
{
if (cmd == null || cmd.length() < 4)
throw new InvalidCommandNameException("Syntax error");
StringTokenizer st = new StringTokenizer(cmd);
if (!st.hasMoreTokens())
throw new InvalidCommandNameException("Syntax error");
return st.nextToken().toUpperCase();
}
}