/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions Copyright 2014-2015 ForgeRock AS
*/
package org.opends.guitools.controlpanel.util;
import static org.forgerock.util.Reject.*;
import static org.opends.messages.ConfigMessages.*;
import static org.opends.server.util.StaticUtils.*;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Set;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.ConditionResult;
import org.opends.server.admin.std.server.BackendCfg;
import org.opends.server.api.ConfigHandler;
import org.opends.server.config.ConfigEntry;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.SearchOperation;
import org.opends.server.core.ServerContext;
import org.opends.server.types.AttributeType;
import org.opends.server.types.BackupConfig;
import org.opends.server.types.BackupDirectory;
import org.opends.server.types.CanceledOperationException;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryEnvironmentConfig;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.IndexType;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.LDIFImportResult;
import org.opends.server.types.RestoreConfig;
import org.opends.server.util.LDIFException;
import org.opends.server.util.LDIFReader;
/**
* A class used to read the configuration from a file. This config file
* handler does not allow to modify the configuration, only to read it.
*/
public class ReadOnlyConfigFileHandler extends ConfigHandler<BackendCfg>
{
/**
* The mapping that holds all of the configuration entries that have been read
* from the LDIF file.
*/
private HashMap<DN,ConfigEntry> configEntries = new HashMap<>();
/** The reference to the configuration root entry. */
private ConfigEntry configRootEntry;
/** The server root. */
private String serverRoot;
/** The instance root. */
private String instanceRoot;
private DN[] baseDNs;
/** {@inheritDoc} */
@Override
public void finalizeConfigHandler()
{
finalizeBackend();
}
/** {@inheritDoc} */
@Override
public ConfigEntry getConfigEntry(DN entryDN) throws ConfigException
{
return configEntries.get(entryDN);
}
/** {@inheritDoc} */
@Override
public ConfigEntry getConfigRootEntry() throws ConfigException
{
return configRootEntry;
}
/** {@inheritDoc} */
@Override
public String getServerRoot()
{
return serverRoot;
}
/** {@inheritDoc} */
@Override
public String getInstanceRoot()
{
return instanceRoot;
}
/** {@inheritDoc} */
@Override
public synchronized void initializeConfigHandler(String configFile,
boolean checkSchema)
throws InitializationException
{
File f = new File(configFile);
// We will use the LDIF reader to read the configuration file. Create an
// LDIF import configuration to do this and then get the reader.
LDIFReader reader = null;
try
{
try
{
LDIFImportConfig importConfig =
new LDIFImportConfig(f.getAbsolutePath());
reader = new LDIFReader(importConfig);
}
catch (Throwable t)
{
throw new InitializationException(
ERR_CONFIG_FILE_CANNOT_OPEN_FOR_READ.get(f.getAbsolutePath(), t), t);
}
if (! f.exists())
{
LocalizableMessage message =
ERR_CONFIG_FILE_DOES_NOT_EXIST.get(f.getAbsolutePath());
throw new InitializationException(message);
}
configEntries.clear();
// Read the first entry from the configuration file.
Entry entry;
try
{
entry = reader.readEntry(checkSchema);
if (entry == null)
{
LocalizableMessage message = ERR_CONFIG_FILE_EMPTY.get(f.getAbsolutePath());
throw new InitializationException(message);
}
configRootEntry = new ConfigEntry(entry, null);
baseDNs = new DN[] { configRootEntry.getDN() };
configEntries.put(entry.getName(), configRootEntry);
// Iterate through the rest of the configuration file and process the
// remaining entries.
while (entry != null)
{
// Read the next entry from the configuration.
entry = reader.readEntry(checkSchema);
if (entry != null)
{
DN entryDN = entry.getName();
DN parentDN = entryDN.parent();
ConfigEntry parentEntry = null;
if (parentDN != null)
{
parentEntry = configEntries.get(parentDN);
}
if (parentEntry == null)
{
if (parentDN == null)
{
LocalizableMessage message = ERR_CONFIG_FILE_UNKNOWN_PARENT.get(
entryDN, reader.getLastEntryLineNumber(), f.getAbsolutePath());
throw new InitializationException(message);
}
else
{
LocalizableMessage message = ERR_CONFIG_FILE_NO_PARENT.get(entryDN,
reader.getLastEntryLineNumber(), f.getAbsolutePath(), parentDN);
throw new InitializationException(message);
}
}
else
{
ConfigEntry configEntry = new ConfigEntry(entry, parentEntry);
parentEntry.addChild(configEntry);
configEntries.put(entryDN, configEntry);
}
}
}
}
catch (InitializationException ie)
{
throw ie;
}
catch (LDIFException le)
{
throw new InitializationException(
ERR_CONFIG_FILE_INVALID_LDIF_ENTRY.get(le.getLineNumber(), f.getAbsolutePath(), le), le);
}
catch (Throwable t)
{
throw new InitializationException(
ERR_CONFIG_FILE_READ_ERROR.get(f.getAbsolutePath(), t), t);
}
// Determine the appropriate server root.
File rootFile = DirectoryServer.getEnvironmentConfig().getServerRoot();
serverRoot = rootFile.getAbsolutePath();
File instanceRootFile =
DirectoryEnvironmentConfig.getInstanceRootFromServerRoot(rootFile);
instanceRoot = instanceRootFile.getAbsolutePath();
}
catch (InitializationException ie)
{
throw ie;
}
catch (Throwable t)
{
}
finally
{
close(reader);
}
}
/** {@inheritDoc} */
@Override
public void writeSuccessfulStartupConfig()
{
}
/** {@inheritDoc} */
@Override
public void writeUpdatedConfig() throws DirectoryException
{
}
/** {@inheritDoc} */
@Override
public void addEntry(Entry entry, AddOperation arg1)
throws DirectoryException, CanceledOperationException
{
}
/** {@inheritDoc} */
@Override
public void configureBackend(BackendCfg cfg, ServerContext serverContext) throws ConfigException
{
}
/** {@inheritDoc} */
@Override
public void createBackup(BackupConfig arg0) throws DirectoryException
{
}
/** {@inheritDoc} */
@Override
public void deleteEntry(DN arg0, DeleteOperation arg1)
throws DirectoryException, CanceledOperationException
{
}
/** {@inheritDoc} */
@Override
public void exportLDIF(LDIFExportConfig arg0) throws DirectoryException
{
}
/** {@inheritDoc} */
@Override
public DN[] getBaseDNs()
{
return baseDNs;
}
/** {@inheritDoc} */
@Override
public Entry getEntry(DN entryDN)
throws DirectoryException
{
ConfigEntry configEntry = configEntries.get(entryDN);
if (configEntry != null)
{
return configEntry.getEntry();
}
return null;
}
/** {@inheritDoc} */
@Override
public long getEntryCount()
{
return configEntries.size();
}
/** {@inheritDoc} */
@Override
public Set<String> getSupportedControls()
{
return Collections.emptySet();
}
/** {@inheritDoc} */
@Override
public Set<String> getSupportedFeatures()
{
return Collections.emptySet();
}
/** {@inheritDoc} */
@Override
public ConditionResult hasSubordinates(DN entryDN) throws DirectoryException
{
ConfigEntry baseEntry = configEntries.get(entryDN);
if (baseEntry != null)
{
return ConditionResult.valueOf(baseEntry.hasChildren());
}
return ConditionResult.UNDEFINED;
}
/** {@inheritDoc} */
@Override
public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext)
throws DirectoryException
{
return null;
}
/** {@inheritDoc} */
@Override
public void openBackend() throws ConfigException, InitializationException
{
}
/** {@inheritDoc} */
@Override
public boolean isIndexed(AttributeType arg0, IndexType arg1)
{
return false;
}
/** {@inheritDoc} */
@Override
public long getNumberOfChildren(DN parentDN) throws DirectoryException {
checkNotNull(parentDN, "parentDN must not be null");
return numSubordinates(parentDN, false);
}
/** {@inheritDoc} */
@Override
public long getNumberOfEntriesInBaseDN(DN baseDN) throws DirectoryException {
checkNotNull(baseDN, "baseDN must not be null");
return numSubordinates(baseDN, true) + 1;
}
private long numSubordinates(DN entryDN, boolean subtree) throws DirectoryException
{
final ConfigEntry baseEntry = configEntries.get(entryDN);
if (baseEntry == null)
{
return -1;
}
if(!subtree)
{
return baseEntry.getChildren().size();
}
long count = 0;
for (ConfigEntry child : baseEntry.getChildren().values())
{
count += numSubordinates(child.getDN(), true);
count++;
}
return count;
}
/** {@inheritDoc} */
@Override
public void removeBackup(BackupDirectory backupDirectory, String backupID)
throws DirectoryException
{
}
/** {@inheritDoc} */
@Override
public void renameEntry(DN currentDN, Entry entry, ModifyDNOperation modifyDNOperation)
throws DirectoryException, CanceledOperationException
{
}
/** {@inheritDoc} */
@Override
public void replaceEntry(Entry oldEntry, Entry newEntry, ModifyOperation modifyOperation)
throws DirectoryException, CanceledOperationException
{
}
/** {@inheritDoc} */
@Override
public void restoreBackup(RestoreConfig restoreConfig) throws DirectoryException
{
}
/** {@inheritDoc} */
@Override
public void search(SearchOperation searchOperation)
throws DirectoryException, CanceledOperationException
{
}
/** {@inheritDoc} */
@Override
public boolean supports(BackendOperation backendOperation)
{
return false;
}
}