();
}
/**
* Returns a short (preferably less than fifteen characters) description
* of the kind of authentication which is supported by this realm.
*
* @return Description of the kind of authentication that is directly
* supported by this realm.
*/
public String getAuthType(){
return AUTH_TYPE;
}
/**
* Returns the name of all the groups that this user belongs to.
* This is called from web path role verification, though
* it should not be.
*
* @param username Name of the user in this realm whose group listing
* is needed.
* @return Enumeration of group names (strings).
* @exception InvalidOperationException thrown if the realm does not
* support this operation - e.g. Certificate realm does not support
* this operation.
*/
public Enumeration getGroupNames (String username)
throws InvalidOperationException, NoSuchUserException
{
Vector v = (Vector)groupCache.get(username);
if (v == null) {
v = loadGroupNames(username);
}
return v.elements();
}
/**
* Set group membership info for a user.
*
* See bugs 4646133,4646270 on why this is here.
*
*/
public void setGroupNames(String username, String[] groups)
{
Vector v = null;
if (groups == null) {
v = emptyVector;
} else {
v = new Vector(groups.length + 1);
for (int i=0; iGroup info is loaded when user authenticates, however in some
* cases (such as run-as) the group membership info is needed
* without an authentication event.
*
*/
private Vector loadGroupNames(String username){
String[] grps = findGroups(username);
if (grps == null) {
_logger.fine("No groups returned for user: "+username);
}
setGroupNames(username, grps);
return (Vector)groupCache.get(username);
}
/**
* Test if a user is valid
* @param user user's identifier
* @param password user's password
* @return true if valid
*/
private boolean isUserValid(String user, String password){
Connection connection=null;
try{
connection = getConnection();
final String identifierQuery = this.getProperty(KEY_FIND_IDENTIFIER);
final PreparedStatement statement = connection.prepareStatement(identifierQuery);
statement.setString(1,user);
statement.setString(2,password);
final ResultSet result = statement.executeQuery();
final boolean valid = result.next();
_logger.info("User validity:"+valid);
return valid;
}catch(Exception lex){
// Provide isolation, if any exception has happen we can not access !
_logger.log(Level.SEVERE,"Problem while testing user:"+user,lex);
return false;
}finally{
if(connection!=null){
try{
connection.close();
}catch(SQLException s){
_logger.log(Level.WARNING,"Was not able to close connection",s);
}
}
}
}
/**
* Delegate method for retreiving users groups
* @param user user's identifier
* @return array of group key
*/
private String[] findGroups(String user){
Connection connection=null;
try{
connection = getConnection();
final String identifierQuery = this.getProperty(KEY_FIND_GROUPS);
final PreparedStatement statement = connection.prepareStatement(identifierQuery);
statement.setString(1,user);
final ResultSet result = statement.executeQuery();
final List groups = new ArrayList();
while(result.next()){
groups.add(result.getString(1));
}
final String[] groupArray = new String[groups.size()];
_logger.info("JDBC Groups:"+groups+" for user:"+user);
return groups.toArray(groupArray);
}catch(Exception lex){
// Provide isolation, if any exception has happen we can not access !
_logger.log(Level.SEVERE,"Problem while testing user:"+user,lex);
return null;
}finally{
// Do some early cleaning
if(connection!=null){
try{
connection.close();
}catch(SQLException s){
_logger.log(Level.WARNING,"Was not able to close connection",s);
}
}
}
}
/**
* Return a connection from the properties configured
* @return a connection
* @todo bring some cache to speedup AA
*/
private Connection getConnection() throws LoginException {
final String binding = this.getProperty(KEY_DATASOURCE);
final String userName = this.getProperty(KEY_USER);
final String password = this.getProperty(KEY_PASSWORD);
try{
final InitialContext ic = new InitialContext();
final DataSource dataSource = (DataSource) ic.lookup(binding);
final Connection connection = dataSource.getNonTxConnection(userName,password);
connection.setAutoCommit(false); // Usefull ?
return connection;
}catch(Exception ex){
// Whatever has happend this is a show stopper, so wrap it and throw it
LoginException loginEx = new LoginException("Unable to connect to datasource "+
binding+" using login "+userName+" and password "+password);
loginEx.initCause(ex);
throw loginEx;
}
}
}