class POP3AuthProvider implements AuthProvider {

    private static final Logger Log = LoggerFactory.getLogger(POP3AuthProvider.class);

    private Cache<String, String> authCache = null;
    private String host = null;
    private String domain = null;
    private int port = -1;
    private boolean useSSL = false;
    private boolean authRequiresDomain = false;
    private boolean debugEnabled;

    /**
     * Initialiazes the POP3AuthProvider with values from the global config file.
     */
    public POP3AuthProvider() {
        // Convert XML based provider setup to Database based
        JiveGlobals.migrateProperty("pop3.authCache.enabled");
        JiveGlobals.migrateProperty("pop3.ssl");
        JiveGlobals.migrateProperty("pop3.authRequiresDomain");
        JiveGlobals.migrateProperty("pop3.host");
        JiveGlobals.migrateProperty("pop3.debug");
        JiveGlobals.migrateProperty("pop3.domain");
        JiveGlobals.migrateProperty("pop3.port");

        if (Boolean.valueOf(JiveGlobals.getProperty("pop3.authCache.enabled"))) {
            String cacheName = "POP3 Authentication";
            authCache = CacheFactory.createCache(cacheName);
        }

        useSSL = Boolean.valueOf(JiveGlobals.getProperty("pop3.ssl"));
        authRequiresDomain = Boolean.valueOf(JiveGlobals.getProperty("pop3.authRequiresDomain"));

        host = JiveGlobals.getProperty("pop3.host");
        if (host == null || host.length() < 1) {
            throw new IllegalArgumentException("pop3.host is null or empty");
        }

        debugEnabled = Boolean.valueOf(JiveGlobals.getProperty("pop3.debug"));

        domain = JiveGlobals.getProperty("pop3.domain");

        port = JiveGlobals.getIntProperty("pop3.port", useSSL ? 995 : 110);

        if (Log.isDebugEnabled()) {
            Log.debug("POP3AuthProvider: Created new POP3AuthProvider instance, fields:");
            Log.debug("\t host: " + host);
            Log.debug("\t port: " + port);
            Log.debug("\t domain: " + domain);
            Log.debug("\t useSSL: " + useSSL);
            Log.debug("\t authRequiresDomain: " + authRequiresDomain);
            Log.debug("\t authCacheEnabled: " + (authCache != null));
            if (authCache != null) {
                Log.debug("\t authCacheSize: " + authCache.getLongCacheSize());
                Log.debug("\t authCacheMaxLifetime: " + authCache.getMaxLifetime());
            }
        }
    }

    @Override
    public void authenticate(String username, String password) throws UnauthorizedException {<FILL_FUNCTION_BODY>}

    @Override
    public String getPassword(String username)
            throws UserNotFoundException, UnsupportedOperationException
    {
        throw new UnsupportedOperationException();
    }

     @Override
     public void setPassword(String username, String password) throws UserNotFoundException {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean supportsPasswordRetrieval() {
        return false;
    }
    
    @Override
    public boolean isScramSupported() {
        return false;
    }

    @Override
    public String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException {
        throw new UnsupportedOperationException();
    }

    @Override
    public int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException {
        throw new UnsupportedOperationException();
    }
}

        if (username == null || password == null) {
            throw new UnauthorizedException();
        }
        if (username.contains("@")) {
            // Check that the specified domain matches the server's domain
            int index = username.indexOf("@");
            String domain = username.substring(index + 1);
            if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
                username = username.substring(0, index);
            }
        } else {
            // Unknown domain. Return authentication failed.
            throw new UnauthorizedException();
        }

        Log.debug("POP3AuthProvider.authenticate("+username+", ******)");

            // If cache is enabled, see if the auth is in cache.
            if (authCache != null && authCache.containsKey(username)) {
                String hash = authCache.get(username);
                if (StringUtils.hash(password).equals(hash)) {
                    return;
                }
            }

        Properties mailProps = new Properties();
        mailProps.setProperty("mail.debug", String.valueOf(debugEnabled));
        Session session = Session.getInstance(mailProps, null);
        Store store;
        try {
            store = session.getStore(useSSL ? "pop3s" : "pop3");
        }
        catch(NoSuchProviderException e) {
            Log.error(e.getMessage(), e);
            throw new UnauthorizedException(e);
        }

        try {
            if (authRequiresDomain) {
                store.connect(host, port, username + "@" + domain, password);
            }
            else {
                store.connect(host, port, username, password);
            }
        }
        catch(Exception e) {
            Log.error(e.getMessage(), e);
            throw new UnauthorizedException(e);
        }

        if (! store.isConnected()) {
            throw new UnauthorizedException("Could not authenticate user");
        }

        try {
            store.close();
        }
        catch (Exception e) {
            // Ignore.
        }

        // If cache is enabled, add the item to cache.
        if (authCache != null) {
            authCache.put(username, StringUtils.hash(password));
        }

        // See if the user exists in the database. If not, automatically create them.
        UserManager userManager = UserManager.getInstance();
        try {
            userManager.getUser(username);
        }
        catch (UserNotFoundException unfe) {
            String email = username + "@" + (domain!=null?domain:host);
            try {
                Log.debug("POP3AuthProvider: Automatically creating new user account for " + username);
                // Create user; use a random password for better safety in the future.
                // Note that we have to go to the user provider directly -- because the
                // provider is read-only, UserManager will usually deny access to createUser.
                UserManager.getUserProvider().createUser(username, StringUtils.randomString(8),
                        null, email);
            }
            catch (UserAlreadyExistsException uaee) {
                // Ignore.
            }
        }
    
<no_super_class>