001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008 Sun Microsystems, Inc. 025 * Portions copyright 2014-2015 ForgeRock AS. 026 */ 027 028package org.forgerock.opendj.config.client.ldap; 029 030import static org.forgerock.opendj.ldap.Connections.*; 031 032import java.io.BufferedReader; 033import java.io.BufferedWriter; 034import java.io.File; 035import java.io.FileReader; 036import java.io.FileWriter; 037import java.io.IOException; 038import java.util.ArrayList; 039import java.util.Iterator; 040import java.util.List; 041import java.util.SortedSet; 042 043import org.forgerock.i18n.LocalizableMessage; 044import org.forgerock.i18n.slf4j.LocalizedLogger; 045import org.forgerock.opendj.config.AbstractManagedObjectDefinition; 046import org.forgerock.opendj.config.Configuration; 047import org.forgerock.opendj.config.ConfigurationClient; 048import org.forgerock.opendj.config.DefinitionDecodingException; 049import org.forgerock.opendj.config.InstantiableRelationDefinition; 050import org.forgerock.opendj.config.LDAPProfile; 051import org.forgerock.opendj.config.ManagedObjectNotFoundException; 052import org.forgerock.opendj.config.ManagedObjectPath; 053import org.forgerock.opendj.config.OptionalRelationDefinition; 054import org.forgerock.opendj.config.PropertyDefinition; 055import org.forgerock.opendj.config.SetRelationDefinition; 056import org.forgerock.opendj.config.client.DriverBasedManagementContext; 057import org.forgerock.opendj.config.client.ManagedObject; 058import org.forgerock.opendj.config.client.ManagedObjectDecodingException; 059import org.forgerock.opendj.config.client.ManagementContext; 060import org.forgerock.opendj.config.client.OperationRejectedException; 061import org.forgerock.opendj.config.client.spi.Driver; 062import org.forgerock.opendj.ldap.AbstractConnectionWrapper; 063import org.forgerock.opendj.ldap.Connection; 064import org.forgerock.opendj.ldap.Entry; 065import org.forgerock.opendj.ldap.LdapException; 066import org.forgerock.opendj.ldap.MemoryBackend; 067import org.forgerock.opendj.ldap.requests.UnbindRequest; 068import org.forgerock.opendj.ldif.LDIF; 069import org.forgerock.opendj.ldif.LDIFEntryReader; 070import org.forgerock.opendj.ldif.LDIFEntryWriter; 071import org.forgerock.opendj.server.config.client.RootCfgClient; 072import org.forgerock.util.Reject; 073 074/** 075 * An LDAP management connection context. 076 */ 077public final class LDAPManagementContext extends DriverBasedManagementContext { 078 079 private static final class ManagementContextWrapper implements ManagementContext { 080 private final ManagementContext delegate; 081 private final List<IOException> exceptions; 082 083 private ManagementContextWrapper(ManagementContext result, List<IOException> exceptions) { 084 this.delegate = result; 085 this.exceptions = exceptions; 086 } 087 088 @Override 089 public boolean managedObjectExists(ManagedObjectPath<?, ?> path) throws ManagedObjectNotFoundException, 090 LdapException { 091 return delegate.managedObjectExists(path); 092 } 093 094 @Override 095 public <C extends ConfigurationClient, S extends Configuration> String[] listManagedObjects( 096 ManagedObjectPath<?, ?> parent, SetRelationDefinition<C, S> rd) throws ManagedObjectNotFoundException, 097 LdapException { 098 return delegate.listManagedObjects(parent, rd); 099 } 100 101 @Override 102 public <C extends ConfigurationClient, S extends Configuration> String[] listManagedObjects( 103 ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd, 104 AbstractManagedObjectDefinition<? extends C, ? extends S> d) throws ManagedObjectNotFoundException, 105 LdapException { 106 return delegate.listManagedObjects(parent, rd, d); 107 } 108 109 @Override 110 public <C extends ConfigurationClient, S extends Configuration> String[] listManagedObjects( 111 ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd) 112 throws ManagedObjectNotFoundException, LdapException { 113 return delegate.listManagedObjects(parent, rd); 114 } 115 116 @Override 117 public ManagedObject<RootCfgClient> getRootConfigurationManagedObject() { 118 return delegate.getRootConfigurationManagedObject(); 119 } 120 121 @Override 122 public RootCfgClient getRootConfiguration() { 123 return delegate.getRootConfiguration(); 124 } 125 126 @Override 127 public <P> SortedSet<P> getPropertyValues(ManagedObjectPath<?, ?> path, PropertyDefinition<P> pd) 128 throws DefinitionDecodingException, LdapException, ManagedObjectNotFoundException { 129 return delegate.getPropertyValues(path, pd); 130 } 131 132 @Override 133 public <P> P getPropertyValue(ManagedObjectPath<?, ?> path, PropertyDefinition<P> pd) 134 throws DefinitionDecodingException, LdapException, ManagedObjectNotFoundException { 135 return delegate.getPropertyValue(path, pd); 136 } 137 138 @Override 139 public <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getManagedObject( 140 ManagedObjectPath<C, S> path) throws DefinitionDecodingException, ManagedObjectDecodingException, 141 ManagedObjectNotFoundException, LdapException { 142 return delegate.getManagedObject(path); 143 } 144 145 @Override 146 public <C extends ConfigurationClient, S extends Configuration> boolean deleteManagedObject( 147 ManagedObjectPath<?, ?> parent, SetRelationDefinition<C, S> rd, String name) 148 throws ManagedObjectNotFoundException, OperationRejectedException, LdapException { 149 return delegate.deleteManagedObject(parent, rd, name); 150 } 151 152 @Override 153 public <C extends ConfigurationClient, S extends Configuration> boolean deleteManagedObject( 154 ManagedObjectPath<?, ?> parent, OptionalRelationDefinition<C, S> rd) 155 throws ManagedObjectNotFoundException, OperationRejectedException, LdapException { 156 return delegate.deleteManagedObject(parent, rd); 157 } 158 159 @Override 160 public <C extends ConfigurationClient, S extends Configuration> boolean deleteManagedObject( 161 ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd, String name) 162 throws ManagedObjectNotFoundException, OperationRejectedException, LdapException { 163 return delegate.deleteManagedObject(parent, rd, name); 164 } 165 166 @Override 167 public void close() throws IOException { 168 delegate.close(); 169 if (!exceptions.isEmpty()) { 170 throw exceptions.get(0); 171 } 172 } 173 } 174 175 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 176 177 /** 178 * Create a new LDAP management context using the provided LDAP connection. 179 * 180 * @param connection 181 * The LDAP connection. 182 * @param profile 183 * The LDAP profile. 184 * @return Returns the new management context. 185 */ 186 public static ManagementContext newManagementContext(Connection connection, LDAPProfile profile) { 187 Reject.ifNull(connection, profile); 188 LDAPDriver driver = new LDAPDriver(connection, profile); 189 LDAPManagementContext context = new LDAPManagementContext(driver); 190 driver.setManagementContext(context); 191 return context; 192 } 193 194 private static ManagementContext newLDIFManagementContext(final File ldifFile, final LDAPProfile profile, 195 final List<IOException> exceptions) throws IOException { 196 final BufferedReader configReader = new BufferedReader(new FileReader(ldifFile)); 197 try { 198 final MemoryBackend memoryBackend = new MemoryBackend(new LDIFEntryReader(configReader)); 199 final Connection co = new AbstractConnectionWrapper<Connection>(newInternalConnection(memoryBackend)) { 200 @Override 201 public void close() { 202 try { 203 final BufferedWriter configWriter = new BufferedWriter(new FileWriter(ldifFile)); 204 try { 205 final Iterator<Entry> entries = memoryBackend.getAll().iterator(); 206 entries.next(); // skip RootDSE 207 LDIF.copyTo(LDIF.newEntryIteratorReader(entries), new LDIFEntryWriter(configWriter)); 208 } finally { 209 configWriter.close(); 210 } 211 } catch (IOException e) { 212 if (exceptions != null) { 213 exceptions.add(e); 214 } else { 215 logger.error(LocalizableMessage.raw( 216 "IOException occured during LDIF context management close:", e)); 217 } 218 } 219 } 220 221 @Override 222 public void close(UnbindRequest request, String reason) { 223 close(); 224 } 225 }; 226 227 // We need to add the root dse entry to make the configuration framework work. 228 co.add(LDIFEntryReader.valueOfLDIFEntry("dn:", "objectClass:top", "objectClass:ds-root-dse")); 229 return LDAPManagementContext.newManagementContext(co, LDAPProfile.getInstance()); 230 } finally { 231 configReader.close(); 232 } 233 } 234 235 /** 236 * Returns a LDIF management context on the provided LDIF file. 237 * 238 * @param ldifFile 239 * The LDIF file to manage 240 * @param profile 241 * The LDAP profile 242 * @return A LDIF file management context 243 * @throws IOException 244 * If problems occurs while reading the file. 245 */ 246 public static ManagementContext newLDIFManagementContext(final File ldifFile, final LDAPProfile profile) 247 throws IOException { 248 final List<IOException> exceptions = new ArrayList<>(); 249 return new ManagementContextWrapper(newLDIFManagementContext(ldifFile, profile, exceptions), exceptions); 250 } 251 252 /** The LDAP management context driver. */ 253 private final LDAPDriver driver; 254 255 /** Private constructor. */ 256 private LDAPManagementContext(LDAPDriver driver) { 257 this.driver = driver; 258 } 259 260 /** {@inheritDoc} */ 261 @Override 262 protected Driver getDriver() { 263 return driver; 264 } 265}