/*
 * Copyright 2012-2019 the original author or authors.
 *
 * 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
 *
 *      https://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.springframework.boot.actuate.audit;

import java.time.Instant;
import java.util.LinkedList;
import java.util.List;

import org.springframework.util.Assert;

In-memory AuditEventRepository implementation.
Author:Dave Syer, Phillip Webb, Vedran Pavic
Since:1.0.0
/** * In-memory {@link AuditEventRepository} implementation. * * @author Dave Syer * @author Phillip Webb * @author Vedran Pavic * @since 1.0.0 */
public class InMemoryAuditEventRepository implements AuditEventRepository { private static final int DEFAULT_CAPACITY = 1000; private final Object monitor = new Object();
Circular buffer of the event with tail pointing to the last element.
/** * Circular buffer of the event with tail pointing to the last element. */
private AuditEvent[] events; private volatile int tail = -1; public InMemoryAuditEventRepository() { this(DEFAULT_CAPACITY); } public InMemoryAuditEventRepository(int capacity) { this.events = new AuditEvent[capacity]; }
Set the capacity of this event repository.
Params:
  • capacity – the capacity
/** * Set the capacity of this event repository. * @param capacity the capacity */
public void setCapacity(int capacity) { synchronized (this.monitor) { this.events = new AuditEvent[capacity]; } } @Override public void add(AuditEvent event) { Assert.notNull(event, "AuditEvent must not be null"); synchronized (this.monitor) { this.tail = (this.tail + 1) % this.events.length; this.events[this.tail] = event; } } @Override public List<AuditEvent> find(String principal, Instant after, String type) { LinkedList<AuditEvent> events = new LinkedList<>(); synchronized (this.monitor) { for (int i = 0; i < this.events.length; i++) { AuditEvent event = resolveTailEvent(i); if (event != null && isMatch(principal, after, type, event)) { events.addFirst(event); } } } return events; } private boolean isMatch(String principal, Instant after, String type, AuditEvent event) { boolean match = true; match = match && (principal == null || event.getPrincipal().equals(principal)); match = match && (after == null || event.getTimestamp().isAfter(after)); match = match && (type == null || event.getType().equals(type)); return match; } private AuditEvent resolveTailEvent(int offset) { int index = ((this.tail + this.events.length - offset) % this.events.length); return this.events[index]; } }