/******************************************************************************* * Copyright 2011 André Rouél * * 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(); } } }