
org.efaps.admin.user.Person Maven / Gradle / Ivy
/*
* Copyright 2003 - 2010 The eFaps Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Revision: $Rev: 8229 $
* Last Changed: $Date: 2012-11-22 14:25:34 -0500 (Thu, 22 Nov 2012) $
* Last Changed By: $Author: [email protected] $
*/
package org.efaps.admin.user;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.efaps.admin.EFapsSystemConfiguration;
import org.efaps.admin.common.SystemConfiguration;
import org.efaps.admin.datamodel.Type;
import org.efaps.admin.datamodel.attributevalue.PasswordStore;
import org.efaps.ci.CIAdminUser;
import org.efaps.db.Context;
import org.efaps.db.PrintQuery;
import org.efaps.db.Update;
import org.efaps.db.Update.Status;
import org.efaps.db.transaction.ConnectionResource;
import org.efaps.jaas.AppAccessHandler;
import org.efaps.util.ChronologyType;
import org.efaps.util.DateTimeUtil;
import org.efaps.util.EFapsException;
import org.efaps.util.cache.AbstractCache;
import org.efaps.util.cache.CacheReloadException;
import org.joda.time.Chronology;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class represents the instance of a person/user in eFaps.
*
* @author The eFasp Team
* @version $Id: Person.java 8229 2012-11-22 19:25:34Z [email protected] $
*/
public final class Person
extends AbstractUserObject
{
/**
* Needed for serialization.
*/
private static final long serialVersionUID = 1L;
/**
* Enum for all known and updated attributes from a person. Only this could
* be defined which are in the SQL table T_USERPERSON.
*/
public enum AttrName {
/** Attribute Name for the First Name of the person. */
FIRSTNAME("FIRSTNAME"),
/** Attribute Name for the Last Name of the person. */
LASTNAME("LASTNAME"),
/** Attribute Name for the Chronology of the person. */
CHRONOLOGY("CHRONOLOGY"),
/** Attribute Name for the Timezone of the person. */
TIMZONE("TIMZONE"),
/** Attribute Name for the Locale of the person. */
LOCALE("LOCALE"),
/** Attribute Name for the language of the person. */
LANGUAGE("LANG", true);
/**
* The name of the depending SQL column for an attribute in the table.
*/
private final String sqlColumn;
/**
* The name of the depending SQL column for an attribute in the table.
*/
private final boolean integer;
/**
* Constructor setting the instance variables.
*
* @param _sqlColumn name of the column in the table
*/
private AttrName(final String _sqlColumn)
{
this(_sqlColumn, false);
}
/**
* Constructor setting the instance variables.
*
* @param _sqlColumn name of the column in the table
* @param _integer is the column a integer column
*/
private AttrName(final String _sqlColumn,
final boolean _integer)
{
this.sqlColumn = _sqlColumn;
this.integer = _integer;
}
}
/**
* Logging instance used to give logging information of this class.
*/
private static final Logger LOG = LoggerFactory.getLogger(Person.class);
/**
* Stores all instances of class {@link Person}.
*
* @see #getCache
*/
private static final AbstractCache CACHE = new PersonCache();
/**
* Key to access the cache4Name in the Context.
*/
private static final String CACHE4NAMEKEY = "org.efaps.admin.user.Person.eFapsPersonCache4Name";
/**
* Key to access the cache4ID in the Context.
*/
private static final String CACHE4IDKEY = "org.efaps.admin.user.Person.eFapsPersonCache4Id";
/**
* HashSet instance variable to hold all id of roles for this person.
*
* @see #getRoles
* @see #add(Role)
*/
private final Set roles = new HashSet();
/**
* HashSet instance variable to hold all id of groups for this person.
*
* @see #getGroups
* @see #add(Group)
*/
private final Set groups = new HashSet();
/**
* HashSet instance variable to hold all id of groups for this person.
*
* @see #getCompanies
* @see #add(Company)
*/
private final Set companies = new HashSet();
/**
* The map is used to store all attribute values depending on attribute
* names defined in {@link #AttrName}.
*
* @see #setAttrValue
* @see #updateAttrValue
* @see #AttrName
*/
private final Map attrValues = new HashMap();
/**
* The map is used to store information about updates on attribute values.
* This information is needed if the database must be updated.
*
* @see #updateAttrValue
* @see #commitAttrValuesInDB
* @see #AttrName
*/
private final Map attrUpdated = new HashMap();
/**
* The constructor creates a new instance of class {@link Person} and sets
* the {@link #key} and {@link #id}.
*
* @param _id id of the person to set
* @param _name name of the person to set
* @param _status status of the person to set
*/
private Person(final long _id,
final String _name,
final boolean _status)
{
super(_id, null, _name, _status);
}
/**
* Checks, if the given person is assigned to this user object. Here it is
* only tested if the person is the same as the user of the parameter.
*
* @param _person person to test
* @return true if the person is the same person as this person,
* otherwise false
*/
@Override
public boolean hasChildPerson(final Person _person)
{
return _person.getId() == getId();
}
/**
* Add a role to this person.
*
* @param _role role to add to this person
* @see #roles
*/
private void add(final Role _role)
{
this.roles.add(_role.getId());
}
/**
* Tests, if the given role is assigned to this person.
*
* @param _role role to test
* @return true
if role is assigned to this person, otherwise
* false
*/
public boolean isAssigned(final Role _role)
{
return this.roles.contains(_role.getId());
}
/**
* Add a role to this person.
*
* @param _group group to add to this person
* @see #groups
*/
private void add(final Group _group)
{
this.groups.add(_group.getId());
}
/**
* Tests, if the given group is assigned to this person.
*
* @param _group group to test
* @return true
if group is assigned to this person, otherwise
* false
*/
public boolean isAssigned(final Group _group)
{
return this.groups.contains(_group.getId());
}
/**
* Add a role to this person.
*
* @param _group group to add to this person
* @see #groups
*/
private void add(final Company _group)
{
this.companies.add(_group.getId());
}
/**
* Tests, if the given group is assigned to this person.
*
* @param _company Company to test
* @return true
if group is assigned to this person, otherwise
* false
*/
public boolean isAssigned(final Company _company)
{
return this.companies.contains(_company.getId());
}
/**
* All assigned roles in {@link #roles} and groups in {@link #groups} are
* removed in the cache from this person instance. This is needed if the
* person assignments are rebuild (e.g. from a login servlet).
*/
public void cleanUp()
{
this.roles.clear();
this.groups.clear();
this.companies.clear();
}
/**
* The method sets the attribute values in the cache for given attribute
* name to given new attribute value.
*
* @param _attrName name of attribute to set
* @param _value new value to set
* @see #attrValues
*/
private void setAttrValue(final AttrName _attrName,
final String _value)
{
synchronized (this.attrValues) {
this.attrValues.put(_attrName, _value);
}
}
/**
* Returns for given attribute name the value in the cache.
*
* @param _attrName name of attribute for which the value must returned
* @return attribute value of given attribute name
*/
public String getAttrValue(final AttrName _attrName)
{
return this.attrValues.get(_attrName);
}
/**
* @return attribute value of first name
*/
public String getFirstName()
{
return this.attrValues.get(Person.AttrName.FIRSTNAME);
}
/**
* @return attribute value of last name
*/
public String getLastName()
{
return this.attrValues.get(Person.AttrName.LASTNAME);
}
/**
* Method to get the Locale of this Person. Default is the "English" Locale.
*
* @return Locale of this Person
*/
public Locale getLocale()
{
final Locale ret;
if (this.attrValues.get(Person.AttrName.LOCALE) != null) {
final String localeStr = this.attrValues.get(Person.AttrName.LOCALE);
final String[] countries = localeStr.split("_");
if (countries.length == 2) {
ret = new Locale(countries[0], countries[1]);
} else if (countries.length == 3) {
ret = new Locale(countries[0], countries[1], countries[2]);
} else {
ret = new Locale(localeStr);
}
} else {
ret = Locale.ENGLISH;
}
return ret;
}
/**
* Method to get the Language of the UserInterface for this Person. Default
* is english.
*
* @return iso code of a language
*/
public String getLanguage()
{
return this.attrValues.get(Person.AttrName.LANGUAGE) != null
? this.attrValues.get(Person.AttrName.LANGUAGE)
: Locale.ENGLISH.getISO3Language();
}
/**
* Method to get the Timezone of this Person. Default is the "UTC" Timezone.
*
* @return Timezone of this Person
*/
public DateTimeZone getTimeZone()
{
return this.attrValues.get(Person.AttrName.TIMZONE) != null
? DateTimeZone.forID(this.attrValues.get(Person.AttrName.TIMZONE))
: DateTimeZone.UTC;
}
/**
* Method to get the Chronology of this Person. Default is the "ISO8601"
* Chronology.
*
* @return Chronology of this Person
*/
public Chronology getChronology()
{
return getChronologyType().getInstance(getTimeZone());
}
/**
* Method to get the ChronologyType of this Person. Default is the "ISO8601"
* ChronologyType.
*
* @return ChronologyType of this Person
*/
public ChronologyType getChronologyType()
{
final String chronoKey = this.attrValues.get(Person.AttrName.CHRONOLOGY);
final ChronologyType chronoType;
if (chronoKey != null) {
chronoType = ChronologyType.getByKey(chronoKey);
} else {
chronoType = ChronologyType.ISO8601;
}
return chronoType;
}
/**
* Updates a value for an attribute in the cache and marks then as modified.
* Only after calling method {@link #commitAttrValuesInDB} the updated
* attribute value is stored in the database!
*
* @param _attrName name of attribute to update
* @param _value new value to set directly
*/
public void updateAttrValue(final AttrName _attrName,
final String _value)
{
this.updateAttrValue(_attrName, _value, _value);
}
/**
* Updates a value for an attribute in the cache and marks then as modified.
* Only after calling method {@link #commitAttrValuesInDB} the updated
* attribute value is stored in the database!
*
* @param _attrName name of attribute to update
* @param _value new value to set directly
* @param _updateValue new value to be set in the database
* @see #attrUpdated
* @see #attrValues
*/
public void updateAttrValue(final AttrName _attrName,
final String _value,
final String _updateValue)
{
synchronized (this.attrUpdated) {
synchronized (this.attrValues) {
this.attrValues.put(_attrName, _value);
}
this.attrUpdated.put(_attrName, _updateValue);
}
}
/**
* Commits update attribute defined in {@link #attrUpdated} with method
* {@link #updateAttrValue} to the database. After database update,
* {@link #attrUpdated} is cleared.
*
* @throws EFapsException on error
* @see #attrUpdated
* @see #attrValues
* @see #updateAttrValue
*
*/
public void commitAttrValuesInDB()
throws EFapsException
{
synchronized (this.attrUpdated) {
if (this.attrUpdated.size() > 0) {
ConnectionResource rsrc = null;
try {
final Context context = Context.getThreadContext();
rsrc = context.getConnectionResource();
final StringBuilder cmd = new StringBuilder();
PreparedStatement stmt = null;
try {
cmd.append("update T_USERPERSON set ");
boolean first = true;
for (final AttrName attrName : this.attrUpdated.keySet()) {
if (first) {
first = false;
} else {
cmd.append(",");
}
cmd.append(attrName.sqlColumn).append("=?");
}
cmd.append(" where ID=").append(getId());
stmt = rsrc.getConnection().prepareStatement(cmd.toString());
int col = 1;
for (final AttrName attrName : this.attrUpdated.keySet()) {
final String tmp = this.attrUpdated.get(attrName);
if (attrName.integer) {
stmt.setInt(col, tmp == null ? 0 : Integer.parseInt(tmp.trim()));
} else {
stmt.setString(col, tmp == null ? null : tmp.trim());
}
col++;
}
final int rows = stmt.executeUpdate();
if (rows == 0) {
Person.LOG.error("could not update '" + cmd.toString() + "' person with user name '"
+ getName() + "' (id = " + getId() + ")");
throw new EFapsException(Person.class, "commitAttrValuesInDB.NotUpdated", cmd.toString(),
getName(), getId());
}
// TODO: update modified date
} catch (final SQLException e) {
Person.LOG.error("could not update '" + cmd.toString() + "' person with user name '" + getName()
+ "' (id = " + getId() + ")", e);
throw new EFapsException(Person.class, "commitAttrValuesInDB.SQLException", e, cmd.toString(),
getName(), getId());
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
throw new EFapsException(Person.class, "commitAttrValuesInDB.SQLException", e, cmd
.toString(), getName(), getId());
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
this.attrUpdated.clear();
}
}
}
/**
* The instance method checks if the given password is the same password as
* the password in the database.
*
* @param _passwd password to check for this person
* @return true if password is correct, otherwise false
* @throws EFapsException if query for the password check failed
*/
public boolean checkPassword(final String _passwd)
throws EFapsException
{
boolean ret = false;
final PrintQuery query = new PrintQuery(CIAdminUser.Person.getType(), getId());
query.addAttribute(CIAdminUser.Person.Password,
CIAdminUser.Person.LastLogin,
CIAdminUser.Person.LoginTry,
CIAdminUser.Person.LoginTriesCounter,
CIAdminUser.Person.Status);
if (query.execute()) {
final PasswordStore pwd = query.getAttribute(CIAdminUser.Person.Password);
if (pwd.checkCurrent(_passwd)) {
ret = query.getAttribute(CIAdminUser.Person.Status);
} else {
setFalseLogin(query.getAttribute(CIAdminUser.Person.LoginTry),
query.getAttribute(CIAdminUser.Person.LoginTriesCounter));
}
}
return ret;
}
/**
* Method that sets the time and the number of failed logins.
*
* @param _logintry time of the false Login
* @param _count number of tries
* @throws EFapsException on error
*/
private void setFalseLogin(final DateTime _logintry,
final int _count)
throws EFapsException
{
if (_count > 0) {
final Timestamp now = DateTimeUtil.getCurrentTimeFromDB();
final SystemConfiguration kernelConfig = EFapsSystemConfiguration.KERNEL.get();
// Admin_User_LoginTimeBeforeRetry
final int dif = kernelConfig.getAttributeValueAsInteger("LoginTimeBeforeRetry");
// Admin_User_LoginTries
final int maxtries = kernelConfig.getAttributeValueAsInteger("LoginTries");
final int count = _count + 1;
if (dif > 0 && (now.getTime() - _logintry.getMillis()) > dif * 60 * 1000) {
updateFalseLoginDB(1);
} else {
updateFalseLoginDB(count);
}
if (maxtries > 0 && count > maxtries && getStatus()) {
setStatusInDB(false);
}
} else {
updateFalseLoginDB(1);
}
}
/**
* Method to set the number of false Login tries in the eFaps-DataBase.
*
* @param _tries number or tries
* @throws EFapsException on error
*/
private void updateFalseLoginDB(final int _tries)
throws EFapsException
{
ConnectionResource rsrc = null;
try {
final Context context = Context.getThreadContext();
rsrc = context.getConnectionResource();
Statement stmt = null;
final StringBuilder cmd = new StringBuilder();
try {
cmd.append("update T_USERPERSON ").append("set LOGINTRY=").append(
Context.getDbType().getCurrentTimeStamp()).append(", LOGINTRIES=").append(_tries)
.append(" where ID=").append(getId());
stmt = rsrc.getConnection().createStatement();
final int rows = stmt.executeUpdate(cmd.toString());
if (rows == 0) {
Person.LOG.error("could not execute '" + cmd.toString()
+ "' to update last login information for person '" + toString() + "'");
throw new EFapsException(getClass(), "updateLastLogin.NotUpdated", cmd.toString(), getName());
}
} catch (final SQLException e) {
Person.LOG.error("could not execute '" + cmd.toString()
+ "' to update last login information for person '" + toString() + "'", e);
throw new EFapsException(getClass(), "updateLastLogin.SQLException", e, cmd.toString(), getName());
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
throw new EFapsException(getClass(), "updateLastLogin.SQLException", e, cmd.toString(), getName());
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
}
/**
* The instance method sets the new password for the current context user.
* Before the new password is set, some checks are made.
*
* @param _newPasswd new Password to set
* @throws EFapsException on error
* @return true if password set, else false
*/
public Status setPassword(final String _newPasswd)
throws EFapsException
{
final Type type = CIAdminUser.Person.getType();
if (_newPasswd.length() == 0) {
throw new EFapsException(getClass(), "PassWordLength", 1, _newPasswd.length());
}
final Update update = new Update(type, "" + getId());
final Status status = update.add(CIAdminUser.Person.Password, _newPasswd);
if (status.isOk()) {
update.execute();
update.close();
} else {
Person.LOG.error("Password could not be set by the Update, due to restrictions " + "e.g. length???");
throw new EFapsException(getClass(), "TODO");
}
return status;
}
/**
* The instance method reads all information from the database.
*
* @throws EFapsException on error
* @see #readFromDBAttributes()
*/
protected void readFromDB()
throws EFapsException
{
readFromDBAttributes();
this.roles.clear();
for (final Role role : getRolesFromDB()) {
add(role);
}
this.groups.clear();
for (final Group group : getGroupsFromDB(null)) {
add(group);
}
this.companies.clear();
for (final Company company : getCompaniesFromDB(null)) {
add(company);
}
}
/**
* All attributes from this person are read from the database.
*
* @throws EFapsException if the attributes for this person could not be
* read
*/
private void readFromDBAttributes()
throws EFapsException
{
ConnectionResource rsrc = null;
try {
rsrc = Context.getThreadContext().getConnectionResource();
Statement stmt = null;
try {
stmt = rsrc.getConnection().createStatement();
final StringBuilder cmd = new StringBuilder("select ");
for (final AttrName attrName : Person.AttrName.values()) {
cmd.append(attrName.sqlColumn).append(",");
}
cmd.append("0 as DUMMY ").append("from V_USERPERSON ").append("where V_USERPERSON.ID=").append(getId());
final ResultSet resultset = stmt.executeQuery(cmd.toString());
if (resultset.next()) {
for (final AttrName attrName : Person.AttrName.values()) {
final String tmp = resultset.getString(attrName.sqlColumn);
setAttrValue(attrName, tmp == null ? null : tmp.trim());
}
}
resultset.close();
} catch (final SQLException e) {
Person.LOG.error("read attributes for person with SQL statement is not " + "possible", e);
throw new EFapsException(Person.class, "readFromDBAttributes.SQLException", e, getName(), getId());
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
Person.LOG.error("close of SQL statement is not possible", e);
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
}
/**
* The method reads directly from the database all stored companies for this
* person. The found roles are returned as instance of {@link Set}.
*
* @param _jaasSystem JAAS system for which the roles must get from eFaps
* (if value is null
, all companies independent from
* the related JAAS system are returned)
* @return set of all found companies for given JAAS system
* @throws EFapsException on error
*/
public Set getCompaniesFromDB(final JAASSystem _jaasSystem)
throws EFapsException
{
final Set ret = new HashSet();
ConnectionResource rsrc = null;
try {
rsrc = Context.getThreadContext().getConnectionResource();
Statement stmt = null;
try {
final StringBuilder cmd = new StringBuilder();
cmd.append("select ").append("USERABSTRACTTO ").append("from V_USERPERSON2COMPANY ")
.append("where USERABSTRACTFROM=").append(getId());
if (_jaasSystem != null) {
cmd.append(" and JAASSYSID=").append(_jaasSystem.getId());
}
stmt = rsrc.getConnection().createStatement();
final ResultSet resultset = stmt.executeQuery(cmd.toString());
while (resultset.next()) {
ret.add(Company.get(resultset.getLong(1)));
}
resultset.close();
} catch (final SQLException e) {
throw new EFapsException(getClass(), "getCompaniesFromDB.SQLException", e, getName());
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
throw new EFapsException(getClass(), "getCompaniesFromDB.SQLException", e, getName());
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
return ret;
}
/**
* The depending roles for the user are set for the given JAAS system. All
* roles are added to the loaded roles in the cache of this person.
*
* @param _jaasSystem JAAS system for which the roles are set
* @param _companies set of company to set for the JAAS system
* @throws EFapsException from calling methods
*/
public void setCompanies(final JAASSystem _jaasSystem,
final Set _companies)
throws EFapsException
{
if (_jaasSystem == null) {
throw new EFapsException(getClass(), "setRoles.nojaasSystem", getName());
}
if (_companies == null) {
throw new EFapsException(getClass(), "setRoles.noRoles", getName());
}
for (final Company role : _companies) {
add(role);
}
}
/**
* The method reads directly from the database all stores roles for the this
* person. The found roles are returned as instance of {@link java.util.Set}
* .
*
* @return set of all found roles for all JAAS systems
* @see #getRolesFromDB(JAASSystem);
* @throws EFapsException on error
*/
public Set getRolesFromDB()
throws EFapsException
{
return getRolesFromDB((JAASSystem) null);
}
/**
* The method reads directly from the database all stores roles for the this
* person. The found roles are returned as instance of {@link java.util.Set}
* .
*
* @param _jaasSystem JAAS system for which the roles are searched in eFaps
* (if value is null
, all roles independent from the
* related JAAS system are returned)
* @return set of all found roles for given JAAS system
* @throws EFapsException on error
*/
public Set getRolesFromDB(final JAASSystem _jaasSystem)
throws EFapsException
{
final Set ret = new HashSet();
ConnectionResource rsrc = null;
try {
rsrc = Context.getThreadContext().getConnectionResource();
Statement stmt = null;
try {
final StringBuilder cmd = new StringBuilder();
cmd.append("select ").append("USERABSTRACTTO ").append("from V_USERPERSON2ROLE ").append(
"where USERABSTRACTFROM=").append(getId());
if (_jaasSystem != null) {
cmd.append(" and JAASSYSID=").append(_jaasSystem.getId());
}
stmt = rsrc.getConnection().createStatement();
final ResultSet resultset = stmt.executeQuery(cmd.toString());
final Set roleNames = AppAccessHandler.getLoginRoles();
while (resultset.next()) {
final Role role = Role.get(resultset.getLong(1));
if (!AppAccessHandler.excludeMode()
|| (AppAccessHandler.excludeMode() && roleNames.contains(role.getName()))) {
ret.add(role);
}
}
resultset.close();
} catch (final SQLException e) {
throw new EFapsException(getClass(), "getRolesFromDB.SQLException", e, getName());
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
throw new EFapsException(getClass(), "getRolesFromDB.SQLException", e, getName());
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
return ret;
}
/**
* The depending roles for the user are set for the given JAAS system. All
* roles are added to the loaded roles in the cache of this person.
*
* @param _jaasSystem JAAS system for which the roles are set
* @param _roles set of roles to set for the JAAS system
* @see #assignRoleInDb
* @see #unassignRoleInDb
* @throws EFapsException from calling methods
*/
public void setRoles(final JAASSystem _jaasSystem,
final Set _roles)
throws EFapsException
{
if (_jaasSystem == null) {
throw new EFapsException(getClass(), "setRoles.nojaasSystem", getName());
}
if (_roles == null) {
throw new EFapsException(getClass(), "setRoles.noRoles", getName());
}
for (final Role role : _roles) {
add(role);
}
// current roles
final Set rolesInDb = getRolesFromDB(_jaasSystem);
// compare new roles with current roles (add missing roles)
for (final Role role : _roles) {
if (!rolesInDb.contains(role)) {
assignRoleInDb(_jaasSystem, role);
}
}
// compare current roles with new roles (remove roles which are to much)
for (final Role role : rolesInDb) {
if (!_roles.contains(role)) {
unassignRoleInDb(_jaasSystem, role);
}
}
}
/**
* For this person, a role is assigned for the given JAAS system.
*
* @param _jaasSystem JAAS system for which the role is assigned
* @param _role role to assign
* @see AbstractUserObject#assignToUserObjectInDb(Type, JAASSystem,
* AbstractUserObject)
* @throws EFapsException on error
*/
public void assignRoleInDb(final JAASSystem _jaasSystem,
final Role _role)
throws EFapsException
{
assignToUserObjectInDb(CIAdminUser.Person2Role.getType(), _jaasSystem, _role);
}
/**
* The given role is unassigned for the given JAAS system from this person.
*
* @param _jaasSystem JAAS system for which the role is assigned
* @param _role role to unassign
* @see AbstractUserObject#unassignFromUserObjectInDb(Type, JAASSystem,
* AbstractUserObject)
* @throws EFapsException on error
*/
public void unassignRoleInDb(final JAASSystem _jaasSystem,
final Role _role)
throws EFapsException
{
unassignFromUserObjectInDb(CIAdminUser.Person2Role.getType(), _jaasSystem, _role);
}
/**
* The method reads directly from eFaps all stored groups for the this
* person. The found groups are returned as instance of {@link Set}.
*
* @param _jaasSystem JAAS system for which the groups must fetched from
* eFaps (if value is null
, all groups independent
* from the related JAAS system are returned)
* @throws EFapsException on error
* @return set of all found groups for given JAAS system
*/
public Set getGroupsFromDB(final JAASSystem _jaasSystem)
throws EFapsException
{
final Set ret = new HashSet();
ConnectionResource rsrc = null;
try {
rsrc = Context.getThreadContext().getConnectionResource();
Statement stmt = null;
try {
final StringBuilder cmd = new StringBuilder();
cmd.append("select ").append("USERABSTRACTTO ").append("from V_USERPERSON2GROUP ").append(
"where USERABSTRACTFROM=").append(getId());
if (_jaasSystem != null) {
cmd.append(" and JAASSYSID=").append(_jaasSystem.getId());
}
stmt = rsrc.getConnection().createStatement();
final ResultSet resultset = stmt.executeQuery(cmd.toString());
while (resultset.next()) {
ret.add(Group.get(resultset.getLong(1)));
}
resultset.close();
} catch (final SQLException e) {
throw new EFapsException(getClass(), "getGroupsFromDB.SQLException", e, getName());
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
throw new EFapsException(getClass(), "getGroupsFromDB.SQLException", e, getName());
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
return ret;
}
/**
* The depending groups for the user are set for the given JAAS system. All
* groups are added to the loaded groups in the cache of this person.
*
* @param _jaasSystem JAAS system for which the roles are set
* @param _groups set of groups to set for the JAAS system
* @see #assignGroupInDb(JAASSystem, Group)
* @see #unassignGroupInDb(JAASSystem, Group)
* @throws EFapsException from calling methods
*/
public void setGroups(final JAASSystem _jaasSystem,
final Set _groups)
throws EFapsException
{
if (_jaasSystem == null) {
throw new EFapsException(getClass(), "setGroups.nojaasSystem", getName());
}
if (_groups == null) {
throw new EFapsException(getClass(), "setGroups.noGroups", getName());
}
for (final Group group : _groups) {
add(group);
}
// current groups
final Set groupsInDb = getGroupsFromDB(_jaasSystem);
// compare new roles with current groups (add missing groups)
for (final Group group : _groups) {
if (!groupsInDb.contains(group)) {
assignGroupInDb(_jaasSystem, group);
}
}
// compare current roles with new groups (remove groups which are to
// much)
for (final Group group : groupsInDb) {
if (!_groups.contains(group)) {
unassignGroupInDb(_jaasSystem, group);
}
}
}
/**
* For this person, a group is assigned for the given JAAS system.
*
* @param _jaasSystem JAAS system for which the group is assigned
* @param _group group to assign
* @throws EFapsException on error
* @see AbstractUserObject#assignToUserObjectInDb
*/
public void assignGroupInDb(final JAASSystem _jaasSystem,
final Group _group)
throws EFapsException
{
assignToUserObjectInDb(CIAdminUser.Person2Group.getType(), _jaasSystem, _group);
}
/**
* The given group is unassigned for the given JAAS system from this person.
*
* @param _jaasSystem JAAS system for which the role is assigned
* @param _group group to unassign
* @throws EFapsException on error
* @see AbstractUserObject#unassignFromUserObjectInDb
*/
public void unassignGroupInDb(final JAASSystem _jaasSystem,
final Group _group)
throws EFapsException
{
unassignFromUserObjectInDb(CIAdminUser.Person2Group.getType(), _jaasSystem, _group);
}
/**
* Update the last login date of this person to current time stamp.
*
* @throws EFapsException if the last login information could not be updated
*/
public void updateLastLogin()
throws EFapsException
{
ConnectionResource rsrc = null;
try {
final Context context = Context.getThreadContext();
rsrc = context.getConnectionResource();
Statement stmt = null;
final StringBuilder cmd = new StringBuilder();
try {
cmd.append("update T_USERPERSON ").append("set LASTLOGIN=").append(
Context.getDbType().getCurrentTimeStamp()).append(", LOGINTRIES=0 ")
.append("where ID=").append(getId());
stmt = rsrc.getConnection().createStatement();
final int rows = stmt.executeUpdate(cmd.toString());
if (rows == 0) {
Person.LOG.error("could not execute '" + cmd.toString()
+ "' to update last login information for person '" + toString() + "'");
throw new EFapsException(getClass(), "updateLastLogin.NotUpdated", cmd.toString(), getName());
}
} catch (final SQLException e) {
Person.LOG.error("could not execute '" + cmd.toString()
+ "' to update last login information for person '" + toString() + "'", e);
throw new EFapsException(getClass(), "updateLastLogin.SQLException", e, cmd.toString(), getName());
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
throw new EFapsException(getClass(), "updateLastLogin.SQLException", e, cmd.toString(), getName());
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
}
/**
* This is the getter method for instance variable {@link #roles}.
*
* @return the value of the instance variable {@link #roles}.
* @see #roles
*/
public Set getRoles()
{
return this.roles;
}
/**
* This is the getter method for instance variable {@link #groups}.
*
* @return the value of the instance variable {@link #groups}.
* @see #groups
*/
public Set getGroups()
{
return this.groups;
}
/**
* Getter method for instance variable {@link #companies}.
*
* @return value of instance variable {@link #companies}
*/
public Set getCompanies()
{
return this.companies;
}
/**
* Method to initialize the Cache of this CacheObjectInterface.
*/
public static void initialize()
{
Person.CACHE.initialize(Person.class);
}
/**
* Returns a string representation of this person.
*
* @return string representation of this person
*/
@Override
public String toString()
{
return new ToStringBuilder(this)
.appendSuper(super.toString())
.append("attrValues", this.attrValues)
.append("roles", this.roles)
.append("groups", this.groups)
.append("companies", this.companies)
.toString();
}
/**
* Returns for given parameter _id the instance of class
* {@link Person}.
*
* @param _id id to search in the cache
* @throws EFapsException on error
* @return instance of class {@link Person}
* @see #CACHE
* @see #getFromDB
*/
public static Person get(final long _id)
throws EFapsException
{
Person ret = Person.getCache().get(_id);
if (ret == null) {
ret = Person.getFromDB("select "
+ "V_USERPERSON.ID,"
+ "V_USERPERSON.NAME, "
+ "STATUS "
+ "from V_USERPERSON "
+ "where V_USERPERSON.ID=" + _id);
}
return ret;
}
/**
* Returns for given parameter _name the instance of class
* {@link Person}.
*
* @param _name name to search in the cache
* @throws EFapsException on error
* @return instance of class {@link Person}
* @see #CACHE
* @see #getFromDB
*/
public static Person get(final String _name)
throws EFapsException
{
Person ret = Person.getCache().get(_name);
if (ret == null) {
ret = Person.getFromDB("select "
+ "V_USERPERSON.ID,"
+ "V_USERPERSON.NAME, "
+ "STATUS "
+ "from V_USERPERSON "
+ "where V_USERPERSON.NAME='" + _name + "'");
}
return ret;
}
/**
* The static method reads with the help of given sql statement the id and
* name of the person, creates a new person instance, adds the instance to
* the cache and read all related information for the person instance with
* {@link #readFromDB}.
*
* @param _sql sql statement used to get the person from database
* @throws EFapsException on error
* @return person instance with the found values from database
* @see #get(long)
* @see #get(String)
* @see #readFromDB
*/
private static Person getFromDB(final String _sql)
throws EFapsException
{
Person ret = null;
ConnectionResource rsrc = null;
try {
rsrc = Context.getThreadContext().getConnectionResource();
Statement stmt = null;
try {
stmt = rsrc.getConnection().createStatement();
final ResultSet resultset = stmt.executeQuery(_sql);
if (resultset.next()) {
final long id = resultset.getLong(1);
final String name = resultset.getString(2);
final boolean status = resultset.getBoolean(3);
ret = new Person(id, name.trim(), status);
Person.getCache().addObject(ret);
}
resultset.close();
} catch (final SQLException e) {
Person.LOG.error("search for person with SQL statement '" + _sql + "' is not possible", e);
throw new EFapsException(Person.class, "getFromDB.SQLException", e, _sql);
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
Person.LOG.error("close of SQL statement is not possible", e);
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
if (ret != null) {
ret.readFromDB();
}
return ret;
}
/**
* Returns for given parameter _jaasKey the instance of class
* {@link Person}. The parameter _jaasKey is the name of the person
* used in the given JAAS system for the person.
*
* @param _jaasSystem JAAS system for which the JAAS key is named
* @param _jaasKey key in the foreign JAAS system for which the person is
* searched
* @throws EFapsException on error
* @return instance of class {@link Person}, or null
if person
* is not found
* @see #get(long)
*/
public static Person getWithJAASKey(final JAASSystem _jaasSystem,
final String _jaasKey)
throws EFapsException
{
long personId = 0;
ConnectionResource rsrc = null;
try {
rsrc = Context.getThreadContext().getConnectionResource();
Statement stmt = null;
try {
final StringBuilder cmd = new StringBuilder();
cmd.append("select ").append("ID ").append("from V_USERPERSONJASSKEY ").append("where JAASKEY='")
.append(_jaasKey).append("' ").append("and JAASSYSID=").append(_jaasSystem.getId());
stmt = rsrc.getConnection().createStatement();
final ResultSet resultset = stmt.executeQuery(cmd.toString());
if (resultset.next()) {
personId = resultset.getLong(1);
}
resultset.close();
} catch (final SQLException e) {
Person.LOG.error("search for person for JAAS system '" + _jaasSystem.getName() + "' with key '"
+ _jaasKey + "' is not possible", e);
throw new EFapsException(Person.class, "getWithJAASKey.SQLException", e, _jaasSystem.getName(),
_jaasKey);
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
throw new EFapsException(Person.class, "getWithJAASKey.SQLException", e, _jaasSystem.getName(),
_jaasKey);
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
return Person.get(personId);
}
/**
* @param _jaasSystem JAAS system which want to create a new person in eFaps
* @param _jaasKey key of the person in the JAAS system
* @param _userName name in the eFaps system (used as proposal, it's tested
* for uniqueness and changed if needed!)
* @return new created person
* @throws EFapsException if person could not be created in eFaps
* @see #assignToJAASSystem
*/
public static Person createPerson(final JAASSystem _jaasSystem,
final String _jaasKey,
final String _userName)
throws EFapsException
{
long persId = 0;
final Type persType = CIAdminUser.Person.getType();
ConnectionResource rsrc = null;
try {
final Context context = Context.getThreadContext();
rsrc = context.getConnectionResource();
PreparedStatement stmt = null;
try {
StringBuilder cmd = new StringBuilder();
// TODO: check for uniqueness!
// TODO: hard coded mofifier and creator
if (Context.getDbType().supportsGetGeneratedKeys()) {
cmd.append("insert into ").append(persType.getMainTable().getSqlTable()).append(
"(TYPEID,NAME,CREATOR,CREATED,MODIFIER,MODIFIED) ").append("values (");
} else {
persId = Context.getDbType().getNewId(rsrc.getConnection(), persType.getMainTable().getSqlTable(),
"ID");
cmd.append("insert into ").append(persType.getMainTable().getSqlTable()).append(
"(ID,TYPEID,NAME,CREATOR,CREATED,MODIFIER,MODIFIED) ").append("values (").append(
persId).append(",");
}
cmd.append(persType.getId()).append(",").append("'").append(_userName).append("',").append(
context.getPersonId()).append(",").append(Context.getDbType().getCurrentTimeStamp())
.append(",").append(context.getPersonId()).append(",").append(
Context.getDbType().getCurrentTimeStamp()).append(")");
if (persId == 0) {
stmt = rsrc.getConnection().prepareStatement(cmd.toString(), new String[] { "ID" });
} else {
stmt = rsrc.getConnection().prepareStatement(cmd.toString());
}
int rows = stmt.executeUpdate();
if (rows == 0) {
Person.LOG.error("could not execute '" + cmd.toString() + "' for JAAS system '"
+ _jaasSystem.getName() + "' person with key '" + _jaasKey
+ "' and user name '" + _userName + "'");
throw new EFapsException(Person.class, "createPerson.NotInserted", cmd.toString(), _jaasSystem
.getName(), _jaasKey, _userName);
}
if (persId == 0) {
final ResultSet resultset = stmt.getGeneratedKeys();
if (resultset.next()) {
persId = resultset.getLong(1);
}
}
stmt.close();
cmd = new StringBuilder();
cmd.append("insert into T_USERPERSON").append("(ID,FIRSTNAME,LASTNAME,EMAIL) ").append("values (")
.append(persId).append(",'-','-','-')");
stmt = rsrc.getConnection().prepareStatement(cmd.toString());
rows = stmt.executeUpdate();
if (rows == 0) {
Person.LOG.error("could not execute '" + cmd.toString() + "' for JAAS system '"
+ _jaasSystem.getName()
+ "' person with key '" + _jaasKey + "' and user name '" + _userName + "'");
throw new EFapsException(Person.class, "createPerson.NotInserted", cmd.toString(), _jaasSystem
.getName(), _jaasKey, _userName);
}
} catch (final SQLException e) {
Person.LOG.error("could not create for JAAS system '" + _jaasSystem.getName() + "' person with key '"
+ _jaasKey + "' and user name '" + _userName + "'", e);
throw new EFapsException(Person.class, "createPerson.SQLException", e, _jaasSystem.getName(), _jaasKey,
_userName);
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (final SQLException e) {
throw new EFapsException(Person.class, "createPerson.SQLException", e, _jaasSystem.getName(),
_jaasKey);
}
}
rsrc.commit();
} finally {
if ((rsrc != null) && rsrc.isOpened()) {
rsrc.abort();
}
}
final Person ret = Person.get(persId);
ret.assignToJAASSystem(_jaasSystem, _jaasKey);
return ret;
}
/**
* Static getter method for the type hashtable {@link #CACHE}.
*
* @return value of static variable {@link #CACHE}
*/
public static AbstractCache getCache()
{
return Person.CACHE;
}
/**
* This Class is used to store a Person in the Cache.
*/
private static final class PersonCache
extends AbstractCache
implements Serializable
{
/**
* Needed for serialization.
*/
private static final long serialVersionUID = 1L;
/**
* Method is overwritten because the map is stored in the context.
*
* @return Map by id
*/
@Override
@SuppressWarnings("unchecked")
public Map getCache4Id()
{
Map map = null;
try {
map = (PersonMap) Context.getThreadContext().getSessionAttribute(Person.CACHE4IDKEY);
if (map == null) {
map = new PersonMap();
Context.getThreadContext().setSessionAttribute(Person.CACHE4IDKEY, map);
}
} catch (final EFapsException e) {
Person.LOG.error("could not read or set a SessionAttribute for " + Person.CACHE4IDKEY, e);
}
return map;
}
/**
* Method is overwritten because the map is stored in the context.
*
* @return Map by name
*/
@Override
@SuppressWarnings("unchecked")
protected Map getCache4Name()
{
Map map = null;
try {
map = (Map) Context.getThreadContext().getSessionAttribute(Person.CACHE4NAMEKEY);
if (map == null) {
map = new PersonMap();
Context.getThreadContext().setSessionAttribute(Person.CACHE4NAMEKEY, map);
}
} catch (final EFapsException e) {
Person.LOG.error("could not read or set a SessionAttribute for the " + Person.CACHE4NAMEKEY, e);
}
return map;
}
/**
* Method is overwritten because the map is stored in the context.
*
* {@inheritDoc}
*/
@Override
protected void setCache4Id(final Map _cache4Id)
{
try {
Context.getThreadContext().setSessionAttribute(Person.CACHE4IDKEY, _cache4Id);
} catch (final EFapsException e) {
Person.LOG.error("could set a SessionAttribute for the " + Person.CACHE4IDKEY, e);
}
}
/**
* Method is overwritten because the map is stored in the context.
*
* {@inheritDoc}
*/
@Override
protected void setCache4Name(final Map _cache4Name)
{
try {
Context.getThreadContext().setSessionAttribute(Person.CACHE4NAMEKEY, _cache4Name);
} catch (final EFapsException e) {
Person.LOG.error("could not set a SessionAttribute for the " + Person.CACHE4NAMEKEY, e);
}
}
/**
* {@inheritDoc}
*/
@Override
protected Map getNewCache4Id()
{
return new PersonMap();
}
/**
* {@inheritDoc}
*/
@Override
protected Map getNewCache4Name()
{
return new PersonMap();
}
/**
* Method must not be overwritten (used), because the person cache is
* stored inside the session and is growing dynamically during the
* session up to a maximum value defined by a SystemAttribute.
*
* @param _cache4Id cache 4 id
* @param _cache4Name cache 4 name
* @param _cache4UUID not used
* @throws CacheReloadException on error
*/
@Override
protected void readCache(final Map _cache4Id,
final Map _cache4Name,
final Map _cache4UUID)
throws CacheReloadException
{
try {
Context.getThreadContext().setSessionAttribute(Person.CACHE4NAMEKEY, _cache4Name);
Context.getThreadContext().setSessionAttribute(Person.CACHE4IDKEY, _cache4Id);
} catch (final EFapsException e) {
throw new CacheReloadException("error in reading cache for Person", e);
}
}
/**
* Implementation of a LinkedHashMap with limited capacity.
*/
public class PersonMap extends LinkedHashMap
{
/**
* Needed for serialization.
*/
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(final Entry _eldest)
{
int size = 0;
final SystemConfiguration config = EFapsSystemConfiguration.KERNEL.get();
if (config != null) {
try {
size = EFapsSystemConfiguration.KERNEL.get().getAttributeValueAsInteger("Cache4PersonMaxSize");
} catch (final EFapsException e) {
Person.LOG.debug("error", e);
}
}
if (size < 1) {
size = 100;
}
return size() > size;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy