001/*
002* CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2008-2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2013-2015 ForgeRock AS.
026 */
027package org.forgerock.opendj.server.core;
028
029import java.util.List;
030import java.util.Set;
031import java.util.concurrent.CopyOnWriteArrayList;
032
033import org.forgerock.i18n.LocalizableMessage;
034import org.forgerock.opendj.ldap.DN;
035import org.forgerock.opendj.ldap.LdapException;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038
039/**
040 * This class provides a skeletal implementation of the {@link DataProvider}
041 * interface, to minimize the effort required to implement this interface.
042 */
043public abstract class AbstractDataProvider implements DataProvider {
044    private static final Logger debugLogger = LoggerFactory.getLogger(AbstractDataProvider.class);
045
046    /** The list of event listeners associated with this data provider. */
047    private final List<DataProviderEventListener> eventListeners = new CopyOnWriteArrayList<>();
048
049    /** Creates a new abstract data provider. */
050    protected AbstractDataProvider() {
051        // No implementation required.
052    }
053
054    /**
055     * {@inheritDoc}
056     * <p>
057     * The default implementation is to invoke {@code getEntry(dn)} and return
058     * {@code true} if the entry was successfully retrieved.
059     */
060    @Override
061    public boolean containsEntry(final DN dn) throws LdapException {
062        return getEntry(dn) != null;
063    }
064
065    /** {@inheritDoc} */
066    @Override
067    public final void deregisterEventListener(final DataProviderEventListener listener) {
068        eventListeners.remove(listener);
069    }
070
071    /** {@inheritDoc} */
072    @Override
073    public final void registerEventListener(final DataProviderEventListener listener) {
074        eventListeners.add(listener);
075    }
076
077    /**
078     * {@inheritDoc}
079     * <p>
080     * The default implementation is to return false for all base DNs indicating
081     * that change notification is not supported.
082     */
083    @Override
084    public boolean supportsChangeNotification(final DN baseDN) throws LdapException {
085        return false;
086    }
087
088    /**
089     * Notify all event listeners that this data provider has changed state due
090     * to an operational error, configuration change, or an administrative
091     * action.
092     * <p>
093     * This method can be used to forward events to parent data providers.
094     *
095     * @param event
096     *            The data provider event.
097     */
098    protected final void notifyDataProviderEventOccurred(final DataProviderEvent event) {
099        for (final DataProviderEventListener listener : eventListeners) {
100            try {
101                listener.handleDataProviderEvent(event);
102            } catch (final Exception e) {
103                debugLogger.trace("Unexpected error occurred while invoking listener", e);
104            }
105        }
106    }
107
108    /**
109     * Notify all event listeners that this data provider has changed state due
110     * to an operational error, configuration change, or an administrative
111     * action.
112     * <p>
113     * This method is equivalent to the following code:
114     *
115     * <pre>
116     * DataProviderEvent event = new DataProviderEvent(reason, types);
117     * notifyDataProviderStateChanged(event);
118     * </pre>
119     *
120     * @param reason
121     *            A message describing this event.
122     * @param types
123     *            The types of event that have occurred in the data provider.
124     */
125    protected final void notifyDataProviderEventOccurred(final LocalizableMessage reason,
126            final Set<DataProviderEvent.Type> types) {
127        final DataProviderEvent event = new DataProviderEvent(reason, types);
128        notifyDataProviderEventOccurred(event);
129    }
130
131}