Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2016 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.
Expand Down Expand Up @@ -80,6 +80,7 @@ public AuditEvent(String principal, String type, String... data) {
public AuditEvent(Date timestamp, String principal, String type,
Map<String, Object> data) {
Assert.notNull(timestamp, "Timestamp must not be null");
Assert.notNull(principal, "Principal must not be null");
Assert.notNull(type, "Type must not be null");
this.timestamp = timestamp;
this.principal = principal;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2016 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.
Expand All @@ -23,9 +23,18 @@
* Repository for {@link AuditEvent}s.
*
* @author Dave Syer
* @author Vedran Pavic
*/
public interface AuditEventRepository {

/**
* Find audit events since the time provided.
* @param after timestamp of earliest result required
* @return audit events
* @since 1.4.0
*/
List<AuditEvent> find(Date after);

/**
* Find audit events relating to the specified principal since the time provided.
* @param principal the principal name to search for
Expand All @@ -34,6 +43,17 @@ public interface AuditEventRepository {
*/
List<AuditEvent> find(String principal, Date after);

/**
* Find audit events of specified type relating to the specified principal since the
* time provided.
* @param principal the principal name to search for
* @param type the event type to search for
* @param after timestamp of earliest result required
* @return audit events of specified type relating to the principal
* @since 1.4.0
*/
List<AuditEvent> find(String principal, String type, Date after);

/**
* Log an event.
* @param event the audit event to log
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2016 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.
Expand All @@ -20,11 +20,14 @@
import java.util.LinkedList;
import java.util.List;

import org.springframework.util.Assert;

/**
* In-memory {@link AuditEventRepository} implementation.
*
* @author Dave Syer
* @author Phillip Webb
* @author Vedran Pavic
*/
public class InMemoryAuditEventRepository implements AuditEventRepository {

Expand All @@ -33,7 +36,7 @@ public class InMemoryAuditEventRepository implements AuditEventRepository {
/**
* Circular buffer of the event with tail pointing to the last element.
*/
private AuditEvent[] events;
private final AuditEvent[] events;

private volatile int tail = -1;

Expand All @@ -45,39 +48,84 @@ public InMemoryAuditEventRepository(int capacity) {
this.events = new AuditEvent[capacity];
}

/**
* Set the capacity of this event repository.
* @param capacity the capacity
*/
public synchronized void setCapacity(int capacity) {
this.events = new AuditEvent[capacity];
@Override
public List<AuditEvent> find(Date after) {
LinkedList<AuditEvent> events = new LinkedList<AuditEvent>();
synchronized (this.events) {
for (int i = 0; i < this.events.length; i++) {
AuditEvent event = resolveTailEvent(i);
if (event == null) {
break;
}
if (isMatch(event, after)) {
events.addFirst(event);
}
}
}
return events;
}

@Override
public synchronized List<AuditEvent> find(String principal, Date after) {
public List<AuditEvent> find(String principal, Date after) {
Assert.notNull(principal, "Principal must not be null");
LinkedList<AuditEvent> events = new LinkedList<AuditEvent>();
for (int i = 0; i < this.events.length; i++) {
int index = ((this.tail + this.events.length - i) % this.events.length);
AuditEvent event = this.events[index];
if (event == null) {
break;
}
if (isMatch(event, principal, after)) {
events.addFirst(event);
synchronized (this.events) {
for (int i = 0; i < this.events.length; i++) {
AuditEvent event = resolveTailEvent(i);
if (event == null) {
break;
}
if (isMatch(event, principal, after)) {
events.addFirst(event);
}
}
}
return events;
}

private boolean isMatch(AuditEvent auditEvent, String principal, Date after) {
return (principal == null || auditEvent.getPrincipal().equals(principal))
&& (after == null || auditEvent.getTimestamp().compareTo(after) >= 0);
@Override
public List<AuditEvent> find(String principal, String type, Date after) {
Assert.notNull(principal, "Principal must not be null");
Assert.notNull(type, "Type must not be null");
LinkedList<AuditEvent> events = new LinkedList<AuditEvent>();
synchronized (this.events) {
for (int i = 0; i < this.events.length; i++) {
AuditEvent event = resolveTailEvent(i);
if (event == null) {
break;
}
if (isMatch(event, principal, type, after)) {
events.addFirst(event);
}
}
}
return events;
}

@Override
public synchronized void add(AuditEvent event) {
this.tail = (this.tail + 1) % this.events.length;
this.events[this.tail] = event;
public void add(AuditEvent event) {
Assert.notNull(event, "AuditEvent must not be null");
synchronized (this.events) {
this.tail = (this.tail + 1) % this.events.length;
this.events[this.tail] = event;
}
}

private AuditEvent resolveTailEvent(int offset) {
int index = ((this.tail + this.events.length - offset) % this.events.length);
return this.events[index];
}

private boolean isMatch(AuditEvent event, Date after) {
return (after == null || event.getTimestamp().compareTo(after) >= 0);
}

private boolean isMatch(AuditEvent event, String principal, Date after) {
return (event.getPrincipal().equals(principal) && isMatch(event, after));
}

private boolean isMatch(AuditEvent event, String principal, String type, Date after) {
return (event.getType().equals(type) && isMatch(event, principal, after));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,25 @@

import java.util.Collections;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link AuditEvent}.
*
* @author Dave Syer
* @author Vedran Pavic
*/
public class AuditEventTests {

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void testNowEvent() throws Exception {
public void nowEvent() throws Exception {
AuditEvent event = new AuditEvent("phil", "UNKNOWN",
Collections.singletonMap("a", (Object) "b"));
assertThat(event.getData().get("a")).isEqualTo("b");
Expand All @@ -40,10 +46,32 @@ public void testNowEvent() throws Exception {
}

@Test
public void testConvertStringsToData() throws Exception {
public void convertStringsToData() throws Exception {
AuditEvent event = new AuditEvent("phil", "UNKNOWN", "a=b", "c=d");
assertThat(event.getData().get("a")).isEqualTo("b");
assertThat(event.getData().get("c")).isEqualTo("d");
}

@Test
public void nullTimestamp() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Timestamp must not be null");
new AuditEvent(null, "phil", "UNKNOWN",
Collections.singletonMap("a", (Object) "b"));
}

@Test
public void nullPrincipal() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Principal must not be null");
new AuditEvent(null, "UNKNOWN", Collections.singletonMap("a", (Object) "b"));
}

@Test
public void nullType() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Type must not be null");
new AuditEvent("phil", null, Collections.singletonMap("a", (Object) "b"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import java.util.List;
import java.util.Map;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.assertj.core.api.Assertions.assertThat;

Expand All @@ -31,9 +33,13 @@
*
* @author Dave Syer
* @author Phillip Webb
* @author Vedran Pavic
*/
public class InMemoryAuditEventRepositoryTests {

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void lessThanCapacity() throws Exception {
InMemoryAuditEventRepository repository = new InMemoryAuditEventRepository();
Expand All @@ -43,7 +49,6 @@ public void lessThanCapacity() throws Exception {
assertThat(events.size()).isEqualTo(2);
assertThat(events.get(0).getType()).isEqualTo("a");
assertThat(events.get(1).getType()).isEqualTo("b");

}

@Test
Expand All @@ -58,6 +63,14 @@ public void capacity() throws Exception {
assertThat(events.get(1).getType()).isEqualTo("c");
}

@Test
public void addNullAuditEvent() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("AuditEvent must not be null");
InMemoryAuditEventRepository repository = new InMemoryAuditEventRepository();
repository.add(null);
}

@Test
public void findByPrincipal() throws Exception {
InMemoryAuditEventRepository repository = new InMemoryAuditEventRepository();
Expand All @@ -71,6 +84,19 @@ public void findByPrincipal() throws Exception {
assertThat(events.get(1).getType()).isEqualTo("c");
}

@Test
public void findByPrincipalAndType() throws Exception {
InMemoryAuditEventRepository repository = new InMemoryAuditEventRepository();
repository.add(new AuditEvent("dave", "a"));
repository.add(new AuditEvent("phil", "b"));
repository.add(new AuditEvent("dave", "c"));
repository.add(new AuditEvent("phil", "d"));
List<AuditEvent> events = repository.find("dave", "a", null);
assertThat(events.size()).isEqualTo(1);
assertThat(events.get(0).getPrincipal()).isEqualTo("dave");
assertThat(events.get(0).getType()).isEqualTo("a");
}

@Test
public void findByDate() throws Exception {
Calendar calendar = Calendar.getInstance();
Expand All @@ -87,7 +113,7 @@ public void findByDate() throws Exception {
calendar.add(Calendar.DAY_OF_YEAR, 1);
repository.add(new AuditEvent(calendar.getTime(), "phil", "d", data));
calendar.add(Calendar.DAY_OF_YEAR, 1);
List<AuditEvent> events = repository.find(null, after);
List<AuditEvent> events = repository.find(after);
assertThat(events.size()).isEqualTo(2);
assertThat(events.get(0).getType()).isEqualTo("c");
assertThat(events.get(1).getType()).isEqualTo("d");
Expand Down