/**
* Copyright (c) 2006-2009, Redv.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Redv.com nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Created on 2006-10-16 12:39:17
*/
package cn.net.openid.jos.service;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.LocaleUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openid4java.server.ServerManager;
import cn.net.openid.jos.dao.AttributeDao;
import cn.net.openid.jos.dao.AttributeValueDao;
import cn.net.openid.jos.dao.DomainDao;
import cn.net.openid.jos.dao.EmailConfirmationInfoDao;
import cn.net.openid.jos.dao.EmailDao;
import cn.net.openid.jos.dao.PasswordDao;
import cn.net.openid.jos.dao.PersonaDao;
import cn.net.openid.jos.dao.RealmDao;
import cn.net.openid.jos.dao.SiteDao;
import cn.net.openid.jos.dao.UserDao;
import cn.net.openid.jos.domain.Attribute;
import cn.net.openid.jos.domain.AttributeValue;
import cn.net.openid.jos.domain.Domain;
import cn.net.openid.jos.domain.DomainRuntime;
import cn.net.openid.jos.domain.Email;
import cn.net.openid.jos.domain.EmailConfirmationInfo;
import cn.net.openid.jos.domain.Password;
import cn.net.openid.jos.domain.Persona;
import cn.net.openid.jos.domain.Realm;
import cn.net.openid.jos.domain.Site;
import cn.net.openid.jos.domain.User;
import cn.net.openid.jos.service.exception.EmailConfirmationInfoNotFoundException;
import cn.net.openid.jos.service.exception.LastPasswordException;
import cn.net.openid.jos.service.exception.NoPermissionException;
import cn.net.openid.jos.service.exception.PersonaInUseException;
import cn.net.openid.jos.service.exception.UnresolvedDomainException;
/**
* Service implementation.
*
* @author Sutra Zhou
*/
public class JosServiceImpl implements JosService {
/**
* The logger.
*/
private static final Log LOG = LogFactory.getLog(JosServiceImpl.class);
/**
* Indicate the logger is debug enabled.
*/
private static final boolean DEBUG = LOG.isDebugEnabled();
/**
* Server managers.
*/
private final Map<Domain, ServerManager> serverManagers =
new HashMap<Domain, ServerManager>();
/**
* The configurator password.
*/
private String configuratorPassword;
/**
* The available locales.
*/
private Collection<Locale> availableLocales;
/**
* The pattern of the system reserved word.
*/
private Pattern systemReservedWordPattern;
/**
* The password generator.
*/
private PasswordGenerator passwordGenerator;
/**
* The minimum length of the generated one time password.
*/
private int oneTimePasswordMinLength;
/**
* The maximum length of the generated one time password.
*/
private int oneTimePasswordMaxLength;
/**
* The length of seed to generate email confirmation code.
*/
private int emailConfirmationCodeSeedLength;
/* DAOs */
/**
* The {@link Domain} DAO.
*/
private DomainDao domainDao;
/**
* The {@link User} DAO.
*/
private UserDao userDao;
/**
* The {@link Password} DAO.
*/
private PasswordDao passwordDao;
/**
* The {@link Email} DAO.
*/
private EmailDao emailDao;
/**
* The {@link EmailConfirmationInfo} DAO.
*/
private EmailConfirmationInfoDao emailConfirmationInfoDao;
/**
* The {@link Attribute} DAO.
*/
private AttributeDao attributeDao;
/**
* The {@link AttributeValue} DAO.
*/
private AttributeValueDao attributeValueDao;
/**
* The {@link Realm} DAO.
*/
private RealmDao realmDao;
/**
* The {@link Site} DAO.
*/
private SiteDao siteDao;
/**
* The {@link Persona} DAO.
*/
private PersonaDao personaDao;
/**
* The default constructor.
*/
public JosServiceImpl() {
this.availableLocales = Collections.unmodifiableCollection(Arrays
.asList(Locale.getAvailableLocales()));
}
/**
* Set the configurator password.
*
* @param configuratorPassword
* the configuratorPassword to set
*/
public void setConfiguratorPassword(final String configuratorPassword) {
String s = StringUtils.trimToNull(configuratorPassword);
if ("BLANK".equals(s) || StringUtils.isBlank(s)) {
this.configuratorPassword = null;
} else {
this.configuratorPassword = s;
}
}
/**
* Set the regular expression of the pattern of the system wide reserved
* word.
*
* @param systemReservedWordPattern
* the systemReservedWordPattern to set
*/
public void setSystemReservedWordPattern(
final String systemReservedWordPattern) {
this.systemReservedWordPattern = Pattern
.compile(systemReservedWordPattern.trim());
}
/**
* Set the minimum length of the generated one time password.
*
* @param oneTimePasswordMinLength
* the oneTimePasswordMinLength to set
*/
public void setOneTimePasswordMinLength(
final int oneTimePasswordMinLength) {
this.oneTimePasswordMinLength = oneTimePasswordMinLength;
}
/**
* Set the maximum length of the generated one time password.
*
* @param oneTimePasswordMaxLength
* the oneTimePasswordMaxLength to set
*/
public void setOneTimePasswordMaxLength(
final int oneTimePasswordMaxLength) {
this.oneTimePasswordMaxLength = oneTimePasswordMaxLength;
}
/**
* Set the length of seed to generate email confirmation code.
*
* @param emailConfirmationCodeSeedLength
* the emailConfirmationCodeSeedLength to set
*/
public void setEmailConfirmationCodeSeedLength(
final int emailConfirmationCodeSeedLength) {
this.emailConfirmationCodeSeedLength = emailConfirmationCodeSeedLength;
}
/**
* Set the {@link Domain} DAO.
*
* @param domainDao
* the domainDao to set
*/
public void setDomainDao(final DomainDao domainDao) {
this.domainDao = domainDao;
}
/**
* Set the {@link User} DAO.
*
* @param userDao
* the userDao to set
*/
public void setUserDao(final UserDao userDao) {
this.userDao = userDao;
}
/**
* Set the {@link Password} DAO.
*
* @param passwordDao
* the passwordDao to set
*/
public void setPasswordDao(final PasswordDao passwordDao) {
this.passwordD