KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > security > realm > factory > JResourceDS


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2004 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * Initial developer(s): Florent BENOIT & Ludovic BERT
22  * --------------------------------------------------------------------------
23  * $Id: JResourceDS.java,v 1.15 2005/04/28 08:43:25 benoitf Exp $
24  * --------------------------------------------------------------------------
25  */

26
27 package org.objectweb.jonas.security.realm.factory;
28
29 import java.security.NoSuchAlgorithmException JavaDoc;
30 import java.sql.Connection JavaDoc;
31 import java.sql.DriverManager JavaDoc;
32 import java.sql.PreparedStatement JavaDoc;
33 import java.sql.ResultSet JavaDoc;
34 import java.sql.SQLException JavaDoc;
35 import java.util.ArrayList JavaDoc;
36
37 import javax.naming.Context JavaDoc;
38 import javax.naming.InitialContext JavaDoc;
39 import javax.naming.NamingException JavaDoc;
40 import javax.naming.Reference JavaDoc;
41 import javax.naming.StringRefAddr JavaDoc;
42 import javax.sql.DataSource JavaDoc;
43
44 import org.objectweb.jonas.dbm.ConnectionManager;
45 import org.objectweb.jonas.security.realm.lib.HashHelper;
46 import org.objectweb.jonas.security.realm.principals.User;
47
48 import org.objectweb.util.monolog.api.BasicLevel;
49
50 /**
51  * This class extends the JResource class for the Datasource implementation.
52  * @author Florent Benoit
53  */

54 public class JResourceDS extends JResource implements JResourceDSMBean {
55
56     /**
57      * Type of the factory
58      */

59     private static final String JavaDoc FACTORY_TYPE = "org.objectweb.jonas.security.realm.factory.JResourceDS";
60
61     /**
62      * Name of the factory
63      */

64     private static final String JavaDoc FACTORY_NAME = "org.objectweb.jonas.security.realm.factory.JResourceDSFactory";
65
66     /**
67      * Name of the datasource resource to use.
68      */

69     private String JavaDoc dsName = null;
70
71     /**
72      * Name of table which have the username/password
73      */

74     private String JavaDoc userTable = null;
75
76     /**
77      * Column of the username of the user table
78      */

79     private String JavaDoc userTableUsernameCol = null;
80
81     /**
82      * Column of the password of the user table
83      */

84     private String JavaDoc userTablePasswordCol = null;
85
86     /**
87      * Name of table which have the username/role
88      */

89     private String JavaDoc roleTable = null;
90
91     /**
92      * Column of the username of the role table
93      */

94     private String JavaDoc roleTableUsernameCol = null;
95
96     /**
97      * Column of the role of the role table
98      */

99     private String JavaDoc roleTableRolenameCol = null;
100
101     /**
102      * Default algorithm. If specified, the default is not 'clear' password
103      */

104     private String JavaDoc algorithm = null;
105
106     /**
107      * Datasource to use
108      */

109     private DataSource JavaDoc dataSource = null;
110
111     /**
112      * User defined query for retrieving principals
113      */

114     private String JavaDoc userPrincipalsQuery = null;
115
116     /**
117      * User defined query for retrieving roles
118      */

119     private String JavaDoc userRolesQuery = null;
120
121     /**
122      * Constructor. Use the super constructor
123      * @throws Exception if super constructor fail
124      */

125     public JResourceDS() throws Exception JavaDoc {
126         super();
127
128     }
129
130     /**
131      * Set the name of the resource to use
132      * @param dsName name of the resource
133      */

134     public void setDsName(String JavaDoc dsName) {
135         this.dsName = dsName;
136     }
137
138     /**
139      * Set the name of the table which have the username/password
140      * @param userTable name of the table which have the username/password
141      */

142     public void setUserTable(String JavaDoc userTable) {
143         this.userTable = userTable;
144     }
145
146     /**
147      * Set the name of the column of the username of the user table
148      * @param userTableUsernameCol name of the column of the username of the
149      * user table
150      */

151     public void setUserTableUsernameCol(String JavaDoc userTableUsernameCol) {
152         this.userTableUsernameCol = userTableUsernameCol;
153     }
154
155     /**
156      * Set the name of column of the password of the user table
157      * @param userTablePasswordCol name of column of the password of the user
158      * table
159      */

160     public void setUserTablePasswordCol(String JavaDoc userTablePasswordCol) {
161         this.userTablePasswordCol = userTablePasswordCol;
162     }
163
164     /**
165      * Set the name of table which have the username/role
166      * @param roleTable name of table which have the username/role
167      */

168     public void setRoleTable(String JavaDoc roleTable) {
169         this.roleTable = roleTable;
170     }
171
172     /**
173      * Set the name of the column of the username of the role table
174      * @param roleTableUsernameCol name of the column of the username of the
175      * role table
176      */

177     public void setRoleTableUsernameCol(String JavaDoc roleTableUsernameCol) {
178         this.roleTableUsernameCol = roleTableUsernameCol;
179     }
180
181     /**
182      * Set the name of the column of the role of the role table
183      * @param roleTableRolenameCol name of the column of the role of the role
184      * table
185      */

186     public void setRoleTableRolenameCol(String JavaDoc roleTableRolenameCol) {
187         this.roleTableRolenameCol = roleTableRolenameCol;
188     }
189
190     /**
191      * Set the default algorithm to use
192      * @param algorithm algorithm to be used
193      */

194     public void setAlgorithm(String JavaDoc algorithm) {
195         this.algorithm = algorithm;
196     }
197
198     /**
199      * Set the user defined query for retrieving principals
200      * @param userPrincipalsQuery the user defined query for retrieving
201      * principals
202      */

203     public void setUserPrincipalsQuery(String JavaDoc userPrincipalsQuery) {
204         this.userPrincipalsQuery = userPrincipalsQuery;
205     }
206
207     /**
208      * Set the user defined query for retrieving roles
209      * @param userRolesQuery the user defined query for retrieving roles
210      */

211     public void setUserRolesQuery(String JavaDoc userRolesQuery) {
212         this.userRolesQuery = userRolesQuery;
213     }
214
215     /**
216      * Get the name of the resource to use
217      * @return name of the resource
218      */

219     public String JavaDoc getDsName() {
220         return dsName;
221     }
222
223     /**
224      * Get the name of the table which have the username/password
225      * @return name of the table which have the username/password
226      */

227     public String JavaDoc getUserTable() {
228         return userTable;
229     }
230
231     /**
232      * Get the name of the column of the username of the user table
233      * @return name of the column of the username of the user table
234      */

235     public String JavaDoc getUserTableUsernameCol() {
236         return userTableUsernameCol;
237     }
238
239     /**
240      * Get the name of column of the password of the user table
241      * @return name of column of the password of the user table
242      */

243     public String JavaDoc getUserTablePasswordCol() {
244         return userTablePasswordCol;
245     }
246
247     /**
248      * Get the name of table which have the username/role
249      * @return name of table which have the username/role
250      */

251     public String JavaDoc getRoleTable() {
252         return roleTable;
253     }
254
255     /**
256      * Get the name of the column of the username of the role table
257      * @return name of the column of the username of the role table
258      */

259     public String JavaDoc getRoleTableUsernameCol() {
260         return roleTableUsernameCol;
261     }
262
263     /**
264      * Get the name of the column of the role of the role table
265      * @return name of the column of the role of the role table
266      */

267     public String JavaDoc getRoleTableRolenameCol() {
268         return roleTableRolenameCol;
269     }
270
271     /**
272      * Get the default algorithm
273      * @return the default algorithm
274      */

275     public String JavaDoc getAlgorithm() {
276         return algorithm;
277     }
278
279     /**
280      * Gets the user defined query for retrieving principals
281      * @return the user defined query for retrieving principals
282      */

283     public String JavaDoc setUserPrincipalsQuery() {
284         return userPrincipalsQuery;
285     }
286
287     /**
288      * Gets the user defined query for retrieving roles
289      * @return the user defined query for retrieving roles
290      */

291     public String JavaDoc setUserRolesQuery() {
292         return userRolesQuery;
293     }
294
295     /**
296      * Check if a user is found and return it
297      * @param username the wanted user name
298      * @return the user found or null
299      * @throws JResourceException if there is a SQLException
300      */

301     public User findUser(String JavaDoc username) throws JResourceException {
302
303         if (username == null) {
304             return null;
305         }
306
307         // Build new user
308
User user = new User();
309
310         Connection JavaDoc connection = getConnection();
311
312         user.setName(username);
313
314         // Get the password of the user
315
ResultSet JavaDoc rs = null;
316         String JavaDoc password = null;
317         try {
318             PreparedStatement JavaDoc usrStmt = userStatement(connection, username);
319             rs = usrStmt.executeQuery();
320             if (rs == null || !rs.next()) {
321                 throw new JResourceException("No user found with username '" + username + "'.");
322             }
323
324             int records = rs.getRow();
325             if (records > 1) {
326                 getLogger().log(BasicLevel.ERROR, "There are more than one user with the name" + username);
327             }
328             password = rs.getString(1).trim();
329             rs.close();
330             usrStmt.close();
331         } catch (SQLException JavaDoc sqle) {
332             closeConnection(connection);
333             throw new JResourceException(sqle.getMessage());
334         }
335
336         if (password == null) {
337             closeConnection(connection);
338             return null;
339         }
340         user.setPassword(password);
341
342         // Get the roles of the user
343
try {
344             PreparedStatement JavaDoc rlStmt = roleStatement(connection, username);
345             rs = rlStmt.executeQuery();
346
347             while (rs.next()) {
348                 String JavaDoc role = rs.getString(1).trim();
349                 user.addRole(role);
350             }
351             rs.close();
352             rlStmt.close();
353         } catch (SQLException JavaDoc sqle) {
354             closeConnection(connection);
355             throw new JResourceException(sqle.getMessage());
356         }
357
358         // Commit the connection if it is not automatic
359
try {
360             if (!connection.getAutoCommit()) {
361                 connection.commit();
362             }
363         } catch (SQLException JavaDoc sqle) {
364             if (getLogger().isLoggable(BasicLevel.DEBUG)) {
365                 getLogger().log(BasicLevel.DEBUG, "Cannot commit on the current connection : : '"
366                         + sqle.getMessage() + "'");
367             }
368         }
369         closeConnection(connection);
370         return user;
371     }
372
373     /**
374      * Check if the given credential is the right credential for the given user
375      * @param user user to check its credentials
376      * @param credentials the given credentials
377      * @return true if the credential is valid for this user
378      */

379     public boolean isValidUser(User user, String JavaDoc credentials) {
380
381         boolean validated = false;
382
383         //Get algorithm and hashpassword
384
String JavaDoc pass = user.getHashPassword().getPassword();
385         String JavaDoc algo = user.getHashPassword().getAlgorithm();
386
387         // Crypt password ?
388
if (algo != null) {
389             try {
390                 validated = HashHelper.hashPassword(credentials, algo)
391                         .equalsIgnoreCase(pass);
392             } catch (NoSuchAlgorithmException JavaDoc nsae) {
393                 getLogger().log(
394                         BasicLevel.ERROR,
395                         "Can't make a password with the algorithm " + algo
396                                 + ". " + nsae.getMessage());
397             }
398         } else if ((algorithm != null) && (!algorithm.equals(""))) {
399             // Encode password with the specified algorithm (no clear)
400
try {
401                 validated = HashHelper.hashPassword(credentials, algorithm)
402                         .equalsIgnoreCase(pass);
403             } catch (NoSuchAlgorithmException JavaDoc nsae) {
404                 getLogger().log(
405                         BasicLevel.ERROR,
406                         "Can't make a password with the algorithm " + algorithm
407                                 + ". " + nsae.getMessage());
408             }
409         } else {
410             // clear password
411
validated = credentials.equals(pass);
412         }
413         return validated;
414     }
415
416     /**
417      * Get all the roles (from the roles and from the groups) of the given user
418      * @param user the given user
419      * @return the array list of all the roles for a given user
420      * @throws JResourceException if it fails
421      */

422     public ArrayList JavaDoc getArrayListCombinedRoles(User user)
423             throws JResourceException {
424
425         ArrayList JavaDoc allCombinedRoles = new ArrayList JavaDoc();
426
427         // Return empty array if user null
428
if (user == null) {
429             return allCombinedRoles;
430         }
431         // Add all user roles
432
String JavaDoc[] userRoles = user.getArrayRoles();
433         for (int r = 0; r < userRoles.length; r++) {
434             String JavaDoc roleName = userRoles[r];
435             if (!allCombinedRoles.contains(roleName)) {
436                 allCombinedRoles.add(roleName);
437             }
438         }
439         user.setCombinedRoles(allCombinedRoles);
440
441         return allCombinedRoles;
442     }
443
444     /**
445      * String representation of the MemoryRealm
446      * @return the xml representation of the MemoryRealm
447      */

448     public String JavaDoc toXML() {
449         StringBuffer JavaDoc xml = new StringBuffer JavaDoc(" <dsrealm name=\"");
450         xml.append(getName());
451         xml.append("\"\n dsName=\"");
452         if (dsName != null) {
453             xml.append(dsName);
454         }
455         xml.append("\"\n userTable=\"");
456         if (userTable != null) {
457             xml.append(userTable);
458         }
459         xml.append("\" userTableUsernameCol=\"");
460         if (userTableUsernameCol != null) {
461             xml.append(userTableUsernameCol);
462         }
463         xml.append("\" userTablePasswordCol=\"");
464         if (userTablePasswordCol != null) {
465             xml.append(userTablePasswordCol);
466         }
467         xml.append("\"\n roleTable=\"");
468         if (roleTable != null) {
469             xml.append(roleTable);
470         }
471         xml.append("\" roleTableUsernameCol=\"");
472         if (roleTableUsernameCol != null) {
473             xml.append(roleTableUsernameCol);
474         }
475         xml.append("\" roleTableRolenameCol=\"");
476         if (roleTableRolenameCol != null) {
477             xml.append(roleTableRolenameCol);
478         }
479
480         if ((userPrincipalsQuery != null) && (!userPrincipalsQuery.equals(""))) {
481             xml.append("\"\n userPrincipalsQuery=\"");
482             xml.append(userPrincipalsQuery);
483         }
484
485         if ((userRolesQuery != null) && (!userRolesQuery.equals(""))) {
486             xml.append("\"\n userRolesQuery=\"");
487             xml.append(userRolesQuery);
488         }
489
490         if ((algorithm != null) && (!algorithm.equals(""))) {
491             xml.append("\"\n algorithm=\"");
492             xml.append(algorithm);
493         }
494
495         xml.append("\" />");
496         return xml.toString();
497     }
498
499     /**
500      * The string representation of this realm is the XML
501      * @return XML representation
502      */

503     public String JavaDoc toString() {
504         return this.toXML();
505     }
506
507     /**
508      * Retrieves the Reference of the object. The Reference contains the factory
509      * used to create this object and the optional parameters used to configure
510      * the factory.
511      * @return the non-null Reference of the object.
512      * @throws NamingException if a naming exception was encountered while
513      * retrieving the reference.
514      */

515     public Reference JavaDoc getReference() throws NamingException JavaDoc {
516
517         // Build the reference to the factory FACTORY_TYPE
518
Reference JavaDoc reference = new Reference JavaDoc(FACTORY_TYPE, FACTORY_NAME, null);
519
520         // Add ref addr
521
reference.add(new StringRefAddr JavaDoc("name", getName()));
522         reference.add(new StringRefAddr JavaDoc("dsName", dsName));
523         reference.add(new StringRefAddr JavaDoc("userTable", userTable));
524         reference.add(new StringRefAddr JavaDoc("userTableUsernameCol",
525                 userTableUsernameCol));
526         reference.add(new StringRefAddr JavaDoc("userTablePasswordCol",
527                 userTablePasswordCol));
528         reference.add(new StringRefAddr JavaDoc("roleTable", roleTable));
529         reference.add(new StringRefAddr JavaDoc("roleTableUsernameCol",
530                 roleTableUsernameCol));
531         reference.add(new StringRefAddr JavaDoc("roleTableRolenameCol",
532                 roleTableRolenameCol));
533         reference.add(new StringRefAddr JavaDoc("userPrincipalsQuery",
534                 userPrincipalsQuery));
535         reference.add(new StringRefAddr JavaDoc("userRolesQuery", userRolesQuery));
536         reference.add(new StringRefAddr JavaDoc("algorithm", algorithm));
537
538         return reference;
539     }
540
541     /**
542      * Try to close the given connection
543      * @param c the connection to close
544      */

545     private void closeConnection(Connection JavaDoc c) {
546         if (c == null) {
547             return;
548         }
549         try {
550             c.close();
551         } catch (Exception JavaDoc e) {
552             if (getLogger().isLoggable(BasicLevel.DEBUG)) {
553                 getLogger().log(BasicLevel.DEBUG, "Can not close the connection");
554             }
555         }
556
557     }
558
559     /**
560      * Get a connection from the dataSource
561      * @return the connection from the dataSource
562      * @throws JResourceException if an SQLException is thrown by
563      * dataSource.getConnection()
564      */

565     private Connection JavaDoc getConnection() throws JResourceException {
566
567         // If no dataSource, get an instance
568
if (dataSource == null) {
569             // Finds DataSource from JNDI
570
Context JavaDoc initialContext = null;
571             try {
572                 initialContext = new InitialContext JavaDoc();
573                 dataSource = (DataSource JavaDoc) initialContext.lookup(dsName);
574             } catch (Exception JavaDoc e) {
575                 String JavaDoc err = "Could not found resource " + dsName
576                         + " in the registry" + e.getMessage();
577                 getLogger().log(BasicLevel.ERROR, err);
578                 throw new JResourceException(err);
579             }
580         }
581
582         Connection JavaDoc c = null;
583
584         // Check if the request come from a client or inside the server
585
// Required until a dbm datasource can be called from a client
586
if (dataSource instanceof ConnectionManager) {
587             ConnectionManager cm = (ConnectionManager) dataSource;
588             // Client or server case ?
589
if (cm.isClientCase()) {
590                 // Build a JDBC connection with getting parameters from the object
591
// ConnectionManager
592
try {
593                     // Load driver
594
Class.forName(cm.getClassName());
595                     // create the connection
596
c = DriverManager.getConnection(cm.getUrl(), cm.getUserName(),
597                             cm.getPassword());
598                 } catch (Exception JavaDoc de) {
599                     getLogger().log(BasicLevel.ERROR, de.getMessage());
600                     throw new JResourceException(
601                             "Can not build a connection using the jdbc parameters :"
602                                     + de.getMessage());
603                 }
604             }
605         }
606
607         if (c == null) {
608             //Use the datasource
609
// Retrieve connection from the datasource
610
try {
611                 c = dataSource.getConnection();
612             } catch (SQLException JavaDoc sqle) {
613                 getLogger().log(BasicLevel.ERROR, sqle.getMessage());
614                 throw new JResourceException(sqle.getMessage());
615             }
616
617         }
618
619         return c;
620     }
621
622     /**
623      * Return the user query. It select the password for a specific user
624      * @return the user query
625      */

626     private String JavaDoc userQuery() {
627
628         if (userPrincipalsQuery != null) {
629             if (getLogger().isLoggable(BasicLevel.DEBUG)) {
630                 getLogger().log(
631                         BasicLevel.DEBUG,
632                         "Return user defined SQL query for user"
633                                 + userPrincipalsQuery);
634             }
635             return userPrincipalsQuery;
636         } else {
637
638             /*
639              * SELECT userTablePasswordCol FROM userTable WHERE
640              * userTableUsernameCol = ?
641              */

642             StringBuffer JavaDoc stringBuffer = new StringBuffer JavaDoc("SELECT ");
643             stringBuffer.append(userTablePasswordCol);
644             stringBuffer.append(" FROM ");
645             stringBuffer.append(userTable);
646             stringBuffer.append(" WHERE ");
647             stringBuffer.append(userTableUsernameCol);
648             stringBuffer.append(" = ?");
649             return (stringBuffer.toString());
650         }
651     }
652
653     /**
654      * Return the roles query. It select the roles for a specific user
655      * @return the roles query
656      */

657     private String JavaDoc rolesOfUserQuery() {
658
659         if (userRolesQuery != null) {
660             if (getLogger().isLoggable(BasicLevel.DEBUG)) {
661                 getLogger().log(
662                         BasicLevel.DEBUG,
663                         "Return user defined SQL query for roles"
664                                 + userRolesQuery);
665             }
666             return userRolesQuery;
667         } else {
668
669             /*
670              * SELECT r.roleTableRolenameCol FROM userTable u, roleTable r WHERE
671              * u.userTableUsernameCol = r.roleTableUsernameCol AND
672              * u.userTableUsernameCol = ?
673              */

674
675             StringBuffer JavaDoc stringBuffer = new StringBuffer JavaDoc("SELECT r.");
676             stringBuffer.append(roleTableRolenameCol);
677             stringBuffer.append(" FROM ");
678             stringBuffer.append(userTable);
679             stringBuffer.append(" u, ");
680             stringBuffer.append(roleTable);
681             stringBuffer.append(" r WHERE u.");
682             stringBuffer.append(userTableUsernameCol);
683             stringBuffer.append(" = r.");
684             stringBuffer.append(roleTableUsernameCol);
685             stringBuffer.append(" AND u.");
686             stringBuffer.append(userTableUsernameCol);
687             stringBuffer.append(" = ?");
688             return stringBuffer.toString();
689         }
690     }
691
692     /**
693      * Return a statement for the given username by using the userQuery query
694      * @param connection connection to use
695      * @param username the given user
696      * @return a statement for the given user
697      * @throws SQLException if the SQL statement fails
698      */

699     private PreparedStatement JavaDoc userStatement(Connection JavaDoc connection,
700             String JavaDoc username) throws SQLException JavaDoc {
701
702         if (getLogger().isLoggable(BasicLevel.DEBUG)) {
703             getLogger().log(BasicLevel.DEBUG,
704                     "Creating user statement for the user '" + username + "'");
705         }
706
707         PreparedStatement JavaDoc userStatement = connection.prepareStatement(userQuery());
708
709         userStatement.setString(1, username);
710         return userStatement;
711     }
712
713     /**
714      * Return a statement for the given username by using the rolesOfUserQuery
715      * query
716      * @param connection connection to use
717      * @param username the given user
718      * @return a roles of user statement for the given user
719      * @throws SQLException if the SQL statement fails
720      */

721     private PreparedStatement JavaDoc roleStatement(Connection JavaDoc connection,
722             String JavaDoc username) throws SQLException JavaDoc {
723
724         if (getLogger().isLoggable(BasicLevel.DEBUG)) {
725             getLogger().log(BasicLevel.DEBUG,
726                     "Creating role statement for the user " + username + "'");
727         }
728         PreparedStatement JavaDoc roleStatement = connection.prepareStatement(rolesOfUserQuery());
729
730         roleStatement.setString(1, username);
731
732         return roleStatement;
733     }
734
735     /**
736      * Remove all the Mbeans used by this resource
737      * @throws JResourceException if the MBeans can not be removed
738      */

739     public void removeMBeans() throws JResourceException {
740         //no MBeans
741
}
742
743 }
Popular Tags