001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2017 ForgeRock AS.
016 */
017package org.opends.server.replication.plugin;
018
019import static org.opends.server.replication.plugin.MultimasterReplication.updateReplicationServersCount;
020
021import java.util.List;
022
023import org.forgerock.i18n.LocalizableMessage;
024import org.forgerock.opendj.config.server.ConfigException;
025import org.forgerock.opendj.config.server.ConfigurationChangeListener;
026import org.forgerock.opendj.ldap.ResultCode;
027import org.forgerock.opendj.config.server.ConfigurationAddListener;
028import org.forgerock.opendj.config.server.ConfigurationDeleteListener;
029import org.forgerock.opendj.server.config.server.ReplicationDomainCfg;
030import org.forgerock.opendj.server.config.server.ReplicationServerCfg;
031import org.forgerock.opendj.server.config.server.ReplicationSynchronizationProviderCfg;
032import org.opends.server.replication.server.ReplicationServer;
033import org.opends.server.replication.service.DSRSShutdownSync;
034import org.forgerock.opendj.config.server.ConfigChangeResult;
035
036/**
037 * This class is used to create and object that can
038 * register in the admin framework as a listener for changes, add and delete
039 * on the ReplicationServer configuration objects.
040 */
041public class ReplicationServerListener implements
042        ConfigurationAddListener<ReplicationServerCfg>,
043        ConfigurationChangeListener<ReplicationDomainCfg>,
044        ConfigurationDeleteListener<ReplicationServerCfg>
045{
046  private final DSRSShutdownSync dsrsShutdownSync;
047  private ReplicationServer replicationServer;
048
049  /**
050   * Build a ReplicationServer Listener from the given Multimaster
051   * configuration.
052   *
053   * @param configuration The configuration that will be used to listen
054   *                      for replicationServer configuration changes.
055   * @param dsrsShutdownSync Synchronization object for shutdown of combined DS/RS instances.
056   * @throws ConfigException if the ReplicationServerListener can't register for
057   *                         listening to changes on the provided configuration
058   *                         object.
059   */
060  ReplicationServerListener(ReplicationSynchronizationProviderCfg configuration, DSRSShutdownSync dsrsShutdownSync)
061      throws ConfigException
062  {
063    configuration.addReplicationServerAddListener(this);
064    configuration.addReplicationServerDeleteListener(this);
065
066    this.dsrsShutdownSync = dsrsShutdownSync;
067    if (configuration.hasReplicationServer())
068    {
069      final ReplicationServerCfg cfg = configuration.getReplicationServer();
070      replicationServer = new ReplicationServer(cfg, dsrsShutdownSync);
071      updateReplicationServersCount(cfg.getReplicationServer().size());
072    }
073  }
074
075  @Override
076  public ConfigChangeResult applyConfigurationAdd(ReplicationServerCfg cfg)
077  {
078    final ConfigChangeResult ccr = new ConfigChangeResult();
079    try
080    {
081      replicationServer = new ReplicationServer(cfg, dsrsShutdownSync);
082      updateReplicationServersCount(cfg.getReplicationServer().size());
083    }
084    catch (ConfigException e)
085    {
086      // we should never get to this point because the configEntry has
087      // already been validated in configAddisAcceptable
088      ccr.setResultCode(ResultCode.CONSTRAINT_VIOLATION);
089    }
090    return ccr;
091  }
092
093  @Override
094  public boolean isConfigurationAddAcceptable(
095      ReplicationServerCfg cfg, List<LocalizableMessage> unacceptableReasons)
096  {
097    return ReplicationServer.isConfigurationAcceptable(cfg, unacceptableReasons);
098  }
099
100  /**
101   * Shutdown the replication server.
102   */
103  public void shutdown()
104  {
105    if (replicationServer != null)
106    {
107      replicationServer.shutdown();
108    }
109  }
110
111  @Override
112  public ConfigChangeResult applyConfigurationDelete(ReplicationServerCfg cfg)
113  {
114    // There can be only one replicationServer, just shutdown the
115    // replicationServer currently configured.
116    if (replicationServer != null)
117    {
118      replicationServer.remove();
119    }
120    return new ConfigChangeResult();
121  }
122
123  @Override
124  public boolean isConfigurationDeleteAcceptable(
125      ReplicationServerCfg cfg, List<LocalizableMessage> unacceptableReasons)
126  {
127    return true;
128  }
129
130  /**
131   * Returns the associated Replication Server.
132   * @return The replication server.
133   */
134  public ReplicationServer getReplicationServer()
135  {
136    return replicationServer;
137  }
138
139  @Override
140  public boolean isConfigurationChangeAcceptable(ReplicationDomainCfg configuration,
141      List<LocalizableMessage> unacceptableReasons)
142  {
143    return true;
144  }
145
146  @Override
147  public ConfigChangeResult applyConfigurationChange(ReplicationDomainCfg configuration)
148  {
149    updateReplicationServersCount(configuration.getReplicationServer().size());
150    return new ConfigChangeResult();
151  }
152}