Browse Source
* Added AuditEvent and AuditEventRepository * Also AuditApplicationEvent and AuditListener for handling AUditEvents as Spring ApplicationEvents [Fixes #48155753]pull/1/head
7 changed files with 375 additions and 0 deletions
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* 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.springframework.bootstrap.service.audit; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* A value object representing an audit event: at a particular time, a particular user or |
||||
* agent carried out an action of a particular type. This object records the details of |
||||
* such an event. |
||||
* |
||||
* @author Dave Syer |
||||
* |
||||
*/ |
||||
public class AuditEvent { |
||||
|
||||
final private Date timestamp; |
||||
final private String principal; |
||||
final private String type; |
||||
final private Map<String, Object> data; |
||||
|
||||
/** |
||||
* Create a new audit event for the current time from data provided as name-value |
||||
* pairs |
||||
*/ |
||||
public AuditEvent(String principal, String type, String... data) { |
||||
this(new Date(), principal, type, convert(data)); |
||||
} |
||||
|
||||
/** |
||||
* Create a new audit event for the current time |
||||
*/ |
||||
public AuditEvent(String principal, String type, Map<String, Object> data) { |
||||
this(new Date(), principal, type, data); |
||||
} |
||||
|
||||
/** |
||||
* Create a new audit event. |
||||
*/ |
||||
public AuditEvent(Date timestamp, String principal, String type, |
||||
Map<String, Object> data) { |
||||
this.timestamp = timestamp; |
||||
this.principal = principal; |
||||
this.type = type; |
||||
this.data = Collections.unmodifiableMap(data); |
||||
} |
||||
|
||||
public Date getTimestamp() { |
||||
return this.timestamp; |
||||
} |
||||
|
||||
public String getPrincipal() { |
||||
return this.principal; |
||||
} |
||||
|
||||
public String getType() { |
||||
return this.type; |
||||
} |
||||
|
||||
public Map<String, Object> getData() { |
||||
return this.data; |
||||
} |
||||
|
||||
private static Map<String, Object> convert(String[] data) { |
||||
Map<String, Object> result = new HashMap<String, Object>(); |
||||
for (String entry : data) { |
||||
if (entry.contains("=")) { |
||||
int index = entry.indexOf("="); |
||||
result.put(entry.substring(0, index), entry.substring(index + 1)); |
||||
} else { |
||||
result.put(entry, null); |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* 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.springframework.bootstrap.service.audit; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author Dave Syer |
||||
* |
||||
*/ |
||||
public interface AuditEventRepository { |
||||
|
||||
/** |
||||
* Find audit events relating to the specified principal since the time provided. |
||||
* |
||||
* @param principal the principal name to search for |
||||
* @param after timestamp of earliest result required |
||||
* @return audit events relating to the principal |
||||
*/ |
||||
List<AuditEvent> find(String principal, Date after); |
||||
|
||||
/** |
||||
* Log an event. |
||||
* |
||||
* @param event the audit event to log |
||||
*/ |
||||
void add(AuditEvent event); |
||||
|
||||
} |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* 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.springframework.bootstrap.service.audit; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author Dave Syer |
||||
* |
||||
*/ |
||||
public class InMemoryAuditEventRepository implements AuditEventRepository { |
||||
|
||||
private int capacity = 100; |
||||
|
||||
private Map<String, List<AuditEvent>> events = new HashMap<String, List<AuditEvent>>(); |
||||
|
||||
/** |
||||
* @param capacity the capacity to set |
||||
*/ |
||||
public void setCapacity(int capacity) { |
||||
this.capacity = capacity; |
||||
} |
||||
|
||||
@Override |
||||
public List<AuditEvent> find(String principal, Date after) { |
||||
synchronized (this.events) { |
||||
return Collections.unmodifiableList(getEvents(principal)); |
||||
} |
||||
} |
||||
|
||||
private List<AuditEvent> getEvents(String principal) { |
||||
if (!this.events.containsKey(principal)) { |
||||
this.events.put(principal, new ArrayList<AuditEvent>()); |
||||
} |
||||
return this.events.get(principal); |
||||
} |
||||
|
||||
@Override |
||||
public void add(AuditEvent event) { |
||||
synchronized (this.events) { |
||||
List<AuditEvent> list = getEvents(event.getPrincipal()); |
||||
while (list.size() >= this.capacity) { |
||||
list.remove(0); |
||||
} |
||||
list.add(event); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* 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.springframework.bootstrap.service.audit.listener; |
||||
|
||||
import org.springframework.bootstrap.service.audit.AuditEvent; |
||||
import org.springframework.context.ApplicationEvent; |
||||
|
||||
/** |
||||
* @author Dave Syer |
||||
* |
||||
*/ |
||||
public class AuditApplicationEvent extends ApplicationEvent { |
||||
|
||||
private AuditEvent auditEvent; |
||||
|
||||
/** |
||||
* @param auditEvent the source of this event |
||||
*/ |
||||
public AuditApplicationEvent(AuditEvent auditEvent) { |
||||
super(auditEvent); |
||||
this.auditEvent = auditEvent; |
||||
} |
||||
|
||||
/** |
||||
* @return the audit event |
||||
*/ |
||||
public AuditEvent getAuditEvent() { |
||||
return this.auditEvent; |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* 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.springframework.bootstrap.service.audit.listener; |
||||
|
||||
import org.springframework.bootstrap.service.audit.AuditEventRepository; |
||||
import org.springframework.context.ApplicationListener; |
||||
|
||||
/** |
||||
* @author Dave Syer |
||||
* |
||||
*/ |
||||
public class AuditListener implements ApplicationListener<AuditApplicationEvent> { |
||||
|
||||
private final AuditEventRepository auditEventRepository; |
||||
|
||||
public AuditListener(AuditEventRepository auditEventRepository) { |
||||
this.auditEventRepository = auditEventRepository; |
||||
} |
||||
|
||||
@Override |
||||
public void onApplicationEvent(AuditApplicationEvent event) { |
||||
this.auditEventRepository.add(event.getAuditEvent()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* 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.springframework.bootstrap.service.audit; |
||||
|
||||
import java.util.Collections; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertNotNull; |
||||
|
||||
/** |
||||
* @author Dave Syer |
||||
* |
||||
*/ |
||||
public class AuditEventTests { |
||||
|
||||
@Test |
||||
public void testNowEvent() throws Exception { |
||||
AuditEvent event = new AuditEvent("phil", "UNKNOWN", Collections.singletonMap( |
||||
"a", (Object) "b")); |
||||
assertEquals("b", event.getData().get("a")); |
||||
assertEquals("UNKNOWN", event.getType()); |
||||
assertEquals("phil", event.getPrincipal()); |
||||
assertNotNull(event.getTimestamp()); |
||||
} |
||||
|
||||
@Test |
||||
public void testConvertStringsToData() throws Exception { |
||||
AuditEvent event = new AuditEvent("phil", "UNKNOWN", "a=b", "c=d"); |
||||
assertEquals("b", event.getData().get("a")); |
||||
assertEquals("d", event.getData().get("c")); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* |
||||
* Copyright 2012-2013 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 |
||||
* |
||||
* 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.springframework.bootstrap.service.audit; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
/** |
||||
* @author Dave Syer |
||||
* |
||||
*/ |
||||
public class InMemoryAuditEventRepositoryTests { |
||||
|
||||
private InMemoryAuditEventRepository repository = new InMemoryAuditEventRepository(); |
||||
|
||||
@Test |
||||
public void testAddToCapacity() throws Exception { |
||||
this.repository.setCapacity(2); |
||||
this.repository.add(new AuditEvent("phil", "UNKNOWN")); |
||||
this.repository.add(new AuditEvent("phil", "UNKNOWN")); |
||||
this.repository.add(new AuditEvent("dave", "UNKNOWN")); |
||||
this.repository.add(new AuditEvent("dave", "UNKNOWN")); |
||||
this.repository.add(new AuditEvent("phil", "UNKNOWN")); |
||||
assertEquals(2, this.repository.find("phil", new Date(0L)).size()); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue