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.google.common.base.Functions.toStringFunction;
019import static com.google.common.base.Throwables.propagate;
020import static com.google.common.collect.Collections2.transform;
021import static com.google.common.collect.Sets.newHashSet;
022import static org.fcrepo.kernel.FedoraJcrTypes.FEDORA_BINARY;
023import static org.fcrepo.kernel.FedoraJcrTypes.FEDORA_NON_RDF_SOURCE_DESCRIPTION;
024import static org.fcrepo.kernel.FedoraJcrTypes.FEDORA_CONTAINER;
025import static org.fcrepo.kernel.FedoraJcrTypes.FEDORA_RESOURCE;
026import static org.slf4j.LoggerFactory.getLogger;
027
028import javax.jcr.PathNotFoundException;
029import javax.jcr.RepositoryException;
030import javax.jcr.Session;
031import javax.jcr.observation.Event;
032
033import com.google.common.base.Predicate;
034
035import org.fcrepo.kernel.observer.EventFilter;
036import org.slf4j.Logger;
037
038import java.util.Arrays;
039import java.util.Collection;
040import java.util.Collections;
041import java.util.HashSet;
042
043/**
044 * {@link EventFilter} that passes only events emitted from nodes with a Fedora
045 * JCR type, or properties attached to them, except in the case of a node
046 * removal. In that case, since we cannot test the node for its types, we assume
047 * that any non-JCR namespaced node is fair game.
048 *
049 * @author ajs6f
050 * @author barmintor
051 * @since Dec 2013
052 * @author eddies
053 * @since Feb 7, 2013
054 * @author escowles
055 * @since Oct 3, 2013
056 */
057public class DefaultFilter implements EventFilter {
058
059    private static final Logger LOGGER = getLogger(DefaultFilter.class);
060
061    private static final HashSet<String> fedoraMixins =
062            newHashSet(FEDORA_BINARY, FEDORA_CONTAINER, FEDORA_NON_RDF_SOURCE_DESCRIPTION, FEDORA_RESOURCE);
063
064    /**
065     * Default constructor.
066     */
067    public DefaultFilter() {
068    }
069
070    @Override
071    public Predicate<Event> getFilter(final Session session) {
072        return new DefaultFilter();
073    }
074
075    @Override
076    public boolean apply(final Event event) {
077        try {
078            return !Collections.disjoint(getMixinTypes(event), fedoraMixins);
079        } catch (final PathNotFoundException e) {
080            LOGGER.trace("Dropping event from outside our assigned workspace:\n", e);
081            return false;
082        } catch (final RepositoryException e) {
083            throw propagate(e);
084        }
085    }
086
087    protected static Collection<String> getMixinTypes(final Event event)
088            throws PathNotFoundException, RepositoryException {
089        try {
090            final org.modeshape.jcr.api.observation.Event modeEvent =
091                    (org.modeshape.jcr.api.observation.Event) event;
092            return transform(Arrays.asList(modeEvent.getMixinNodeTypes()), toStringFunction());
093        } catch (final ClassCastException e) {
094            throw new ClassCastException(event + " is not a Modeshape Event");
095        }
096    }
097
098}