net.sf.jacclog.persistence.jpa.internal.LogEntryRepository.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.jacclog.persistence.jpa.internal.LogEntryRepository.java

Source

/*******************************************************************************
 * Copyright 2011 Andr Roul
 * 
 * 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 net.sf.jacclog.persistence.jpa.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TemporalType;

import net.sf.jacclog.persistence.jpa.entity.HttpRequestHeaderField;
import net.sf.jacclog.persistence.jpa.entity.HttpResponseHeaderField;
import net.sf.jacclog.persistence.jpa.entity.LogEntry;
import net.sf.jacclog.service.repository.domain.PersistableHttpRequestHeaderField;
import net.sf.jacclog.service.repository.domain.PersistableHttpResponseHeaderField;

import org.joda.time.Interval;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogEntryRepository {

    private static final Logger LOG = LoggerFactory.getLogger(LogEntryRepository.class);

    private static final String PERSISTENCE_UNIT_NAME = "jacclogPU";

    private final EntityManagerFactory entityManagerFactory;

    private final HttpRequestHeaderFieldRepository requestFieldRepository;

    private final HttpResponseHeaderFieldRepository responseFieldRepository;

    public LogEntryRepository() {
        entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        requestFieldRepository = new HttpRequestHeaderFieldRepository(entityManagerFactory);
        responseFieldRepository = new HttpResponseHeaderFieldRepository(entityManagerFactory);
    }

    public LogEntryRepository(final Map<String, String> properties) {
        if (properties == null) {
            throw new IllegalArgumentException("Argument 'properties' can not be null.");
        }

        entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, properties);
        requestFieldRepository = new HttpRequestHeaderFieldRepository(entityManagerFactory);
        responseFieldRepository = new HttpResponseHeaderFieldRepository(entityManagerFactory);
    }

    /**
     * Count all log entries within a start and end date.
     * 
     * @param period
     * @return
     */
    public long count(final Date start, final Date end) {
        if (start == null) {
            throw new IllegalArgumentException("Argument 'start' can not be null.");
        }

        if (end == null) {
            throw new IllegalArgumentException("Argument 'end' can not be null.");
        }

        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final Long count = entityManager
                .createQuery("SELECT count(o) FROM LogEntry o WHERE o.requestTime between :start and :end",
                        Long.class)
                .setParameter("start", start, TemporalType.DATE).setParameter("end", end, TemporalType.DATE)
                .getSingleResult();
        entityManager.close();
        return count;
    }

    /**
     * Counts all log entries within an interval
     * 
     * @param interval
     * @return
     */
    public long count(final Interval interval) {
        if (interval == null) {
            throw new IllegalArgumentException("Argument 'interval' can not be null.");
        }
        return count(interval.getStart().toDate(), interval.getEnd().toDate());
    }

    public long countAll() {
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final Long count = entityManager.createQuery("SELECT count(o) FROM LogEntry o", Long.class)
                .getSingleResult();
        entityManager.close();
        return count;
    }

    /**
     * Find all log entries within a start and end date.
     * 
     * @param start
     * @param end
     * @return
     */
    public List<LogEntry> find(final Date start, final Date end) {
        if (start == null) {
            throw new IllegalArgumentException("Argument 'start' can not be null.");
        }

        if (end == null) {
            throw new IllegalArgumentException("Argument 'end' can not be null.");
        }

        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final List<LogEntry> entries = entityManager
                .createQuery("SELECT o FROM LogEntry o WHERE o.requestTime between :start and :end", LogEntry.class)
                .setParameter("start", start, TemporalType.DATE).setParameter("end", end, TemporalType.DATE)
                .getResultList();
        entityManager.close();
        return entries;
    }

    /**
     * Finds all log entries between a start and end date ordered by ID. In addition by specifying a starting position
     * and maximum number of results it restricts the size of the result set.<br>
     * <br>
     * The end date should be greater than start date.
     * 
     * @param start
     *            Start date
     * @param end
     *            End date
     * @param startPosition
     *            Position of the first result, numbered from 0
     * @param maxResults
     *            Maximum number of results to retrieve
     * @throws IllegalArgumentException
     *             If the start date is null
     * @throws IllegalArgumentException
     *             If the end date is null
     * @throws IllegalArgumentException
     *             If the start is greater than the end date is null
     * @return A list of log entries
     */
    public List<LogEntry> find(final Date start, final Date end, final int startPosition, final int maxResults) {
        if (start == null) {
            throw new IllegalArgumentException("Argument 'start' can not be null.");
        }

        if (end == null) {
            throw new IllegalArgumentException("Argument 'end' can not be null.");
        }

        if (start.after(end)) {
            throw new IllegalArgumentException("The end date should be greater than the start date.");
        }

        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final List<LogEntry> entries = entityManager
                .createQuery("SELECT o FROM LogEntry o WHERE o.requestTime BETWEEN :start and :end ORDER BY o.id",
                        LogEntry.class)
                .setParameter("start", start, TemporalType.DATE).setParameter("end", end, TemporalType.DATE)
                .setFirstResult(startPosition).setMaxResults(maxResults).getResultList();
        entityManager.close();
        return entries;
    }

    /**
     * Finds all log entries in the specific range by specifying a starting position and a maximum number of results.
     * 
     * @param startPosition
     *            Position of the first result, numbered from 0
     * @param maxResults
     *            Maximum number of results to retrieve
     * @return A list of log entries
     */
    public List<LogEntry> find(final int startPosition, final int maxResults) {
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final List<LogEntry> entries = entityManager.createQuery("SELECT o FROM LogEntry o", LogEntry.class)
                .setFirstResult(startPosition).setMaxResults(maxResults).getResultList();
        entityManager.close();
        return entries;
    }

    /**
     * Finds all log entries between an interval.
     * 
     * @param interval
     *            A period of time between two dates.
     * @return A list of log entries
     */
    public List<LogEntry> find(final Interval interval) {
        if (interval == null) {
            throw new IllegalArgumentException("Argument 'interval' can not be null.");
        }

        return find(interval.getStart().toDate(), interval.getEnd().toDate());
    }

    /**
     * Finds all log entries between an interval and ordered by ID. In addition by specifying a starting position and a
     * maximum number of results it restricts the size of the result set.
     * 
     * @param interval
     *            A period of time between two dates.
     * @param startPosition
     *            Position of the first result, numbered from 0
     * @param maxResults
     *            Maximum number of results to retrieve
     * @throws IllegalArgumentException
     *             If the interval is null
     * @return A list of log entries
     */
    public List<LogEntry> find(final Interval interval, final int startPosition, final int maxResults) {
        if (interval == null) {
            throw new IllegalArgumentException("Argument 'interval' can not be null.");
        }

        return find(interval.getStart().toDate(), interval.getEnd().toDate(), startPosition, maxResults);
    }

    public LogEntry find(final Long id) {
        if (id == null) {
            throw new IllegalArgumentException("Argument 'id' can not be null.");
        }

        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final LogEntry entry = entityManager.find(LogEntry.class, id);
        entityManager.close();
        return entry;
    }

    public List<LogEntry> findAll() {
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final List<LogEntry> entries = entityManager.createQuery("SELECT o FROM LogEntry o", LogEntry.class)
                .getResultList();
        entityManager.close();
        return entries;
    }

    public LogEntry merge(final LogEntry entry) {
        if (entry == null) {
            throw new IllegalArgumentException("Argument 'entry' must be set.");
        }

        LogEntry merged = null;
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        entityManager.getTransaction().begin();
        try {
            merged = entityManager.merge(entry);
            entityManager.getTransaction().commit();
        } catch (final RuntimeException e1) {
            if (entityManager.getTransaction().isActive()) {
                try {
                    entityManager.getTransaction().rollback();
                } catch (final RuntimeException e2) {
                    // Log rollback failure or something
                    throw e2;
                }
            }
            throw e1;
        } finally {
            if (entityManager != null) {
                entityManager.clear();
                entityManager.close();
            }
        }

        return merged;
    }

    public void persist(final Collection<LogEntry> entries) {
        if (entries == null) {
            throw new IllegalArgumentException("Argument 'entries' can not be null.");
        }

        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        entityManager.getTransaction().begin();
        try {
            for (final LogEntry entry : entries) {
                persistHeaders(entry);
                entityManager.persist(entry);
            }
            entityManager.getTransaction().commit();
        } catch (final RuntimeException e1) {
            if (entityManager.getTransaction().isActive()) {
                try {
                    entityManager.getTransaction().rollback();
                } catch (final RuntimeException e2) {
                    // Log rollback failure or something
                    throw e2;
                }
            }
            throw e1;
        } finally {
            if (entityManager != null) {
                entityManager.clear();
                entityManager.close();
            }
        }
    }

    public void persist(final LogEntry entry) {
        if (entry == null) {
            throw new IllegalArgumentException("Argument 'entry' must be set.");
        }

        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        entityManager.getTransaction().begin();
        try {
            persistHeaders(entry);
            entityManager.persist(entry);
            entityManager.getTransaction().commit();
        } catch (final RuntimeException e1) {
            if (entityManager.getTransaction().isActive()) {
                try {
                    entityManager.getTransaction().rollback();
                } catch (final RuntimeException e2) {
                    // Log rollback failure or something
                    throw e2;
                }
            }
            throw e1;
        } finally {
            if (entityManager != null) {
                entityManager.clear();
                entityManager.close();
            }
        }
    }

    private void persistHeaders(final LogEntry entry) {
        persistRequestHeaders(entry);
        persistResponseHeaders(entry);
    }

    private void persistRequestHeaders(final LogEntry entry) {
        final Set<PersistableHttpRequestHeaderField> attachedFields = new HashSet<PersistableHttpRequestHeaderField>();
        for (final PersistableHttpRequestHeaderField field : entry.getRequestHeaders()) {
            final HttpRequestHeaderField attached = requestFieldRepository.find(field.getType(), field.getValue());
            if (attached == null) {
                final HttpRequestHeaderField entity = HttpRequestHeaderFieldMapper.map(field);
                try {
                    requestFieldRepository.persist(entity);
                } catch (final RuntimeException e) {
                    // an exception here leads to an IllegalStateException while persisting the related log entry
                    // (synchronization error)
                    final HttpRequestHeaderField a = requestFieldRepository.find(entity);
                    LOG.info(e.getLocalizedMessage() + ": " + a);
                }
                attachedFields.add(entity);
            } else {
                attachedFields.add(attached);
            }
        }
        entry.setRequestHeaders(attachedFields);
    }

    private void persistResponseHeaders(final LogEntry entry) {
        final Set<PersistableHttpResponseHeaderField> attachedFields = new HashSet<PersistableHttpResponseHeaderField>();
        for (final PersistableHttpResponseHeaderField field : entry.getResponseHeaders()) {
            final HttpResponseHeaderField attached = responseFieldRepository.find(field.getType(),
                    field.getValue());
            if (attached == null) {
                final HttpResponseHeaderField entity = HttpResponseHeaderFieldMapper.map(field);
                try {
                    responseFieldRepository.persist(entity);
                } catch (final RuntimeException e) {
                    // an exception here leads to an IllegalStateException while persisting the related log entry
                    // (synchronization error)
                    final HttpResponseHeaderField a = responseFieldRepository.find(entity);
                    LOG.info(e.getLocalizedMessage() + ": " + a);
                }
                attachedFields.add(entity);
            } else {
                attachedFields.add(attached);
            }
        }
        entry.setResponseHeaders(attachedFields);
    }

    public void remove(final List<LogEntry> entries) {
        if (entries == null || entries.isEmpty()) {
            throw new IllegalArgumentException("Argument 'entries' can not be null or empty.");
        }

        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final List<LogEntry> attached = new ArrayList<LogEntry>(entries.size());
        for (final LogEntry entry : entries) {
            attached.add(entityManager.find(LogEntry.class, entry.getId()));
        }
        entityManager.getTransaction().begin();
        try {
            for (final LogEntry entry : attached) {
                entityManager.remove(entry);
            }
            entityManager.getTransaction().commit();
        } catch (final RuntimeException e1) {
            if (entityManager.getTransaction().isActive()) {
                try {
                    entityManager.getTransaction().rollback();
                } catch (final RuntimeException e2) {
                    // Log rollback failure or something
                    throw e2;
                }
            }
            throw e1;
        } finally {
            if (entityManager != null) {
                entityManager.clear();
                entityManager.close();
            }
        }
    }

    public void remove(final LogEntry entry) {
        if (entry == null) {
            throw new IllegalArgumentException("Argument 'entry' can not be null.");
        }

        if (entry.getId() == null) {
            throw new IllegalArgumentException("The ID for an log entry can not be null.");
        }

        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        final LogEntry attached = entityManager.find(LogEntry.class, entry.getId());
        entityManager.getTransaction().begin();
        try {
            entityManager.remove(attached);
            entityManager.getTransaction().commit();
        } catch (final RuntimeException e1) {
            if (entityManager.getTransaction().isActive()) {
                try {
                    entityManager.getTransaction().rollback();
                } catch (final RuntimeException e2) {
                    // Log rollback failure or something
                    throw e2;
                }
            }
            throw e1;
        } finally {
            if (entityManager != null) {
                entityManager.clear();
                entityManager.close();
            }
        }
    }

    public void start() {
        LOG.debug("Starting LogEntryRepository...");
    }

    public void stop() {
        LOG.debug("Closing EntityManagerFactory of LogEntryRepository...");

        if (entityManagerFactory != null) {
            entityManagerFactory.close();
        }
    }

}