de.fiz.ddb.aas.utils.LDAPEngineUtility.java Source code

Java tutorial

Introduction

Here is the source code for de.fiz.ddb.aas.utils.LDAPEngineUtility.java

Source

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.fiz.ddb.aas.utils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.SortKey;

import org.apache.commons.lang.StringUtils;

import de.fiz.ddb.aas.administration.AasPrincipal;
import de.fiz.ddb.aas.administration.Constants;
import de.fiz.ddb.aas.administration.DdbProperties;
import de.fiz.ddb.aas.authorization.PrivilegeEnum;
import de.fiz.ddb.aas.authorization.Scope;
import de.fiz.ddb.aas.auxiliaryobjects.OIDs;
import de.fiz.ddb.aas.auxiliaryobjects.Privilege;
import de.fiz.ddb.aas.auxiliaryobjects.SearchParameters;
import de.fiz.ddb.ldap.connector.LDAPConnector;

/**
 * 
 * @author bkl
 */
public abstract class LDAPEngineUtility {

    protected static final Logger LOG = Logger.getLogger(LDAPConnector.class.getName());

    protected final PropertiesSerializer serializer = new JsonPropertiesSerializer();

    public static SimpleDateFormat _dateISO8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

    // ***************************************************************************
    // ***************************************************************************
    /*
     * public Attribute privilegeToLdapGroup(Set<Privilege> globalPrivileges,
     * Map<String, Set<Privilege>> orgPrivileges) {
     * 
     * BasicAttribute attribute = new BasicAttribute("member"); for ( Privilege
     * vPrivilege : globalPrivileges ) {
     * attribute.add(vPrivilege.ldapGroupname() + "," + this.getBaseDn()); }
     * 
     * for ( String vOIDs : orgPrivileges.keySet() ) { for ( Privilege
     * vPrivilege : orgPrivileges.get(vOIDs) ) {
     * attribute.add(vPrivilege.ldapGroupname() + ",o=" + vOIDs + "," +
     * this.getBaseDn()); } }
     * 
     * return attribute; }
     */

    // ***************************************************************************
    public Set<PrivilegeEnum> privilegeDiff(Set<PrivilegeEnum> p0, Set<PrivilegeEnum> p1) {
        // Set<Privilege> privilege = new HashSet<Privilege> ();
        Set<PrivilegeEnum> privilege = EnumSet.noneOf(PrivilegeEnum.class);
        for (PrivilegeEnum p : p1) {
            if (!p0.contains(p)) {
                privilege.add(p);
            }
        }
        return privilege;
    }

    // ***************************************************************************
    /*
     * public Map<String, Set<Privilege>> orgPrivilegeDiff(Map<String,
     * Set<Privilege>> op0, Map<String, Set<Privilege>> op1) { HashMap<String,
     * Set<Privilege>> orgPrivilege = new HashMap<String, Set<Privilege>>();
     * Set<Privilege> vDiffSet = null; for ( String vOIDs : op1.keySet() ) { if
     * ( op0.containsKey(vOIDs) ) { // -- nur die Differenz kommt rein, aber nur
     * dann, wenn sie nicht leer ist if (!(vDiffSet =
     * privilegeDiff(op0.get(vOIDs), op1.get(vOIDs))).isEmpty()) {
     * orgPrivilege.put(vOIDs, vDiffSet); } } else { // -- alles muss rein:
     * orgPrivilege.put(vOIDs, op1.get(vOIDs)); } } return orgPrivilege; }
     */
    public Map<OIDs, Set<PrivilegeEnum>> orgPrivilegeDiff(Map<OIDs, Set<PrivilegeEnum>> op0,
            Map<OIDs, Set<PrivilegeEnum>> op1) {
        HashMap<OIDs, Set<PrivilegeEnum>> orgPrivilege = new HashMap<OIDs, Set<PrivilegeEnum>>();
        Set<PrivilegeEnum> vDiffSet;
        for (OIDs vOIDs : op1.keySet()) {
            if (op0.containsKey(vOIDs)) {
                // -- nur die Differenz kommt rein, aber nur dann, wenn sie
                // nicht leer ist
                if (!(vDiffSet = privilegeDiff(op0.get(vOIDs), op1.get(vOIDs))).isEmpty()) {
                    orgPrivilege.put(vOIDs, vDiffSet);
                }
            } else {
                // -- alles muss rein:
                orgPrivilege.put(vOIDs, op1.get(vOIDs));
            }
        }
        return orgPrivilege;
    }

    // ***************************************************************************
    public StringBuilder normalizeKommataString(StringBuilder pKommataStr) {
        if ((pKommataStr != null) && (pKommataStr.length() > 0)) {
            if (pKommataStr.indexOf(",") > 0) {
                String[] vStrLst = pKommataStr.toString().split(",");
                pKommataStr.delete(0, pKommataStr.length());
                for (int i = 0; i < vStrLst.length; i++) {
                    if (pKommataStr.length() > 0) {
                        pKommataStr.append(",");
                    }
                    pKommataStr.append(vStrLst[i].trim());
                }
            }
        }
        return pKommataStr;
    }

    // ***************************************************************************
    public StringBuilder getOrgDN(OIDs pOIDs) {
        StringBuilder vResult = null;
        try {
            if (pOIDs != null) {
                if (pOIDs.getOrgRDN() != null) {
                    vResult = new StringBuilder(Constants.ldap_ddbOrg_Id).append("=")
                            .append(pOIDs.getOrgRDN().replaceAll(",", "," + Constants.ldap_ddbOrg_Id + "="))
                            .append(",").append(LDAPConnector.getSingletonInstance().getInstitutionBaseDN());
                }
            }
        } catch (IllegalAccessException ex) {
            LOG.log(Level.SEVERE, "Connection-Error", ex);
        }
        return vResult;
    }

    // ***************************************************************************
    public StringBuilder getLicensedOrgsDN(OIDs pOIDs) {
        StringBuilder vResult = null;
        try {
            if (pOIDs != null) {
                if (pOIDs.getOrgRDN() != null) {
                    vResult = new StringBuilder(Constants.ldap_ddbOrg_Id).append("=")
                            .append(pOIDs.getOrgRDN().replaceAll(",", "," + Constants.ldap_ddbOrg_Id + "="))
                            .append(",")
                            .append(LDAPConnector.getSingletonInstance().getLicensedInstitutionsBaseDN());
                }
            }
        } catch (IllegalAccessException ex) {
            LOG.log(Level.SEVERE, "Connection-Error", ex);
        }
        return vResult;
    }

    // ***************************************************************************
    public NamingEnumeration<SearchResult> query(String pBaseDn, String filter, String[] attributeFilter,
            Integer pScope) throws NamingException, IllegalAccessException {
        InitialLdapContext ctx = null;
        try {
            ctx = LDAPConnector.getSingletonInstance().takeCtx();
            return this.query(ctx, pBaseDn, filter, attributeFilter, pScope);
        } finally {
            if (ctx != null) {
                try {
                    LDAPConnector.getSingletonInstance().putCtx(ctx);
                } catch (IllegalAccessException ex) {
                    LOG.log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    public NamingEnumeration<SearchResult> query(DirContext ctx, String pBaseDn, String filter,
            String[] attributeFilter, Integer pScope) throws NamingException, IllegalAccessException {
        NamingEnumeration<SearchResult> vResult;
        SearchControls sControl = new SearchControls();
        if (attributeFilter != null) {
            sControl.setReturningAttributes(attributeFilter);
        }
        int vScope = SearchControls.SUBTREE_SCOPE;
        if (pScope != null) {
            vScope = pScope.intValue();
        }
        sControl.setSearchScope(vScope);
        vResult = ctx.search(((pBaseDn != null) && (pBaseDn.length() > 0) ? pBaseDn
                : LDAPConnector.getSingletonInstance().getBaseDn()), filter, sControl);
        return vResult;
    }

    // ***************************************************************************
    protected Set<PrivilegeEnum> convertLdapGroupsToOrganizationPrivileges(
            NamingEnumeration<SearchResult> pPrivilegesResult) {
        Set<PrivilegeEnum> vResult = EnumSet.noneOf(PrivilegeEnum.class);
        NamingEnumeration<SearchResult> vSearchResults = pPrivilegesResult;
        try {
            if (pPrivilegesResult != null) {
                PrivilegeEnum p;
                SearchResult sr;
                String vCnPrivileg;
                // construct privileges
                while (vSearchResults.hasMore()) {
                    sr = vSearchResults.next();
                    vCnPrivileg = (String) sr.getAttributes().get(Constants.ldap_ddbPrivilege_Cn).get();
                    p = this.mapToPrivilege(sr.getAttributes(), Constants.ldap_ddbPrivilege_Cn);
                    if (p != null) {
                        vResult.add(p);
                    } else {
                        LOG.log(Level.WARNING,
                                "Es ist ein nicht existierende Privileg: ''{0}'' im LDAP gespeichert!",
                                new Object[] { vCnPrivileg });
                    }
                }
                // -- releases this context's resources immediately, instead of
                // waiting for the garbage collector
                vSearchResults.close();
            }
        } catch (NamingException ne) {
            LOG.log(Level.SEVERE, null, ne);
        } finally {
            // -- releases this context's resources immediately, instead of
            // waiting for the garbage collector
            if (vSearchResults != null) {
                try {
                    vSearchResults.close();
                } catch (NamingException ex) {
                }
            }
        }
        return vResult;
    }

    // ***************************************************************************
    private Privilege convertLdapGroupToOrgPriv(SearchResult sr) throws NamingException, IllegalAccessException {
        Privilege vOrgPrivilege = null;
        String vCnPrivileg = null, vPrivEntryDN = null, vOrgEntryDN = null;
        PrivilegeEnum vPrivilege;
        Attribute vAttr;
        String vMemberRef;
        String[] vStrs;
        if (sr != null) {
            try {
                // -- Beispiel fr entryDN:
                // Organisationeles Privileg:
                // cn=ddb_ingest,o=99900189,o=00001475,dc=ddb,dc=iais,dc=fraunhofer,dc=de
                // construct privileges
                vCnPrivileg = (String) sr.getAttributes().get(Constants.ldap_ddbPrivilege_Cn).get();
                vPrivilege = this.mapToPrivilege(sr.getAttributes(), Constants.ldap_ddbPrivilege_Cn);
                // vPrivEntryDN = (vAttr = sr.getAttributes().get("entryDN")) !=
                // null ? String.valueOf(vAttr.get()) : null; //
                // organizationName
                vPrivEntryDN = sr.getNameInNamespace(); // liefert das gleiche
                // wie oben...
                if ((vPrivilege != null) && (vPrivEntryDN != null)) {
                    // vOrgEntryDN =
                    // vPrivEntryDN.substring(vPrivEntryDN.indexOf(",") + 1,
                    // vPrivEntryDN.indexOf(",dc") );
                    vOrgEntryDN = vPrivEntryDN.substring(vPrivEntryDN.indexOf(",") + 1);
                    vOrgPrivilege = new Privilege(vPrivilege);
                    vAttr = sr.getAttributes().get(Constants.ldap_ddbPrivilege_Member);
                    for (int i = 0; i < vAttr.size(); i++) {
                        if (((vMemberRef = String.valueOf(vAttr.get(i))) != null) && (vMemberRef.length() > 0)) {
                            if (((vStrs = vMemberRef.split(",")).length >= 1)
                                    && ((vStrs = vStrs[0].split("=")).length == 2)
                                    && (vStrs[0].trim().equalsIgnoreCase(Constants.ldap_ddbPerson_Id))) {
                                vOrgPrivilege.add(vStrs[1].trim());
                            }
                        }
                    }
                } else {
                    LOG.log(Level.WARNING, "Ein fehlerhaftes Privileg: Privileg: ''{0}'', Privileg-Entry: ''{1}''.",
                            new Object[] { vCnPrivileg, vPrivEntryDN });
                }
            } catch (NamingException ex) {
                LOG.log(Level.SEVERE, "CnPrivileg: '" + vCnPrivileg + "', PrivEntryDN: '" + vPrivEntryDN
                        + "', OrgEntryDN: '" + vOrgEntryDN + "'");
                throw ex;
            }
        }
        return vOrgPrivilege;
    }

    // ***************************************************************************
    protected Set<Privilege> convertLdapGroupsToOrganizationPrivilegesWithUsers(
            NamingEnumeration<SearchResult> pPrivilegesSearchResults)
            throws NamingException, IllegalAccessException {
        Set<Privilege> vResult = new HashSet<Privilege>();
        try {
            Privilege vOrgPrivilege;
            // construct privileges
            while (pPrivilegesSearchResults.hasMore()) {
                if ((vOrgPrivilege = this.convertLdapGroupToOrgPriv(pPrivilegesSearchResults.next())) != null) {
                    vResult.add(vOrgPrivilege);
                }
            }
        } finally {
            // -- releases this context's resources immediately, instead of
            // waiting for the garbage collector
            if (pPrivilegesSearchResults != null) {
                try {
                    pPrivilegesSearchResults.close();
                } catch (NamingException ex) {
                }
            }
        }
        return vResult;
    }

    // ***************************************************************************
    protected Privilege convertLdapGroupToOrganizationPrivilegeWithUsers(
            NamingEnumeration<SearchResult> pPrivilegesSearchResults)
            throws NamingException, IllegalAccessException {
        Privilege vOrgPrivilege = null;
        try {
            if ((pPrivilegesSearchResults != null) && (pPrivilegesSearchResults.hasMore())) {
                vOrgPrivilege = this.convertLdapGroupToOrgPriv(pPrivilegesSearchResults.next());
            }
        } finally {
            // -- releases this context's resources immediately, instead of
            // waiting for the garbage collector
            if (pPrivilegesSearchResults != null) {
                try {
                    pPrivilegesSearchResults.close();
                    pPrivilegesSearchResults = null;
                } catch (NamingException ex) {
                }
            }
        }
        return vOrgPrivilege;
    }

    // ***************************************************************************
    /*
     * Map a specific Ldap Group to a DDB Privilege
     */
    public PrivilegeEnum mapToPrivilege(Attributes attributes, String attributeName) {
        Attribute attributeValue = null;
        PrivilegeEnum privilege = null;
        if (attributes != null && (attributeValue = attributes.get(attributeName)) != null) {
            try {
                String attributeString = String.valueOf(attributeValue.get()).toLowerCase(Locale.GERMAN);
                try {
                    privilege = PrivilegeEnum.valueOf(attributeString.substring(4).toUpperCase(Locale.GERMAN));
                } catch (IllegalArgumentException iae) {
                    LOG.log(Level.WARNING, "Name: {0}={1} - no such privilege",
                            new Object[] { attributeName, attributeString });
                }
            } catch (NamingException ne) {
                LOG.log(Level.SEVERE, "Can't convert LDAP Group " + attributeValue + " to DDB Privilege.",
                        ne.getMessage());
            }
        }
        return privilege;
    }

    // ***************************************************************************

    /**
     * Converts SearchFileds Map to LDAP search String
     * 
     * @param scope
     * @param searchParameters
     * @return String ldap search string
     */
    public String convertSearchParametersToSearchString(final Scope scope,
            final SearchParameters searchParameters) {
        // (| (& (sn=Geisel) (mail=*)) (sn=L*))
        // (& (| (sn=Geisel) (mail=*)) (sn=L*))
        if (searchParameters == null || scope == null) {
            return null;
        }
        String objectClass;
        if (scope.equals(Scope.ORGANIZATION)) {
            objectClass = Constants.ldap_ddbOrg_ObjectClass;
        } else {
            objectClass = Constants.ldap_ddbPerson_ObjectClass;
        }
        StringBuilder builder = new StringBuilder("(& ");
        builder.append("(objectclass=").append(objectClass).append(") ");
        if (searchParameters.getSearchFields() != null) {
            for (Entry<String, List<String>> entry : searchParameters.getSearchFields().entrySet()) {
                if (StringUtils.isBlank(LdapObjectFieldnameMapper.getNameInLdap(entry.getKey(), scope))) {
                    throw new IllegalArgumentException(entry.getKey() + " is no search-field");
                }
                String ldapKey = LdapObjectFieldnameMapper.getNameInLdap(entry.getKey(), scope);
                boolean isWildcardField = LdapObjectFieldnameMapper.isWildcardField(ldapKey, scope);
                if (entry.getValue() != null) {
                    if (entry.getValue().size() > 1) {
                        builder.append("(| ");
                    }
                    for (String value : entry.getValue()) {
                        builder.append("(").append(ldapKey).append("=");
                        if (isWildcardField && !value.startsWith("*")) {
                            builder.append("*");
                        }
                        builder.append(value);
                        if (isWildcardField && !value.endsWith("*")) {
                            builder.append("*");
                        }
                        builder.append(") ");
                    }
                    if (entry.getValue().size() > 1) {
                        builder.append(") ");
                    }
                }
            }
            if (searchParameters.getQ() != null && searchParameters.getQ().length > 0) {
                builder.append("(| ");
                for (String qPart : searchParameters.getQ()) {
                    for (String key : LdapObjectFieldnameMapper.getAllNamesInLdap(scope)) {
                        boolean isWildcardField = LdapObjectFieldnameMapper.isWildcardField(key, scope);
                        builder.append("(").append(key).append("=");
                        if (isWildcardField && !qPart.startsWith("*")) {
                            builder.append("*");
                        }
                        builder.append(qPart);
                        if (isWildcardField && !qPart.endsWith("*")) {
                            builder.append("*");
                        }
                        builder.append(") ");
                    }
                }
                builder.append(") ");
            }
        }
        builder.append(") ");
        return builder.toString();
    }

    /**
     * Converts sort-string to Ldap SortKey[]. sort-string is like cql-sort:
     * sortfield1/sort.descending sortfield2/sort.ascending
     * 
     * @param sort
     * @return SortKey[]
     */
    public SortKey[] convertSortStringToLdapSortKeys(final Scope scope, final String sort) {
        if (StringUtils.isBlank(sort) || scope == null) {
            return null;
        }
        String[] sortParts = sort.split("\\s");
        List<SortKey> sortKeys = new ArrayList<SortKey>();
        for (int i = 0; i < sortParts.length; i++) {
            if (!StringUtils.isBlank(sortParts[i])) {
                String[] sortKeyParts = sortParts[i].split("\\/");
                boolean ascending = true;
                if (sortKeyParts.length > 1 && sortKeyParts[1].equals("sort.descending")) {
                    ascending = false;
                }
                if (!StringUtils.isBlank(LdapObjectFieldnameMapper.getNameInLdap(sortKeyParts[0], scope))) {
                    SortKey sortKey = new SortKey(LdapObjectFieldnameMapper.getNameInLdap(sortKeyParts[0], scope),
                            ascending, null);
                    sortKeys.add(sortKey);
                }
            }
        }
        return sortKeys.toArray(new SortKey[0]);
    }

    /**
     * Converts LDAP date string tolong
     * 
     * @param ldapDate
     *            String
     * @return long
     */
    public long convertLdapDateToLong(final String ldapDate) {
        if (StringUtils.isBlank(ldapDate)) {
            return 0;
        }
        return new GregorianCalendar(Integer.valueOf(ldapDate.substring(0, 4)), // year,
                Integer.valueOf(ldapDate.substring(4, 6)), // month,
                Integer.valueOf(ldapDate.substring(6, 8)), // dayOfMonth,
                Integer.valueOf(ldapDate.substring(8, 10)), // hourOfDay,
                Integer.valueOf(ldapDate.substring(10, 12)), // minute,
                Integer.valueOf(ldapDate.substring(12, 14)) // second
        ).getTimeInMillis();
    }

    /**
     * get actual date as LDAP-String
     * 
     * @return String LDAP-Date String
     */
    public String getActualLdapDate() {
        return new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()) + "Z";
    }

    /**
     * get attribute values of given resource and attributes.
     * 
     * @param scope
     *            scope
     * @param id
     *            id of resource
     * @param attributeName
     *            attribute-name to retrieve
     * 
     * @return String attribute value
     * @throws NamingException
     * @throws IllegalAccessException
     */
    public Map<String, String> getResourceAttributes(Scope scope, String id, String[] attributeNames)
            throws NamingException, IllegalAccessException {
        Map<String, String> returnMap = new HashMap<String, String>();
        String baseDn = null;
        String filter = getIdFilter(scope, id);
        int levelScope = 0;
        InitialLdapContext ctx = null;
        NamingEnumeration<SearchResult> results = null;
        if (scope == Scope.ORGANIZATION) {
            baseDn = LDAPConnector.getSingletonInstance().getInstitutionBaseDN();
            levelScope = SearchControls.SUBTREE_SCOPE;
        } else if (scope == Scope.PERSON) {
            baseDn = LDAPConnector.getSingletonInstance().getPersonBaseDN();
            levelScope = SearchControls.ONELEVEL_SCOPE;
        }
        try {
            ctx = LDAPConnector.getSingletonInstance().takeCtx();
            results = query(ctx, baseDn, filter, attributeNames, levelScope);
            if (results.hasMore()) {
                SearchResult searchResult = results.next();
                if (results.hasMore()) {
                    throw new IllegalAccessException("found more than one object with id=" + id);
                }
                Attributes attributes = searchResult.getAttributes();
                for (int i = 0; i < attributeNames.length; i++) {
                    Attribute attribute = attributes.get(attributeNames[i]);
                    if (attribute == null) {
                        returnMap.put(attributeNames[i], (String) null);
                    } else {
                        returnMap.put(attributeNames[i], (String) attribute.get());
                    }
                }
                return returnMap;
            } else {
                throw new NameNotFoundException("id not found");
            }

        } finally {
            if (ctx != null) {
                try {
                    LDAPConnector.getSingletonInstance().putCtx(ctx);
                } catch (IllegalAccessException ex) {
                    LOG.log(Level.SEVERE, null, ex);
                }
            }
            if (results != null) {
                try {
                    results.close();
                } catch (NamingException e) {
                    LOG.log(Level.WARNING, null, e);
                }
            }
        }
    }

    /**
     * set attributes of given resource.
     * 
     * @param scope
     *            scope
     * @param id
     *            id of resource
     * @param attributeNames
     *            attribute-names and values to set
     * 
     * @throws NamingException
     * @throws IllegalAccessException
     */
    public void setResourceAttributes(Scope scope, String entryDn, Map<String, String> attributes)
            throws NamingException, IllegalAccessException {
        InitialLdapContext ctx = null;
        try {
            ctx = LDAPConnector.getSingletonInstance().takeCtx();
            BasicAttributes saveAttributes = new BasicAttributes(true);
            for (Entry<String, String> entry : attributes.entrySet()) {
                saveAttributes.put(new BasicAttribute(entry.getKey(), entry.getValue()));
            }
            ctx.modifyAttributes(entryDn, DirContext.REPLACE_ATTRIBUTE, saveAttributes);
        } finally {
            if (ctx != null) {
                try {
                    LDAPConnector.getSingletonInstance().putCtx(ctx);
                } catch (IllegalAccessException ex) {
                    LOG.log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    /**
     * get filter-string for given id and scope.
     * 
     * @param scope
     *            scope
     * @param id
     *            id of resource
     * 
     * @return String id-filter as String
     * @throws IllegalAccessException
     */
    public String getIdFilter(Scope scope, String id) throws IllegalAccessException {
        if (id == null) {
            throw new IllegalAccessException("id may not be null");
        }
        if (scope == Scope.ORGANIZATION) {
            return new StringBuilder("(& (objectclass=").append(Constants.ldap_ddbOrg_ObjectClass).append(") (")
                    .append(Constants.ldap_ddbOrg_Id).append("=").append(id).append("))").toString();
        } else if (scope == Scope.PERSON) {
            return new StringBuilder("(& (objectclass=").append(Constants.ldap_ddbPerson_ObjectClass).append(") (")
                    .append(Constants.ldap_ddbPerson_Id).append("=").append(id).append("))").toString();
        } else {
            throw new IllegalAccessException("scope does not match");
        }
    }

    /**
     * set modification-properties in LDAP.
     * 
     * @param isCreate
     *            if also createProperties should be set.
     * @param performer
     *            performer.
     * @param id
     *            id to set properties for.
     * @param scope
     *            scope.
     * 
     * @return
     * @throws
     */
    public void setModificationPropertiesInLdap(boolean isCreate, AasPrincipal performer, String id, Scope scope)
            throws NamingException, IllegalAccessException {
        String propertiesAttName = null;
        if (scope == Scope.PERSON) {
            propertiesAttName = Constants.ldap_ddbPerson_Properties;
        } else if (scope == Scope.ORGANIZATION) {
            propertiesAttName = Constants.ldap_ddbOrg_Properties;
        } else {
            throw new IllegalAccessException("scope does not match");
        }

        Map<String, String> attributes = getResourceAttributes(scope, id,
                new String[] { propertiesAttName, Constants.ldap_ddb_EntryDN });
        DdbProperties properties = null;
        String entryDn = null;
        if (attributes != null && StringUtils.isNotBlank(attributes.get(Constants.ldap_ddb_EntryDN))) {
            if (StringUtils.isNotBlank(attributes.get(propertiesAttName))) {
                properties = serializer.deserialize(attributes.get(propertiesAttName));
            }
            properties = PropertiesHelper.setModificationProperties(properties, isCreate, performer);
            entryDn = attributes.get(Constants.ldap_ddb_EntryDN);
        } else {
            throw new NameNotFoundException("entry with id=" + id + " not found");
        }
        InitialLdapContext ctx = null;
        try {
            ctx = LDAPConnector.getSingletonInstance().takeCtx();
            Attributes saveAttributes = new BasicAttributes(true);
            saveAttributes.put(new BasicAttribute(propertiesAttName, serializer.serialize(properties)));
            ctx.modifyAttributes(entryDn, DirContext.REPLACE_ATTRIBUTE, saveAttributes);
        } finally {
            if (ctx != null) {
                try {
                    LDAPConnector.getSingletonInstance().putCtx(ctx);
                } catch (IllegalAccessException ex) {
                    LOG.log(Level.SEVERE, null, ex);
                }
            }
        }

    }

    /**
     * generate unique confirmation-token
     * 
     * @return String unique confirmation-token
     */
    public String generateConfirmationToken() {
        return UUID.randomUUID().toString();
    }
}