ReferentialIntegrityPlugin.java revision ea1068c292e9b341af6d6b563cd8988a96be20a9
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster/*
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * CDDL HEADER START
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The contents of this file are subject to the terms of the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Common Development and Distribution License, Version 1.0 only
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * (the "License"). You may not use this file except in compliance
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * or http://forgerock.org/license/CDDLv1.0.html.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * See the License for the specific language governing permissions
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * and limitations under the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * When distributing Covered Code, include this CDDL HEADER in each
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * file and include the License file at legal-notices/CDDLv1_0.txt.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If applicable, add the following below this CDDL HEADER, with the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * fields enclosed by brackets "[]" replaced with your own identifying
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * information:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Portions Copyright [yyyy] [name of copyright owner]
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * CDDL HEADER END
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Copyright 2008-2010 Sun Microsystems, Inc.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Portions Copyright 2011-2015 ForgeRock AS.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Portions copyright 2011 profiq s.r.o.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
3286da3756e1d2f07709aafdbc5419b26ff71dffPhill Cunningtonpackage org.opends.server.plugins;
3286da3756e1d2f07709aafdbc5419b26ff71dffPhill Cunnington
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport static org.opends.messages.PluginMessages.*;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport static org.opends.server.protocols.internal.InternalClientConnection.*;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport static org.opends.server.protocols.internal.Requests.*;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport static org.opends.server.schema.SchemaConstants.*;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport static org.opends.server.util.StaticUtils.*;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.BufferedReader;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.io.BufferedWriter;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.io.File;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.io.FileReader;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.io.FileWriter;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.io.IOException;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.util.Collections;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.util.HashSet;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.util.LinkedHashMap;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.util.LinkedHashSet;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.util.LinkedList;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.util.List;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.util.Map;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport java.util.Set;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.i18n.LocalizableMessage;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.i18n.slf4j.LocalizedLogger;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.opendj.config.server.ConfigChangeResult;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.opendj.config.server.ConfigException;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.opendj.ldap.ByteString;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.opendj.ldap.ModificationType;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.opendj.ldap.ResultCode;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.opendj.ldap.SearchScope;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.opends.server.admin.server.ConfigurationChangeListener;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.opends.server.admin.std.meta.PluginCfgDefn;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.admin.std.meta.ReferentialIntegrityPluginCfgDefn.CheckReferencesScopeCriteria;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.admin.std.server.PluginCfg;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.admin.std.server.ReferentialIntegrityPluginCfg;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.api.Backend;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.api.DirectoryThread;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.api.ServerShutdownListener;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.api.plugin.DirectoryServerPlugin;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.api.plugin.PluginResult;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.api.plugin.PluginType;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.core.DeleteOperation;
3286da3756e1d2f07709aafdbc5419b26ff71dffPhill Cunningtonimport org.opends.server.core.DirectoryServer;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.core.ModifyOperation;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.protocols.internal.InternalClientConnection;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.protocols.internal.InternalSearchOperation;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.protocols.internal.SearchRequest;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.opends.server.types.*;
564945e59b60a40c3b9458177b2ff63e2947686cPeter Majorimport org.opends.server.types.operation.PostOperationDeleteOperation;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.types.operation.PostOperationModifyDNOperation;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.types.operation.PreOperationAddOperation;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.types.operation.PreOperationModifyOperation;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport org.opends.server.types.operation.SubordinateModifyDNOperation;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster/**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This class implements a Directory Server post operation plugin that performs
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Referential Integrity processing on successful delete and modify DN
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * operations. The plugin uses a set of configuration criteria to determine
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * what attribute types to check referential integrity on, and, the set of
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * base DNs to search for entries that might need referential integrity
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * processing. If none of these base DNs are specified in the configuration,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * then the public naming contexts are used as the base DNs by default.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <BR><BR>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The plugin also has an option to process changes in background using
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * a thread that wakes up periodically looking for change records in a log
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * file.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterpublic class ReferentialIntegrityPlugin
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas extends DirectoryServerPlugin<ReferentialIntegrityPluginCfg>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster implements ConfigurationChangeListener<ReferentialIntegrityPluginCfg>,
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas ServerShutdownListener
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster{
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //Current plugin configuration.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private ReferentialIntegrityPluginCfg currentConfiguration;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //List of attribute types that will be checked during referential integrity
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //processing.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private LinkedHashSet<AttributeType>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster attributeTypes = new LinkedHashSet<AttributeType>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //List of base DNs that limit the scope of the referential integrity checking.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private Set<DN> baseDNs = new LinkedHashSet<DN>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //The update interval the background thread uses. If it is 0, then
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //the changes are processed in foreground.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private long interval;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden //The flag used by the background thread to check if it should exit.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden private boolean stopRequested=false;
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major //The thread name.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden private static final String name =
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden "Referential Integrity Background Update Thread";
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden //The name of the logfile that the update thread uses to process change
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major //records. Defaults to "logs/referint", but can be changed in the
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major //configuration.
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major private String logFileName;
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major //The File class that logfile corresponds to.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden private File logFile;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden //The Thread class that the background thread corresponds to.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden private Thread backGroundThread=null;
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major /**
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * Used to save a map in the modifyDN operation attachment map that holds
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * the old entry DNs and the new entry DNs related to a modify DN rename to
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major * new superior operation.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden public static final String MODIFYDN_DNS="modifyDNs";
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major /**
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major * Used to save a set in the delete operation attachment map that
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major * holds the subordinate entry DNs related to a delete operation.
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major */
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major public static final String DELETE_DNS="deleteDNs";
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //The buffered reader that is used to read the log file by the background
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //thread.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private BufferedReader reader;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
e6d7ebe1d98f7f030969e521b061f8643253475eDirk Hogan //The buffered writer that is used to write update records in the log
e6d7ebe1d98f7f030969e521b061f8643253475eDirk Hogan //when the plugin is in background processing mode.
e6d7ebe1d98f7f030969e521b061f8643253475eDirk Hogan private BufferedWriter writer;
e6d7ebe1d98f7f030969e521b061f8643253475eDirk Hogan
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /* Specifies the mapping between the attribute type (specified in the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * attributeTypes list) and the filter which the plugin should use
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * to verify the integrity of the value of the given attribute.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private LinkedHashMap<AttributeType, SearchFilter> attrFiltMap =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster new LinkedHashMap<AttributeType, SearchFilter>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * {@inheritDoc}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @Override
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public final void initializePlugin(Set<PluginType> pluginTypes,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ReferentialIntegrityPluginCfg pluginCfg)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throws ConfigException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster pluginCfg.addReferentialIntegrityChangeListener(this);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster LinkedList<LocalizableMessage> unacceptableReasons = new LinkedList<LocalizableMessage>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (!isConfigurationAcceptable(pluginCfg, unacceptableReasons))
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ConfigException(unacceptableReasons.getFirst());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster applyConfigurationChange(pluginCfg);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // Set up log file. Note: it is not allowed to change once the plugin is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // active.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster setUpLogFile(pluginCfg.getLogFile());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster interval=pluginCfg.getUpdateInterval();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //Set up background processing if interval > 0.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(interval > 0)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster setUpBackGroundProcessing();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * {@inheritDoc}
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @Override
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major public ConfigChangeResult applyConfigurationChange(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ReferentialIntegrityPluginCfg newConfiguration)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster final ConfigChangeResult ccr = new ConfigChangeResult();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //Load base DNs from new configuration.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster LinkedHashSet<DN> newConfiguredBaseDNs = new LinkedHashSet<DN>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(DN baseDN : newConfiguration.getBaseDN())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster newConfiguredBaseDNs.add(baseDN);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //Load attribute types from new configuration.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster LinkedHashSet<AttributeType> newAttributeTypes =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster new LinkedHashSet<AttributeType>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (AttributeType type : newConfiguration.getAttributeType())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster newAttributeTypes.add(type);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // Load the attribute-filter mapping
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster LinkedHashMap<AttributeType, SearchFilter> newAttrFiltMap =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster new LinkedHashMap<AttributeType, SearchFilter>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (String attrFilt : newConfiguration.getCheckReferencesFilterCriteria())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int sepInd = attrFilt.lastIndexOf(":");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String attr = attrFilt.substring(0, sepInd);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String filtStr = attrFilt.substring(sepInd + 1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster AttributeType attrType =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster DirectoryServer.getAttributeType(attr.toLowerCase());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster SearchFilter filter =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster SearchFilter.createFilterFromString(filtStr);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster newAttrFiltMap.put(attrType, filter);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster catch (DirectoryException de)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /* This should never happen because the filter has already
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * been verified.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster logger.error(de.getMessageObject());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //User is not allowed to change the logfile name, append a message that the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //server needs restarting for change to take effect.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // The first time the plugin is initialised the 'logFileName' is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // not initialised, so in order to verify if it is equal to the new
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // log file name, we have to make sure the variable is not null.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String newLogFileName=newConfiguration.getLogFile();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(logFileName != null && !logFileName.equals(newLogFileName))
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ccr.setAdminActionRequired(true);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ccr.addMessage(INFO_PLUGIN_REFERENT_LOGFILE_CHANGE_REQUIRES_RESTART.get(logFileName, newLogFileName));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //Switch to the new lists.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster baseDNs = newConfiguredBaseDNs;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster attributeTypes = newAttributeTypes;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster attrFiltMap = newAttrFiltMap;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //If the plugin is enabled and the interval has changed, process that
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //change. The change might start or stop the background processing thread.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster long newInterval=newConfiguration.getUpdateInterval();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (newConfiguration.isEnabled() && newInterval != interval)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster processIntervalChange(newInterval, ccr.getMessages());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster currentConfiguration = newConfiguration;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return ccr;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest * {@inheritDoc}
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest */
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest @Override
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public boolean isConfigurationAcceptable(PluginCfg configuration,
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest List<LocalizableMessage> unacceptableReasons)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster boolean isAcceptable = true;
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest ReferentialIntegrityPluginCfg pluginCfg =
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest (ReferentialIntegrityPluginCfg) configuration;
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest for (PluginCfgDefn.PluginType t : pluginCfg.getPluginType())
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest switch (t)
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest case POSTOPERATIONDELETE:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster case POSTOPERATIONMODIFYDN:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster case SUBORDINATEMODIFYDN:
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest case SUBORDINATEDELETE:
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest case PREOPERATIONMODIFY:
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest case PREOPERATIONADD:
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest // These are acceptable.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster break;
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster default:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster isAcceptable = false;
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest unacceptableReasons.add(ERR_PLUGIN_REFERENT_INVALID_PLUGIN_TYPE.get(t));
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest }
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest }
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest Set<DN> cfgBaseDNs = pluginCfg.getBaseDN();
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest if ((cfgBaseDNs == null) || cfgBaseDNs.isEmpty())
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest cfgBaseDNs = DirectoryServer.getPublicNamingContexts().keySet();
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest }
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest // Iterate through all of the defined attribute types and ensure that they
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // have acceptable syntaxes and that they are indexed for equality below all
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // base DNs.
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest Set<AttributeType> theAttributeTypes = pluginCfg.getAttributeType();
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest for (AttributeType type : theAttributeTypes)
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest if (! isAttributeSyntaxValid(type))
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster isAcceptable = false;
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest unacceptableReasons.add(
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest ERR_PLUGIN_REFERENT_INVALID_ATTRIBUTE_SYNTAX.get(
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest type.getNameOrOID(),
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest type.getSyntax().getName()));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (DN baseDN : cfgBaseDNs)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest Backend<?> b = DirectoryServer.getBackend(baseDN);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((b != null) && (!b.isIndexed(type, IndexType.EQUALITY)))
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster isAcceptable = false;
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest unacceptableReasons.add(ERR_PLUGIN_REFERENT_ATTR_UNINDEXED.get(
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest pluginCfg.dn(), type.getNameOrOID(), b.getBackendID()));
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest }
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest }
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /* Iterate through the attribute-filter mapping and verify that the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * map contains attributes listed in the attribute-type parameter
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * and that the filter is valid.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (String attrFilt : pluginCfg.getCheckReferencesFilterCriteria())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int sepInd = attrFilt.lastIndexOf(":");
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest String attr = attrFilt.substring(0, sepInd).trim();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String filtStr = attrFilt.substring(sepInd + 1).trim();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest /* TODO: strip the ;options part? */
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest /* Get the attribute type for the given attribute. The attribute
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * type has to be present in the attributeType list.
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest */
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster AttributeType attrType =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster DirectoryServer.getAttributeType(attr.toLowerCase());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest if (attrType == null || !theAttributeTypes.contains(attrType))
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster isAcceptable = false;
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest unacceptableReasons.add(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ERR_PLUGIN_REFERENT_ATTR_NOT_LISTED.get(attr));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /* Verify the filter.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster SearchFilter.createFilterFromString(filtStr);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major catch (DirectoryException de)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster isAcceptable = false;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster unacceptableReasons.add(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ERR_PLUGIN_REFERENT_BAD_FILTER.get(filtStr, de.getMessage()));
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return isAcceptable;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major /**
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * {@inheritDoc}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major @Override
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major public boolean isConfigurationChangeAcceptable(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ReferentialIntegrityPluginCfg configuration,
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major List<LocalizableMessage> unacceptableReasons)
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return isConfigurationAcceptable(configuration, unacceptableReasons);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * {@inheritDoc}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @SuppressWarnings("unchecked")
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @Override
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public PluginResult.PostOperation
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster doPostOperation(PostOperationModifyDNOperation
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster modifyDNOperation)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // If the operation itself failed, then we don't need to do anything because
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // nothing changed.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (modifyDNOperation.getResultCode() != ResultCode.SUCCESS)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return PluginResult.PostOperation.continueOperationProcessing();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Map<DN,DN>modDNmap=
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster (Map<DN, DN>) modifyDNOperation.getAttachment(MODIFYDN_DNS);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(modDNmap == null)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster modDNmap=new LinkedHashMap<DN,DN>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster modifyDNOperation.setAttachment(MODIFYDN_DNS, modDNmap);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster DN oldEntryDN=modifyDNOperation.getOriginalEntry().getName();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster DN newEntryDN=modifyDNOperation.getUpdatedEntry().getName();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster modDNmap.put(oldEntryDN, newEntryDN);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster processModifyDN(modDNmap, (interval != 0));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return PluginResult.PostOperation.continueOperationProcessing();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * {@inheritDoc}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @SuppressWarnings("unchecked")
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @Override
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public PluginResult.PostOperation doPostOperation(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster PostOperationDeleteOperation deleteOperation)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // If the operation itself failed, then we don't need to do anything because
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // nothing changed.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (deleteOperation.getResultCode() != ResultCode.SUCCESS)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return PluginResult.PostOperation.continueOperationProcessing();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Set<DN> deleteDNset =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster (Set<DN>) deleteOperation.getAttachment(DELETE_DNS);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(deleteDNset == null)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster deleteDNset = new HashSet<DN>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster deleteOperation.setAttachment(MODIFYDN_DNS, deleteDNset);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
3286da3756e1d2f07709aafdbc5419b26ff71dffPhill Cunnington deleteDNset.add(deleteOperation.getEntryDN());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster processDelete(deleteDNset, (interval != 0));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return PluginResult.PostOperation.continueOperationProcessing();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * {@inheritDoc}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @SuppressWarnings("unchecked")
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @Override
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public PluginResult.SubordinateModifyDN processSubordinateModifyDN(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster SubordinateModifyDNOperation modifyDNOperation, Entry oldEntry,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Entry newEntry, List<Modification> modifications)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //This cast gives an unchecked cast warning, suppress it since the cast
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //is ok.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Map<DN,DN>modDNmap=
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster (Map<DN, DN>) modifyDNOperation.getAttachment(MODIFYDN_DNS);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(modDNmap == null)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //First time through, create the map and set it in the operation
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //attachment.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster modDNmap=new LinkedHashMap<DN,DN>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster modifyDNOperation.setAttachment(MODIFYDN_DNS, modDNmap);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster modDNmap.put(oldEntry.getName(), newEntry.getName());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return PluginResult.SubordinateModifyDN.continueOperationProcessing();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * {@inheritDoc}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @SuppressWarnings("unchecked")
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @Override
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public PluginResult.SubordinateDelete processSubordinateDelete(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster DeleteOperation deleteOperation, Entry entry)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // This cast gives an unchecked cast warning, suppress it
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // since the cast is ok.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Set<DN> deleteDNset =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster (Set<DN>) deleteOperation.getAttachment(DELETE_DNS);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(deleteDNset == null)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // First time through, create the set and set it in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // the operation attachment.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster deleteDNset = new HashSet<DN>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster deleteOperation.setAttachment(DELETE_DNS, deleteDNset);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster deleteDNset.add(entry.getName());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return PluginResult.SubordinateDelete.continueOperationProcessing();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Verify that the specified attribute has either a distinguished name syntax
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * or "name and optional UID" syntax.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param attribute The attribute to check the syntax of.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return Returns <code>true</code> if the attribute has a valid syntax.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private boolean isAttributeSyntaxValid(AttributeType attribute)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return (attribute.getSyntax().getOID().equals(SYNTAX_DN_OID) ||
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster attribute.getSyntax().getOID().equals(SYNTAX_NAME_AND_OPTIONAL_UID_OID));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Process the specified new interval value. This processing depends on what
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the current interval value is and new value will be. The values have been
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * checked for equality at this point and are not equal.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If the old interval is 0, then the server is in foreground mode and
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the background thread needs to be started using the new interval value.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If the new interval value is 0, the the server is in background mode
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * and the the background thread needs to be stopped.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If the user just wants to change the interval value, the background thread
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * needs to be interrupted so that it can use the new interval value.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param newInterval The new interval value to use.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param msgs An array list of messages that thread stop and start messages
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * can be added to.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void processIntervalChange(long newInterval, List<LocalizableMessage> msgs)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(interval == 0) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster DirectoryServer.registerShutdownListener(this);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster interval=newInterval;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster msgs.add(INFO_PLUGIN_REFERENT_BACKGROUND_PROCESSING_STARTING.get(interval));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster setUpBackGroundProcessing();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if(newInterval == 0) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster LocalizableMessage message=
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster INFO_PLUGIN_REFERENT_BACKGROUND_PROCESSING_STOPPING.get();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster msgs.add(message);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster processServerShutdown(message);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster interval=newInterval;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster interval=newInterval;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster backGroundThread.interrupt();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster msgs.add(INFO_PLUGIN_REFERENT_BACKGROUND_PROCESSING_UPDATE_INTERVAL_CHANGED.get(interval, newInterval));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Process a modify DN post operation using the specified map of old and new
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * entry DNs. The boolean "log" is used to determine if the map
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is written to the log file for the background thread to pick up. If the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * map is to be processed in foreground, than each base DN or public
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * naming context (if the base DN configuration is empty) is processed.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param modDNMap The map of old entry and new entry DNs from the modify
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * DN operation.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param log Set to <code>true</code> if the map should be written to a log
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * file so that the background thread can process the changes at
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * a later time.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void processModifyDN(Map<DN, DN> modDNMap, boolean log)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(modDNMap != null)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(log)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster writeLog(modDNMap);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster else
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(DN baseDN : getBaseDNsToSearch())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster doBaseDN(baseDN, modDNMap);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Used by both the background thread and the delete post operation to
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * process a delete operation on the specified entry DN. The
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * boolean "log" is used to determine if the DN is written to the log file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * for the background thread to pick up. This value is set to false if the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * background thread is processing changes. If this method is being called
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * by a delete post operation, then setting the "log" value to false will
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * cause the DN to be processed in foreground
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If the DN is to be processed, than each base DN or public naming
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * context (if the base DN configuration is empty) is is checked to see if
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * entries under it contain references to the deleted entry DN that need
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * to be removed.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param entryDN The DN of the deleted entry.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param log Set to <code>true</code> if the DN should be written to a log
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * file so that the background thread can process the change at
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * a later time.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void processDelete(Set<DN> deleteDNset, boolean log)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(log)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster writeLog(deleteDNset);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster else
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(DN baseDN : getBaseDNsToSearch())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster doBaseDN(baseDN, deleteDNset);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Used by the background thread to process the specified old entry DN and
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * new entry DN. Each base DN or public naming context (if the base DN
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * configuration is empty) is checked to see if they contain entries with
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * references to the old entry DN that need to be changed to the new entry DN.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param oldEntryDN The entry DN before the modify DN operation.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param newEntryDN The entry DN after the modify DN operation.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void processModifyDN(DN oldEntryDN, DN newEntryDN)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(DN baseDN : getBaseDNsToSearch())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster searchBaseDN(baseDN, oldEntryDN, newEntryDN);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Return a set of DNs that are used to search for references under. If the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * base DN configuration set is empty, then the public naming contexts
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * are used.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return A set of DNs to use in the reference searches.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private Set<DN> getBaseDNsToSearch()
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (baseDNs.isEmpty())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return DirectoryServer.getPublicNamingContexts().keySet();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return baseDNs;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Search a base DN using a filter built from the configured attribute
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * types and the specified old entry DN. For each entry that is found from
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the search, delete the old entry DN from the entry. If the new entry
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * DN is not null, then add it to the entry.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param baseDN The DN to base the search at.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param oldEntryDN The old entry DN that needs to be deleted or replaced.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param newEntryDN The new entry DN that needs to be added. May be null
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * if the original operation was a delete.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void searchBaseDN(DN baseDN, DN oldEntryDN, DN newEntryDN)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //Build an equality search with all of the configured attribute types
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster //and the old entry DN.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster HashSet<SearchFilter> componentFilters=new HashSet<SearchFilter>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(AttributeType attributeType : attributeTypes)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster componentFilters.add(SearchFilter.createEqualityFilter(attributeType,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ByteString.valueOf(oldEntryDN.toString())));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster SearchFilter orFilter = SearchFilter.createORFilter(componentFilters);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster final SearchRequest request = newSearchRequest(baseDN, SearchScope.WHOLE_SUBTREE, orFilter);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster InternalSearchOperation operation = getRootConnection().processSearch(request);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster switch (operation.getResultCode().asEnum())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster case SUCCESS:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster break;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster case NO_SUCH_OBJECT:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster logger.debug(INFO_PLUGIN_REFERENT_SEARCH_NO_SUCH_OBJECT, baseDN);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster default:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster logger.error(ERR_PLUGIN_REFERENT_SEARCH_FAILED, operation.getErrorMessage());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (SearchResultEntry entry : operation.getSearchEntries())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster deleteAddAttributesEntry(entry, oldEntryDN, newEntryDN);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This method is used in foreground processing of a modify DN operation.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * It uses the specified map to perform base DN searching for each map
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * entry. The key is the old entry DN and the value is the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * new entry DN.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param baseDN The DN to base the search at.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param modifyDNmap The map containing the modify DN old and new entry DNs.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void doBaseDN(DN baseDN, Map<DN,DN> modifyDNmap)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(Map.Entry<DN,DN> mapEntry: modifyDNmap.entrySet())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster searchBaseDN(baseDN, mapEntry.getKey(), mapEntry.getValue());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This method is used in foreground processing of a delete operation.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * It uses the specified set to perform base DN searching for each
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * element.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param baseDN The DN to base the search at.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param deleteDNset The set containing the delete DNs.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void doBaseDN(DN baseDN, Set<DN> deleteDNset)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(DN deletedEntryDN : deleteDNset)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster searchBaseDN(baseDN, deletedEntryDN, null);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * For each attribute type, delete the specified old entry DN and
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * optionally add the specified new entry DN if the DN is not null.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The specified entry is used to see if it contains each attribute type so
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * those types that the entry contains can be modified. An internal modify
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is performed to change the entry.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param e The entry that contains the old references.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param oldEntryDN The old entry DN to remove references to.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param newEntryDN The new entry DN to add a reference to, if it is not
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * null.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void deleteAddAttributesEntry(Entry e, DN oldEntryDN, DN newEntryDN)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster LinkedList<Modification> mods = new LinkedList<Modification>();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster DN entryDN=e.getName();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(AttributeType type : attributeTypes)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(e.hasAttribute(type))
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ByteString value = ByteString.valueOf(oldEntryDN.toString());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (e.hasValue(type, null, value))
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster mods.add(new Modification(ModificationType.DELETE, Attributes
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster .create(type, value)));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // If the new entry DN exists, create an ADD modification for it.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(newEntryDN != null)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster mods.add(new Modification(ModificationType.ADD, Attributes
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster .create(type, newEntryDN.toString())));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major }
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major }
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major InternalClientConnection conn =
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major InternalClientConnection.getRootConnection();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ModifyOperation modifyOperation =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster conn.processModify(entryDN, mods);
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major if(modifyOperation.getResultCode() != ResultCode.SUCCESS)
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major {
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major logger.error(ERR_PLUGIN_REFERENT_MODIFY_FAILED, entryDN, modifyOperation.getErrorMessage());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Sets up the log file that the plugin can write update recored to and
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major * the background thread can use to read update records from. The specifed
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * log file name is the name to use for the file. If the file exists from
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * a previous run, use it.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param logFileName The name of the file to use, may be absolute.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @throws ConfigException If a new file cannot be created if needed.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void setUpLogFile(String logFileName)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throws ConfigException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster this.logFileName=logFileName;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster logFile=getFileForPath(logFileName);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(!logFile.exists())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster logFile.createNewFile();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster catch (IOException io)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ConfigException(ERR_PLUGIN_REFERENT_CREATE_LOGFILE.get(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster io.getMessage()), io);
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Sets up a buffered writer that the plugin can use to write update records
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas * @throws IOException If a new file writer cannot be created.
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas *
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas */
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas private void setupWriter() throws IOException {
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas writer=new BufferedWriter(new FileWriter(logFile, true));
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas }
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major /**
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major * Sets up a buffered reader that the background thread can use to read
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major * update records with.
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @throws IOException If a new file reader cannot be created.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void setupReader() throws IOException {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster reader=new BufferedReader(new FileReader(logFile));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Write the specified map of old entry and new entry DNs to the log
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * file. Each entry of the map is a line in the file, the key is the old
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * entry normalized DN and the value is the new entry normalized DN.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The DNs are separated by the tab character. This map is related to a
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * modify DN operation.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param modDNmap The map of old entry and new entry DNs.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void writeLog(Map<DN,DN> modDNmap) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster synchronized(logFile)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster setupWriter();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for(Map.Entry<DN,DN> mapEntry : modDNmap.entrySet())
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster writer.write(mapEntry.getKey().toString() + "\t" + mapEntry.getValue().toString());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster writer.newLine();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster writer.flush();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster writer.close();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster catch (IOException io)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster logger.error(ERR_PLUGIN_REFERENT_CLOSE_LOGFILE, io.getMessage());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Write the specified entry DNs to the log file.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * These entry DNs are related to a delete operation.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param deletedEntryDN The DN of the deleted entry.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void writeLog(Set<DN> deleteDNset) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster synchronized(logFile)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster setupWriter();
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major for (DN deletedEntryDN : deleteDNset)
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major writer.write(deletedEntryDN.toString());
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major writer.newLine();
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major writer.flush();
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major writer.close();
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major catch (IOException io)
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major {
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden logger.error(ERR_PLUGIN_REFERENT_CLOSE_LOGFILE, io.getMessage());
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major /**
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * Process all of the records in the log file. Each line of the file is read
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * and parsed to determine if it was a delete operation (a single normalized
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * DN) or a modify DN operation (two normalized DNs separated by a tab). The
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * corresponding operation method is called to perform the referential
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * integrity processing as though the operation was just processed. After
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * all of the records in log file have been processed, the log file is
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * cleared so that new records can be added.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major *
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major */
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden private void processLog() {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major synchronized(logFile) {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major try {
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major if(logFile.length() == 0)
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major {
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major return;
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major }
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major setupReader();
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major String line;
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major while((line=reader.readLine()) != null) {
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major try {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major String[] a=line.split("[\t]");
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major DN origDn = DN.valueOf(a[0]);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major //If there is only a single DN string than it must be a delete.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major if(a.length == 1) {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major processDelete(Collections.singleton(origDn), false);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major } else {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major DN movedDN=DN.valueOf(a[1]);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major processModifyDN(origDn, movedDN);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major } catch (DirectoryException ex) {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major //This exception should rarely happen since the plugin wrote the DN
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major //strings originally.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major logger.error(ERR_PLUGIN_REFERENT_CANNOT_DECODE_STRING_AS_DN, ex.getMessage());
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major reader.close();
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major logFile.delete();
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major logFile.createNewFile();
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major } catch (IOException io) {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major logger.error(ERR_PLUGIN_REFERENT_REPLACE_LOGFILE, io.getMessage());
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Return the listener name.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return The name of the listener.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @Override
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public String getShutdownListenerName() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return name;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * {@inheritDoc}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster @Override
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public final void finalizePlugin() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster currentConfiguration.removeReferentialIntegrityChangeListener(this);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if(interval > 0)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster processServerShutdown(null);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Process a server shutdown. If the background thread is running it needs
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * to be interrupted so it can read the stop request variable and exit.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param reason The reason message for the shutdown.
*
*/
@Override
public void processServerShutdown(LocalizableMessage reason)
{
stopRequested = true;
// Wait for back ground thread to terminate
while (backGroundThread != null && backGroundThread.isAlive()) {
try {
// Interrupt if its sleeping
backGroundThread.interrupt();
backGroundThread.join();
}
catch (InterruptedException ex) {
//Expected.
}
}
DirectoryServer.deregisterShutdownListener(this);
backGroundThread=null;
}
/**
* Returns the interval time converted to milliseconds.
*
* @return The interval time for the background thread.
*/
private long getInterval() {
return interval * 1000;
}
/**
* Sets up background processing of referential integrity by creating a
* new background thread to process updates.
*
*/
private void setUpBackGroundProcessing() {
if(backGroundThread == null) {
DirectoryServer.registerShutdownListener(this);
stopRequested = false;
backGroundThread = new BackGroundThread();
backGroundThread.start();
}
}
/**
* Used by the background thread to determine if it should exit.
*
* @return Returns <code>true</code> if the background thread should exit.
*
*/
private boolean isShuttingDown() {
return stopRequested;
}
/**
* The background referential integrity processing thread. Wakes up after
* sleeping for a configurable interval and checks the log file for update
* records.
*
*/
private class BackGroundThread extends DirectoryThread {
/**
* Constructor for the background thread.
*/
public
BackGroundThread() {
super(name);
}
/**
* Run method for the background thread.
*/
@Override
public void run() {
while(!isShuttingDown()) {
try {
sleep(getInterval());
} catch(InterruptedException e) {
continue;
} catch(Exception e) {
logger.traceException(e);
}
processLog();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public PluginResult.PreOperation doPreOperation(
PreOperationModifyOperation modifyOperation)
{
/* Skip the integrity checks if the enforcing is not enabled
*/
if (!currentConfiguration.isCheckReferences())
{
return PluginResult.PreOperation.continueOperationProcessing();
}
final List<Modification> mods = modifyOperation.getModifications();
final Entry entry = modifyOperation.getModifiedEntry();
/* Make sure the entry belongs to one of the configured naming
* contexts.
*/
DN entryDN = entry.getName();
DN entryBaseDN = getEntryBaseDN(entryDN);
if (entryBaseDN == null)
{
return PluginResult.PreOperation.continueOperationProcessing();
}
for (Modification mod : mods)
{
final ModificationType modType = mod.getModificationType();
/* Process only ADD and REPLACE modification types.
*/
if ((modType != ModificationType.ADD)
&& (modType != ModificationType.REPLACE))
{
break;
}
AttributeType attrType = mod.getAttribute().getAttributeType();
Set<String> attrOptions = mod.getAttribute().getOptions();
Attribute modifiedAttribute = entry.getExactAttribute(attrType,
attrOptions);
if (modifiedAttribute != null)
{
PluginResult.PreOperation result =
isIntegrityMaintained(modifiedAttribute, entryDN, entryBaseDN);
if (result.getResultCode() != ResultCode.SUCCESS)
{
return result;
}
}
}
/* At this point, everything is fine.
*/
return PluginResult.PreOperation.continueOperationProcessing();
}
/**
* {@inheritDoc}
*/
@Override
public PluginResult.PreOperation doPreOperation(
PreOperationAddOperation addOperation)
{
/* Skip the integrity checks if the enforcing is not enabled.
*/
if (!currentConfiguration.isCheckReferences())
{
return PluginResult.PreOperation.continueOperationProcessing();
}
final Entry entry = addOperation.getEntryToAdd();
/* Make sure the entry belongs to one of the configured naming
* contexts.
*/
DN entryDN = entry.getName();
DN entryBaseDN = getEntryBaseDN(entryDN);
if (entryBaseDN == null)
{
return PluginResult.PreOperation.continueOperationProcessing();
}
for (AttributeType attrType : attributeTypes)
{
final List<Attribute> attrs = entry.getAttribute(attrType, false);
if (attrs != null)
{
PluginResult.PreOperation result =
isIntegrityMaintained(attrs, entryDN, entryBaseDN);
if (result.getResultCode() != ResultCode.SUCCESS)
{
return result;
}
}
}
/* If we reahed this point, everything is fine.
*/
return PluginResult.PreOperation.continueOperationProcessing();
}
/**
* Verifies that the integrity of values is maintained.
* @param attrs Attribute list which refers to another entry in the
* directory.
* @param entryDN DN of the entry which contains the <CODE>attr</CODE>
* attribute.
* @return The SUCCESS if the integrity is maintained or
* CONSTRAINT_VIOLATION oherwise
*/
private PluginResult.PreOperation
isIntegrityMaintained(List<Attribute> attrs, DN entryDN, DN entryBaseDN)
{
for(Attribute attr : attrs)
{
PluginResult.PreOperation result =
isIntegrityMaintained(attr, entryDN, entryBaseDN);
if (result != PluginResult.PreOperation.continueOperationProcessing())
{
return result;
}
}
return PluginResult.PreOperation.continueOperationProcessing();
}
/**
* Verifies that the integrity of values is maintained.
* @param attr Attribute which refers to another entry in the
* directory.
* @param entryDN DN of the entry which contains the <CODE>attr</CODE>
* attribute.
* @return The SUCCESS if the integrity is maintained or
* CONSTRAINT_VIOLATION otherwise
*/
private PluginResult.PreOperation isIntegrityMaintained(Attribute attr, DN entryDN, DN entryBaseDN)
{
try
{
for (ByteString attrVal : attr)
{
DN valueEntryDN = DN.decode(attrVal);
final Entry valueEntry;
if (currentConfiguration.getCheckReferencesScopeCriteria() == CheckReferencesScopeCriteria.NAMING_CONTEXT)
{
if (valueEntryDN.matchesBaseAndScope(entryBaseDN, SearchScope.SUBORDINATES))
{
return PluginResult.PreOperation.stopProcessing(ResultCode.CONSTRAINT_VIOLATION,
ERR_PLUGIN_REFERENT_NAMINGCONTEXT_MISMATCH.get(valueEntryDN, attr.getName(), entryDN));
}
valueEntry = DirectoryServer.getEntry(valueEntryDN);
}
else
{
valueEntry = DirectoryServer.getEntry(valueEntryDN);
}
// Verify that the value entry exists in the backend.
if (valueEntry == null)
{
return PluginResult.PreOperation.stopProcessing(ResultCode.CONSTRAINT_VIOLATION,
ERR_PLUGIN_REFERENT_ENTRY_MISSING.get(valueEntryDN, attr.getName(), entryDN));
}
// Verify that the value entry conforms to the filter.
SearchFilter filter = attrFiltMap.get(attr.getAttributeType());
if (filter != null && !filter.matchesEntry(valueEntry))
{
return PluginResult.PreOperation.stopProcessing(ResultCode.CONSTRAINT_VIOLATION,
ERR_PLUGIN_REFERENT_FILTER_MISMATCH.get(valueEntry.getName(), attr.getName(), entryDN, filter));
}
}
}
catch (Exception de)
{
return PluginResult.PreOperation.stopProcessing(ResultCode.OTHER,
ERR_PLUGIN_REFERENT_EXCEPTION.get(de.getLocalizedMessage()));
}
return PluginResult.PreOperation.continueOperationProcessing();
}
/**
* Verifies if the entry with the specified DN belongs to the
* configured naming contexts.
* @param dn DN of the entry.
* @return Returns <code>true</code> if the entry matches any of the
* configured base DNs, and <code>false</code> if not.
*/
private DN getEntryBaseDN(DN dn)
{
/* Verify that the entry belongs to one of the configured naming
* contexts.
*/
DN namingContext = null;
if (baseDNs.isEmpty())
{
baseDNs = DirectoryServer.getPublicNamingContexts().keySet();
}
for (DN baseDN : baseDNs)
{
if (dn.matchesBaseAndScope(baseDN, SearchScope.SUBORDINATES))
{
namingContext = baseDN;
break;
}
}
return namingContext;
}
}