Java tutorial
/* * 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(); } }