KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > realm > MemoryRealm


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.realm;
20
21
22 import java.security.Principal JavaDoc;
23 import java.io.File JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Map JavaDoc;
27 import org.apache.catalina.Container;
28 import org.apache.catalina.LifecycleException;
29 import org.apache.catalina.util.StringManager;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.tomcat.util.digester.Digester;
33
34
35 /**
36  * Simple implementation of <b>Realm</b> that reads an XML file to configure
37  * the valid users, passwords, and roles. The file format (and default file
38  * location) are identical to those currently supported by Tomcat 3.X.
39  * <p>
40  * <strong>IMPLEMENTATION NOTE</strong>: It is assumed that the in-memory
41  * collection representing our defined users (and their roles) is initialized
42  * at application startup and never modified again. Therefore, no thread
43  * synchronization is performed around accesses to the principals collection.
44  *
45  * @author Craig R. McClanahan
46  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
47  */

48
49 public class MemoryRealm extends RealmBase {
50
51     private static Log log = LogFactory.getLog(MemoryRealm.class);
52
53     // ----------------------------------------------------- Instance Variables
54

55
56     /**
57      * The Container with which this Realm is associated.
58      */

59     private Container container = null;
60
61
62     /**
63      * The Digester we will use to process in-memory database files.
64      */

65     private static Digester digester = null;
66
67
68     /**
69      * Descriptive information about this Realm implementation.
70      */

71     protected final String JavaDoc info =
72         "org.apache.catalina.realm.MemoryRealm/1.0";
73
74
75     /**
76      * Descriptive information about this Realm implementation.
77      */

78
79     protected static final String JavaDoc name = "MemoryRealm";
80
81
82     /**
83      * The pathname (absolute or relative to Catalina's current working
84      * directory) of the XML file containing our database information.
85      */

86     private String JavaDoc pathname = "conf/tomcat-users.xml";
87
88
89     /**
90      * The set of valid Principals for this Realm, keyed by user name.
91      */

92     private Map JavaDoc principals = new HashMap JavaDoc();
93
94
95     /**
96      * The string manager for this package.
97      */

98     private static StringManager sm =
99         StringManager.getManager(Constants.Package);
100
101
102     /**
103      * Has this component been started?
104      */

105     private boolean started = false;
106
107
108     // ------------------------------------------------------------- Properties
109

110
111     /**
112      * Return descriptive information about this Realm implementation and
113      * the corresponding version number, in the format
114      * <code>&lt;description&gt;/&lt;version&gt;</code>.
115      */

116     public String JavaDoc getInfo() {
117
118         return info;
119
120     }
121
122
123     /**
124      * Return the pathname of our XML file containing user definitions.
125      */

126     public String JavaDoc getPathname() {
127
128         return pathname;
129
130     }
131
132
133     /**
134      * Set the pathname of our XML file containing user definitions. If a
135      * relative pathname is specified, it is resolved against "catalina.base".
136      *
137      * @param pathname The new pathname
138      */

139     public void setPathname(String JavaDoc pathname) {
140
141         this.pathname = pathname;
142
143     }
144
145
146     // --------------------------------------------------------- Public Methods
147

148
149     /**
150      * Return the Principal associated with the specified username and
151      * credentials, if there is one; otherwise return <code>null</code>.
152      *
153      * @param username Username of the Principal to look up
154      * @param credentials Password or other credentials to use in
155      * authenticating this username
156      */

157     public Principal JavaDoc authenticate(String JavaDoc username, String JavaDoc credentials) {
158
159         GenericPrincipal principal =
160             (GenericPrincipal) principals.get(username);
161
162         boolean validated = false;
163         if (principal != null) {
164             if (hasMessageDigest()) {
165                 // Hex hashes should be compared case-insensitive
166
validated = (digest(credentials)
167                              .equalsIgnoreCase(principal.getPassword()));
168             } else {
169                 validated =
170                     (digest(credentials).equals(principal.getPassword()));
171             }
172         }
173
174         if (validated) {
175             if (log.isDebugEnabled())
176                 log.debug(sm.getString("memoryRealm.authenticateSuccess", username));
177             return (principal);
178         } else {
179             if (log.isDebugEnabled())
180                 log.debug(sm.getString("memoryRealm.authenticateFailure", username));
181             return (null);
182         }
183
184     }
185
186
187     // -------------------------------------------------------- Package Methods
188

189
190     /**
191      * Add a new user to the in-memory database.
192      *
193      * @param username User's username
194      * @param password User's password (clear text)
195      * @param roles Comma-delimited set of roles associated with this user
196      */

197     void addUser(String JavaDoc username, String JavaDoc password, String JavaDoc roles) {
198
199         // Accumulate the list of roles for this user
200
ArrayList JavaDoc list = new ArrayList JavaDoc();
201         roles += ",";
202         while (true) {
203             int comma = roles.indexOf(',');
204             if (comma < 0)
205                 break;
206             String JavaDoc role = roles.substring(0, comma).trim();
207             list.add(role);
208             roles = roles.substring(comma + 1);
209         }
210
211         // Construct and cache the Principal for this user
212
GenericPrincipal principal =
213             new GenericPrincipal(this, username, password, list);
214         principals.put(username, principal);
215
216     }
217
218
219     // ------------------------------------------------------ Protected Methods
220

221
222     /**
223      * Return a configured <code>Digester</code> to use for processing
224      * the XML input file, creating a new one if necessary.
225      */

226     protected synchronized Digester getDigester() {
227
228         if (digester == null) {
229             digester = new Digester();
230             digester.setValidating(false);
231             digester.addRuleSet(new MemoryRuleSet());
232         }
233         return (digester);
234
235     }
236
237
238     /**
239      * Return a short name for this Realm implementation.
240      */

241     protected String JavaDoc getName() {
242
243         return (name);
244
245     }
246
247
248     /**
249      * Return the password associated with the given principal's user name.
250      */

251     protected String JavaDoc getPassword(String JavaDoc username) {
252
253         GenericPrincipal principal =
254             (GenericPrincipal) principals.get(username);
255         if (principal != null) {
256             return (principal.getPassword());
257         } else {
258             return (null);
259         }
260
261     }
262
263
264     /**
265      * Return the Principal associated with the given user name.
266      */

267     protected Principal JavaDoc getPrincipal(String JavaDoc username) {
268
269         return (Principal JavaDoc) principals.get(username);
270
271     }
272
273     /**
274      * Returns the principals for this realm.
275      *
276      * @return The principals, keyed by user name (a String)
277      */

278     protected Map JavaDoc getPrincipals() {
279         return principals;
280     }
281
282
283     // ------------------------------------------------------ Lifecycle Methods
284

285
286     /**
287      * Prepare for active use of the public methods of this Component.
288      *
289      * @exception LifecycleException if this component detects a fatal error
290      * that prevents it from being started
291      */

292     public synchronized void start() throws LifecycleException {
293
294         // Perform normal superclass initialization
295
super.start();
296
297         // Validate the existence of our database file
298
File JavaDoc file = new File JavaDoc(pathname);
299         if (!file.isAbsolute())
300             file = new File JavaDoc(System.getProperty("catalina.base"), pathname);
301         if (!file.exists() || !file.canRead())
302             throw new LifecycleException
303                 (sm.getString("memoryRealm.loadExist",
304                               file.getAbsolutePath()));
305
306         // Load the contents of the database file
307
if (log.isDebugEnabled())
308             log.debug(sm.getString("memoryRealm.loadPath",
309                              file.getAbsolutePath()));
310         Digester digester = getDigester();
311         try {
312             synchronized (digester) {
313                 digester.push(this);
314                 digester.parse(file);
315             }
316         } catch (Exception JavaDoc e) {
317             throw new LifecycleException("memoryRealm.readXml", e);
318         } finally {
319             digester.reset();
320         }
321
322     }
323
324
325     /**
326      * Gracefully shut down active use of the public methods of this Component.
327      *
328      * @exception LifecycleException if this component detects a fatal error
329      * that needs to be reported
330      */

331     public synchronized void stop() throws LifecycleException {
332
333         // Perform normal superclass finalization
334
super.stop();
335
336         // No shutdown activities required
337

338     }
339
340
341 }
342
Popular Tags