001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2016 ForgeRock AS. 016 */ 017package org.opends.guitools.controlpanel.util; 018 019import static org.forgerock.util.Reject.*; 020import static org.opends.messages.ConfigMessages.*; 021import static org.opends.server.util.StaticUtils.*; 022 023import java.io.File; 024import java.util.Collections; 025import java.util.HashMap; 026import java.util.Set; 027 028import org.forgerock.i18n.LocalizableMessage; 029import org.forgerock.opendj.config.server.ConfigException; 030import org.forgerock.opendj.ldap.ConditionResult; 031import org.opends.server.admin.std.server.BackendCfg; 032import org.opends.server.api.ConfigHandler; 033import org.opends.server.config.ConfigEntry; 034import org.opends.server.core.AddOperation; 035import org.opends.server.core.DeleteOperation; 036import org.opends.server.core.DirectoryServer; 037import org.opends.server.core.ModifyDNOperation; 038import org.opends.server.core.ModifyOperation; 039import org.opends.server.core.SearchOperation; 040import org.opends.server.core.ServerContext; 041import org.forgerock.opendj.ldap.schema.AttributeType; 042import org.opends.server.types.BackupConfig; 043import org.opends.server.types.BackupDirectory; 044import org.opends.server.types.CanceledOperationException; 045import org.forgerock.opendj.ldap.DN; 046import org.opends.server.types.DirectoryEnvironmentConfig; 047import org.opends.server.types.DirectoryException; 048import org.opends.server.types.Entry; 049import org.opends.server.types.IndexType; 050import org.opends.server.types.InitializationException; 051import org.opends.server.types.LDIFExportConfig; 052import org.opends.server.types.LDIFImportConfig; 053import org.opends.server.types.LDIFImportResult; 054import org.opends.server.types.RestoreConfig; 055import org.opends.server.util.LDIFException; 056import org.opends.server.util.LDIFReader; 057 058/** 059 * A class used to read the configuration from a file. This config file 060 * handler does not allow to modify the configuration, only to read it. 061 */ 062public class ReadOnlyConfigFileHandler extends ConfigHandler<BackendCfg> 063{ 064 /** 065 * The mapping that holds all of the configuration entries that have been read 066 * from the LDIF file. 067 */ 068 private HashMap<DN,ConfigEntry> configEntries = new HashMap<>(); 069 070 /** The reference to the configuration root entry. */ 071 private ConfigEntry configRootEntry; 072 073 /** The server root. */ 074 private String serverRoot; 075 076 /** The instance root. */ 077 private String instanceRoot; 078 079 private DN[] baseDNs; 080 081 /** {@inheritDoc} */ 082 @Override 083 public void finalizeConfigHandler() 084 { 085 finalizeBackend(); 086 } 087 088 /** {@inheritDoc} */ 089 @Override 090 public ConfigEntry getConfigEntry(DN entryDN) throws ConfigException 091 { 092 return configEntries.get(entryDN); 093 } 094 095 /** {@inheritDoc} */ 096 @Override 097 public ConfigEntry getConfigRootEntry() throws ConfigException 098 { 099 return configRootEntry; 100 } 101 102 /** {@inheritDoc} */ 103 @Override 104 public String getServerRoot() 105 { 106 return serverRoot; 107 } 108 109 /** {@inheritDoc} */ 110 @Override 111 public String getInstanceRoot() 112 { 113 return instanceRoot; 114 } 115 116 /** {@inheritDoc} */ 117 @Override 118 public synchronized void initializeConfigHandler(String configFile, 119 boolean checkSchema) 120 throws InitializationException 121 { 122 File f = new File(configFile); 123 // We will use the LDIF reader to read the configuration file. Create an 124 // LDIF import configuration to do this and then get the reader. 125 LDIFReader reader = null; 126 try 127 { 128 try 129 { 130 LDIFImportConfig importConfig = 131 new LDIFImportConfig(f.getAbsolutePath()); 132 133 reader = new LDIFReader(importConfig); 134 } 135 catch (Throwable t) 136 { 137 throw new InitializationException( 138 ERR_CONFIG_FILE_CANNOT_OPEN_FOR_READ.get(f.getAbsolutePath(), t), t); 139 } 140 141 if (! f.exists()) 142 { 143 LocalizableMessage message = 144 ERR_CONFIG_FILE_DOES_NOT_EXIST.get(f.getAbsolutePath()); 145 throw new InitializationException(message); 146 } 147 148 configEntries.clear(); 149 150 // Read the first entry from the configuration file. 151 Entry entry; 152 try 153 { 154 entry = reader.readEntry(checkSchema); 155 if (entry == null) 156 { 157 LocalizableMessage message = ERR_CONFIG_FILE_EMPTY.get(f.getAbsolutePath()); 158 throw new InitializationException(message); 159 } 160 configRootEntry = new ConfigEntry(entry, null); 161 162 baseDNs = new DN[] { configRootEntry.getDN() }; 163 164 configEntries.put(entry.getName(), configRootEntry); 165 // Iterate through the rest of the configuration file and process the 166 // remaining entries. 167 while (entry != null) 168 { 169 // Read the next entry from the configuration. 170 entry = reader.readEntry(checkSchema); 171 if (entry != null) 172 { 173 DN entryDN = entry.getName(); 174 DN parentDN = entryDN.parent(); 175 ConfigEntry parentEntry = null; 176 if (parentDN != null) 177 { 178 parentEntry = configEntries.get(parentDN); 179 } 180 if (parentEntry == null) 181 { 182 if (parentDN == null) 183 { 184 LocalizableMessage message = ERR_CONFIG_FILE_UNKNOWN_PARENT.get( 185 entryDN, reader.getLastEntryLineNumber(), f.getAbsolutePath()); 186 throw new InitializationException(message); 187 } 188 else 189 { 190 LocalizableMessage message = ERR_CONFIG_FILE_NO_PARENT.get(entryDN, 191 reader.getLastEntryLineNumber(), f.getAbsolutePath(), parentDN); 192 throw new InitializationException(message); 193 } 194 } 195 else 196 { 197 ConfigEntry configEntry = new ConfigEntry(entry, parentEntry); 198 parentEntry.addChild(configEntry); 199 configEntries.put(entryDN, configEntry); 200 } 201 } 202 } 203 } 204 catch (InitializationException ie) 205 { 206 throw ie; 207 } 208 catch (LDIFException le) 209 { 210 throw new InitializationException( 211 ERR_CONFIG_FILE_INVALID_LDIF_ENTRY.get(le.getLineNumber(), f.getAbsolutePath(), le), le); 212 } 213 catch (Throwable t) 214 { 215 throw new InitializationException( 216 ERR_CONFIG_FILE_READ_ERROR.get(f.getAbsolutePath(), t), t); 217 } 218 219 220 // Determine the appropriate server root. 221 File rootFile = DirectoryServer.getEnvironmentConfig().getServerRoot(); 222 serverRoot = rootFile.getAbsolutePath(); 223 224 File instanceRootFile = 225 DirectoryEnvironmentConfig.getInstanceRootFromServerRoot(rootFile); 226 instanceRoot = instanceRootFile.getAbsolutePath(); 227 } 228 catch (InitializationException ie) 229 { 230 throw ie; 231 } 232 catch (Throwable t) 233 { 234 } 235 finally 236 { 237 close(reader); 238 } 239 } 240 241 /** {@inheritDoc} */ 242 @Override 243 public void writeSuccessfulStartupConfig() 244 { 245 } 246 247 /** {@inheritDoc} */ 248 @Override 249 public void writeUpdatedConfig() throws DirectoryException 250 { 251 } 252 253 /** {@inheritDoc} */ 254 @Override 255 public void addEntry(Entry entry, AddOperation arg1) 256 throws DirectoryException, CanceledOperationException 257 { 258 } 259 260 /** {@inheritDoc} */ 261 @Override 262 public void configureBackend(BackendCfg cfg, ServerContext serverContext) throws ConfigException 263 { 264 } 265 266 /** {@inheritDoc} */ 267 @Override 268 public void createBackup(BackupConfig arg0) throws DirectoryException 269 { 270 } 271 272 /** {@inheritDoc} */ 273 @Override 274 public void deleteEntry(DN arg0, DeleteOperation arg1) 275 throws DirectoryException, CanceledOperationException 276 { 277 } 278 279 /** {@inheritDoc} */ 280 @Override 281 public void exportLDIF(LDIFExportConfig arg0) throws DirectoryException 282 { 283 } 284 285 /** {@inheritDoc} */ 286 @Override 287 public DN[] getBaseDNs() 288 { 289 return baseDNs; 290 } 291 292 /** {@inheritDoc} */ 293 @Override 294 public Entry getEntry(DN entryDN) 295 throws DirectoryException 296 { 297 ConfigEntry configEntry = configEntries.get(entryDN); 298 if (configEntry != null) 299 { 300 return configEntry.getEntry(); 301 } 302 return null; 303 } 304 305 /** {@inheritDoc} */ 306 @Override 307 public long getEntryCount() 308 { 309 return configEntries.size(); 310 } 311 312 /** {@inheritDoc} */ 313 @Override 314 public Set<String> getSupportedControls() 315 { 316 return Collections.emptySet(); 317 } 318 319 /** {@inheritDoc} */ 320 @Override 321 public Set<String> getSupportedFeatures() 322 { 323 return Collections.emptySet(); 324 } 325 326 /** {@inheritDoc} */ 327 @Override 328 public ConditionResult hasSubordinates(DN entryDN) throws DirectoryException 329 { 330 ConfigEntry baseEntry = configEntries.get(entryDN); 331 if (baseEntry != null) 332 { 333 return ConditionResult.valueOf(baseEntry.hasChildren()); 334 } 335 return ConditionResult.UNDEFINED; 336 } 337 338 /** {@inheritDoc} */ 339 @Override 340 public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext) 341 throws DirectoryException 342 { 343 return null; 344 } 345 346 /** {@inheritDoc} */ 347 @Override 348 public void openBackend() throws ConfigException, InitializationException 349 { 350 } 351 352 /** {@inheritDoc} */ 353 @Override 354 public boolean isIndexed(AttributeType arg0, IndexType arg1) 355 { 356 return false; 357 } 358 359 /** {@inheritDoc} */ 360 @Override 361 public long getNumberOfChildren(DN parentDN) throws DirectoryException { 362 checkNotNull(parentDN, "parentDN must not be null"); 363 return numSubordinates(parentDN, false); 364 } 365 366 /** {@inheritDoc} */ 367 @Override 368 public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException { 369 checkNotNull(baseDN, "baseDN must not be null"); 370 return numSubordinates(baseDN, true) + 1; 371 } 372 373 private long numSubordinates(DN entryDN, boolean subtree) throws DirectoryException 374 { 375 final ConfigEntry baseEntry = configEntries.get(entryDN); 376 if (baseEntry == null) 377 { 378 return -1; 379 } 380 381 if(!subtree) 382 { 383 return baseEntry.getChildren().size(); 384 } 385 long count = 0; 386 for (ConfigEntry child : baseEntry.getChildren().values()) 387 { 388 count += numSubordinates(child.getDN(), true); 389 count++; 390 } 391 return count; 392 } 393 394 /** {@inheritDoc} */ 395 @Override 396 public void removeBackup(BackupDirectory backupDirectory, String backupID) 397 throws DirectoryException 398 { 399 } 400 401 /** {@inheritDoc} */ 402 @Override 403 public void renameEntry(DN currentDN, Entry entry, ModifyDNOperation modifyDNOperation) 404 throws DirectoryException, CanceledOperationException 405 { 406 } 407 408 /** {@inheritDoc} */ 409 @Override 410 public void replaceEntry(Entry oldEntry, Entry newEntry, ModifyOperation modifyOperation) 411 throws DirectoryException, CanceledOperationException 412 { 413 } 414 415 /** {@inheritDoc} */ 416 @Override 417 public void restoreBackup(RestoreConfig restoreConfig) throws DirectoryException 418 { 419 } 420 421 /** {@inheritDoc} */ 422 @Override 423 public void search(SearchOperation searchOperation) 424 throws DirectoryException, CanceledOperationException 425 { 426 } 427 428 /** {@inheritDoc} */ 429 @Override 430 public boolean supports(BackendOperation backendOperation) 431 { 432 return false; 433 } 434}