/* * ==================== * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2008-2009 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common Development * and Distribution License("CDDL") (the "License"). You may not use this file * except in compliance with the License. * * You can obtain a copy of the License at * http://IdentityConnectors.dev.java.net/legal/license.txt * See the License for the specific language governing permissions and limitations * under the License. * * When distributing the Covered Code, include this CDDL Header Notice in each file * and include the License file at identityconnectors/legal/license.txt. * If applicable, add the following below this CDDL Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * ==================== */ package org.identityconnectors.ldap.sync.sunds; import org.testng.annotations.Test; import static org.identityconnectors.ldap.LdapUtil.quietCreateLdapName; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.ModificationItem; import javax.naming.ldap.LdapContext; import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import org.identityconnectors.common.logging.Log; import org.identityconnectors.ldap.LdapConnection; import org.identityconnectors.ldap.sync.sunds.LdifParser.ChangeSeparator; import org.identityconnectors.ldap.sync.sunds.LdifParser.Line; import org.identityconnectors.ldap.sync.sunds.LdifParser.NameValue; import org.identityconnectors.ldap.sync.sunds.LdifParser.Separator; /** * A simple, and in no way complete, way to modify an LDAP server * based on an LDIF file. */ public class LdapModifyForTests { private static final Log log = Log.getLog(LdapModifyForTests.class); public static void modify(LdapConnection conn, String ldif) throws NamingException { LdifParser parser = new LdifParser(ldif); Iterator<Line> lines = parser.iterator(); String dn = null; String changeType = null; Map<String, List<String>> added = new HashMap<String, List<String>>(); Map<String, List<String>> deleted = new HashMap<String, List<String>>(); Map<String, List<String>> modifyMap = null; String newRdn = null; String deleteOldRdn = "true"; while (lines.hasNext()) { Line line = lines.next(); if (line instanceof ChangeSeparator && dn != null) { performChange(conn, dn, changeType, added, deleted, newRdn, deleteOldRdn); dn = null; changeType = null; added.clear(); deleted.clear(); modifyMap = null; newRdn = null; deleteOldRdn = "true"; continue; } if (dn == null) { NameValue nameValue = (NameValue) line; if (!"dn".equalsIgnoreCase(nameValue.getName())) { throw new IllegalArgumentException(); } dn = nameValue.getValue(); continue; } if (changeType == null) { NameValue nameValue = (NameValue) line; if (!"changeType".equalsIgnoreCase(nameValue.getName())) { throw new IllegalArgumentException(); } changeType = nameValue.getValue(); continue; } if ("add".equalsIgnoreCase(changeType)) { NameValue nameValue = (NameValue) line; List<String> values = added.get(nameValue.getName()); if (values == null) { values = new ArrayList<String>(); added.put(nameValue.getName(), values); } values.add(nameValue.getValue()); } else if ("modify".equalsIgnoreCase(changeType)) { if (line instanceof Separator) { modifyMap = null; continue; } if (modifyMap == null) { NameValue nameValue = (NameValue) line; String op = nameValue.getName(); if ("add".equalsIgnoreCase(op)) { modifyMap = added; } else if ("delete".equalsIgnoreCase(op)) { modifyMap = deleted; } else { throw new IllegalArgumentException(); } continue; } if (modifyMap != null) { NameValue nameValue = (NameValue) line; List<String> values = modifyMap.get(nameValue.getName()); if (values == null) { values = new ArrayList<String>(); modifyMap.put(nameValue.getName(), values); } values.add(nameValue.getValue()); } } else if ("modrdn".equalsIgnoreCase(changeType)) { NameValue nameValue = (NameValue) line; if ("newRdn".equalsIgnoreCase(nameValue.getName())) { newRdn = nameValue.getValue(); } else if ("deleteOldRdn".equalsIgnoreCase(nameValue.getName())) { deleteOldRdn = nameValue.getValue().toLowerCase(Locale.US); } } } } private static void performChange(LdapConnection conn, String dn, String changeType, Map<String, List<String>> added, Map<String, List<String>> deleted, String newRdn, String deleteOldRdn) throws NamingException { if ("add".equalsIgnoreCase(changeType)) { BasicAttributes attrs = new BasicAttributes(); for (Entry<String, List<String>> entry : added.entrySet()) { Attribute attr = new BasicAttribute(entry.getKey()); for (String each : entry.getValue()) { attr.add(each); } attrs.put(attr); } LdapName newName = quietCreateLdapName(dn); log.ok("Creating context {0} with attributes {1}", newName, attrs); String container = newName.getPrefix(newName.size() - 1).toString(); Rdn rdn = newName.getRdn(newName.size() - 1); LdapContext containerCtx = (LdapContext) conn.getInitialContext().lookup(container); containerCtx.createSubcontext(rdn.toString(), attrs); } else if ("modify".equalsIgnoreCase(changeType)) { List<ModificationItem> modItems = new ArrayList<ModificationItem>(); addModificationItems(DirContext.ADD_ATTRIBUTE, added, modItems); addModificationItems(DirContext.REMOVE_ATTRIBUTE, deleted, modItems); log.ok("Modifying context {0} with attributes {1}", dn, modItems); conn.getInitialContext().modifyAttributes(dn, modItems.toArray(new ModificationItem[modItems.size()])); } else if ("delete".equalsIgnoreCase(changeType)) { log.ok("Deleting context {0}"); conn.getInitialContext().destroySubcontext(dn); } else if ("modrdn".equalsIgnoreCase(changeType)) { LdapName oldName = quietCreateLdapName(dn); LdapName newName = (LdapName) oldName.getPrefix(oldName.size() - 1); newName.add(newRdn); log.ok("Renaming context {0} to {1}", oldName, newName); LdapContext ctx = conn.getInitialContext().newInstance(null); try { ctx.addToEnvironment("java.naming.ldap.deleteRDN", deleteOldRdn); ctx.rename(oldName, newName); } finally { ctx.close(); } } } private static void addModificationItems(int operation, Map<String, List<String>> map, List<ModificationItem> toList) { for (Entry<String, List<String>> entry : map.entrySet()) { Attribute attr = new BasicAttribute(entry.getKey()); for (String each : entry.getValue()) { attr.add(each); } toList.add(new ModificationItem(operation, attr)); } } @Test public void dummy() { // This is here because the class needs to end in "Tests" for it not to be // included in the jar, but then JUnit complains about no runnable methods. } }