001    /*
002      Copyright (C) 2002 Laurent Martelli <laurent@aopsys.com>
003      
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
017    
018    package org.objectweb.jac.aspects.authentication;
019    
020    import org.objectweb.jac.aspects.gui.DisplayContext;
021    import org.objectweb.jac.aspects.gui.GuiAC;
022    import org.objectweb.jac.core.Collaboration;
023    import org.objectweb.jac.core.Display;
024    import org.objectweb.jac.core.rtti.ClassRepository;
025    import org.objectweb.jac.core.rtti.MethodItem;
026    import org.objectweb.jac.util.Log;
027    
028    /**
029     * This Authenticator ask for a username and password. The number of
030     * allowed attempts to enter a valid (username,password) is
031     * configurable. It needs a DisplayContext attribute in order to
032     * be able to interact with the user. */
033    
034    public abstract class PasswordAuthenticator implements Authenticator {   
035    
036        int retries = 3;
037    
038        /**
039         * The default constructor with 3 retries in case of failing. */
040    
041        public PasswordAuthenticator() {}
042    
043        /**
044         * This constructor can be used to parametrize the number of
045         * retries.
046         *
047         * @param retries the number of retries */
048    
049        public PasswordAuthenticator(int retries) {
050            this.retries = retries;
051        }
052    
053        /**
054         * This method perform the authentication by calling the
055         * askUserNameAndPassword and checkPassword methods.
056         *
057         * @return the username if the authentication succeded, null
058         * otherwise
059         *
060         * @see #askUsernameAndPassword(String,String)
061         * @see #checkPassword(String,String) */
062    
063        public String authenticate() throws AuthenticationFailedException {
064            DisplayContext context = 
065                (DisplayContext)Collaboration.get().getAttribute(GuiAC.DISPLAY_CONTEXT);
066            if (context!=null) {
067                Display display = context.getDisplay();
068                MethodItem method = 
069                    ClassRepository.get().getClass(this).getMethod(
070                        "askUsernameAndPassword");
071                String username = null;
072                for (int i=retries; i>0 && username==null; i--) {
073                    Object[] parameters = new Object[method.getParameterTypes().length];
074                    if (!display.showInput(this,method,parameters)) {
075                        // cancel
076                        Log.trace("authentication","Authentication cancelled");
077                        return null;
078                    } 
079                    if (checkPassword((String)parameters[0],(String)parameters[1])) {
080                        username = (String)parameters[0];
081                    }
082                }
083                if (username==null) {
084                    throw new AuthenticationFailedException(
085                        "Wrong username and password");
086                } else {
087                    return username;
088                }
089            } else {
090                Log.warning("no display context available, cannot authenticate user");
091                return null;
092            }
093        }
094       
095        /**
096         * This method has to be implemented by subclasses to perform the
097         * actual password checking mechanism.
098         * 
099         * @param username the username
100         * @param password the password
101         * @return true if the username exists and if the password is valid
102         * for this username */
103    
104        abstract boolean checkPassword(String username, String password);
105    
106        /**
107         * This empty method is used to popup a dialog on the current
108         * display so that the user can fill in the authentication
109         * information.
110         *
111         * @param username the username
112         * @param password the password */
113    
114        public void askUsernameAndPassword(String username, String password) {}
115    
116    }