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