From 0a2dab16770cce10bda6fa2cc2e2d9c7d64c5dbf Mon Sep 17 00:00:00 2001 From: Martin Schreier Date: Sun, 13 Feb 2022 10:27:32 +0100 Subject: Improving event API --- .../main/java/org/apache/archiva/event/Event.java | 112 ------------- .../org/apache/archiva/event/EventHandler.java | 31 ---- .../org/apache/archiva/event/EventManager.java | 80 ---------- .../java/org/apache/archiva/event/EventSource.java | 33 ---- .../java/org/apache/archiva/event/EventType.java | 166 ------------------- .../org/apache/archiva/event/EventManagerTest.java | 140 ---------------- .../archiva-consumer-archetype/pom.xml | 6 + .../archiva-base/archiva-event-api/pom.xml | 41 +++++ .../apache/archiva/event/AbstractEventManager.java | 84 ++++++++++ .../apache/archiva/event/BasicEventManager.java | 41 +++++ .../main/java/org/apache/archiva/event/Event.java | 150 +++++++++++++++++ .../org/apache/archiva/event/EventContext.java | 48 ++++++ .../apache/archiva/event/EventContextBuilder.java | 72 +++++++++ .../org/apache/archiva/event/EventHandler.java | 31 ++++ .../java/org/apache/archiva/event/EventSource.java | 33 ++++ .../java/org/apache/archiva/event/EventType.java | 177 +++++++++++++++++++++ .../archiva/event/context/RepositoryContext.java | 90 +++++++++++ .../apache/archiva/event/context/RestContext.java | 96 +++++++++++ .../apache/archiva/event/context/UserContext.java | 71 +++++++++ .../org/apache/archiva/event/package-info.java | 37 +++++ .../archiva/event/BasicEventManagerTest.java | 139 ++++++++++++++++ .../archiva-base/archiva-event-central/pom.xml | 44 +++++ .../archiva/event/central/CentralEventManager.java | 42 +++++ .../src/main/resources/META-INF/spring-context.xml | 32 ++++ .../archiva-repository-admin-default/pom.xml | 4 + .../archiva-base/archiva-repository-api/pom.xml | 4 + .../archiva/repository/RepositoryHandler.java | 4 +- .../archiva/repository/event/RepositoryEvent.java | 22 +++ .../archiva-base/archiva-repository-layer/pom.xml | 4 + .../repository/base/AbstractRepository.java | 8 +- .../repository/base/AbstractRepositoryHandler.java | 10 +- .../repository/base/ArchivaRepositoryRegistry.java | 20 ++- .../base/managed/ManagedRepositoryHandler.java | 2 + .../base/group/RepositoryGroupHandlerTest.java | 4 +- archiva-modules/archiva-base/pom.xml | 2 + .../archiva-maven/archiva-maven-repository/pom.xml | 4 + .../maven/repository/MavenRepositoryProvider.java | 12 +- .../rest/api/v2/model/MavenManagedRepository.java | 31 ---- .../api/v2/model/MavenManagedRepositoryUpdate.java | 9 +- .../api/v2/model/map/MavenRepositoryMapper.java | 12 +- .../apache/archiva/rest/api/v2/svc/ErrorKeys.java | 6 + .../v2/model/map/MavenRepositoryMapperTest.java | 45 ++++++ .../archiva-rest/archiva-rest-services/pom.xml | 4 + .../archiva/rest/v2/svc/AbstractService.java | 51 ++++++ .../DefaultMavenManagedRepositoryService.java | 57 +++---- .../NativeMavenManagedRepositoryServiceTest.java | 3 +- pom.xml | 10 ++ 47 files changed, 1467 insertions(+), 657 deletions(-) delete mode 100644 archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/Event.java delete mode 100644 archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventHandler.java delete mode 100644 archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventManager.java delete mode 100644 archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventSource.java delete mode 100644 archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventType.java delete mode 100644 archiva-modules/archiva-base/archiva-common/src/test/java/org/apache/archiva/event/EventManagerTest.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/pom.xml create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/AbstractEventManager.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/BasicEventManager.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/Event.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContext.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContextBuilder.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventHandler.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventSource.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventType.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RepositoryContext.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RestContext.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/UserContext.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/package-info.java create mode 100644 archiva-modules/archiva-base/archiva-event-api/src/test/java/org/apache/archiva/event/BasicEventManagerTest.java create mode 100644 archiva-modules/archiva-base/archiva-event-central/pom.xml create mode 100644 archiva-modules/archiva-base/archiva-event-central/src/main/java/org/apache/archiva/event/central/CentralEventManager.java create mode 100644 archiva-modules/archiva-base/archiva-event-central/src/main/resources/META-INF/spring-context.xml create mode 100644 archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/AbstractService.java diff --git a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/Event.java b/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/Event.java deleted file mode 100644 index eda85701e..000000000 --- a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/Event.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.apache.archiva.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 java.time.LocalDateTime; -import java.util.EventObject; - -/** - * Base class for events. Events have a type and a source. - * The source is the instance that raised the event. - * - * There are different event types for a given event. The types are represented in a hierarchical structure. - * - * 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 { - - private static final long serialVersionUID = -7171846575892044990L; - - public static final EventType ANY = EventType.ROOT; - - private Event previous; - private final EventType type; - private final LocalDateTime createTime; - - public Event(EventType type, Object originator) { - super(originator); - this.type = type; - this.createTime = LocalDateTime.now(); - } - - private Event(Event previous, Object originator) { - super(originator); - this.previous = previous; - this.type = previous.getType(); - this.createTime = previous.getCreateTime(); - } - - /** - * Returns the event type that is associated with this event instance. - * @return the event type - */ - public EventType getType() { - return type; - }; - - /** - * Returns the time, when the event was created. - * @return - */ - public LocalDateTime getCreateTime() { - return createTime; - } - - - /** - * Recreates the event with the given instance as the new source. The - * current source is stored in the previous event. - * @param newSource The new source - * @return a new event instance, where this is stored as previous event - */ - public Event copyFor(Object newSource) { - Event newEvent = (Event) this.clone(); - newEvent.previous = this; - newEvent.source = newSource; - return newEvent; - } - - /** - * Returns the previous event or null, if this is a root event. - * @return the previous event or null, if it does not exist - */ - public Event getPreviousEvent() { - return previous; - } - - /** - * Returns true, if the event has a previous event. - * @return true, if this has a previous event, otherwise false - */ - public boolean hasPreviousEvent() { - return previous!=null; - } - - @Override - protected Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - // this should not happen - throw new RuntimeException("Event is not clonable"); - } - } -} diff --git a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventHandler.java b/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventHandler.java deleted file mode 100644 index f98adcdab..000000000 --- a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apache.archiva.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 java.util.EventListener; - -/** - * A listener that accepts events. - */ -public interface EventHandler extends EventListener { - - void handle(T event); -} diff --git a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventManager.java b/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventManager.java deleted file mode 100644 index 00a240066..000000000 --- a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventManager.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.apache.archiva.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.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -public class EventManager implements EventSource -{ - - private static final Logger LOG = LoggerFactory.getLogger(EventManager.class); - - private final ConcurrentHashMap, Set> handlerMap = new ConcurrentHashMap<>(); - - private final Object source; - - public EventManager(Object source) { - if (source==null) { - throw new IllegalArgumentException("The source may not be null"); - } - this.source = source; - } - - @Override - public void registerEventHandler(EventType type, EventHandler eventHandler) { - Set handlers = handlerMap.computeIfAbsent(type, t -> new LinkedHashSet<>()); - if (!handlers.contains(eventHandler)) { - handlers.add(eventHandler); - } - } - - @Override - public void unregisterEventHandler(EventType type, EventHandler eventHandler) { - if (handlerMap.containsKey(type)) { - handlerMap.get(type).remove(eventHandler); - } - } - - public void fireEvent(Event fireEvent) { - final EventType type = fireEvent.getType(); - Event event; - if (fireEvent.getSource()!=source) { - event = fireEvent.copyFor(source); - } else { - event = fireEvent; - } - for (EventType handlerType : handlerMap.keySet()) { - if (EventType.isInstanceOf(type, handlerType)) { - for (EventHandler handler : handlerMap.get(handlerType)) { - try { - handler.handle(event); - } catch (Exception e) { - // We catch all errors from handlers - LOG.error("An error occured during event handling: {}", e.getMessage(), e); - } - } - } - } - } -} diff --git a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventSource.java b/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventSource.java deleted file mode 100644 index 452a5e9d9..000000000 --- a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventSource.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.apache.archiva.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. - */ - -/** - * A repository event source raises events to its registered listeners. - * Listeners register to event types that are structured hierarchical. - * - */ -public interface EventSource { - - void registerEventHandler( EventType type, EventHandler eventHandler); - - void unregisterEventHandler(EventType type, EventHandler eventHandler); - -} diff --git a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventType.java b/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventType.java deleted file mode 100644 index 50d42679e..000000000 --- a/archiva-modules/archiva-base/archiva-common/src/main/java/org/apache/archiva/event/EventType.java +++ /dev/null @@ -1,166 +0,0 @@ -package org.apache.archiva.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 java.io.InvalidObjectException; -import java.io.ObjectStreamException; -import java.io.Serializable; -import java.util.*; - -/** - * Event types define a hierarchical structure of events. Each event is bound to a certain event type. - * All event types have a super type, only the root event type {@link EventType#ROOT} has no super type. - * - * Event types should be stored as static fields on the events itself. - * - * @param The type class parameter allows to define the types in a type safe way and represents a event class, - * where the type is associated to. - */ -public class EventType implements Serializable { - - - public static final EventType ROOT = new EventType<>(); - - private final String name; - private final EventType superType; - private WeakHashMap, Void> subTypes; - - /** - * Creates a type with the given name and the root type as parent. - * @param name the name of the new type - */ - public EventType(String name) { - this.superType = ROOT; - this.name = name; - } - - /** - * Creates a event type instance with the given super type and name. - * - * @param superType The super type or null, if this is the root type. - * @param name - */ - public EventType(EventType superType, String name) { - if (superType==null) { - throw new NullPointerException("Super Type may not be null"); - } - this.name = name; - this.superType = superType; - superType.register(this); - } - - /** - * Creates the root type - */ - private EventType() { - this.name="ROOT"; - this.superType=null; - } - - public String name() { - return name; - } - - public EventType getSuperType() { - return superType; - } - - private void register(EventType subType) { - if (subTypes == null) { - subTypes = new WeakHashMap<>(); - } - for (EventType t : subTypes.keySet()) { - if (((t.name == null && subType.name == null) || (t.name != null && t.name.equals(subType.name)))) { - throw new IllegalArgumentException("EventType \"" + subType + "\"" - + "with parent \"" + subType.getSuperType()+"\" already exists"); - } - } - subTypes.put(subType, null); - } - - - public static List> fetchSuperTypes(EventType type) { - List> typeList = new ArrayList<>(); - EventType cType = type; - while (cType!=null) { - typeList.add(cType); - cType = cType.getSuperType(); - } - return typeList; - } - - public static boolean isInstanceOf(EventType type, EventType baseType) { - EventType cType = type; - while(cType!=null) { - if (cType == baseType) { - return true; - } - cType = cType.getSuperType(); - } - return false; - } - - - private Object writeReplace() throws ObjectStreamException { - Deque path = new LinkedList<>(); - EventType t = this; - while (t != ROOT) { - path.addFirst(t.name); - t = t.superType; - } - return new EventTypeSerialization(new ArrayList<>(path)); - } - - static class EventTypeSerialization implements Serializable { - private static final long serialVersionUID = 1841649460281865547L; - private List path; - - public EventTypeSerialization(List path) { - this.path = path; - } - - private Object readResolve() throws ObjectStreamException { - EventType t = ROOT; - for (int i = 0; i < path.size(); ++i) { - String p = path.get(i); - if (t.subTypes != null) { - EventType s = findSubType(t.subTypes.keySet(), p); - if (s == null) { - throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")"); - } - t = s; - } else { - throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")"); - } - } - return t; - } - - private EventType findSubType(Set subTypes, String name) { - for (EventType t : subTypes) { - if (((t.name == null && name == null) || (t.name != null && t.name.equals(name)))) { - return t; - } - } - return null; - } - - } -} diff --git a/archiva-modules/archiva-base/archiva-common/src/test/java/org/apache/archiva/event/EventManagerTest.java b/archiva-modules/archiva-base/archiva-common/src/test/java/org/apache/archiva/event/EventManagerTest.java deleted file mode 100644 index f894cb574..000000000 --- a/archiva-modules/archiva-base/archiva-common/src/test/java/org/apache/archiva/event/EventManagerTest.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.apache.archiva.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.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * @author Martin Stockhammer - */ -public class EventManagerTest -{ - - private class TestHandler implements EventHandler { - - private List eventList = new ArrayList<>( ); - @Override - public void handle( Event event ) - { - eventList.add( event ); - } - - public List getEventList() { - return eventList; - } - } - - private EventType testType = new EventType<>( "TEST" ); - private EventType testTestType = new EventType<>( testType,"TEST.TEST" ); - private EventType otherType = new EventType( "OTHER" ); - - @Test - public void registerEventHandler( ) - { - EventManager eventManager = new EventManager( this ); - TestHandler handler1 = new TestHandler( ); - TestHandler handler2 = new TestHandler( ); - TestHandler handler3 = new TestHandler( ); - TestHandler handler4 = new TestHandler( ); - - eventManager.registerEventHandler( Event.ANY, handler1 ); - eventManager.registerEventHandler( testType, handler2 ); - eventManager.registerEventHandler( testTestType, handler3 ); - eventManager.registerEventHandler( otherType, handler4 ); - - Event event1 = new Event( testType, this ); - eventManager.fireEvent( event1 ); - assertEquals( 1, handler1.eventList.size( ) ); - assertEquals( 1, handler2.eventList.size( ) ); - assertEquals( 0, handler3.eventList.size( ) ); - assertEquals( 0, handler4.eventList.size( ) ); - - Event event2 = new Event( testTestType, event1 ); - eventManager.fireEvent( event2 ); - assertEquals( 2, handler1.eventList.size( ) ); - assertEquals( 2, handler2.eventList.size( ) ); - assertEquals( 1, handler3.eventList.size( ) ); - assertEquals( 0, handler4.eventList.size( ) ); - - Event event3 = new Event( otherType, event1 ); - eventManager.fireEvent( event3 ); - assertEquals( 3, handler1.eventList.size( ) ); - assertEquals( 2, handler2.eventList.size( ) ); - assertEquals( 1, handler3.eventList.size( ) ); - assertEquals( 1, handler4.eventList.size( ) ); - - - - } - - @Test - public void unregisterEventHandler( ) - { - EventManager eventManager = new EventManager( this ); - TestHandler handler1 = new TestHandler( ); - TestHandler handler2 = new TestHandler( ); - TestHandler handler3 = new TestHandler( ); - TestHandler handler4 = new TestHandler( ); - - eventManager.registerEventHandler( Event.ANY, handler1 ); - eventManager.registerEventHandler( testType, handler2 ); - eventManager.registerEventHandler( testTestType, handler3 ); - eventManager.registerEventHandler( otherType, handler4 ); - - eventManager.unregisterEventHandler( Event.ANY, handler1 ); - Event event1 = new Event( testType, this ); - eventManager.fireEvent( event1 ); - assertEquals( 0, handler1.eventList.size( ) ); - assertEquals( 1, handler2.eventList.size( ) ); - assertEquals( 0, handler3.eventList.size( ) ); - assertEquals( 0, handler4.eventList.size( ) ); - - eventManager.unregisterEventHandler( otherType, handler2 ); - Event event2 = new Event( testType, this ); - eventManager.fireEvent( event2 ); - assertEquals( 0, handler1.eventList.size( ) ); - assertEquals( 2, handler2.eventList.size( ) ); - assertEquals( 0, handler3.eventList.size( ) ); - assertEquals( 0, handler4.eventList.size( ) ); - } - - @Test - public void fireEvent( ) - { - Object other = new Object( ); - EventManager eventManager = new EventManager( this ); - assertThrows( NullPointerException.class, ( ) -> eventManager.fireEvent( null ) ); - Event event = new Event( EventType.ROOT, other ); - assertEquals( other, event.getSource( ) ); - TestHandler handler = new TestHandler( ); - eventManager.registerEventHandler( EventType.ROOT, handler ); - eventManager.fireEvent( event ); - assertEquals( 1, handler.getEventList( ).size( ) ); - Event newEvent = handler.getEventList( ).get( 0 ); - assertNotEquals( event, newEvent ); - assertEquals( this, newEvent.getSource( ) ); - - } -} \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/pom.xml b/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/pom.xml index 42844565e..6e2f82f47 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/pom.xml +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/pom.xml @@ -76,6 +76,12 @@ jcl-over-slf4j + + + org.apache.archiva.event + archiva-event-api + test + org.apache.archiva archiva-consumer-api diff --git a/archiva-modules/archiva-base/archiva-event-api/pom.xml b/archiva-modules/archiva-base/archiva-event-api/pom.xml new file mode 100644 index 000000000..6c9119c53 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/pom.xml @@ -0,0 +1,41 @@ + + + + + + archiva-base + org.apache.archiva + 3.0.0-SNAPSHOT + + 4.0.0 + + Archiva :: Base :: Event API + org.apache.archiva.event + archiva-event-api + + + + org.apache.archiva + archiva-common + + + + \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/AbstractEventManager.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/AbstractEventManager.java new file mode 100644 index 000000000..6d2ddff7a --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/AbstractEventManager.java @@ -0,0 +1,84 @@ +package org.apache.archiva.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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Martin Schreier + */ +public class AbstractEventManager implements EventSource +{ + private static final Logger log = LoggerFactory.getLogger( AbstractEventManager.class ); + + protected final ConcurrentHashMap, Set> handlerMap = new ConcurrentHashMap<>(); + + @Override + public void registerEventHandler( EventType type, EventHandler eventHandler) { + Set handlers = handlerMap.computeIfAbsent(type, t -> new LinkedHashSet<>()); + if (!handlers.contains(eventHandler)) { + handlers.add(eventHandler); + } + log.debug( "Event handler registered: " + eventHandler.getClass( ) ); + } + + @Override + public void unregisterEventHandler( EventType type, EventHandler eventHandler) { + if (handlerMap.containsKey(type)) { + handlerMap.get(type).remove(eventHandler); + log.debug( "Event handler unregistered: " + eventHandler.getClass( ) ); + } + } + + /** + * Fires the given event for the given source. If the source of the provided event does not match the source + * parameter the event will be chained. + * + * The event will be sent to all registered event handler. Exceptions during handling are not propagated to the + * caller. + * + * @param fireEvent the event to fire + * @param source the source object + */ + public void fireEvent(Event fireEvent, Object source) { + final EventType type = fireEvent.getType(); + Event event; + if (fireEvent.getSource()!=source) { + event = fireEvent.copyFor(source); + } else { + event = fireEvent; + } + for (EventType handlerType : handlerMap.keySet()) { + if (EventType.isInstanceOf(type, handlerType)) { + for (EventHandler handler : handlerMap.get(handlerType)) { + try { + handler.handle(event); + } catch (Throwable e) { + // We catch all errors from handlers + log.error("An error occured during event handling: {}", e.getMessage(), e); + } + } + } + } + } +} diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/BasicEventManager.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/BasicEventManager.java new file mode 100644 index 000000000..f952b9eaa --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/BasicEventManager.java @@ -0,0 +1,41 @@ +package org.apache.archiva.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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BasicEventManager extends AbstractEventManager implements EventSource +{ + + private static final Logger LOG = LoggerFactory.getLogger( BasicEventManager.class); + + private final Object source; + + public BasicEventManager( Object source) { + if (source==null) { + throw new IllegalArgumentException("The source may not be null"); + } + this.source = source; + } + + public void fireEvent(Event fireEvent) { + super.fireEvent( fireEvent, source ); + } +} 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 new file mode 100644 index 000000000..2439105de --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/Event.java @@ -0,0 +1,150 @@ +package org.apache.archiva.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 java.time.LocalDateTime; +import java.util.EventObject; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Base class for events. Events have a type and a source. + * The source is the instance that raised the event. + * + * There are different event types for a given event. The types are represented in a hierarchical structure. + * + * 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 { + + private static final long serialVersionUID = -7171846575892044990L; + + public static final EventType ANY = EventType.ROOT; + + private Event previous; + private final EventType type; + private final LocalDateTime createTime; + + private HashMap, EventContext> contextMap = new HashMap<>( ); + + public Event(EventType type, Object originator) { + super(originator); + this.type = type; + this.createTime = LocalDateTime.now(); + } + + private Event(Event previous, Object originator) { + super(originator); + this.previous = previous; + this.type = previous.getType(); + this.createTime = previous.getCreateTime(); + this.contextMap = previous.contextMap; + } + + /** + * Returns the event type that is associated with this event instance. + * @return the event type + */ + public EventType getType() { + return type; + }; + + /** + * Returns the time, when the event was created. + * @return + */ + public LocalDateTime getCreateTime() { + return createTime; + } + + public T getContext(Class contextClazz) throws IllegalArgumentException { + if (contextMap.containsKey( contextClazz )) { + return (T) contextMap.get( contextClazz ); + } else { + T ctx = null; + for ( Map.Entry, EventContext> clazzEntry : contextMap.entrySet()) { + if ( contextClazz.isAssignableFrom( clazzEntry.getKey() ) ) + { + ctx = (T) clazzEntry.getValue( ); + break; + } + } + if (ctx!=null) { + contextMap.put( contextClazz, ctx ); + return ctx; + } + } + throw new IllegalArgumentException( "No matching event context registered for " + contextClazz ); + } + + public Map getContextData() { + return contextMap.entrySet( ).stream( ).flatMap( ctx -> ctx.getValue( ).getData( ).entrySet( ).stream( ) ) + .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue ) ); + } + + public void setContext( Class clazz, T context) { + this.contextMap.put( clazz, context ); + } + + public void setContext( T context) { + this.contextMap.put( context.getClass(), context ); + } + + /** + * Recreates the event with the given instance as the new source. The + * current source is stored in the previous event. + * @param newSource The new source + * @return a new event instance, where this is stored as previous event + */ + public Event copyFor(Object newSource) { + Event newEvent = (Event) this.clone(); + newEvent.previous = this; + newEvent.source = newSource; + newEvent.contextMap = this.contextMap; + return newEvent; + } + + /** + * Returns the previous event or null, if this is a root event. + * @return the previous event or null, if it does not exist + */ + public Event getPreviousEvent() { + return previous; + } + + /** + * Returns true, if the event has a previous event. + * @return true, if this has a previous event, otherwise false + */ + public boolean hasPreviousEvent() { + return previous!=null; + } + + @Override + protected Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this should not happen + throw new RuntimeException("Event is not clonable"); + } + } +} 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 new file mode 100644 index 000000000..9e113de06 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContext.java @@ -0,0 +1,48 @@ +package org.apache.archiva.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 java.util.Map; + +/** + * Context information about a specific event. + * This is used to provide specific information about the event context by using the generic + * event interface. + * Some event handler may need information about the underlying event but have no access to the + * API classes that represent the event. + * + * Context information is always string based and should not depend on external classes apart from JDK classes. + * + * @author Martin Schreier + */ +public interface EventContext +{ + /** + * Returns the prefix used for entry keys in the repository data map. + * @return the prefix string for this context + */ + String getPrefix(); + + /** + * Returns the context data as map of strings. Each entry key is prefixed with + * the unique prefix of this context. + * + * @return the map of key value pairs stored in this context + */ + Map getData(); +} 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 new file mode 100644 index 000000000..41f10ceec --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventContextBuilder.java @@ -0,0 +1,72 @@ +package org.apache.archiva.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.context.RepositoryContext; +import org.apache.archiva.event.context.RestContext; +import org.apache.archiva.event.context.UserContext; + +/** + * Static helper class that allows to set certain context data + * + * @author Martin Schreier + */ +public class EventContextBuilder +{ + Event evt; + + public static void setUserContext(Event evt, String user, String remoteAddress) { + 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 setRepositoryContext(Event evt, String id, String type, String flavour ) { + evt.setContext( RepositoryContext.class, new RepositoryContext( id, type, flavour ) ); + } + + private EventContextBuilder( Event evt) { + this.evt = evt; + } + + public static EventContextBuilder withEvent( Event evt ) + { + return new EventContextBuilder( evt ); + } + + public EventContextBuilder withUser( String user, String remoteAddress) { + setUserContext( this.evt, user, remoteAddress ); + return this; + } + + public EventContextBuilder witRest( String service, String path, String operation, int resultCode, String... parameters) { + setRestcontext( this.evt, service, path, operation, resultCode, parameters ); + return this; + } + + public EventContextBuilder withRepository(String id, String type, String flavour) { + setRepositoryContext( this.evt, id, type, flavour ); + return this; + } + + public Event apply() { + return this.evt; + } +} diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventHandler.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventHandler.java new file mode 100644 index 000000000..f98adcdab --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventHandler.java @@ -0,0 +1,31 @@ +package org.apache.archiva.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 java.util.EventListener; + +/** + * A listener that accepts events. + */ +public interface EventHandler extends EventListener { + + void handle(T event); +} diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventSource.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventSource.java new file mode 100644 index 000000000..452a5e9d9 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventSource.java @@ -0,0 +1,33 @@ +package org.apache.archiva.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. + */ + +/** + * A repository event source raises events to its registered listeners. + * Listeners register to event types that are structured hierarchical. + * + */ +public interface EventSource { + + void registerEventHandler( EventType type, EventHandler eventHandler); + + void unregisterEventHandler(EventType type, EventHandler eventHandler); + +} diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventType.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventType.java new file mode 100644 index 000000000..6927c818a --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/EventType.java @@ -0,0 +1,177 @@ +package org.apache.archiva.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 java.io.InvalidObjectException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.*; + +/** + * Event types define a hierarchical structure of events. Each event is bound to a certain event type. + * All event types have a super type, only the root event type {@link EventType#ROOT} has no super type. + * + * Event types should be stored as static fields on the events itself. + * + * @param The type class parameter allows to define the types in a type safe way and represents a event class, + * where the type is associated to. + */ +public class EventType implements Serializable { + + + public static final EventType ROOT = new EventType<>(); + + private final String name; + private final EventType superType; + private WeakHashMap, Void> subTypes; + + /** + * Creates a type with the given name and the root type as parent. + * @param name the name of the new type + */ + public EventType(String name) { + this.superType = ROOT; + this.name = name; + } + + /** + * Creates a event type instance with the given super type and name. + * + * @param superType The super type or null, if this is the root type. + * @param name + */ + public EventType(EventType superType, String name) { + if (superType==null) { + throw new NullPointerException("Super Type may not be null"); + } + this.name = name; + this.superType = superType; + superType.register(this); + } + + /** + * Creates the root type + */ + private EventType() { + this.name="ROOT"; + this.superType=null; + } + + public String name() { + return name; + } + + public EventType getSuperType() { + return superType; + } + + public String getPath() { + List path = new ArrayList<>( ); + EventType eventType = this; + while(eventType!=ROOT) + { + path.add( eventType.name( ) ); + eventType = this.getSuperType( ); + } + Collections.reverse( path ); + return String.join( "/", path ); + } + + private void register(EventType subType) { + if (subTypes == null) { + subTypes = new WeakHashMap<>(); + } + for (EventType t : subTypes.keySet()) { + if (((t.name == null && subType.name == null) || (t.name != null && t.name.equals(subType.name)))) { + throw new IllegalArgumentException("EventType \"" + subType + "\"" + + "with parent \"" + subType.getSuperType()+"\" already exists"); + } + } + subTypes.put(subType, null); + } + + + public static List> fetchSuperTypes(EventType type) { + List> typeList = new ArrayList<>(); + EventType cType = type; + while (cType!=null) { + typeList.add(cType); + cType = cType.getSuperType(); + } + return typeList; + } + + public static boolean isInstanceOf(EventType type, EventType baseType) { + EventType cType = type; + while(cType!=null) { + if (cType == baseType) { + return true; + } + cType = cType.getSuperType(); + } + return false; + } + + + private Object writeReplace() throws ObjectStreamException { + Deque path = new LinkedList<>(); + EventType t = this; + while (t != ROOT) { + path.addFirst(t.name); + t = t.superType; + } + return new EventTypeSerialization(new ArrayList<>(path)); + } + + static class EventTypeSerialization implements Serializable { + private static final long serialVersionUID = 1841649460281865547L; + private List path; + + public EventTypeSerialization(List path) { + this.path = path; + } + + private Object readResolve() throws ObjectStreamException { + EventType t = ROOT; + for (int i = 0; i < path.size(); ++i) { + String p = path.get(i); + if (t.subTypes != null) { + EventType s = findSubType(t.subTypes.keySet(), p); + if (s == null) { + throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")"); + } + t = s; + } else { + throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")"); + } + } + return t; + } + + private EventType findSubType(Set subTypes, String name) { + for (EventType t : subTypes) { + if (((t.name == null && name == null) || (t.name != null && t.name.equals(name)))) { + return t; + } + } + return null; + } + + } +} 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 new file mode 100644 index 000000000..4df023d1b --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RepositoryContext.java @@ -0,0 +1,90 @@ +package org.apache.archiva.event.context; +/* + * 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.EventContext; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * This context provides repository data. + * + * @author Martin Schreier + */ +public class RepositoryContext implements EventContext, Serializable +{ + private static final long serialVersionUID = -4172663291198878307L; + + private static final String PREFIX = "repository"; + + private final String id; + private final String type; + private final String flavour; + + public RepositoryContext( String id, String type, String flavour ) + { + this.id = id; + this.type = type; + this.flavour = flavour; + } + + /** + * Returns the repository id + * @return the repository id + */ + public String getId( ) + { + return id; + } + + /** + * Returns the repository type (e.g. MAVEN) + * @return the string representation of the repository type + */ + public String getType( ) + { + return type; + } + + /** + * Returns the repository flavour (e.g. Remote, Managed, Group) + * @return + */ + public String getFlavour( ) + { + return flavour; + } + + @Override + public Map getData( ) + { + Map values = new HashMap<>( ); + values.put( PREFIX+".id", id ); + values.put( PREFIX+".type", type ); + values.put( PREFIX+".flavour", flavour ); + return values; + } + + @Override + public String getPrefix( ) + { + return PREFIX; + } +} 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 new file mode 100644 index 000000000..615759d42 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/RestContext.java @@ -0,0 +1,96 @@ +package org.apache.archiva.event.context; +/* + * 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.EventContext; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Provides information about a REST call. + * + * @author Martin Schreier + */ +public class RestContext implements EventContext, Serializable +{ + private static final long serialVersionUID = -4109505194250928317L; + + public static final String PREFIX = "rest"; + + private final String service; + private final String path; + private final String operation; + private final List parameters; + private final int resultCode; + + + public RestContext( String service, String path, String operation, int resultCode, String... parameters ) + { + this.service = service; + this.path = path; + this.operation = operation; + this.resultCode = resultCode; + this.parameters = Arrays.asList( parameters ); + } + + public String getService( ) + { + return service; + } + + public String getPath( ) + { + return path; + } + + public String getOperation( ) + { + return operation; + } + + public List getParameters( ) + { + return parameters; + } + + public int getResultCode( ) + { + return resultCode; + } + + @Override + public Map getData( ) + { + Map 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 ) ); + return values; + } + + @Override + public String getPrefix( ) + { + return PREFIX; + } +} 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 new file mode 100644 index 000000000..8a83c73c8 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/context/UserContext.java @@ -0,0 +1,71 @@ +package org.apache.archiva.event.context; +/* + * 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.EventContext; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * This context provides user information. + * + * @author Martin Schreier + */ +public class UserContext implements EventContext, Serializable +{ + private static final long serialVersionUID = -3499164111736559781L; + + private static final String PREFIX = "user"; + + private final String userId; + private final String remoteAddress; + + public UserContext( String user, String remoteAddress ) + { + this.userId = user == null ? "" : user; + this.remoteAddress = remoteAddress == null ? "" : remoteAddress; + + } + + public String getUserId( ) + { + return userId; + } + + public String getRemoteAddress( ) + { + return remoteAddress; + } + + @Override + public Map getData( ) + { + Map values = new HashMap<>( ); + values.put( PREFIX+".user_id", userId ); + values.put( PREFIX+".remote_address", remoteAddress ); + return values; + } + + @Override + public String getPrefix( ) + { + return PREFIX; + } +} diff --git a/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/package-info.java b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/package-info.java new file mode 100644 index 000000000..30db350f0 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/main/java/org/apache/archiva/event/package-info.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +/** + * This module provides an event mechanism for all archiva subsystems. + * + * The events are hierarchical organized. That means each subsystem has its own event manager that collects events + * and processes and forwards them to the parent event manager (normally the central event manager). + * Each event manager clones the event and stores the origin event in the chain before forwarding them to the parent manager. + * + * Event Types are also hierarchical. There is one special type {@link org.apache.archiva.event.EventType#ROOT} that is the + * root type and has no parent type. All other types must be descendants of the ROOT type. + * + * Event types may have certain methods to access context information. But context information can also be accessed in a + * subsystem independent way using the event context data. Event contexts provide access to data without using the + * subsystem API and classes. + * Event types may be used for filtering events. + * + * @since 3.0 + * @author Martin Schreier + */ +package org.apache.archiva.event; \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-event-api/src/test/java/org/apache/archiva/event/BasicEventManagerTest.java b/archiva-modules/archiva-base/archiva-event-api/src/test/java/org/apache/archiva/event/BasicEventManagerTest.java new file mode 100644 index 000000000..6e0ba611b --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-api/src/test/java/org/apache/archiva/event/BasicEventManagerTest.java @@ -0,0 +1,139 @@ +package org.apache.archiva.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.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Martin Stockhammer + */ +public class BasicEventManagerTest +{ + + private class TestHandler implements EventHandler { + + private List eventList = new ArrayList<>( ); + @Override + public void handle( Event event ) + { + eventList.add( event ); + } + + public List getEventList() { + return eventList; + } + } + + private EventType testType = new EventType<>( "TEST" ); + private EventType testTestType = new EventType<>( testType,"TEST.TEST" ); + private EventType otherType = new EventType( "OTHER" ); + + @Test + public void registerEventHandler( ) + { + BasicEventManager eventManager = new BasicEventManager( this ); + TestHandler handler1 = new TestHandler( ); + TestHandler handler2 = new TestHandler( ); + TestHandler handler3 = new TestHandler( ); + TestHandler handler4 = new TestHandler( ); + + eventManager.registerEventHandler( Event.ANY, handler1 ); + eventManager.registerEventHandler( testType, handler2 ); + eventManager.registerEventHandler( testTestType, handler3 ); + eventManager.registerEventHandler( otherType, handler4 ); + + Event event1 = new Event( testType, this ); + eventManager.fireEvent( event1 ); + assertEquals( 1, handler1.eventList.size( ) ); + assertEquals( 1, handler2.eventList.size( ) ); + assertEquals( 0, handler3.eventList.size( ) ); + assertEquals( 0, handler4.eventList.size( ) ); + + Event event2 = new Event( testTestType, event1 ); + eventManager.fireEvent( event2 ); + assertEquals( 2, handler1.eventList.size( ) ); + assertEquals( 2, handler2.eventList.size( ) ); + assertEquals( 1, handler3.eventList.size( ) ); + assertEquals( 0, handler4.eventList.size( ) ); + + Event event3 = new Event( otherType, event1 ); + eventManager.fireEvent( event3 ); + assertEquals( 3, handler1.eventList.size( ) ); + assertEquals( 2, handler2.eventList.size( ) ); + assertEquals( 1, handler3.eventList.size( ) ); + assertEquals( 1, handler4.eventList.size( ) ); + + + + } + + @Test + public void unregisterEventHandler( ) + { + BasicEventManager eventManager = new BasicEventManager( this ); + TestHandler handler1 = new TestHandler( ); + TestHandler handler2 = new TestHandler( ); + TestHandler handler3 = new TestHandler( ); + TestHandler handler4 = new TestHandler( ); + + eventManager.registerEventHandler( Event.ANY, handler1 ); + eventManager.registerEventHandler( testType, handler2 ); + eventManager.registerEventHandler( testTestType, handler3 ); + eventManager.registerEventHandler( otherType, handler4 ); + + eventManager.unregisterEventHandler( Event.ANY, handler1 ); + Event event1 = new Event( testType, this ); + eventManager.fireEvent( event1 ); + assertEquals( 0, handler1.eventList.size( ) ); + assertEquals( 1, handler2.eventList.size( ) ); + assertEquals( 0, handler3.eventList.size( ) ); + assertEquals( 0, handler4.eventList.size( ) ); + + eventManager.unregisterEventHandler( otherType, handler2 ); + Event event2 = new Event( testType, this ); + eventManager.fireEvent( event2 ); + assertEquals( 0, handler1.eventList.size( ) ); + assertEquals( 2, handler2.eventList.size( ) ); + assertEquals( 0, handler3.eventList.size( ) ); + assertEquals( 0, handler4.eventList.size( ) ); + } + + @Test + public void fireEvent( ) + { + Object other = new Object( ); + BasicEventManager eventManager = new BasicEventManager( this ); + assertThrows( NullPointerException.class, ( ) -> eventManager.fireEvent( null ) ); + Event event = new Event( EventType.ROOT, other ); + assertEquals( other, event.getSource( ) ); + TestHandler handler = new TestHandler( ); + eventManager.registerEventHandler( EventType.ROOT, handler ); + eventManager.fireEvent( event ); + assertEquals( 1, handler.getEventList( ).size( ) ); + Event newEvent = handler.getEventList( ).get( 0 ); + assertNotEquals( event, newEvent ); + assertEquals( this, newEvent.getSource( ) ); + + } +} \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-event-central/pom.xml b/archiva-modules/archiva-base/archiva-event-central/pom.xml new file mode 100644 index 000000000..cd8a5b084 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-central/pom.xml @@ -0,0 +1,44 @@ + + + + + + archiva-base + org.apache.archiva + 3.0.0-SNAPSHOT + + 4.0.0 + + org.apache.archiva.event + archiva-event-central + + + + org.apache.archiva.event + archiva-event-api + + + org.springframework + spring-context + + + + \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-event-central/src/main/java/org/apache/archiva/event/central/CentralEventManager.java b/archiva-modules/archiva-base/archiva-event-central/src/main/java/org/apache/archiva/event/central/CentralEventManager.java new file mode 100644 index 000000000..44ba9df43 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-central/src/main/java/org/apache/archiva/event/central/CentralEventManager.java @@ -0,0 +1,42 @@ +package org.apache.archiva.event.central; +/* + * 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.AbstractEventManager; +import org.apache.archiva.event.Event; +import org.apache.archiva.event.EventHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +/** + * Event manager that collects all events from archiva subsystems. + * + * @author Martin Schreier + */ +@Service("eventManager#archiva") +public class CentralEventManager extends AbstractEventManager implements EventHandler +{ + private static final Logger log = LoggerFactory.getLogger( CentralEventManager.class ); + + @Override + public void handle( Event event ) + { + log.info( "Event: type={}, sourceClass={}, source={}", event.getType( ), event.getSource().getClass(), event.getSource() ); + } +} diff --git a/archiva-modules/archiva-base/archiva-event-central/src/main/resources/META-INF/spring-context.xml b/archiva-modules/archiva-base/archiva-event-central/src/main/resources/META-INF/spring-context.xml new file mode 100644 index 000000000..654b2f876 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-event-central/src/main/resources/META-INF/spring-context.xml @@ -0,0 +1,32 @@ + + + + + + + + + \ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml index 8c231f2c1..b34922d17 100644 --- a/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml +++ b/archiva-modules/archiva-base/archiva-repository-admin/archiva-repository-admin-default/pom.xml @@ -33,6 +33,10 @@ + + org.apache.archiva.event + archiva-event-api + org.apache.archiva.configuration archiva-configuration-provider diff --git a/archiva-modules/archiva-base/archiva-repository-api/pom.xml b/archiva-modules/archiva-base/archiva-repository-api/pom.xml index 4ae27d9e3..820525f9c 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/pom.xml +++ b/archiva-modules/archiva-base/archiva-repository-api/pom.xml @@ -34,6 +34,10 @@ + + org.apache.archiva.event + archiva-event-api + org.apache.archiva archiva-common diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java index 8ed6c37da..4b877d905 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryHandler.java @@ -277,11 +277,11 @@ public interface RepositoryHandler getVariant(); + Class getFlavour(); /** * Returns the repository configuration variant, this handler manages. * @return the concrete configuration variant class */ - Class getConfigurationVariant(); + Class getConfigurationFlavour(); } 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 88c95adde..a4b667b3c 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 @@ -20,8 +20,12 @@ 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.repository.ManagedRepository; +import org.apache.archiva.repository.RemoteRepository; import org.apache.archiva.repository.Repository; +import org.apache.archiva.repository.RepositoryGroup; /** * A repository event is specific to a repository and holds a reference to the repository that @@ -39,6 +43,12 @@ public class RepositoryEvent extends Event public RepositoryEvent(EventType type, Object origin, Repository repository) { super(type, origin); this.repository = repository; + EventContextBuilder builder = EventContextBuilder.withEvent( this ); + if (repository!=null) + { + builder.withRepository( repository.getId( ), repository.getType( ).name( ), getFlavour( repository ) ); + } + builder.apply( ); } public Repository getRepository() { @@ -49,4 +59,16 @@ public class RepositoryEvent extends Event public EventType getType() { return (EventType) super.getType(); } + + private String getFlavour(Repository repository) { + if (repository instanceof RemoteRepository ) { + return RemoteRepository.class.getName( ); + } else if (repository instanceof ManagedRepository ) { + return ManagedRepository.class.getName( ); + } else if ( repository instanceof RepositoryGroup ) { + return RepositoryGroup.class.getName( ); + } else { + return "UNKNOWN"; + } + } } diff --git a/archiva-modules/archiva-base/archiva-repository-layer/pom.xml b/archiva-modules/archiva-base/archiva-repository-layer/pom.xml index b9b6f4558..8c424f6de 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/pom.xml +++ b/archiva-modules/archiva-base/archiva-repository-layer/pom.xml @@ -69,6 +69,10 @@ org.apache.archiva archiva-common + + org.apache.archiva.event + archiva-event-central + org.springframework spring-context diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepository.java index ca15e5f31..7a10b7387 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepository.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepository.java @@ -24,7 +24,7 @@ import com.cronutils.model.definition.CronDefinition; import com.cronutils.model.definition.CronDefinitionBuilder; import org.apache.archiva.event.Event; import org.apache.archiva.event.EventHandler; -import org.apache.archiva.event.EventManager; +import org.apache.archiva.event.BasicEventManager; import org.apache.archiva.event.EventType; import org.apache.archiva.indexer.ArchivaIndexingContext; import org.apache.archiva.repository.EditableRepository; @@ -86,7 +86,7 @@ public abstract class AbstractRepository implements EditableRepository, EventHan public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ); private RepositoryState state; - private final EventManager eventManager; + private final BasicEventManager eventManager; Map>, RepositoryFeature> featureMap = new HashMap<>( ); @@ -100,7 +100,7 @@ public abstract class AbstractRepository implements EditableRepository, EventHan this.storage = repositoryStorage; this.location = repositoryStorage.getLocation(); this.openStatus.compareAndSet(false, true); - this.eventManager = new EventManager(this); + this.eventManager = new BasicEventManager(this); } public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) { @@ -111,7 +111,7 @@ public abstract class AbstractRepository implements EditableRepository, EventHan this.storage = repositoryStorage; this.location = repositoryStorage.getLocation(); this.openStatus.compareAndSet(false, true); - this.eventManager = new EventManager(this); + this.eventManager = new BasicEventManager(this); } protected void setPrimaryLocale(Locale locale) { diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepositoryHandler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepositoryHandler.java index 0e17aacd6..2ffeac281 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepositoryHandler.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/AbstractRepositoryHandler.java @@ -22,7 +22,7 @@ import org.apache.archiva.configuration.model.AbstractRepositoryConfiguration; import org.apache.archiva.configuration.model.Configuration; import org.apache.archiva.configuration.provider.IndeterminateConfigurationException; import org.apache.archiva.event.Event; -import org.apache.archiva.event.EventManager; +import org.apache.archiva.event.BasicEventManager; import org.apache.archiva.event.EventType; import org.apache.archiva.repository.EditableRepository; import org.apache.archiva.repository.Repository; @@ -61,14 +61,14 @@ public abstract class AbstractRepositoryHandler combinedValidator; private final Class repositoryClazz; private final Class configurationClazz; - private final EventManager eventManager; + private final BasicEventManager eventManager; private final Map repositoryMap = new HashMap<>( ); private final ConfigurationHandler configurationHandler; public AbstractRepositoryHandler(Class repositoryClazz, Class configurationClazz, ConfigurationHandler configurationHandler) { this.repositoryClazz = repositoryClazz; this.configurationClazz = configurationClazz; - this.eventManager = new EventManager( this ); + this.eventManager = new BasicEventManager( this ); this.configurationHandler = configurationHandler; } @@ -142,13 +142,13 @@ public abstract class AbstractRepositoryHandler getVariant( ) + public Class getFlavour( ) { return this.repositoryClazz; } @Override - public Class getConfigurationVariant( ) + public Class getConfigurationFlavour( ) { return this.configurationClazz; } diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java index 1d0c32207..c3a3c0b05 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java @@ -31,8 +31,10 @@ import org.apache.archiva.configuration.model.RemoteRepositoryConfiguration; import org.apache.archiva.configuration.model.RepositoryGroupConfiguration; import org.apache.archiva.event.Event; import org.apache.archiva.event.EventHandler; -import org.apache.archiva.event.EventManager; +import org.apache.archiva.event.BasicEventManager; +import org.apache.archiva.event.EventSource; import org.apache.archiva.event.EventType; +import org.apache.archiva.event.central.CentralEventManager; import org.apache.archiva.indexer.ArchivaIndexManager; import org.apache.archiva.indexer.ArchivaIndexingContext; import org.apache.archiva.indexer.IndexCreationFailedException; @@ -65,6 +67,7 @@ import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; +import javax.inject.Named; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -111,9 +114,13 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa @Inject List> repositoryValidatorList; + @Inject + @Named("eventManager#archiva") + CentralEventManager centralEventManager; + private boolean ignoreIndexing = false; - private final EventManager eventManager; + private final BasicEventManager eventManager; private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock( ); @@ -133,7 +140,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa public ArchivaRepositoryRegistry( ConfigurationHandler configurationHandler, List> validatorList ) { - this.eventManager = new EventManager( this ); + this.eventManager = new BasicEventManager( this ); this.configurationHandler = configurationHandler; this.validators = initValidatorList( validatorList ); } @@ -172,6 +179,7 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa provider.addRepositoryEventHandler( this ); } this.configurationHandler.addListener( this ); + registerEventHandler( EventType.ROOT, centralEventManager ); } finally { @@ -1162,15 +1170,15 @@ public class ArchivaRepositoryRegistry implements ConfigurationListener, EventHa @Override public void registerHandler( RepositoryHandler handler ) { - if ( handler.getVariant( ).isAssignableFrom( RepositoryGroup.class ) ) + if ( handler.getFlavour( ).isAssignableFrom( RepositoryGroup.class ) ) { registerGroupHandler( (RepositoryHandler) handler ); } - else if ( handler.getVariant( ).isAssignableFrom( ManagedRepository.class ) ) + else if ( handler.getFlavour( ).isAssignableFrom( ManagedRepository.class ) ) { registerManagedRepositoryHandler( (RepositoryHandler) handler ); } - else if ( handler.getVariant().isAssignableFrom( RemoteRepository.class )) { + else if ( handler.getFlavour().isAssignableFrom( RemoteRepository.class )) { registerRemoteRepositoryHandler( (RepositoryHandler) handler ); } } diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/ManagedRepositoryHandler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/ManagedRepositoryHandler.java index f7cf8a46f..b46c12a79 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/ManagedRepositoryHandler.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/managed/ManagedRepositoryHandler.java @@ -47,6 +47,8 @@ import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.inject.Named; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/RepositoryGroupHandlerTest.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/RepositoryGroupHandlerTest.java index fb607e427..be4933beb 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/RepositoryGroupHandlerTest.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/RepositoryGroupHandlerTest.java @@ -148,7 +148,7 @@ class RepositoryGroupHandlerTest private RepositoryGroupHandler createHandler( ) { - Mockito.when( managedRepositoryHandler.getVariant( ) ).thenReturn( ManagedRepository.class ); + Mockito.when( managedRepositoryHandler.getFlavour( ) ).thenReturn( ManagedRepository.class ); final ManagedRepository internalRepo; try { @@ -161,7 +161,7 @@ class RepositoryGroupHandlerTest Mockito.when( managedRepositoryHandler.get( ArgumentMatchers.eq("internal") ) ).thenReturn( internalRepo ); repositoryRegistry.registerHandler( managedRepositoryHandler ); - Mockito.when( remoteRepositoryHandler.getVariant( ) ).thenReturn( RemoteRepository.class ); + Mockito.when( remoteRepositoryHandler.getFlavour( ) ).thenReturn( RemoteRepository.class ); final RemoteRepository centralRepo; try { diff --git a/archiva-modules/archiva-base/pom.xml b/archiva-modules/archiva-base/pom.xml index 55b0f87f1..91c0278ca 100644 --- a/archiva-modules/archiva-base/pom.xml +++ b/archiva-modules/archiva-base/pom.xml @@ -33,6 +33,7 @@ ${project.parent.basedir} + archiva-event-api archiva-test-utils archiva-common archiva-mock @@ -53,5 +54,6 @@ archiva-security-common archiva-storage-api archiva-storage-fs + archiva-event-central diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/pom.xml b/archiva-modules/archiva-maven/archiva-maven-repository/pom.xml index 7c042b5c7..140652477 100644 --- a/archiva-modules/archiva-maven/archiva-maven-repository/pom.xml +++ b/archiva-modules/archiva-maven/archiva-maven-repository/pom.xml @@ -32,6 +32,10 @@ + + org.apache.archiva.event + archiva-event-api + org.apache.archiva archiva-repository-api diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/maven/repository/MavenRepositoryProvider.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/maven/repository/MavenRepositoryProvider.java index 8319e2704..bb740960c 100644 --- a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/maven/repository/MavenRepositoryProvider.java +++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/maven/repository/MavenRepositoryProvider.java @@ -118,6 +118,16 @@ public class MavenRepositoryProvider implements RepositoryProvider { return repo; } + private Path getBaseDir(String location) { + String lPathStr = location == null ? "" : location; + Path lPath = Paths.get( lPathStr ); + if (lPath.isAbsolute()) { + return lPath.getParent( ); + } else { + return archivaConfiguration.getRepositoryBaseDir( ).resolve( lPath ); + } + } + @Override public MavenRemoteRepository createRemoteInstance(String id, String name) { return createRemoteInstance(id, name, archivaConfiguration.getRemoteRepositoryBaseDir()); @@ -194,7 +204,7 @@ public class MavenRepositoryProvider implements RepositoryProvider { @Override public ManagedRepository createManagedInstance(ManagedRepositoryConfiguration cfg) throws RepositoryException { - MavenManagedRepository repo = createManagedInstance(cfg.getId(), cfg.getName(), Paths.get(cfg.getLocation()).getParent()); + MavenManagedRepository repo = createManagedInstance( cfg.getId( ), cfg.getName( ), getBaseDir( cfg.getLocation( ) ) ); updateManagedInstance(repo, cfg); return repo; } diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java index 01ec552c0..d3ce96819 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepository.java @@ -73,37 +73,6 @@ public class MavenManagedRepository extends Repository super.setType( RepositoryType.MAVEN.name( ) ); } - protected static void update(MavenManagedRepository repo, ManagedRepository beanRepo) { - repo.setDescription( beanRepo.getDescription() ); - repo.setId( beanRepo.getId() ); - repo.setIndex( true ); - repo.setLayout( beanRepo.getLayout() ); - repo.setBlocksRedeployments( beanRepo.blocksRedeployments() ); - repo.setReleaseSchemes( beanRepo.getActiveReleaseSchemes().stream().map( Objects::toString).collect( Collectors.toList()) ); - repo.setLocation( beanRepo.getLocation().toString() ); - repo.setName( beanRepo.getName()); - repo.setScanned( beanRepo.isScanned() ); - repo.setSchedulingDefinition( beanRepo.getSchedulingDefinition() ); - ArtifactCleanupFeature artifactCleanupFeature = beanRepo.getFeature( ArtifactCleanupFeature.class ); - repo.setDeleteSnapshotsOfRelease( artifactCleanupFeature.isDeleteReleasedSnapshots()); - repo.setRetentionCount( artifactCleanupFeature.getRetentionCount()); - repo.setRetentionPeriod( artifactCleanupFeature.getRetentionPeriod() ); - IndexCreationFeature icf = beanRepo.getFeature( IndexCreationFeature.class ); - repo.setIndex( icf.hasIndex( ) ); - repo.setIndexPath( icf.getIndexPath( ).getPath( ) ); - repo.setPackedIndexPath( icf.getPackedIndexPath( ).getPath( ) ); - repo.setSkipPackedIndexCreation( icf.isSkipPackedIndexCreation() ); - StagingRepositoryFeature srf = beanRepo.getFeature( StagingRepositoryFeature.class ); - repo.setHasStagingRepository( srf.isStageRepoNeeded( ) ); - repo.setStagingRepository( srf.getStagingRepository()!=null?srf.getStagingRepository().getId():"" ); - } - - public static MavenManagedRepository of( ManagedRepository beanRepo ) { - MavenManagedRepository repo = new MavenManagedRepository( ); - update( repo, beanRepo ); - return repo; - } - @Schema(name="blocks_redeployments",description = "True, if redeployments to this repository are not allowed") public boolean isBlocksRedeployments( ) { diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java index 5536ae9b0..1fcb1a0e3 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/MavenManagedRepositoryUpdate.java @@ -17,6 +17,7 @@ package org.apache.archiva.rest.api.v2.model; * under the License. */ +import io.swagger.v3.oas.annotations.media.Schema; import org.apache.archiva.repository.ManagedRepository; import java.io.Serializable; @@ -24,17 +25,13 @@ import java.io.Serializable; /** * @author Martin Stockhammer */ +@Schema(name="MavenManagedRepositoryUpdate",description = "Data object for updating maven managed repositories") public class MavenManagedRepositoryUpdate extends MavenManagedRepository implements Serializable { private static final long serialVersionUID = -9181643343284109862L; private boolean resetStats = false; - public static MavenManagedRepositoryUpdate of( ManagedRepository repository ) { - MavenManagedRepositoryUpdate repo = new MavenManagedRepositoryUpdate( ); - update( repo, repository ); - return repo; - } - + @Schema(name="reset_stats",description = "True, if statistics should be reset after update") public boolean isResetStats( ) { return resetStats; diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/map/MavenRepositoryMapper.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/map/MavenRepositoryMapper.java index 1e4ed68a0..75be52388 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/map/MavenRepositoryMapper.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/v2/model/map/MavenRepositoryMapper.java @@ -64,14 +64,22 @@ public class MavenRepositoryMapper extends RestServiceMapperorg.apache.archiva archiva-storage-api + + org.apache.archiva.event + archiva-event-api + org.apache.archiva archiva-repository-admin-api diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/AbstractService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/AbstractService.java new file mode 100644 index 000000000..09e367e8a --- /dev/null +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/AbstractService.java @@ -0,0 +1,51 @@ +package org.apache.archiva.rest.v2.svc; +/* + * 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.redback.rest.services.RedbackAuthenticationThreadLocal; +import org.apache.archiva.redback.rest.services.RedbackRequestInformation; +import org.apache.archiva.redback.users.User; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.Context; + +/** + * @author Martin Schreier + */ +public class AbstractService +{ + @Context + private HttpServletRequest httpServletRequest; + + protected AuditInformation getAuditInformation( ) + { + RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( ); + User user; + String remoteAddr; + if (redbackRequestInformation==null) { + user = null; + remoteAddr = httpServletRequest.getRemoteAddr( ); + } else + { + user = redbackRequestInformation.getUser( ); + remoteAddr = redbackRequestInformation.getRemoteAddr( ); + } + return new AuditInformation( user, remoteAddr ); + } +} diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/maven/DefaultMavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/maven/DefaultMavenManagedRepositoryService.java index 5bec54dff..406acff59 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/maven/DefaultMavenManagedRepositoryService.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/v2/svc/maven/DefaultMavenManagedRepositoryService.java @@ -20,13 +20,12 @@ package org.apache.archiva.rest.v2.svc.maven; import org.apache.archiva.admin.model.AuditInformation; import org.apache.archiva.admin.model.RepositoryAdminException; import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; +import org.apache.archiva.common.MultiModelMapper; import org.apache.archiva.components.rest.model.PagedResult; import org.apache.archiva.components.rest.util.QueryHelper; import org.apache.archiva.configuration.model.ManagedRepositoryConfiguration; import org.apache.archiva.redback.authentication.AuthenticationResult; import org.apache.archiva.redback.authorization.AuthorizationException; -import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal; -import org.apache.archiva.redback.rest.services.RedbackRequestInformation; import org.apache.archiva.redback.system.DefaultSecuritySession; import org.apache.archiva.redback.system.SecuritySession; import org.apache.archiva.redback.system.SecuritySystem; @@ -36,6 +35,7 @@ import org.apache.archiva.redback.users.UserNotFoundException; import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.ReleaseScheme; import org.apache.archiva.repository.Repository; +import org.apache.archiva.repository.RepositoryException; import org.apache.archiva.repository.RepositoryRegistry; import org.apache.archiva.repository.RepositoryType; import org.apache.archiva.repository.content.ContentItem; @@ -44,10 +44,12 @@ import org.apache.archiva.repository.storage.fs.FsStorageUtil; import org.apache.archiva.rest.api.v2.model.FileInfo; import org.apache.archiva.rest.api.v2.model.MavenManagedRepository; import org.apache.archiva.rest.api.v2.model.MavenManagedRepositoryUpdate; +import org.apache.archiva.rest.api.v2.model.map.ServiceMapperFactory; import org.apache.archiva.rest.api.v2.svc.ArchivaRestServiceException; import org.apache.archiva.rest.api.v2.svc.ErrorKeys; import org.apache.archiva.rest.api.v2.svc.ErrorMessage; import org.apache.archiva.rest.api.v2.svc.maven.MavenManagedRepositoryService; +import org.apache.archiva.rest.v2.svc.AbstractService; import org.apache.archiva.security.common.ArchivaRoleConstants; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -65,14 +67,14 @@ import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; -import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_READ_REPOSITORY; import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_ADD_ARTIFACT; +import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_READ_REPOSITORY; /** * @author Martin Stockhammer */ @Service("v2.managedMavenRepositoryService#rest") -public class DefaultMavenManagedRepositoryService implements MavenManagedRepositoryService +public class DefaultMavenManagedRepositoryService extends AbstractService implements MavenManagedRepositoryService { @Context HttpServletResponse httpServletResponse; @@ -80,6 +82,8 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit @Context UriInfo uriInfo; + + private static final Logger log = LoggerFactory.getLogger( DefaultMavenManagedRepositoryService.class ); private static final QueryHelper QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} ); static @@ -96,36 +100,20 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit private final ManagedRepositoryAdmin managedRepositoryAdmin; private final RepositoryRegistry repositoryRegistry; private final SecuritySystem securitySystem; + private final ServiceMapperFactory serviceMapperFactory; + private final MultiModelMapper mapper; + public DefaultMavenManagedRepositoryService( SecuritySystem securitySystem, RepositoryRegistry repositoryRegistry, - ManagedRepositoryAdmin managedRepositoryAdmin ) + ManagedRepositoryAdmin managedRepositoryAdmin, + ServiceMapperFactory serviceMapperFactory ) throws IllegalArgumentException { this.securitySystem = securitySystem; this.repositoryRegistry = repositoryRegistry; this.managedRepositoryAdmin = managedRepositoryAdmin; - } - - protected AuditInformation getAuditInformation( ) - { - RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( ); - User user; - String remoteAddr; - if (redbackRequestInformation==null) { - user = null; - remoteAddr = null; - } else - { - user = redbackRequestInformation.getUser( ); - remoteAddr = redbackRequestInformation.getRemoteAddr( ); - } - return new AuditInformation( user, remoteAddr ); - } - - public static ManagedRepositoryConfiguration toConfig(MavenManagedRepository repo) { - ManagedRepositoryConfiguration cfg = new ManagedRepositoryConfiguration( ); - return cfg; - + this.serviceMapperFactory = serviceMapperFactory; + this.mapper = serviceMapperFactory.getMapper( MavenManagedRepository.class, ManagedRepositoryConfiguration.class, ManagedRepository.class ); } @Override @@ -140,7 +128,7 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit final Comparator comparator = QUERY_HELPER.getComparator( orderBy, order ); int totalCount = Math.toIntExact( repos.stream( ).filter( queryFilter ).count( ) ); return PagedResult.of( totalCount, offset, limit, repos.stream( ).filter( queryFilter ).sorted( comparator ) - .map( MavenManagedRepository::of ).skip( offset ).limit( limit ).collect( Collectors.toList( ) ) ); + .map( mapper::reverseMap ).skip( offset ).limit( limit ).collect( Collectors.toList( ) ) ); } catch (ArithmeticException e) { log.error( "Invalid number of repositories detected." ); @@ -158,7 +146,7 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit if (repo.getType()!=RepositoryType.MAVEN) { throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 ); } - return MavenManagedRepository.of( repo ); + return mapper.reverseMap( repo ); } @Override @@ -220,13 +208,14 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit } try { - managedRepositoryAdmin.addManagedRepository( convert( managedRepository ), managedRepository.hasStagingRepository(), getAuditInformation() ); + repositoryRegistry.putRepository( mapper.map( managedRepository ) ); httpServletResponse.setStatus( 201 ); - return MavenManagedRepository.of( repositoryRegistry.getManagedRepository( repoId ) ); + return mapper.reverseMap( repositoryRegistry.getManagedRepository( repoId ) ); } - catch ( RepositoryAdminException e ) + catch ( RepositoryException e ) { - throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) ); + log.error( "Could not create repository: {}", e.getMessage( ), e ); + throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADD_FAILED, repoId ) ); } } @@ -241,7 +230,7 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit if (newRepo==null) { throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_UPDATE_FAILED, repositoryId ) ); } - return MavenManagedRepository.of( newRepo ); + return mapper.reverseMap( newRepo ); } catch ( RepositoryAdminException e ) { diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/maven/NativeMavenManagedRepositoryServiceTest.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/maven/NativeMavenManagedRepositoryServiceTest.java index 3dffabed1..d012d6175 100644 --- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/maven/NativeMavenManagedRepositoryServiceTest.java +++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/v2/svc/maven/NativeMavenManagedRepositoryServiceTest.java @@ -100,7 +100,6 @@ public class NativeMavenManagedRepositoryServiceTest extends AbstractNativeRestS } - @Disabled @Test @Order( 2 ) void testCreateRepository() { @@ -111,7 +110,7 @@ public class NativeMavenManagedRepositoryServiceTest extends AbstractNativeRestS assertNotNull( json ); assertEquals( "repo001", json.get( "id" ) ); assertEquals( "Repository 001", json.get( "name" ) ); - assertEquals( "maven", json.get( "type" ) ); + assertEquals( "MAVEN", json.get( "type" ) ); assertEquals( "This is repository 001", json.get( "description" ) ); } diff --git a/pom.xml b/pom.xml index 4eaa74622..ffcd4be77 100644 --- a/pom.xml +++ b/pom.xml @@ -236,6 +236,16 @@ + + org.apache.archiva.event + archiva-event-api + ${project.version} + + + org.apache.archiva.event + archiva-event-central + ${project.version} + org.apache.archiva.maven archiva-maven-common -- cgit v1.2.3