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-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2015 ForgeRock AS.
016 */
017package org.forgerock.opendj.server.core;
018
019import java.util.List;
020import java.util.Set;
021import java.util.concurrent.CopyOnWriteArrayList;
022
023import org.forgerock.i18n.LocalizableMessage;
024import org.forgerock.opendj.ldap.DN;
025import org.forgerock.opendj.ldap.LdapException;
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028
029/**
030 * This class provides a skeletal implementation of the {@link DataProvider}
031 * interface, to minimize the effort required to implement this interface.
032 */
033public abstract class AbstractDataProvider implements DataProvider {
034    private static final Logger debugLogger = LoggerFactory.getLogger(AbstractDataProvider.class);
035
036    /** The list of event listeners associated with this data provider. */
037    private final List<DataProviderEventListener> eventListeners = new CopyOnWriteArrayList<>();
038
039    /** Creates a new abstract data provider. */
040    protected AbstractDataProvider() {
041        // No implementation required.
042    }
043
044    /**
045     * {@inheritDoc}
046     * <p>
047     * The default implementation is to invoke {@code getEntry(dn)} and return
048     * {@code true} if the entry was successfully retrieved.
049     */
050    @Override
051    public boolean containsEntry(final DN dn) throws LdapException {
052        return getEntry(dn) != null;
053    }
054
055    /** {@inheritDoc} */
056    @Override
057    public final void deregisterEventListener(final DataProviderEventListener listener) {
058        eventListeners.remove(listener);
059    }
060
061    /** {@inheritDoc} */
062    @Override
063    public final void registerEventListener(final DataProviderEventListener listener) {
064        eventListeners.add(listener);
065    }
066
067    /**
068     * {@inheritDoc}
069     * <p>
070     * The default implementation is to return false for all base DNs indicating
071     * that change notification is not supported.
072     */
073    @Override
074    public boolean supportsChangeNotification(final DN baseDN) throws LdapException {
075        return false;
076    }
077
078    /**
079     * Notify all event listeners that this data provider has changed state due
080     * to an operational error, configuration change, or an administrative
081     * action.
082     * <p>
083     * This method can be used to forward events to parent data providers.
084     *
085     * @param event
086     *            The data provider event.
087     */
088    protected final void notifyDataProviderEventOccurred(final DataProviderEvent event) {
089        for (final DataProviderEventListener listener : eventListeners) {
090            try {
091                listener.handleDataProviderEvent(event);
092            } catch (final Exception e) {
093                debugLogger.trace("Unexpected error occurred while invoking listener", e);
094            }
095        }
096    }
097
098    /**
099     * Notify all event listeners that this data provider has changed state due
100     * to an operational error, configuration change, or an administrative
101     * action.
102     * <p>
103     * This method is equivalent to the following code:
104     *
105     * <pre>
106     * DataProviderEvent event = new DataProviderEvent(reason, types);
107     * notifyDataProviderStateChanged(event);
108     * </pre>
109     *
110     * @param reason
111     *            A message describing this event.
112     * @param types
113     *            The types of event that have occurred in the data provider.
114     */
115    protected final void notifyDataProviderEventOccurred(final LocalizableMessage reason,
116            final Set<DataProviderEvent.Type> types) {
117        final DataProviderEvent event = new DataProviderEvent(reason, types);
118        notifyDataProviderEventOccurred(event);
119    }
120
121}