001 package org.esupportail.cas.server.util;
002
003 import java.lang.reflect.Constructor;
004 import java.lang.reflect.InvocationTargetException;
005 import java.util.Iterator;
006 import java.util.LinkedList;
007 import java.util.List;
008
009 import org.dom4j.Element;
010
011 /**
012 * This abstract class implements a redundant handler, with a list
013 * of servers that will be used for redundancy.
014 *
015 * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>
016 */
017 public abstract class RedundantHandler extends BasicHandler {
018
019 /**
020 * the list of servers to be used for authentication. Modified by
021 * addServer().
022 */
023 private LinkedList servers;
024
025
026 /**
027 * retrieve the list of the servers.
028 *
029 * @return the list of the servers used for authentication.
030 */
031 public final List getServers() {
032 return servers;
033 }
034
035 /**
036 * Constructor.
037 *
038 * @param handlerElement the XML element that declares the handler
039 * in the configuration file
040 * @param configDebug debugging mode of the global configuration
041 */
042 protected RedundantHandler(
043 final Element handlerElement,
044 final Boolean configDebug) {
045 super(handlerElement, configDebug);
046 traceBegin();
047 servers = new LinkedList();
048 traceEnd();
049 }
050
051 /**
052 * Constructor.
053 *
054 * @param serverElementNeeded true to force the handler to have at least one server sub-element
055 * @param serverClassname the classname of the server to create for the handler
056 * @throws Exception Exception
057 */
058 protected final void addServers(
059 final boolean serverElementNeeded,
060 final String serverClassname) throws Exception {
061 traceBegin();
062
063 Element configElement = getConfigElement();
064
065 // check if a config/server element is needed
066 if (configElement == null) {
067 if (serverElementNeeded) {
068 traceThrow(new MisconfiguredHandlerException(
069 "A \"config\" element is needed by \""
070 + getClass().getName()
071 + "\" handlers."));
072 }
073 return;
074 }
075
076 trace("Looking for servers...");
077
078 // get the list of all the server elements
079 List serverElements = configElement.elements("server");
080
081 // check that at least one server is declared
082 if (serverElementNeeded) {
083 if (serverElements.isEmpty()) {
084 traceThrow(new MisconfiguredHandlerException(
085 "At least one \"server\" element is needed to configure \""
086 + getClass().getName()
087 + "\" handlers."));
088 }
089 }
090
091 for (Iterator i = serverElements.iterator(); i.hasNext();) {
092 trace("Found a server.");
093
094 // load the server class
095 Class serverClass = null;
096 try {
097 trace("Getting the " + serverClassname + " class...");
098 serverClass = Class.forName(serverClassname);
099 } catch (ClassNotFoundException e) {
100 // this should never happen
101 traceThrow(new MisconfiguredHandlerException(
102 "Class \""
103 + serverClassname
104 + "\" could not be loaded."));
105 }
106
107 // get the constructor
108 Class[] serverConstructorArgumentTypes = {
109 Boolean.class,
110 RedundantHandler.class,
111 Element.class};
112 Constructor serverConstructor = null;
113 try {
114 trace("Getting the constructor...");
115 serverConstructor = serverClass.getConstructor(serverConstructorArgumentTypes);
116 } catch (Exception e) {
117 traceThrow(new MisconfiguredHandlerException(
118 "The constructor of Class \""
119 + serverClassname
120 + "\" could not be loaded because a \""
121 + e.getClass().getName()
122 + "\" exception was raised: "
123 + e.getMessage()));
124 }
125
126 // create an instance
127 Object[] serverConstructorArguments = {new Boolean(isDebug()), this, i.next()};
128 Server server = null;
129 try {
130 trace("Creating a new instance...");
131 server = (Server) serverConstructor.newInstance(serverConstructorArguments);
132 } catch (InvocationTargetException e) {
133 traceThrow(new MisconfiguredHandlerException(e.getCause().getMessage()));
134 } catch (Exception e) {
135 traceThrow(new MisconfiguredHandlerException(
136 "Class \""
137 + serverClassname
138 + "\" could not be instanciated because a \""
139 + e.getClass().getName()
140 + "\" exception was raised: "
141 + e.getMessage()));
142 }
143
144 // add the newly created object to the list of servers
145 servers.add(server);
146
147 trace("Server added.");
148 }
149
150 trace(servers.size() + " servers found.");
151 traceEnd();
152 }
153
154 /**
155 * Tries to Authenticate a user by accessing all the servers.
156 *
157 * @param username the username to authenticate
158 * @param password the correspoding password
159 *
160 * @return BasicHandlerSUCCEDED on success, or
161 * BasicHandler.FAILED_CONTINUE otherwise.
162 */
163 public final int authenticate(final String username,
164 final String password) {
165 traceBegin();
166
167 for (Iterator i = servers.iterator(); i.hasNext();) {
168 Server server = (Server) i.next();
169 switch (server.authenticate(username, password)) {
170 case Server.AUTHENTICATE_SUCCESS:
171 trace("Server matched.");
172 traceEnd("SUCCEEDED");
173 return SUCCEEDED;
174 case Server.AUTHENTICATE_NOAUTH:
175 trace("Server did not match.");
176 traceEnd("FAILED_CONTINUE");
177 return FAILED_CONTINUE;
178 default:
179 trace("Server failure, trying next");
180 break;
181 }
182 }
183 trace("No server matched.");
184 traceEnd("FAILED_CONTINUE");
185 return FAILED_CONTINUE;
186 }
187
188 }
189