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}