<commit_before>/*
 * Copyright 2015 DuraSpace, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.fcrepo.audit;

import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDdateTime;
import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDstring;
import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createTypedLiteral;
import static java.util.EnumSet.noneOf;
import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode;
import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
import static org.slf4j.LoggerFactory.getLogger;

import static org.fcrepo.audit.AuditProperties.INTERNAL_EVENT;
import static org.fcrepo.audit.AuditProperties.LAST_MODIFIED;
import static org.fcrepo.audit.AuditProperties.LAST_MODIFIED_BY;
import static org.fcrepo.audit.AuditProperties.PREMIS_AGENT;
import static org.fcrepo.audit.AuditProperties.PREMIS_EVENT;
import static org.fcrepo.audit.AuditProperties.PREMIS_TIME;
import static org.fcrepo.audit.AuditProperties.PREMIS_TYPE;
import static org.fcrepo.audit.AuditProperties.PROPERTY_CHANGED;
import static org.fcrepo.audit.AuditProperties.PROV_EVENT;
import static org.fcrepo.audit.AuditProperties.RDF_TYPE;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;

import org.fcrepo.kernel.api.RequiredRdfContext;
import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
import org.fcrepo.kernel.api.models.FedoraResource;
import org.fcrepo.kernel.api.observer.FedoraEvent;
import org.fcrepo.kernel.api.services.ContainerService;
import org.fcrepo.kernel.modeshape.rdf.impl.PrefixingIdentifierTranslator;

import org.modeshape.jcr.api.JcrTools;
import org.modeshape.jcr.api.Repository;
import org.modeshape.jcr.api.Session;
import org.slf4j.Logger;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Statement;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

/**
 * Auditor implementation that creates audit nodes in the repository.
 * @author mohideen
 * @author escowles
 * @since 2015-04-15
 */
public class InternalAuditor implements Auditor {

    /**
     * Logger for this class.
     */
    private static final Logger LOGGER = getLogger(InternalAuditor.class);

    private static final String AUDIT_CONTAINER = "fcrepo.audit.container";

    private static String AUDIT_CONTAINER_LOCATION;

    @Inject
    private EventBus eventBus;

    @Inject
    private Repository repository;

    @Inject
    private ContainerService containerService;

    private Session session;
    private static JcrTools jcrTools = new JcrTools(true);

    /**
     * Register with the EventBus to receive events.
     */
    @PostConstruct
    public void register() {
        try {
            AUDIT_CONTAINER_LOCATION = System.getProperty(AUDIT_CONTAINER);
            if (AUDIT_CONTAINER_LOCATION != null) {
                LOGGER.info("Initializing: {}", this.getClass().getCanonicalName());
                eventBus.register(this);
                if (!AUDIT_CONTAINER_LOCATION.startsWith("/")) {
                    AUDIT_CONTAINER_LOCATION = "/" + AUDIT_CONTAINER_LOCATION;
                }
                if (AUDIT_CONTAINER_LOCATION.endsWith("/")) {
                    AUDIT_CONTAINER_LOCATION = AUDIT_CONTAINER_LOCATION.substring(0,
                            AUDIT_CONTAINER_LOCATION.length() - 2);
                }
                session = repository.login();
                containerService.findOrCreate(session, AUDIT_CONTAINER_LOCATION);

                LOGGER.debug("Registering audit CND");
                jcrTools.registerNodeTypes(session, "audit.cnd");

                session.save();
            } else {
                LOGGER.warn("Cannot Initialize: {}", this.getClass().getCanonicalName());
                LOGGER.warn("System property not found: " + AUDIT_CONTAINER);
            }
        } catch (RepositoryException e) {
            throw new RepositoryRuntimeException(e);
        }
    }

    /**
     * Fedora internal events are received and processed by this method.
     *
     * @param event
     *        The {@link FedoraEvent} to record.
     */
    @Subscribe
    public void recordEvent(final FedoraEvent event) {
        LOGGER.debug("Event detected: {} {}", event.getUserID(), event.getPath());
        boolean isParentNodeLastModifiedEvent = false;
        final String eventType = AuditUtils.getEventURIs(event.getTypes());

        /* adding/removing a file updates the lastModified property of the parent container,
           so ignore updates when only lastModified is changed. */
        if (eventType.contains(PROPERTY_CHANGED)) {
            isParentNodeLastModifiedEvent = !event.getProperties().stream().anyMatch(p ->
                !p.equals(LAST_MODIFIED) && !p.equals(LAST_MODIFIED_BY));
        }

        if (!event.getPath().startsWith(AUDIT_CONTAINER_LOCATION)
                && !isParentNodeLastModifiedEvent) {
            try {
                createAuditNode(event);
            } catch (IOException e) {
                throw new RepositoryRuntimeException(e);
            }
        }
    }

    /**
     * Close external connections
     */
    @PreDestroy
    public void releaseConnections() {
        LOGGER.debug("Tearing down: {}", this.getClass().getCanonicalName());
        eventBus.unregister(this);
    }

    // JCR property name, not URI
    private static final String PREMIS_OBJ = "premis:hasEventRelatedObject";

    /**
     * Creates a node for the audit event under the configured container.
     *
     * @param event to be persisted in the repository
     * @throws java.io.IOException on json mapping error
     */<commit_msg>Removing filtering of events that contain only a lastModified property<commit_after>/*
 * Copyright 2015 DuraSpace, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.fcrepo.audit;

import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDdateTime;
import static com.hp.hpl.jena.datatypes.xsd.XSDDatatype.XSDstring;
import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createTypedLiteral;
import static java.util.EnumSet.noneOf;
import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode;
import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
import static org.slf4j.LoggerFactory.getLogger;

import static org.fcrepo.audit.AuditProperties.INTERNAL_EVENT;
import static org.fcrepo.audit.AuditProperties.PREMIS_AGENT;
import static org.fcrepo.audit.AuditProperties.PREMIS_EVENT;
import static org.fcrepo.audit.AuditProperties.PREMIS_TIME;
import static org.fcrepo.audit.AuditProperties.PREMIS_TYPE;
import static org.fcrepo.audit.AuditProperties.PROV_EVENT;
import static org.fcrepo.audit.AuditProperties.RDF_TYPE;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;

import org.fcrepo.kernel.api.RequiredRdfContext;
import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
import org.fcrepo.kernel.api.models.FedoraResource;
import org.fcrepo.kernel.api.observer.FedoraEvent;
import org.fcrepo.kernel.api.services.ContainerService;
import org.fcrepo.kernel.modeshape.rdf.impl.PrefixingIdentifierTranslator;

import org.modeshape.jcr.api.JcrTools;
import org.modeshape.jcr.api.Repository;
import org.modeshape.jcr.api.Session;
import org.slf4j.Logger;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Statement;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

/**
 * Auditor implementation that creates audit nodes in the repository.
 * @author mohideen
 * @author escowles
 * @since 2015-04-15
 */
public class InternalAuditor implements Auditor {

    /**
     * Logger for this class.
     */
    private static final Logger LOGGER = getLogger(InternalAuditor.class);

    private static final String AUDIT_CONTAINER = "fcrepo.audit.container";

    private static String AUDIT_CONTAINER_LOCATION;

    @Inject
    private EventBus eventBus;

    @Inject
    private Repository repository;

    @Inject
    private ContainerService containerService;

    private Session session;
    private static JcrTools jcrTools = new JcrTools(true);

    /**
     * Register with the EventBus to receive events.
     */
    @PostConstruct
    public void register() {
        try {
            AUDIT_CONTAINER_LOCATION = System.getProperty(AUDIT_CONTAINER);
            if (AUDIT_CONTAINER_LOCATION != null) {
                LOGGER.info("Initializing: {}", this.getClass().getCanonicalName());
                eventBus.register(this);
                if (!AUDIT_CONTAINER_LOCATION.startsWith("/")) {
                    AUDIT_CONTAINER_LOCATION = "/" + AUDIT_CONTAINER_LOCATION;
                }
                if (AUDIT_CONTAINER_LOCATION.endsWith("/")) {
                    AUDIT_CONTAINER_LOCATION = AUDIT_CONTAINER_LOCATION.substring(0,
                            AUDIT_CONTAINER_LOCATION.length() - 2);
                }
                session = repository.login();
                containerService.findOrCreate(session, AUDIT_CONTAINER_LOCATION);

                LOGGER.debug("Registering audit CND");
                jcrTools.registerNodeTypes(session, "audit.cnd");

                session.save();
            } else {
                LOGGER.warn("Cannot Initialize: {}", this.getClass().getCanonicalName());
                LOGGER.warn("System property not found: " + AUDIT_CONTAINER);
            }
        } catch (RepositoryException e) {
            throw new RepositoryRuntimeException(e);
        }
    }

    /**
     * Fedora internal events are received and processed by this method.
     *
     * @param event
     *        The {@link FedoraEvent} to record.
     */
    @Subscribe
    public void recordEvent(final FedoraEvent event) {
        LOGGER.debug("Event detected: {} {}", event.getUserID(), event.getPath());
        if (!event.getPath().startsWith(AUDIT_CONTAINER_LOCATION)) {
            try {
                createAuditNode(event);
            } catch (IOException e) {
                throw new RepositoryRuntimeException(e);
            }
        }
    }

    /**
     * Close external connections
     */
    @PreDestroy
    public void releaseConnections() {
        LOGGER.debug("Tearing down: {}", this.getClass().getCanonicalName());
        eventBus.unregister(this);
    }

    // JCR property name, not URI
    private static final String PREMIS_OBJ = "premis:hasEventRelatedObject";

    /**
     * Creates a node for the audit event under the configured container.
     *
     * @param event to be persisted in the repository
     * @throws java.io.IOException on json mapping error
     */
{'fraction_non_alphanumeric': 0.09643015849503778, 'fraction_numerical': 0.0029625240705080727, 'mean_word_length': 3.2758074730842304, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4621635', 'n_tokens_mistral': 4151, 'n_tokens_neox': 4017, 'n_words': 859}