com.flexive.core.security.UserTicketImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.flexive.core.security.UserTicketImpl.java

Source

/***************************************************************
 *  This file is part of the [fleXive](R) framework.
 *
 *  Copyright (c) 1999-2014
 *  UCS - unique computing solutions gmbh (http://www.ucs.at)
 *  All rights reserved
 *
 *  The [fleXive](R) project is free software; you can redistribute
 *  it and/or modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 or higher as published by the Free Software Foundation.
 *
 *  The GNU Lesser General Public License can be found at
 *  http://www.gnu.org/licenses/lgpl.html.
 *  A copy is found in the textfile LGPL.txt and important notices to the
 *  license from the author are found in LICENSE.txt distributed with
 *  these libraries.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  For further information about UCS - unique computing solutions gmbh,
 *  please see the company website: http://www.ucs.at
 *
 *  For further information about [fleXive](R), please see the
 *  project website: http://www.flexive.org
 *
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package com.flexive.core.security;

import com.flexive.shared.*;
import com.flexive.shared.configuration.SystemParameters;
import com.flexive.shared.content.FxPK;
import com.flexive.shared.exceptions.FxApplicationException;
import com.flexive.shared.exceptions.FxNotFoundException;
import com.flexive.shared.interfaces.AccountEngine;
import com.flexive.shared.interfaces.UserConfigurationEngine;
import com.flexive.shared.security.*;
import com.flexive.shared.structure.FxEnvironment;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.Serializable;
import java.util.*;

/**
 * Implementation of the interface UserTicket.<br>
 * The UserTicket caches informations about a user.
 *
 * @author Gregor Schober (gregor.schober@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
 */
public class UserTicketImpl implements UserTicket, Serializable {
    private static final long serialVersionUID = -8780256553138578843L;
    private static final Log LOG = LogFactory.getLog(UserTicketImpl.class);

    //private static final Log LOG = LogFactory.getLog(UserTicketImpl.class);
    private final String userName;
    private final String loginName;
    private final long userId;
    private final boolean multiLogin;
    private final long mandator;
    private final String applicationId;
    private final boolean webDav;
    private FxLanguage language;

    private boolean globalSupervisor;
    private boolean mandatorSupervisor;
    private long[] groups;
    private Role[] roles;
    private boolean dirty;
    private ACLAssignment[] assignments;
    private long creationTime;
    private FxPK contactData;
    private String remoteHost;

    private static volatile long STRUCTURE_TIMESTAMP = -1;
    private static ACLAssignment[] guestACLAssignments = null;
    private static Role[] guestRoles = null;
    private static long[] guestGroups = null;
    private static FxPK guestContactData = new FxPK(1); // will be updated when the environment is available
    private long failedLoginAttempts = 0;
    private AuthenticationSource authenticationSource = AuthenticationSource.None;

    private String dateFormat, dateTimeFormat, timeFormat;
    private char decimalSeparator;
    private char groupingSeparator;
    private boolean useGroupingSeparator;

    /**
     * Returns a guest ticket, based on the request information data.
     * <p/>
     * The guest ticket always belong to the MANDATOR_PUBLIC.
     * <p/>
     *
     * @return the guest ticket
     */
    public static UserTicket getGuestTicket() {
        FxContext si = FxContext.get();
        if (CacheAdmin.isEnvironmentLoaded()) {
            final FxEnvironment environment = CacheAdmin.getEnvironment();
            if (environment.getTimeStamp() != STRUCTURE_TIMESTAMP) {
                synchronized (UserTicketImpl.class) {
                    if (environment.getTimeStamp() != STRUCTURE_TIMESTAMP) {
                        reloadGuestTicketAssignments(false);
                    }
                }
            }
        }
        synchronized (UserTicketImpl.class) {
            // Don't use the class lock for the entire method, because otherwise it could
            // deadlock when reloadGuestTicketAssignments is called from another thread (FX-435)
            return new UserTicketImpl(si.getApplicationId(), si.isWebDAV(), "GUEST", "GUEST", Account.USER_GUEST,
                    guestContactData, Mandator.MANDATOR_FLEXIVE, true, guestGroups, guestRoles, guestACLAssignments,
                    FxLanguage.DEFAULT, 0, AuthenticationSource.None, FxFormatUtils.DATE_STD,
                    FxFormatUtils.TIME_STD, FxFormatUtils.DATETIME_STD, FxFormatUtils.DECIMAL_SEP_STD,
                    FxFormatUtils.GROUPING_SEP_STD, FxFormatUtils.USE_GROUPING_STD);
        }
    }

    /**
     * (Re)load all assignments for the guest user ticket
     *
     * @param flagDirty flag the UserTicketStores guest ticket as dirty?
     */
    public static synchronized void reloadGuestTicketAssignments(boolean flagDirty) {
        try {
            if (CacheAdmin.isEnvironmentLoaded()) {
                STRUCTURE_TIMESTAMP = CacheAdmin.getEnvironment().getTimeStamp();
            }
            AccountEngine accountInterface = EJBLookup.getAccountEngine();
            final List<ACLAssignment> assignmentList = accountInterface.loadAccountAssignments(Account.USER_GUEST);
            guestACLAssignments = assignmentList.toArray(new ACLAssignment[assignmentList.size()]);
            final List<Role> roles = accountInterface.getRoles(Account.USER_GUEST, RoleLoadMode.ALL);
            guestRoles = roles.toArray(new Role[roles.size()]);
            final List<Long> groupList = FxSharedUtils
                    .getSelectableObjectIdList(accountInterface.getGroups(Account.USER_GUEST));
            guestGroups = ArrayUtils.toPrimitive(groupList.toArray(new Long[groupList.size()]));
            guestContactData = accountInterface.load(Account.USER_GUEST).getContactData();
            if (flagDirty)
                UserTicketStore.flagDirtyHavingUserId(Account.USER_GUEST);
        } catch (FxApplicationException e) {
            guestACLAssignments = null;
            LOG.error(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final boolean isInRole(Role role) {
        return isGlobalSupervisor() || roles != null && ArrayUtils.contains(roles, role);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getApplicationId() {
        return this.applicationId;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isInGroup(long group) {
        return ArrayUtils.contains(groups, group);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isInGroup(String group) {
        for (UserGroup check : CacheAdmin.getEnvironment().getUserGroups())
            if (check.getName().equalsIgnoreCase(group))
                return isInGroup(check.getId());
        return false;
    }

    /**
     * If true the ticket is dirty and needs to be synced with the database.
     *
     * @return true the ticket is dirty and needs to be synced with the database
     */
    public boolean isDirty() {
        return dirty;
    }

    /**
     * Sets the dirty flag.
     *
     * @param value true the ticket is dirty and needs to be synced with the database
     */
    public void setDirty(boolean value) {
        this.dirty = value;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isInGroups(int groups[]) {
        if (groups == null || groups.length == 0) {
            return true;
        }
        for (int group : groups) {
            if (!ArrayUtils.contains(this.groups, (long) group)) {
                return false;
            }
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isInAtLeastOneGroup(long[] groups) {
        if (groups == null || groups.length == 0) {
            return false;
        }
        for (long group : groups) {
            if (ArrayUtils.contains(this.groups, group)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if the user is assigned to at least one of the given ACLs.
     * <p/>
     * <p/>
     * Returns false if the acls parameter is null or empty
     *
     * @param acls the ACLs to check for
     * @return true if the user is a assigned to at least one of the given ACLs
     */
    public boolean hasAtLeastOneACL(long[] acls) {
        if (assignments == null || assignments.length == 0 || acls == null || acls.length == 0) {
            return false;
        }
        for (ACLAssignment aclData : assignments) {
            for (long acl : acls) {
                if (aclData.getAclId() == acl) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isGuest() {
        return (userId == Account.USER_GUEST);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getUserName() {
        return userName;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getLoginName() {
        return loginName;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getUserId() {
        if ( /*FxContext.get().getRunAsSystem() &&*/ FxContext.get().isExecutingRunOnceScripts()) {
            //            System.out.println("Executing run once scripts -> user id set to " + Account.USER_GLOBAL_SUPERVISOR);
            return Account.USER_GLOBAL_SUPERVISOR;
        } else
            return userId;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FxPK getContactData() {
        return contactData;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isMultiLogin() {
        return multiLogin;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isGlobalSupervisor() {
        return globalSupervisor;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isMandatorSupervisor() {
        return (mandatorSupervisor || globalSupervisor);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getMandatorId() {
        return this.mandator;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long[] getGroups() {
        return ArrayUtils.clone(this.groups);
    }

    /**
     * Constructor.
     *
     * @param applicationId the application id this ticket belongs to
     * @param acc           the account
     * @param groups        the groups
     * @param roles         the roles
     * @param aad           the acl assignemnts
     * @param language      the language
     * @param isWebDav      true if this is a webdav ticket
     */
    public UserTicketImpl(String applicationId, boolean isWebDav, Account acc, long[] groups, Role[] roles,
            ACLAssignment aad[], FxLanguage language) {
        this.userName = acc.getName();
        this.loginName = acc.getLoginName();
        this.userId = acc.getId();
        this.contactData = acc.getContactData();
        this.multiLogin = acc.isAllowMultiLogin();
        this.roles = (Role[]) ArrayUtils.clone(roles);
        this.groups = ArrayUtils.clone(groups);
        this.mandator = acc.getMandatorId();
        this.applicationId = applicationId;
        this.assignments = aad.clone();
        this.language = language;
        this.webDav = isWebDav;
        populateData();
    }

    /**
     * Private Constructor.
     *
     * @param applicationId        the application name that the ticket belongs to
     * @param userName             the user name
     * @param loginName            the login name
     * @param userId               the user id
     * @param contactData          contact data pk
     * @param mandatorId           the mandator id that the user belongs to
     * @param multiLogin           true if the account may be logged in more than once at a time
     * @param groups               the groups
     * @param roles                the roles
     * @param assignments          the acl assignemnts
     * @param language             the language
     * @param isWebDav             true if this is a webdav ticket
     * @param failedLoginAttempts  number of failed login attempts
     * @param authenticationSource source of authentication
     * @param dateFormat           date format pattern
     * @param timeFormat           time format pattern
     * @param dateTimeFormat       date/time format pattern
     * @param decimalSeparator     decimal separator
     * @param groupingSeparator    grouping separator
     * @param useGroupingSeparator use the grouping separator?
     */
    private UserTicketImpl(String applicationId, boolean isWebDav, String userName, String loginName, long userId,
            FxPK contactData, long mandatorId, boolean multiLogin, long[] groups, Role[] roles,
            ACLAssignment assignments[], FxLanguage language, long failedLoginAttempts,
            AuthenticationSource authenticationSource, String dateFormat, String timeFormat, String dateTimeFormat,
            char decimalSeparator, char groupingSeparator, boolean useGroupingSeparator) {
        this.applicationId = applicationId;
        this.userName = userName;
        this.loginName = loginName;
        this.userId = userId;
        this.contactData = contactData;
        this.multiLogin = multiLogin;
        this.groups = groups;
        this.roles = roles;
        this.mandator = mandatorId;
        this.assignments = assignments;
        this.language = language;
        this.webDav = isWebDav;
        this.failedLoginAttempts = failedLoginAttempts;
        this.authenticationSource = authenticationSource;
        this.dateFormat = dateFormat;
        this.timeFormat = timeFormat;
        this.dateTimeFormat = dateTimeFormat;
        this.decimalSeparator = decimalSeparator;
        this.groupingSeparator = groupingSeparator;
        this.useGroupingSeparator = useGroupingSeparator;
        populateData();
    }

    /**
     * Helper function for the constructor.
     */
    private void populateData() {

        this.dirty = false;
        this.creationTime = System.currentTimeMillis();
        this.remoteHost = FxContext.get().getRemoteHost();

        // Check ACL assignments
        if (assignments == null) {
            assignments = new ACLAssignment[0];
        }

        // Check groups
        if (this.groups == null || this.groups.length == 0) {
            this.groups = new long[] { UserGroup.GROUP_EVERYONE };
        } else {
            // Group everyone has to be present
            if (!(ArrayUtils.contains(this.groups, UserGroup.GROUP_EVERYONE))) {
                this.groups = ArrayUtils.add(this.groups, UserGroup.GROUP_EVERYONE);
            }
        }

        // Check roles
        if (this.roles == null) {
            this.roles = new Role[0];
        }

        // Set mandator/global supervisor flag
        if (this.userId == Account.USER_GLOBAL_SUPERVISOR || isInRole(Role.GlobalSupervisor)) {
            globalSupervisor = true;
        }
        if (isInRole(Role.MandatorSupervisor)) {
            mandatorSupervisor = true;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void initUserSpecificSettings() {
        final UserConfigurationEngine uce = EJBLookup.getUserConfigurationEngine();
        String _dateFormat = null;
        String _dateTimeFormat = null;
        String _timeFormat = null;
        String _decimalSeparator = null;
        String _groupingSeparator = null;
        Boolean _useGroupingSeparator = null;
        if (userId > Account.NULL_ACCOUNT) {
            try {
                FxContext.startRunningAsSystem();
                _dateFormat = uce.get(userId, SystemParameters.USER_DATEFORMAT,
                        SystemParameters.USER_DATEFORMAT.getKey(), true);
                _dateTimeFormat = uce.get(userId, SystemParameters.USER_DATETIMEFORMAT,
                        SystemParameters.USER_DATETIMEFORMAT.getKey(), true);
                _timeFormat = uce.get(userId, SystemParameters.USER_TIMEFORMAT,
                        SystemParameters.USER_TIMEFORMAT.getKey(), true);
                _decimalSeparator = uce.get(userId, SystemParameters.USER_DECIMALSEPARATOR,
                        SystemParameters.USER_DECIMALSEPARATOR.getKey(), true);
                _groupingSeparator = uce.get(userId, SystemParameters.USER_GROUPINGSEPARATOR,
                        SystemParameters.USER_GROUPINGSEPARATOR.getKey(), true);
                _useGroupingSeparator = uce.get(userId, SystemParameters.USER_USEGROUPINGSEPARATOR,
                        SystemParameters.USER_USEGROUPINGSEPARATOR.getKey(), true);
            } catch (FxNotFoundException e) {
                //ok, might just not be set
            } catch (FxApplicationException e) {
                LOG.error(e);
            } finally {
                FxContext.stopRunningAsSystem();
            }
        }
        this.dateFormat = _dateFormat != null ? _dateFormat : FxFormatUtils.DATE_STD;
        this.timeFormat = _timeFormat != null ? _timeFormat : FxFormatUtils.TIME_STD;
        this.dateTimeFormat = _dateTimeFormat != null ? _dateTimeFormat : FxFormatUtils.DATETIME_STD;
        this.decimalSeparator = _decimalSeparator != null && _decimalSeparator.length() > 0
                ? _decimalSeparator.charAt(0)
                : FxFormatUtils.DECIMAL_SEP_STD;
        this.groupingSeparator = _groupingSeparator != null && _groupingSeparator.length() > 0
                ? _groupingSeparator.charAt(0)
                : FxFormatUtils.GROUPING_SEP_STD;
        this.useGroupingSeparator = _useGroupingSeparator != null ? _useGroupingSeparator
                : FxFormatUtils.USE_GROUPING_STD;
    }

    /**
     * Returns the time that this ticket was created at.
     *
     * @return the time that the ticket was created at
     */
    @Override
    public long getCreationTime() {
        return this.creationTime;
    }

    /**
     * @return remote host the user logged in from (if available and applicable)
     */
    @Override
    public String getRemoteHost() {
        if (remoteHost == null)
            return "unknown";
        return remoteHost;
    }

    /**
     * Returns a string representation of the ticket.
     *
     * @return a string representation of the ticket.
     */
    @Override
    public String toString() {
        return this.getClass() + "@[" + "id=" + this.userId + "; contactData=" + this.contactData + "; name:"
                + this.userName + "; mandator:" + this.mandator + "; language: " + this.getLanguage().getIso2digit()
                + "; groups:" + StringUtils.join(ArrayUtils.toObject(this.groups), ',') + "; roles:"
                + StringUtils.join(FxSharedUtils
                        .getSelectableObjectIdList(Arrays.asList((SelectableObjectWithLabel[]) this.roles)), ',')
                + "; globalSupervisor:" + this.globalSupervisor + "; multiLogin:" + this.multiLogin + "]";

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public UserTicketImpl cloneAsGlobalSupervisor() {
        final UserTicketImpl clone = copy();
        clone.globalSupervisor = true;
        return clone;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public UserTicketImpl copy() {
        return new UserTicketImpl(this.applicationId, this.webDav, this.userName, this.loginName, this.userId,
                this.contactData, this.mandator, this.multiLogin, this.groups.clone(), this.roles.clone(),
                ACLAssignment.clone(this.assignments), this.language, this.failedLoginAttempts,
                this.authenticationSource, this.dateFormat, this.timeFormat, this.dateTimeFormat,
                this.decimalSeparator, this.groupingSeparator, this.useGroupingSeparator);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ACLAssignment[] getACLAssignments() {
        return this.assignments.clone();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAssignedToACL(long aclId) {
        for (ACLAssignment item : this.assignments) {
            if (item.getAclId() == aclId && !item.isOwnerGroupAssignment())
                return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean mayReadACL(long aclId, long ownerId) {
        if (this.isGlobalSupervisor())
            return true;
        for (ACLAssignment item : this.assignments) {
            if (item.isOwnerGroupAssignment() && ownerId != userId)
                continue;
            if (item.getMayRead() && item.getAclId() == aclId)
                return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean mayEditACL(long aclId, long ownerId) {
        if (this.isGlobalSupervisor())
            return true;
        for (ACLAssignment item : this.assignments) {
            if (item.isOwnerGroupAssignment() && ownerId != userId)
                continue;
            if (item.getMayEdit() && item.getAclId() == aclId)
                return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean mayExportACL(long aclId, long ownerId) {
        if (this.isGlobalSupervisor())
            return true;
        for (ACLAssignment item : this.assignments) {
            if (item.isOwnerGroupAssignment() && ownerId != userId)
                continue;
            if (item.getMayExport() && item.getAclId() == aclId)
                return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean mayRelateACL(long aclId, long ownerId) {
        if (this.isGlobalSupervisor())
            return true;
        for (ACLAssignment item : this.assignments) {
            if (item.isOwnerGroupAssignment() && ownerId != userId)
                continue;
            if (item.getMayRelate() && item.getAclId() == aclId)
                return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean mayCreateACL(long aclId, long ownerId) {
        if (this.isGlobalSupervisor())
            return true;
        for (ACLAssignment item : this.assignments) {
            if (item.isOwnerGroupAssignment())
                continue; //group owner may never create!
            if (item.getMayCreate() && item.getAclId() == aclId)
                return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean mayDeleteACL(long aclId, long ownerId) {
        if (this.isGlobalSupervisor())
            return true;
        for (ACLAssignment item : this.assignments) {
            if (item.isOwnerGroupAssignment() && ownerId != userId)
                continue;
            if (item.getMayDelete() && item.getAclId() == aclId)
                return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ACLAssignment[] getACLAssignments(ACLCategory category, long ownerId, ACLPermission... perms) {
        Boolean mayCreate = null;
        Boolean mayRead = null;
        Boolean mayEdit = null;
        Boolean mayDelete = null;
        Boolean mayRelate = null;
        Boolean mayExport = null;
        for (ACLPermission perm : perms) {
            switch (perm) {
            case CREATE:
                mayCreate = true;
                break;
            case NOT_CREATE:
                mayCreate = false;
                break;
            case READ:
                mayRead = true;
                break;
            case NOT_READ:
                mayRead = false;
                break;
            case EDIT:
                mayEdit = true;
                break;
            case NOT_EDIT:
                mayEdit = false;
                break;
            case DELETE:
                mayDelete = true;
                break;
            case NOT_DELETE:
                mayDelete = false;
                break;
            case RELATE:
                mayRelate = true;
                break;
            case NOT_RELATE:
                mayRelate = false;
                break;
            case EXPORT:
                mayExport = true;
                break;
            case NOT_EXPORT:
                mayExport = false;
                break;
            }
        }
        List<ACLAssignment> result = new ArrayList<ACLAssignment>(this.assignments.length);
        for (ACLAssignment acl : this.assignments) {
            if (acl.isOwnerGroupAssignment() && ownerId != userId)
                continue;
            if (mayRead != null && mayRead != acl.getMayRead())
                continue;
            if (mayEdit != null && mayEdit != acl.getMayEdit())
                continue;
            if (mayDelete != null && mayDelete != acl.getMayDelete())
                continue;
            if (mayRelate != null && mayRelate != acl.getMayRelate())
                continue;
            if (mayExport != null && mayExport != acl.getMayExport())
                continue;
            if (mayCreate != null && mayCreate != acl.getMayCreate())
                continue;
            if (category != null && category != acl.getACLCategory())
                continue;
            result.add(acl);
        }
        return result.toArray(new ACLAssignment[result.size()]);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getACLsCSV(long ownerId, ACLCategory category, ACLPermission... perms) {
        final StringBuilder result = new StringBuilder();
        Long ACLs[] = getACLsId(ownerId, category, perms);
        for (long acl : ACLs) {
            result.append((result.length() > 0) ? "," : "").append(acl);
        }
        return result.toString();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Long[] getACLsId(long ownerId, ACLCategory category, ACLPermission... perms) {
        Boolean mayCreate = null;
        Boolean mayRead = null;
        Boolean mayEdit = null;
        Boolean mayDelete = null;
        Boolean mayRelate = null;
        Boolean mayExport = null;
        for (ACLPermission perm : perms) {
            switch (perm) {
            case CREATE:
                mayCreate = true;
                break;
            case NOT_CREATE:
                mayCreate = false;
                break;
            case READ:
                mayRead = true;
                break;
            case NOT_READ:
                mayRead = false;
                break;
            case EDIT:
                mayEdit = true;
                break;
            case NOT_EDIT:
                mayEdit = false;
                break;
            case DELETE:
                mayDelete = true;
                break;
            case NOT_DELETE:
                mayDelete = false;
                break;
            case RELATE:
                mayRelate = true;
                break;
            case NOT_RELATE:
                mayRelate = false;
                break;
            case EXPORT:
                mayExport = true;
                break;
            case NOT_EXPORT:
                mayExport = false;
                break;
            }
        }
        Hashtable<Long, boolean[]> hlp = new Hashtable<Long, boolean[]>(this.assignments.length);

        // Condense the ACL right informations
        // If a ACL is assigned via groupX and groupY the rights are taken from both assignments.
        for (ACLAssignment acl : this.assignments) {
            if (acl.isOwnerGroupAssignment() && ownerId != userId)
                continue;
            if (category != null && acl.getACLCategory() != category)
                continue;
            Long key = acl.getAclId();
            boolean[] rights = hlp.get(key);
            if (rights == null) {
                rights = new boolean[] { false, false, false, false, false, false, false };
            }
            if (acl.getMayRead())
                rights[ACLPermission.READ.ordinal()] = true;
            if (acl.getMayEdit())
                rights[ACLPermission.EDIT.ordinal()] = true;
            if (acl.getMayDelete())
                rights[ACLPermission.DELETE.ordinal()] = true;
            if (acl.getMayRelate())
                rights[ACLPermission.RELATE.ordinal()] = true;
            if (acl.getMayExport())
                rights[ACLPermission.EXPORT.ordinal()] = true;
            if (acl.getMayCreate() && !acl.isOwnerGroupAssignment())
                rights[ACLPermission.CREATE.ordinal()] = true;
            hlp.put(key, rights);
        }

        // Return matching ACLs
        Enumeration keys = hlp.keys();
        List<Long> result = new ArrayList<Long>(hlp.size());
        while (keys.hasMoreElements()) {
            Long aclId = (Long) keys.nextElement();
            boolean[] rights = hlp.get(aclId);
            if (mayRead != null && mayRead != rights[ACLPermission.READ.ordinal()])
                continue;
            if (mayEdit != null && mayEdit != rights[ACLPermission.EDIT.ordinal()])
                continue;
            if (mayDelete != null && mayDelete != rights[ACLPermission.DELETE.ordinal()])
                continue;
            if (mayRelate != null && mayRelate != rights[ACLPermission.RELATE.ordinal()])
                continue;
            if (mayExport != null && mayExport != rights[ACLPermission.EXPORT.ordinal()])
                continue;
            if (mayCreate != null && mayCreate != rights[ACLPermission.CREATE.ordinal()])
                continue;
            result.add(aclId);
        }
        return result.toArray(new Long[result.size()]);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ACL[] getACLs(long owner, ACLCategory category, ACLPermission... perms) {
        Long[] acls = getACLsId(owner, category, perms);
        List<ACL> res = new ArrayList<ACL>(acls.length);
        FxEnvironment struct;
        struct = CacheAdmin.getEnvironment();
        for (Long acl : acls) {
            res.add(struct.getACL(acl));
        }
        return res.toArray(new ACL[res.size()]);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FxLanguage getLanguage() {
        return language;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isWebDav() {
        return this.webDav;
    }

    public void setFailedLoginAttempts(long failedLoginAttempts) {
        this.failedLoginAttempts = failedLoginAttempts;
    }

    public void setAuthenticationSource(AuthenticationSource authenticationSource) {
        this.authenticationSource = authenticationSource;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getFailedLoginAttempts() {
        return failedLoginAttempts;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AuthenticationSource getAuthenticationSource() {
        return authenticationSource;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setLanguage(FxLanguage language) {
        if (language != null)
            this.language = language;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getDateFormat() {
        return dateFormat;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getTimeFormat() {
        return timeFormat;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getDateTimeFormat() {
        return dateTimeFormat;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public char getDecimalSeparator() {
        return decimalSeparator;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public char getGroupingSeparator() {
        return groupingSeparator;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean useGroupingSeparator() {
        return useGroupingSeparator;
    }
}