Skip to content

Commit

Permalink
JAMES-1618 centralize error handling to remove code duplication
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/james/project/trunk@1720595 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
chibenwa committed Dec 17, 2015
1 parent 6cdb998 commit d53ba09
Showing 1 changed file with 119 additions and 160 deletions.
Expand Up @@ -24,30 +24,31 @@
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.io.IOUtils;
import org.apache.james.managesieve.api.AuthenticationException;
import org.apache.james.managesieve.api.AuthenticationProcessor;
import org.apache.james.managesieve.api.AuthenticationRequiredException;
import org.apache.james.managesieve.api.ManageSieveException;
import org.apache.james.managesieve.api.Session;
import org.apache.james.managesieve.api.SessionTerminatedException;
import org.apache.james.managesieve.api.SieveParser;
import org.apache.james.managesieve.api.SyntaxException;
import org.apache.james.managesieve.api.UnknownSaslMechanism;
import org.apache.james.managesieve.api.commands.CoreCommands;
import org.apache.james.managesieve.util.ParserUtils;
import org.apache.james.sieverepository.api.ScriptSummary;
import org.apache.james.sieverepository.api.SieveRepository;
import org.apache.james.sieverepository.api.exception.DuplicateException;
import org.apache.james.sieverepository.api.exception.IsActiveException;
import org.apache.james.sieverepository.api.exception.QuotaExceededException;
import org.apache.james.sieverepository.api.exception.ScriptNotFoundException;
import org.apache.james.sieverepository.api.exception.SieveRepositoryException;
import org.apache.james.sieverepository.api.exception.StorageException;
import org.apache.james.sieverepository.api.exception.UserNotFoundException;
import org.apache.james.user.api.UsersRepository;
import org.apache.james.user.api.UsersRepositoryException;

import java.io.IOException;
import java.util.Arrays;
Expand All @@ -56,19 +57,21 @@
import java.util.Map;

public class CoreProcessor implements CoreCommands {


interface CommandWrapper {
String execute() throws ManageSieveException, SieveRepositoryException, IOException;
}

public static final String IMPLEMENTATION_DESCRIPTION = "Apache ManageSieve v1.0";
public static final String MANAGE_SIEVE_VERSION = "1.0";

private final SieveRepository sieveRepository;
private final UsersRepository usersRepository;
private final SieveParser parser;
private final Map<Capabilities, String> capabilitiesBase;
private final Map<SupportedMechanism, AuthenticationProcessor> authenticationProcessorMap;

public CoreProcessor(SieveRepository repository, UsersRepository usersRepository, SieveParser parser) {
this.sieveRepository = repository;
this.usersRepository = usersRepository;
this.parser = parser;
this.capabilitiesBase = precomputedCapabilitiesBase(parser);
this.authenticationProcessorMap = new HashMap<SupportedMechanism, AuthenticationProcessor>();
Expand Down Expand Up @@ -108,15 +111,13 @@ private String computeCapabilityEntryString(Map.Entry<Capabilities, String> entr
}

@Override
public String checkScript(Session session, String content) {
try {
authenticationCheck(session);
return manageWarnings(parser.parse(content));
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (SyntaxException ex) {
return sanitizeString("NO \"Syntax Error: " + ex.getMessage() + "\"");
}
public String checkScript(final Session session, final String content) {
return handleCommandExecution(new CommandWrapper() {
public String execute() throws ManageSieveException, SieveRepositoryException {
authenticationCheck(session);
return manageWarnings(parser.parse(content));
}
}, session);
}

private String manageWarnings(List<String> warnings) {
Expand All @@ -131,142 +132,95 @@ public String apply(String s) {
}
}

private String sanitizeString(String message) {
return Joiner.on("\r\n").join(Splitter.on('\n').split(message));
}

@Override
public String deleteScript(Session session, String name) {
try {
authenticationCheck(session);
sieveRepository.deleteScript(session.getUser(), name);
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (ScriptNotFoundException ex) {
return "NO (NONEXISTENT) \"There is no script by that name\"";
} catch (IsActiveException ex) {
return "NO (ACTIVE) \"You may not delete an active script\"";
} catch (UserNotFoundException e) {
return "NO : Invalid user " + session.getUser();
} catch (StorageException e) {
return "NO : Storage Exception : " + e.getMessage();
}
return "OK";
public String deleteScript(final Session session, final String name) {
return handleCommandExecution(new CommandWrapper() {
public String execute() throws ManageSieveException, SieveRepositoryException {
authenticationCheck(session);
sieveRepository.deleteScript(session.getUser(), name);
return "OK";
}
}, session);
}

@Override
public String getScript(Session session, String name) {
try {
authenticationCheck(session);
String scriptContent = IOUtils.toString(sieveRepository.getScript(session.getUser(), name));
return "{" + scriptContent.length() + "}" + "\r\n" + scriptContent + "\r\nOK";
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (ScriptNotFoundException ex) {
return "NO (NONEXISTENT) \"There is no script by that name\"";
} catch (StorageException ex) {
return "NO \"" + ex.getMessage() + "\"";
} catch (UserNotFoundException e) {
return "NO : Invalid user " + session.getUser();
} catch (IOException e) {
return "NO \"" + e.getMessage() + "\"";
}

public String getScript(final Session session, final String name) {
return handleCommandExecution(new CommandWrapper() {
public String execute() throws ManageSieveException, SieveRepositoryException, IOException {
authenticationCheck(session);
String scriptContent = IOUtils.toString(sieveRepository.getScript(session.getUser(), name));
return "{" + scriptContent.length() + "}" + "\r\n" + scriptContent + "\r\nOK";
}
}, session);
}

@Override
public String haveSpace(Session session, String name, long size) {
try {
authenticationCheck(session);
sieveRepository.haveSpace(session.getUser(), name, size);
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (QuotaExceededException ex) {
return "NO (QUOTA/MAXSIZE) \"Quota exceeded\"";
} catch (UserNotFoundException e) {
return "NO user not found : " + session.getUser();
} catch (StorageException e) {
return "NO storage exception : " + e.getMessage();
}
return "OK";
public String haveSpace(final Session session, final String name, final long size) {
return handleCommandExecution(new CommandWrapper() {
public String execute() throws ManageSieveException, SieveRepositoryException {
authenticationCheck(session);
sieveRepository.haveSpace(session.getUser(), name, size);
return "OK";
}
}, session);
}

@Override
public String listScripts(Session session) {
try {
authenticationCheck(session);
String list = Joiner.on("\r\n").join(
Iterables.transform(sieveRepository.listScripts(session.getUser()), new Function<ScriptSummary, String>() {
public String apply(ScriptSummary scriptSummary) {
return '"' + scriptSummary.getName() + '"' + (scriptSummary.isActive() ? " ACTIVE" : "");
}
}));
if (Strings.isNullOrEmpty(list)) {
return "OK";
} else {
return list + "\r\nOK";
public String listScripts(final Session session) {
return handleCommandExecution(new CommandWrapper() {
public String execute() throws ManageSieveException, SieveRepositoryException {
return listScriptsInternals(session);
}
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (UserNotFoundException e) {
return "NO user not found : " + session.getUser();
} catch (StorageException e) {
return "NO storage exception : " + e.getMessage();
}, session);
}

private String listScriptsInternals(Session session) throws AuthenticationRequiredException, UserNotFoundException, StorageException {
authenticationCheck(session);
String list = Joiner.on("\r\n").join(
Iterables.transform(sieveRepository.listScripts(session.getUser()), new Function<ScriptSummary, String>() {
public String apply(ScriptSummary scriptSummary) {
return '"' + scriptSummary.getName() + '"' + (scriptSummary.isActive() ? " ACTIVE" : "");
}
}));
if (Strings.isNullOrEmpty(list)) {
return "OK";
} else {
return list + "\r\nOK";
}
}

@Override
public String putScript(Session session, String name, String content) {
try {
authenticationCheck(session);
sieveRepository.putScript(session.getUser(), name, content);
return manageWarnings(parser.parse(content));
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (SyntaxException ex) {
return Joiner.on("\r\n").join(Splitter.on('\n').split("NO \"Syntax Error: " + ex.getMessage() + "\""));
} catch (QuotaExceededException ex) {
return "NO (QUOTA/MAXSIZE) \"Quota exceeded\"";
} catch (UserNotFoundException e) {
return "NO user not found : " + session.getUser();
} catch (StorageException e) {
return "NO storage exception : " + e.getMessage();
}
public String putScript(final Session session, final String name, final String content) {
return handleCommandExecution(new CommandWrapper() {
public String execute() throws ManageSieveException, SieveRepositoryException {
authenticationCheck(session);
sieveRepository.putScript(session.getUser(), name, content);
return manageWarnings(parser.parse(content));
}
}, session);
}

@Override
public String renameScript(Session session, String oldName, String newName) {
try {
authenticationCheck(session);
sieveRepository.renameScript(session.getUser(), oldName, newName);
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (ScriptNotFoundException ex) {
return "NO (NONEXISTENT) \"There is no script by that name\"";
} catch (DuplicateException ex) {
return "NO (ALREADYEXISTS) \"A script with that name already exists\"";
} catch (UserNotFoundException e) {
return "NO user not found : " + session.getUser();
} catch (StorageException e) {
return "NO storage exception : " + e.getMessage();
}
return "OK";
public String renameScript(final Session session, final String oldName, final String newName) {
return handleCommandExecution(new CommandWrapper() {
public String execute() throws ManageSieveException, SieveRepositoryException {
authenticationCheck(session);
sieveRepository.renameScript(session.getUser(), oldName, newName);
return "OK";
}
}, session);
}

@Override
public String setActive(Session session, String name) {
try {
authenticationCheck(session);
sieveRepository.setActive(session.getUser(), name);
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (ScriptNotFoundException ex) {
return "NO (NONEXISTENT) \"There is no script by that name\"";
} catch (UserNotFoundException e) {
return "NO : User not found";
} catch (StorageException e) {
return "NO : Storage exception : " + e.getMessage();
}
return "OK";
public String setActive(final Session session, final String name) {
return handleCommandExecution(new CommandWrapper() {
public String execute() throws ManageSieveException, SieveRepositoryException {
authenticationCheck(session);
sieveRepository.setActive(session.getUser(), name);
return "OK";
}
}, session);
}

@Override
Expand All @@ -283,7 +237,7 @@ public String chooseMechanism(Session session, String mechanism) {
if (Strings.isNullOrEmpty(mechanism)) {
return "NO ManageSieve syntax is incorrect : You must specify a SASL mechanism as an argument of AUTHENTICATE command";
}
String unquotedMechanism = unquotaIfNeeded(mechanism);
String unquotedMechanism = ParserUtils.unquote(mechanism);
SupportedMechanism supportedMechanism = SupportedMechanism.retrieveMechanism(unquotedMechanism);

session.setChoosedAuthenticationMechanism(supportedMechanism);
Expand Down Expand Up @@ -346,20 +300,39 @@ public String startTLS(Session session) {
}
}

protected void authenticationCheck(Session session) throws AuthenticationRequiredException {
if (!session.isAuthenticated()) {
throw new AuthenticationRequiredException();
private String handleCommandExecution(CommandWrapper commandWrapper, Session session) {
try {
return commandWrapper.execute();
} catch (AuthenticationException e) {
return "NO Authentication failed with " + e.getCause().getClass() + " : " + e.getMessage();
} catch (QuotaExceededException ex) {
return "NO (QUOTA/MAXSIZE) \"Quota exceeded\"";
} catch (AuthenticationRequiredException ex) {
return "NO";
} catch (DuplicateException ex) {
return "NO (ALREADYEXISTS) \"A script with that name already exists\"";
} catch (ScriptNotFoundException ex) {
return "NO (NONEXISTENT) \"There is no script by that name\"";
} catch (IsActiveException ex) {
return "NO (ACTIVE) \"You may not delete an active script\"";
} catch (UserNotFoundException e) {
return "NO : Invalid user " + session.getUser();
} catch (StorageException e) {
return "NO : Storage Exception : " + e.getMessage();
} catch (SyntaxException e) {
return sanitizeString("NO \"Syntax Error: " + e.getMessage() + "\"");
} catch (ManageSieveException e) {
return sanitizeString("NO \"ManageSieveException: " + e.getMessage() + "\"");
} catch (SieveRepositoryException e) {
return sanitizeString("NO \"SieveRepositoryException: " + e.getMessage() + "\"");
} catch (IOException e) {
return "NO \"" + e.getMessage() + "\"";
}
ensureUser(session);
}

private void ensureUser(Session session) {
try {
if (session.getUser() == null || !usersRepository.contains(session.getUser())) {
throw new RuntimeException("User " + session.getUser() + " not found");
}
} catch (UsersRepositoryException e) {
Throwables.propagate(e);
protected void authenticationCheck(Session session) throws AuthenticationRequiredException {
if (!session.isAuthenticated()) {
throw new AuthenticationRequiredException();
}
}

Expand All @@ -369,28 +342,10 @@ private String buildExtensions(SieveParser parser) {
}

private String taggify(String tag) {
String sanitizedTag = unquotaIfNeeded(tag.trim());
String sanitizedTag = ParserUtils.unquote(tag.trim());
return "(TAG {" + sanitizedTag.length() + "}\r\n" + sanitizedTag + ")";
}

private String unquotaIfNeeded(String tag) {
if (Strings.isNullOrEmpty(tag)) {
return "";
}
int startIndex = 0;
int stopIndex = tag.length();
if (tag.endsWith("\r\n")) {
stopIndex -= 2;
}
if (tag.charAt(0) == '\"') {
startIndex = 1;
}
if (tag.charAt(tag.length() - 1) == '\"') {
stopIndex--;
}
return tag.substring(startIndex, stopIndex);
}

private Map<Capabilities, String> precomputedCapabilitiesBase(SieveParser parser) {
String extensions = buildExtensions(parser);
Map<Capabilities, String> capabilitiesBase = new HashMap<Capabilities, String>();
Expand All @@ -414,4 +369,8 @@ public String apply(SupportedMechanism supportedMechanism) {
}
}));
}

private String sanitizeString(String message) {
return Joiner.on("\r\n").join(Splitter.on('\n').split(message));
}
}

0 comments on commit d53ba09

Please sign in to comment.