You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ma...@apache.org on 2022/02/13 18:24:01 UTC

[archiva] branch master updated: Adding rest events

This is an automated email from the ASF dual-hosted git repository.

martin_s pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/archiva.git


The following commit(s) were added to refs/heads/master by this push:
     new f41b350  Adding rest events
f41b350 is described below

commit f41b35042911a767eb3b14f37c11969ad3144fa9
Author: Martin Schreier <ma...@apache.org>
AuthorDate: Sun Feb 13 19:22:52 2022 +0100

    Adding rest events
---
 .../main/java/org/apache/archiva/event/Event.java  | 10 ++-
 .../org/apache/archiva/event/EventContext.java     |  6 +-
 .../apache/archiva/event/EventContextBuilder.java  | 13 +++-
 .../archiva/event/context/RepositoryContext.java   | 22 +++---
 .../apache/archiva/event/context/RestContext.java  | 41 +++++++----
 .../apache/archiva/event/context/UserContext.java  | 10 +--
 .../archiva/repository/event/RepositoryEvent.java  | 14 +++-
 .../archiva/rest/api/v2/event/RestEvent.java       | 45 +++++++++++
 .../rest/api/v2/event/RestRequestEvent.java        | 53 +++++++++++++
 .../rest/api/v2/event/RestResponseEvent.java       | 51 +++++++++++++
 .../archiva-rest/archiva-rest-services/pom.xml     | 11 ++-
 .../rest/v2/interceptor/AuditInterceptor.java      | 86 ++++++++++++++++++++++
 .../archiva/rest/v2/interceptor/Priorities.java    | 26 +++++++
 .../src/main/resources/META-INF/spring-context.xml |  1 +
 14 files changed, 343 insertions(+), 46 deletions(-)

diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/Event.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/Event.java
index 2439105..87ba24f 100644
--- a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/Event.java
+++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/Event.java
@@ -33,7 +33,7 @@ import java.util.stream.Collectors;
  * Events can be chained, which means a event listener can catch events and rethrow them as its own event.
  *
  */
-public class Event extends EventObject implements Cloneable {
+public class Event<C extends EventContext> extends EventObject implements Cloneable {
 
     private static final long serialVersionUID = -7171846575892044990L;
 
@@ -95,6 +95,10 @@ public class Event extends EventObject implements Cloneable {
         throw new IllegalArgumentException( "No matching event context registered for " + contextClazz );
     }
 
+    public C getContext() {
+        throw new UnsupportedOperationException( );
+    }
+
     public Map<String, String> getContextData() {
         return contextMap.entrySet( ).stream( ).flatMap( ctx -> ctx.getValue( ).getData( ).entrySet( ).stream( ) )
             .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue ) );
@@ -104,8 +108,8 @@ public class Event extends EventObject implements Cloneable {
         this.contextMap.put( clazz, context );
     }
 
-    public <T extends EventContext> void setContext( T context) {
-        this.contextMap.put( context.getClass(), context );
+    public void setContext( C context) {
+        throw new UnsupportedOperationException( );
     }
 
     /**
diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContext.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContext.java
index 9e113de..d74c82c 100644
--- a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContext.java
+++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContext.java
@@ -33,10 +33,10 @@ import java.util.Map;
 public interface EventContext
 {
     /**
-     * Returns the prefix used for entry keys in the repository data map.
-     * @return the prefix string for this context
+     * Returns the id which is also used as prefix for keys in the repository data map.
+     * @return the identifier of this context
      */
-    String getPrefix();
+    String getId();
 
     /**
      * Returns the context data as map of strings. Each entry key is prefixed with
diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContextBuilder.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContextBuilder.java
index 41f10ce..0ccfc95 100644
--- a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContextBuilder.java
+++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContextBuilder.java
@@ -21,6 +21,9 @@ import org.apache.archiva.event.context.RepositoryContext;
 import org.apache.archiva.event.context.RestContext;
 import org.apache.archiva.event.context.UserContext;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * Static helper class that allows to set certain context data
  *
@@ -34,8 +37,9 @@ public class EventContextBuilder
         evt.setContext( UserContext.class, new UserContext( user, remoteAddress ) );
     }
 
-    public static void setRestcontext(Event evt, String service, String path, String operation, int resultCode, String... parameters ) {
-        evt.setContext( RestContext.class, new RestContext( service, path, operation, resultCode, parameters ) );
+    public static void setRestContext( Event evt,  String path, String service, String operation,
+                                       String requestMethod, int resultCode, Map<String, List<String>> pathParameter) {
+        evt.setContext( RestContext.class, new RestContext( path, service, operation, requestMethod, resultCode, pathParameter ) );
     }
 
     public static void setRepositoryContext(Event evt, String id, String type, String flavour ) {
@@ -56,8 +60,9 @@ public class EventContextBuilder
         return this;
     }
 
-    public EventContextBuilder witRest( String service, String path, String operation, int resultCode, String... parameters) {
-        setRestcontext( this.evt, service, path, operation, resultCode, parameters );
+    public EventContextBuilder witRest( String path, String service, String operation, String requestMethod,
+        int resultCode, Map<String,List<String>> pathParameter) {
+        setRestContext( this.evt, path, service,  operation, requestMethod, resultCode, pathParameter );
         return this;
     }
 
diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RepositoryContext.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RepositoryContext.java
index 4df023d..1fb7f48 100644
--- a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RepositoryContext.java
+++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RepositoryContext.java
@@ -32,15 +32,15 @@ public class RepositoryContext implements EventContext, Serializable
 {
     private static final long serialVersionUID = -4172663291198878307L;
 
-    private static final String PREFIX = "repository";
+    private static final String ID = "repository";
 
-    private final String id;
+    private final String repositoryId;
     private final String type;
     private final String flavour;
 
-    public RepositoryContext( String id, String type, String flavour )
+    public RepositoryContext( String repositoryId, String type, String flavour )
     {
-        this.id = id;
+        this.repositoryId = repositoryId;
         this.type = type;
         this.flavour = flavour;
     }
@@ -49,9 +49,9 @@ public class RepositoryContext implements EventContext, Serializable
      * Returns the repository id
      * @return the repository id
      */
-    public String getId( )
+    public String getRepositoryId( )
     {
-        return id;
+        return repositoryId;
     }
 
     /**
@@ -76,15 +76,15 @@ public class RepositoryContext implements EventContext, Serializable
     public Map<String, String> getData( )
     {
         Map<String, String> values = new HashMap<>( );
-        values.put( PREFIX+".id", id );
-        values.put( PREFIX+".type", type );
-        values.put( PREFIX+".flavour", flavour );
+        values.put( ID +".repositoryId", repositoryId );
+        values.put( ID +".type", type );
+        values.put( ID +".flavour", flavour );
         return values;
     }
 
     @Override
-    public String getPrefix( )
+    public String getId( )
     {
-        return PREFIX;
+        return ID;
     }
 }
diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RestContext.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RestContext.java
index 615759d..c413735 100644
--- a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RestContext.java
+++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RestContext.java
@@ -20,7 +20,6 @@ package org.apache.archiva.event.context;
 import org.apache.archiva.event.EventContext;
 
 import java.io.Serializable;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -34,22 +33,25 @@ public class RestContext implements EventContext, Serializable
 {
     private static final long serialVersionUID = -4109505194250928317L;
 
-    public static final String PREFIX = "rest";
+    public static final String ID = "rest";
 
     private final String service;
     private final String path;
     private final String operation;
-    private final List<String> parameters;
+    private final String requestMethod;
     private final int resultCode;
+    private final Map<String, List<String>> pathParameter;
 
 
-    public RestContext( String service, String path, String operation, int resultCode, String... parameters )
+    public RestContext( String path, String service, String operation, String requestMethod, int resultCode,
+                        Map<String, List<String>> pathParameter)
     {
         this.service = service;
         this.path = path;
         this.operation = operation;
         this.resultCode = resultCode;
-        this.parameters = Arrays.asList( parameters );
+        this.requestMethod = requestMethod;
+        this.pathParameter = pathParameter;
     }
 
     public String getService( )
@@ -67,9 +69,9 @@ public class RestContext implements EventContext, Serializable
         return operation;
     }
 
-    public List<String> getParameters( )
+    public String getRequestMethod( )
     {
-        return parameters;
+        return requestMethod;
     }
 
     public int getResultCode( )
@@ -77,20 +79,33 @@ public class RestContext implements EventContext, Serializable
         return resultCode;
     }
 
+    public Map<String, List<String>> getPathParameter() {
+        return pathParameter;
+    }
+
     @Override
     public Map<String, String> getData( )
     {
         Map<String, String> values = new HashMap<>( );
-        values.put( PREFIX+".service", service );
-        values.put( PREFIX+".path", path );
-        values.put( PREFIX+".operation", operation );
-        values.put( PREFIX+".parameter", String.join( ",", parameters ) );
+        values.put( ID +".service", service );
+        values.put( ID +".path", path );
+        values.put( ID +".operation", operation );
+        values.put( ID +".requestMethod", requestMethod );
+        values.put( ID + ".pathParameter", getParamString( ) );
         return values;
     }
 
     @Override
-    public String getPrefix( )
+    public String getId( )
     {
-        return PREFIX;
+        return ID;
+    }
+
+    private String getParamString() {
+        StringBuilder sb = new StringBuilder( );
+        for(Map.Entry<String, List<String>> entry : pathParameter.entrySet()) {
+            sb.append( entry.getKey( ) ).append( String.join( ",", entry.getValue( ) ) );
+        }
+        return sb.toString( );
     }
 }
diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/UserContext.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/UserContext.java
index 8a83c73..9d3eeac 100644
--- a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/UserContext.java
+++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/UserContext.java
@@ -32,7 +32,7 @@ public class UserContext implements EventContext, Serializable
 {
     private static final long serialVersionUID = -3499164111736559781L;
 
-    private static final String PREFIX = "user";
+    private static final String ID = "user";
 
     private final String userId;
     private final String remoteAddress;
@@ -58,14 +58,14 @@ public class UserContext implements EventContext, Serializable
     public Map<String, String> getData( )
     {
         Map<String, String> values = new HashMap<>( );
-        values.put( PREFIX+".user_id", userId );
-        values.put( PREFIX+".remote_address", remoteAddress );
+        values.put( ID +".user_id", userId );
+        values.put( ID +".remote_address", remoteAddress );
         return values;
     }
 
     @Override
-    public String getPrefix( )
+    public String getId( )
     {
-        return PREFIX;
+        return ID;
     }
 }
diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/event/RepositoryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/event/RepositoryEvent.java
index a4b667b..0bd5a05 100644
--- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/event/RepositoryEvent.java
+++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/event/RepositoryEvent.java
@@ -22,6 +22,7 @@ package org.apache.archiva.repository.event;
 import org.apache.archiva.event.Event;
 import org.apache.archiva.event.EventContextBuilder;
 import org.apache.archiva.event.EventType;
+import org.apache.archiva.event.context.RepositoryContext;
 import org.apache.archiva.repository.ManagedRepository;
 import org.apache.archiva.repository.RemoteRepository;
 import org.apache.archiva.repository.Repository;
@@ -31,7 +32,7 @@ import org.apache.archiva.repository.RepositoryGroup;
  * A repository event is specific to a repository and holds a reference to the repository that
  * is related to this event.
  */
-public class RepositoryEvent extends Event
+public class RepositoryEvent extends Event<RepositoryContext>
 {
 
     private static final long serialVersionUID = 4676673476606414834L;
@@ -56,6 +57,17 @@ public class RepositoryEvent extends Event
     }
 
     @Override
+    public RepositoryContext getContext() {
+        return getContext( RepositoryContext.class );
+    }
+
+    @Override
+    public void setContext( RepositoryContext context )
+    {
+        setContext( RepositoryContext.class, context );
+    }
+
+    @Override
     public EventType<? extends RepositoryEvent> getType() {
         return (EventType<? extends RepositoryEvent>) super.getType();
     }
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestEvent.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestEvent.java
new file mode 100644
index 0000000..7c23548
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestEvent.java
@@ -0,0 +1,45 @@
+package org.apache.archiva.rest.api.v2.event;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+
+import org.apache.archiva.event.Event;
+import org.apache.archiva.event.EventContextBuilder;
+import org.apache.archiva.event.EventType;
+import org.apache.archiva.event.context.RestContext;
+
+/**
+ * @author Martin Schreier <ma...@apache.org>
+ */
+public class RestEvent extends Event<RestContext>
+{
+
+    public static EventType<RestEvent> ANY = new EventType<>( Event.ANY, "REST");
+
+
+    public RestEvent( EventType<? extends Event> type, Object originator)
+    {
+        super( type, originator );
+        EventContextBuilder builder = EventContextBuilder.withEvent( this );
+    }
+
+    @Override
+    public RestContext getContext() {
+        return getContext( RestContext.class );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestRequestEvent.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestRequestEvent.java
new file mode 100644
index 0000000..004ade6
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestRequestEvent.java
@@ -0,0 +1,53 @@
+package org.apache.archiva.rest.api.v2.event;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+
+import org.apache.archiva.event.Event;
+import org.apache.archiva.event.EventContextBuilder;
+import org.apache.archiva.event.EventType;
+import org.apache.archiva.event.context.RestContext;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Martin Schreier <ma...@apache.org>
+ */
+public class RestRequestEvent extends RestEvent
+{
+
+    public static EventType<RestRequestEvent> BEFORE = new EventType<>( RestEvent.ANY, "REST.REQUEST.BEFORE" );
+
+
+    public RestRequestEvent( EventType<? extends Event> type, Object originator,
+                             String path, String service, String operation, String requestMethod,
+                             Map<String,List<String>> pathParameter )
+    {
+        super( type, originator );
+        EventContextBuilder builder = EventContextBuilder.withEvent( this );
+        builder.witRest( path, service, operation, requestMethod, -1, pathParameter );
+        builder.apply( );
+    }
+
+    @Override
+    public RestContext getContext( )
+    {
+        return getContext( RestContext.class );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestResponseEvent.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestResponseEvent.java
new file mode 100644
index 0000000..0923221
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/event/RestResponseEvent.java
@@ -0,0 +1,51 @@
+package org.apache.archiva.rest.api.v2.event;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+
+import org.apache.archiva.event.Event;
+import org.apache.archiva.event.EventContextBuilder;
+import org.apache.archiva.event.EventType;
+import org.apache.archiva.event.context.RestContext;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Martin Schreier <ma...@apache.org>
+ */
+public class RestResponseEvent extends RestEvent
+{
+    public static EventType<RestResponseEvent> AFTER = new EventType<>( RestEvent.ANY, "REST.RESPONSE.AFTER" );
+
+    public RestResponseEvent( EventType<? extends Event> type, Object originator,
+                              String path, String service, String operation, String requestMethod, int resultCode,
+                              Map<String, List<String>> pathParameter )
+    {
+        super( type, originator );
+        EventContextBuilder builder = EventContextBuilder.withEvent( this );
+        builder.witRest( path, service, operation, requestMethod, resultCode, pathParameter );
+        builder.apply( );
+    }
+
+    @Override
+    public RestContext getContext( )
+    {
+        return getContext( RestContext.class );
+    }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml
index 519fb1e..c7391c6 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/pom.xml
@@ -252,7 +252,11 @@
 
     <dependency>
        <groupId>jakarta.inject</groupId>
-<artifactId>jakarta.inject-api</artifactId>
+      <artifactId>jakarta.inject-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>jakarta.annotation</groupId>
+      <artifactId>jakarta.annotation-api</artifactId>
     </dependency>
     <dependency>
       <groupId>jakarta.xml.bind</groupId>
@@ -493,11 +497,6 @@
 
     <!-- Needed for JDK >= 9 -->
     <dependency>
-      <groupId>jakarta.annotation</groupId>
-      <artifactId>jakarta.annotation-api</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
       <groupId>org.glassfish.jaxb</groupId>
       <artifactId>jaxb-runtime</artifactId>
       <scope>test</scope>
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/AuditInterceptor.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/AuditInterceptor.java
new file mode 100644
index 0000000..d18ae8c
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/AuditInterceptor.java
@@ -0,0 +1,86 @@
+package org.apache.archiva.rest.v2.interceptor;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.archiva.admin.model.AuditInformation;
+import org.apache.archiva.event.AbstractEventManager;
+import org.apache.archiva.event.Event;
+import org.apache.archiva.event.EventContextBuilder;
+import org.apache.archiva.event.EventHandler;
+import org.apache.archiva.event.EventSource;
+import org.apache.archiva.event.EventType;
+import org.apache.archiva.event.context.RestContext;
+import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
+import org.apache.archiva.redback.rest.services.RedbackRequestInformation;
+import org.apache.archiva.redback.users.User;
+import org.apache.archiva.rest.api.v2.event.RestRequestEvent;
+import org.apache.archiva.rest.api.v2.event.RestResponseEvent;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.ResourceInfo;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.Provider;
+import java.io.IOException;
+import javax.annotation.Priority;
+
+
+/**
+ * @author Martin Schreier <ma...@apache.org>
+ */
+@Provider
+@Service( "restInterceptor#audit" )
+@Priority( Priorities.AUDIT )
+public class AuditInterceptor extends AbstractEventManager implements ContainerRequestFilter, ContainerResponseFilter, EventSource
+{
+    @Context
+    ResourceInfo resourceInfo;
+
+    protected void addAuditInformation( Event<RestContext> evt )
+    {
+        RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get();
+        String user = redbackRequestInformation == null ? "" : redbackRequestInformation.getUser().getUsername();
+        String remoteAddr = redbackRequestInformation == null ? "" : redbackRequestInformation.getRemoteAddr();
+        EventContextBuilder.withEvent( evt ).withUser( user, remoteAddr ).apply();
+    }
+
+    @Override
+    public void filter( ContainerRequestContext requestContext, ContainerResponseContext responseContext ) throws IOException
+    {
+        RestResponseEvent evt = new RestResponseEvent( RestResponseEvent.AFTER,
+            this, requestContext.getUriInfo( ).getPath( ), resourceInfo.getResourceClass( ).getName( ), resourceInfo.getResourceMethod( ).getName( )
+            , requestContext.getMethod( ), responseContext.getStatus( ), requestContext.getUriInfo( ).getPathParameters( ) );
+        addAuditInformation( evt );
+        fireEvent( evt, this );
+    }
+
+    @Override
+    public void filter( ContainerRequestContext requestContext ) throws IOException
+    {
+        RestRequestEvent evt = new RestRequestEvent( RestRequestEvent.BEFORE, this,
+            requestContext.getUriInfo().getPath(), resourceInfo.getResourceClass().getName(),  resourceInfo.getResourceMethod().getName()
+            , requestContext.getMethod(), requestContext.getUriInfo().getPathParameters() );
+        addAuditInformation( evt );
+        fireEvent( evt, this );
+    }
+
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/Priorities.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/Priorities.java
new file mode 100644
index 0000000..91b9319
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/interceptor/Priorities.java
@@ -0,0 +1,26 @@
+package org.apache.archiva.rest.v2.interceptor;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * @author Martin Schreier <ma...@apache.org>
+ */
+public class Priorities
+{
+    public static final int AUDIT = 5000;
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml
index 0449986..95d3019 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/resources/META-INF/spring-context.xml
@@ -74,6 +74,7 @@
       <ref bean="requestValidationInterceptor#rest" />
       <ref bean="archivaRestServiceExceptionMapper"/>
       <ref bean="threadLocalUserCleaner#rest" />
+      <ref bean="restInterceptor#audit" />
     </jaxrs:providers>
 
     <jaxrs:serviceBeans>