package org.subethamail.smtp.auth; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.StringTokenizer; import org.subethamail.smtp.AuthenticationHandler; import org.subethamail.smtp.AuthenticationHandlerFactory; import org.subethamail.smtp.RejectException; /** * This handler combines the behavior of several other authentication handler factories. * * @author Jeff Schnitzer */ public class MultipleAuthenticationHandlerFactory implements AuthenticationHandlerFactory { /** * Maps the auth type (eg "PLAIN") to a handler. The mechanism name (key) is in upper case. */ Map<String, AuthenticationHandlerFactory> plugins = new HashMap<String, AuthenticationHandlerFactory>(); /** * A more orderly list of the supported mechanisms. Mechanism names are in upper case. */ List<String> mechanisms = new ArrayList<String>(); /** */ public MultipleAuthenticationHandlerFactory() { // Starting with an empty list is ok, let the user add them all } /** */ public MultipleAuthenticationHandlerFactory(Collection<AuthenticationHandlerFactory> factories) { for (AuthenticationHandlerFactory fact: factories) { this.addFactory(fact); } } /** */ public void addFactory(AuthenticationHandlerFactory fact) { List<String> partialMechanisms = fact.getAuthenticationMechanisms(); for (String mechanism: partialMechanisms) { if (!this.mechanisms.contains(mechanism)) { this.mechanisms.add(mechanism); this.plugins.put(mechanism, fact); } } } /** */ public List<String> getAuthenticationMechanisms() { return this.mechanisms; } /** */ public AuthenticationHandler create() { return new Handler(); } /** */ class Handler implements AuthenticationHandler { AuthenticationHandler active; /* */ public String auth(String clientInput) throws RejectException { if (this.active == null) { StringTokenizer stk = new StringTokenizer(clientInput); String auth = stk.nextToken(); if (!"AUTH".equalsIgnoreCase(auth)) throw new IllegalArgumentException("Not an AUTH command: " + clientInput); String method = stk.nextToken(); AuthenticationHandlerFactory fact = MultipleAuthenticationHandlerFactory.this.plugins .get(method.toUpperCase(Locale.ENGLISH)); if (fact == null) throw new RejectException(504, "Method not supported"); this.active = fact.create(); } return this.active.auth(clientInput); } /* */ public Object getIdentity() { return this.active.getIdentity(); } } }