001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.kernel.impl.observer;
017
018import static com.codahale.metrics.MetricRegistry.name;
019import static com.google.common.base.Throwables.propagate;
020import static javax.jcr.observation.Event.NODE_REMOVED;
021import static org.slf4j.LoggerFactory.getLogger;
022import org.fcrepo.metrics.RegistryService;
023
024import javax.annotation.PostConstruct;
025import javax.annotation.PreDestroy;
026import javax.inject.Inject;
027import javax.jcr.RepositoryException;
028import javax.jcr.Session;
029import javax.jcr.observation.Event;
030import javax.jcr.observation.EventListener;
031
032import org.modeshape.jcr.api.Repository;
033import org.slf4j.Logger;
034
035import com.codahale.metrics.Counter;
036import com.google.common.eventbus.EventBus;
037
038
039/**
040 * This is a listener that fakes a single event to signify object updates.
041 * The batch of changes is broadcast to the Fedora event listeners as a
042 * change to the jcr:lastModified property.
043 *
044 * @author armintor@gmail.com
045 * @since Dec 5, 2013
046 */
047public class NodeRemovalEventObserver implements EventListener {
048
049    private static final Logger LOGGER = getLogger(NodeRemovalEventObserver.class);
050
051    /**
052     * A simple counter of events that pass through this observer
053     */
054    static final Counter EVENT_COUNTER = RegistryService.getInstance().getMetrics().counter(
055            name(
056            NodeRemovalEventObserver.class, "onEvent"));
057
058    static final int EVENT_TYPES = NODE_REMOVED;
059
060    @Inject
061    private Repository repository;
062
063    @Inject
064    private EventBus eventBus;
065
066    // THIS SESSION SHOULD NOT BE USED TO LOOK UP NODES
067    private Session session;
068
069    /**
070     * Register this observer with the JCR event listeners
071     * @throws RepositoryException if repository exception occurred
072     */
073    @PostConstruct
074    public void buildListener() throws RepositoryException {
075        session = repository.login();
076        session.getWorkspace().getObservationManager().addEventListener(this,
077                EVENT_TYPES, null, true, null, null, false);
078        session.save();
079    }
080
081    /**
082     * logout of the session
083     * @throws RepositoryException if repository exception occurred
084     */
085    @PreDestroy
086    public void stopListening() throws RepositoryException {
087        session.getWorkspace().getObservationManager().removeEventListener(this);
088        session.logout();
089    }
090
091    /**
092     * Filter JCR events and transform them into our own FedoraEvents.
093     *
094     * @param events the JCR events
095     */
096    @Override
097    public void onEvent(final javax.jcr.observation.EventIterator events) {
098
099        // emit node removal events
100        while (events.hasNext()) {
101            final Event e = events.nextEvent();
102            try {
103                final String ePath = e.getPath();
104                final int ls = ePath.lastIndexOf('/');
105                // only propagate non-jcr node removals
106                if (!ePath.startsWith("jcr:", ls + 1)) {
107                    LOGGER.debug("Putting event: {} on the bus", e);
108                    EVENT_COUNTER.inc();
109                    eventBus.post(e);
110                }
111            } catch (final RepositoryException ex) {
112                throw propagate(ex);
113            }
114        }
115    }
116
117}