diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java b/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java index 5302a74a5..1691b58ba 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-consumer-archetype/src/main/resources/archetype-resources/src/test/java/RepositoryProviderMock.java @@ -256,7 +256,7 @@ public class RepositoryProviderMock implements RepositoryProvider } @Override - public void raise(Event event) { + public void handle(Event event) { } diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java index c10a5a849..82959a0b3 100644 --- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java +++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java @@ -285,7 +285,7 @@ public class RepositoryProviderMock implements RepositoryProvider } @Override - public void raise(Event event) { + public void handle(Event event) { } } diff --git a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java index 4fb20b7af..a42ab95cc 100644 --- a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java +++ b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/ArchivaProxyRegistry.java @@ -32,7 +32,7 @@ import org.apache.archiva.repository.ManagedRepository; import org.apache.archiva.repository.RemoteRepository; import org.apache.archiva.repository.RepositoryRegistry; import org.apache.archiva.repository.RepositoryType; -import org.apache.archiva.repository.events.RepositoryEventListener; +import org.apache.archiva.repository.events.EventHandler; import org.apache.archiva.repository.events.RepositoryRegistryEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,7 +51,7 @@ import java.util.stream.Collectors; */ @SuppressWarnings( "SpringJavaInjectionPointsAutowiringInspection" ) @Service("proxyRegistry#default") -public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListener { +public class ArchivaProxyRegistry implements ProxyRegistry, EventHandler { private static final Logger log = LoggerFactory.getLogger(ArchivaProxyRegistry.class); @@ -84,7 +84,7 @@ public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListe updateHandler(); updateConnectors(); updateNetworkProxies(); - repositoryRegistry.register(RepositoryRegistryEvent.RELOADED, this); + repositoryRegistry.registerEventHandler(RepositoryRegistryEvent.RELOADED, this); } private ArchivaConfiguration getArchivaConfiguration() { @@ -217,7 +217,7 @@ public class ArchivaProxyRegistry implements ProxyRegistry, RepositoryEventListe } @Override - public void raise(RepositoryRegistryEvent event) { + public void handle(RepositoryRegistryEvent event) { log.debug("Reload happened, updating proxy list"); if (event.getType()== RepositoryRegistryEvent.RELOADED) { init(); diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java index 96cb597e3..c88dc6310 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/Repository.java @@ -20,7 +20,7 @@ package org.apache.archiva.repository; */ import org.apache.archiva.indexer.ArchivaIndexingContext; -import org.apache.archiva.repository.events.RepositoryEventSource; +import org.apache.archiva.repository.events.EventSource; import org.apache.archiva.repository.storage.RepositoryStorage; import org.apache.archiva.repository.features.RepositoryFeature; import org.apache.archiva.repository.storage.StorageAsset; @@ -35,7 +35,7 @@ import java.util.Set; * * Created by Martin Stockhammer on 21.09.17. */ -public interface Repository extends RepositoryEventSource, RepositoryStorage { +public interface Repository extends EventSource, RepositoryStorage { /** * Return the identifier of the repository. Repository identifier should be unique at least diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java index 3a405fbb0..cba28e148 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/RepositoryProvider.java @@ -22,7 +22,7 @@ package org.apache.archiva.repository; import org.apache.archiva.configuration.ManagedRepositoryConfiguration; import org.apache.archiva.configuration.RemoteRepositoryConfiguration; import org.apache.archiva.configuration.RepositoryGroupConfiguration; -import org.apache.archiva.repository.events.RepositoryEventListener; +import org.apache.archiva.repository.events.EventHandler; import java.io.IOException; import java.util.Set; @@ -40,7 +40,7 @@ import java.util.Set; * * */ -public interface RepositoryProvider extends RepositoryEventListener +public interface RepositoryProvider extends EventHandler { /** diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java index 4b0120776..dc91defc5 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/Event.java @@ -22,51 +22,91 @@ package org.apache.archiva.repository.events; import java.time.LocalDateTime; import java.util.EventObject; -public class Event extends 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 { - public static final EventType ANY = new EventType(null, "ANY"); + private static final long serialVersionUID = -7171846575892044990L; - Event previous; - final Object originator; - final EventType type; - final LocalDateTime instant; + 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.originator = originator; this.type = type; - this.instant = LocalDateTime.now(); + this.createTime = LocalDateTime.now(); } private Event(Event previous, Object originator) { super(originator); this.previous = previous; - this.originator = originator; this.type = previous.getType(); - this.instant = previous.getInstant(); + this.createTime = previous.getCreateTime(); } + /** + * Returns the event type that is associated with this event instance. + * @return the event type + */ public EventType getType() { return type; }; - public LocalDateTime getInstant() { - return instant; + /** + * Returns the time, when the event was created. + * @return + */ + public LocalDateTime getCreateTime() { + return createTime; } - public Object getOriginator() { - return originator; - } - - public Event recreate(Object newOrigin) { - return new Event(this, newOrigin); + + /** + * 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-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventHandler.java similarity index 83% rename from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java rename to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventHandler.java index ffedc4207..9f2d4411e 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventListener.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventHandler.java @@ -19,10 +19,12 @@ package org.apache.archiva.repository.events; * under the License. */ -/** - * A listener that accepts repository events. - */ -public interface RepositoryEventListener { +import java.util.EventListener; - void raise(T event); +/** + * A listener that accepts events. + */ +public interface EventHandler extends EventListener { + + void handle(T event); } diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventManager.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventManager.java new file mode 100644 index 000000000..694cfd9e6 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventManager.java @@ -0,0 +1,79 @@ +package org.apache.archiva.repository.events; + +/* + * 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-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventSource.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventSource.java similarity index 65% rename from archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventSource.java rename to archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventSource.java index f26eb782e..cffaeaf56 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEventSource.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventSource.java @@ -19,18 +19,15 @@ package org.apache.archiva.repository.events; * under the License. */ -import java.util.Set; - /** - * A repository event handler raises events to its registered listeners. - * Listeners may register for all events that are raised or only to a subset of events. + * A repository event source raises events to its registered listeners. + * Listeners register to event types that are structured hierarchical. * */ -public interface RepositoryEventSource { +public interface EventSource { - void register(EventType type, RepositoryEventListener listener); + void registerEventHandler(EventType type, EventHandler eventHandler); - void unregister(EventType type, RepositoryEventListener listener); + void unregisterEventHandler(EventType type, EventHandler eventHandler); - void clearListeners(); } diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java index 4162f9ac1..ab9678ab2 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/EventType.java @@ -19,17 +19,59 @@ package org.apache.archiva.repository.events; * under the License. */ -import java.util.ArrayList; -import java.util.List; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.*; -public class EventType { +/** + * 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() { @@ -40,6 +82,19 @@ public class EventType { 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<>(); @@ -61,4 +116,51 @@ public class EventType { } 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-repository-api/src/main/java/org/apache/archiva/repository/events/IndexCreationEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/IndexCreationEvent.java deleted file mode 100644 index 9a2183470..000000000 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/IndexCreationEvent.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.apache.archiva.repository.events; - -/* - * 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.repository.Repository; - -import java.net.URI; - -public class IndexCreationEvent extends RepositoryValueEvent { - - public static EventType ANY = new EventType<>(RepositoryValueEvent.ANY, "REPOSITORY.VALUE.INDEX"); - public static EventType INDEX_URI_CHANGED = new EventType<>(ANY, "REPOSITORY.VALUE.INDEX.URI_CHANGED"); - public static EventType PACKED_INDEX_URI_CHANGED = new EventType<>(ANY, "REPOSITORY.VALUE.INDEX.PACKED_URI_CHANGED"); - - IndexCreationEvent(EventType type, Object origin, Repository repo, URI oldValue, URI value) { - super(type, origin, repo, oldValue, value); - } - - public static final IndexCreationEvent indexUriChange(O origin, Repository repo, URI oldValue, URI newValue) { - return new IndexCreationEvent(INDEX_URI_CHANGED, origin, repo, oldValue, newValue); - } - - public static final IndexCreationEvent packedIndexUriChange(O origin, Repository repo, URI oldValue, URI newValue) { - return new IndexCreationEvent(PACKED_INDEX_URI_CHANGED, origin, repo, oldValue, newValue); - } -} diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java index 9197b580a..6408eb534 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/LifecycleEvent.java @@ -21,8 +21,17 @@ package org.apache.archiva.repository.events; import org.apache.archiva.repository.Repository; +/** + * Raises events about the repository lifecycle. The following events are raised: + *
    + *
  • REGISTERED: a repository has been registered by the repository registry
  • + *
  • UNREGISTERED: a repository has been removed by the repository registry
  • + *
  • UPDATED: A repository attribute was updated
  • + *
+ */ public class LifecycleEvent extends RepositoryEvent { + private static final long serialVersionUID = -2520982087439428714L; public static EventType ANY = new EventType<>(RepositoryEvent.ANY, "REPOSITORY.LIFECYCLE"); public static EventType REGISTERED = new EventType<>(ANY, "REPOSITORY.LIFECYCLE.REGISTERED"); public static EventType UNREGISTERED = new EventType<>(ANY, "REPOSITORY.LIFECYCLE.UNREGISTERED"); diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java index 24ea42c31..28d4770c0 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryEvent.java @@ -21,9 +21,15 @@ package org.apache.archiva.repository.events; import org.apache.archiva.repository.Repository; +/** + * A repository event is specific to a repository and holds a reference to the repository that + * is related to this event. + */ public class RepositoryEvent extends Event { - public static final EventType ANY = new EventType<>(Event.ANY, "REPOSITORY.UPDATED"); + private static final long serialVersionUID = 4676673476606414834L; + + public static final EventType ANY = new EventType<>(Event.ANY, "REPOSITORY"); private final Repository repository; diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryIndexEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryIndexEvent.java new file mode 100644 index 000000000..9f1b2a60d --- /dev/null +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryIndexEvent.java @@ -0,0 +1,49 @@ +package org.apache.archiva.repository.events; + +/* + * 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.repository.Repository; + +import java.net.URI; + +/** + * These events are thrown, when index information has changed. + */ +public class RepositoryIndexEvent extends RepositoryValueEvent { + + private static final long serialVersionUID = -7801989699524776524L; + + public static EventType ANY = new EventType<>(RepositoryValueEvent.ANY, "REPOSITORY.VALUE.INDEX"); + public static EventType INDEX_URI_CHANGED = new EventType<>(ANY, "REPOSITORY.VALUE.INDEX.URI_CHANGED"); + public static EventType PACKED_INDEX_URI_CHANGED = new EventType<>(ANY, "REPOSITORY.VALUE.INDEX.PACKED_URI_CHANGED"); + + RepositoryIndexEvent(EventType type, Object origin, Repository repo, URI oldValue, URI value) { + super(type, origin, repo, oldValue, value, "index.uri"); + } + + public static final RepositoryIndexEvent indexUriChange(O origin, Repository repo, URI oldValue, URI newValue) { + return new RepositoryIndexEvent(INDEX_URI_CHANGED, origin, repo, oldValue, newValue); + } + + public static final RepositoryIndexEvent packedIndexUriChange(O origin, Repository repo, URI oldValue, URI newValue) { + return new RepositoryIndexEvent(PACKED_INDEX_URI_CHANGED, origin, repo, oldValue, newValue); + } +} diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java index 2b9ac7668..fbaa97199 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryRegistryEvent.java @@ -19,11 +19,29 @@ package org.apache.archiva.repository.events; * under the License. */ +/** + * Repository registry events are raised by the repository registry itself. + */ public class RepositoryRegistryEvent extends Event { - public static EventType ANY = new EventType(Event.ANY, "REGISTRY"); + private static final long serialVersionUID = -4740127827269612094L; + + /** + * All repository registry events + */ + public static EventType ANY = new EventType(EventType.ROOT, "REGISTRY"); + /** + * When the registry has reloaded the registry data from the configuration + */ public static EventType RELOADED = new EventType(ANY, "REGISTRY.RELOADED"); + /** + * When the registry was destroyed. Repository instances may still be referenced, but are not updated. + */ public static EventType DESTROYED = new EventType(ANY, "REGISTRY.DESTROYED"); + /** + * When the registry was initialized + */ + public static EventType INITIALIZED = new EventType(ANY, "REGISTRY.INITIALIZED"); public RepositoryRegistryEvent(EventType type, Object origin) { super(type, origin); diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java index b5f8146a7..448d72027 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/events/RepositoryValueEvent.java @@ -22,21 +22,27 @@ package org.apache.archiva.repository.events; import org.apache.archiva.repository.Repository; /** - * Repository event. Repository events are used for providing information about repository changes. + * Repository value events are used for providing information about repository attribute changes. + * The value event gives information of the attribute value before and after the change. * - * @param + * @param The type of the changed attribute */ public class RepositoryValueEvent extends RepositoryEvent { - public static final EventType> ANY = new EventType(RepositoryEvent.ANY, "REPOSITORY.VALUE.UPDATED"); + private static final long serialVersionUID = 4176597620699304794L; + + public static final EventType> ANY = new EventType(RepositoryEvent.ANY, "REPOSITORY.VALUE"); final V value; final V oldValue; + final String attributeName; - public RepositoryValueEvent(EventType> type, Object origin, Repository repo, V oldValue, V value) { + public RepositoryValueEvent(EventType> type, Object origin, Repository repo, V oldValue, V value, + String attributeName) { super(type, origin, repo); this.value = value; this.oldValue = oldValue; + this.attributeName = attributeName; } public V getValue() { @@ -47,4 +53,8 @@ public class RepositoryValueEvent extends RepositoryEvent { return oldValue; } + public String getAttributeName() { + return attributeName; + } + } diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/AbstractFeature.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/AbstractFeature.java index 6b64d937c..60a1dce3f 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/AbstractFeature.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/AbstractFeature.java @@ -20,35 +20,35 @@ package org.apache.archiva.repository.features; */ import org.apache.archiva.repository.events.Event; -import org.apache.archiva.repository.events.RepositoryEventListener; +import org.apache.archiva.repository.events.EventHandler; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class AbstractFeature { - private List listener = new ArrayList<>(); + private List listener = new ArrayList<>(); AbstractFeature() { } - AbstractFeature(RepositoryEventListener listener) { + AbstractFeature(EventHandler listener) { this.listener.add(listener); } - AbstractFeature(Collection listeners) { + AbstractFeature(Collection listeners) { this.listener.addAll(listeners); } - public void addListener(RepositoryEventListener listener) { + public void addListener(EventHandler listener) { if (!this.listener.contains(listener)) { this.listener.add(listener); } this.listener.add(listener); } - public void removeListener(RepositoryEventListener listener) { + public void removeListener(EventHandler listener) { this.listener.remove(listener); } @@ -57,8 +57,8 @@ public class AbstractFeature { } public void pushEvent(Event event) { - for(RepositoryEventListener listr : listener) { - listr.raise(event); + for(EventHandler listr : listener) { + listr.handle(event); } } diff --git a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java index f834be129..f9de498d7 100644 --- a/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java +++ b/archiva-modules/archiva-base/archiva-repository-api/src/main/java/org/apache/archiva/repository/features/IndexCreationFeature.java @@ -21,8 +21,8 @@ package org.apache.archiva.repository.features; import org.apache.archiva.repository.Repository; -import org.apache.archiva.repository.events.IndexCreationEvent; -import org.apache.archiva.repository.events.RepositoryEventListener; +import org.apache.archiva.repository.events.RepositoryIndexEvent; +import org.apache.archiva.repository.events.EventHandler; import org.apache.archiva.repository.storage.StorageAsset; import org.apache.commons.lang3.StringUtils; @@ -44,7 +44,7 @@ import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_PACKED_INDE * A index may have a remote and a local representation. The remote representation is used for downloading and * updating the local representation. * - * The feature is throwing a {@link IndexCreationEvent}, if the URI of the index has been changed. + * The feature is throwing a {@link RepositoryIndexEvent}, if the URI of the index has been changed. * */ public class IndexCreationFeature extends AbstractFeature implements RepositoryFeature{ @@ -62,7 +62,7 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF private Repository repo; - public IndexCreationFeature(Repository repository, RepositoryEventListener listener) { + public IndexCreationFeature(Repository repository, EventHandler listener) { super(listener); this.repo = repository; try { @@ -129,7 +129,7 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF if ((this.indexPath==null && indexPath!=null) || !this.indexPath.equals(indexPath)) { URI oldVal = this.indexPath; this.indexPath = indexPath; - pushEvent(IndexCreationEvent.indexUriChange(this, repo, oldVal, this.indexPath)); + pushEvent(RepositoryIndexEvent.indexUriChange(this, repo, oldVal, this.indexPath)); } } @@ -173,14 +173,14 @@ public class IndexCreationFeature extends AbstractFeature implements RepositoryF /** * Sets the path (relative or absolute) of the packed index. * - * Throws a {@link IndexCreationEvent.Index#PACKED_INDEX_URI_CHANGE}, if the value changes. + * Throws a {@link RepositoryIndexEvent.Index#PACKED_INDEX_URI_CHANGE}, if the value changes. * * @param packedIndexPath the new path uri for the packed index */ public void setPackedIndexPath(URI packedIndexPath) { URI oldVal = this.packedIndexPath; this.packedIndexPath = packedIndexPath; - pushEvent(IndexCreationEvent.packedIndexUriChange(this, repo, oldVal, this.packedIndexPath)); + pushEvent(RepositoryIndexEvent.packedIndexUriChange(this, repo, oldVal, this.packedIndexPath)); } /** diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java index 5a5aa6c4c..3172c7e7a 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/AbstractRepository.java @@ -56,7 +56,7 @@ import java.util.function.Consumer; * No features are provided. Capabilities and features must be implemented by concrete classes. * */ -public abstract class AbstractRepository implements EditableRepository, RepositoryEventListener +public abstract class AbstractRepository implements EditableRepository, EventHandler { @@ -80,8 +80,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito private String layout = "default"; public static final CronDefinition CRON_DEFINITION = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ); - private Map, List>> listenerTypeMap = new HashMap<>(); - + private final EventManager eventManager; Map>, RepositoryFeature> featureMap = new HashMap<>( ); @@ -95,6 +94,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito this.storage = repositoryStorage; this.location = repositoryStorage.getLocation(); this.openStatus.compareAndSet(false, true); + this.eventManager = new EventManager(this); } public AbstractRepository(Locale primaryLocale, RepositoryType type, String id, String name, RepositoryStorage repositoryStorage) { @@ -105,6 +105,7 @@ public abstract class AbstractRepository implements EditableRepository, Reposito this.storage = repositoryStorage; this.location = repositoryStorage.getLocation(); this.openStatus.compareAndSet(false, true); + this.eventManager = new EventManager(this); } protected void setPrimaryLocale(Locale locale) { @@ -324,8 +325,8 @@ public abstract class AbstractRepository implements EditableRepository, Reposito sf.getStagingRepository().close(); } } - clearListeners(); } + } @Override @@ -334,56 +335,22 @@ public abstract class AbstractRepository implements EditableRepository, Reposito } @Override - public void raise(RepositoryEvent event) { - final EventType currentType = event.getType(); - for (EventType type : listenerTypeMap.keySet()) { - if (EventType.isInstanceOf(currentType, type)) { - callListeners(event, listenerTypeMap.get(type)); - } - } - } - - private void callListeners(RepositoryEvent event, List> evtListeners) { - for(RepositoryEventListener listener : evtListeners) { - try { - listener.raise(event.recreate(this)); - } catch (Throwable e) { - log.error("Could not raise event {} on listener {}: {}", event, listener, e.getMessage()); - } - } - + public void handle(RepositoryEvent event) { + // We just rethrow the events + eventManager.fireEvent(event); } @Override - public void register(EventType eventType, RepositoryEventListener listener) { + public void registerEventHandler(EventType eventType, EventHandler eventHandler) { if (!EventType.isInstanceOf(eventType, RepositoryEvent.ANY)) { throw new IllegalArgumentException("Can only register RepositoryEvent Handlers"); } - final RepositoryEventListener myListener = (RepositoryEventListener) listener; - final EventType type = (EventType) eventType; - - List> listeners; - if (listenerTypeMap.containsKey(type)) { - listeners = listenerTypeMap.get(type); - } else { - listeners = new ArrayList<>(); - listenerTypeMap.put(type, listeners); - } - if (!listeners.contains(listener)) { - listeners.add(myListener); - } + eventManager.registerEventHandler(eventType, eventHandler); } @Override - public void unregister(EventType type, RepositoryEventListener listener) { - for (List> listeners : listenerTypeMap.values()) { - listeners.remove(listener); - } - } - - @Override - public void clearListeners() { - this.listenerTypeMap.clear(); + public void unregisterEventHandler(EventType type, EventHandler eventHandler) { + eventManager.unregisterEventHandler(type, eventHandler); } @Override diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java index 07e7300e5..998b79be8 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/RepositoryRegistry.java @@ -23,6 +23,7 @@ import org.apache.archiva.configuration.*; import org.apache.archiva.indexer.*; import org.apache.archiva.redback.components.registry.RegistryException; import org.apache.archiva.repository.events.*; +import org.apache.archiva.repository.events.EventHandler; import org.apache.archiva.repository.features.IndexCreationFeature; import org.apache.archiva.repository.features.StagingRepositoryFeature; import org.apache.commons.lang3.StringUtils; @@ -53,7 +54,7 @@ import static org.apache.archiva.indexer.ArchivaIndexManager.DEFAULT_INDEX_PATH; * @since 3.0 */ @Service("repositoryRegistry") -public class RepositoryRegistry implements ConfigurationListener, RepositoryEventSource, RepositoryEventListener { +public class RepositoryRegistry implements ConfigurationListener, EventSource, EventHandler { private static final Logger log = LoggerFactory.getLogger(RepositoryRegistry.class); @@ -73,7 +74,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven @Named("repositoryContentFactory#default") RepositoryContentFactory repositoryContentFactory; - private Map, List>> typeListenerMap = new HashMap<>(); + private final EventManager eventManager; private Map managedRepositories = new HashMap<>(); @@ -89,6 +90,10 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven private volatile boolean ignoreConfigEvents = false; + public RepositoryRegistry() { + this.eventManager = new EventManager(this); + } + public void setArchivaConfiguration(ArchivaConfiguration archivaConfiguration) { this.archivaConfiguration = archivaConfiguration; } @@ -181,7 +186,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven private ManagedRepository createNewManagedRepository(RepositoryProvider provider, ManagedRepositoryConfiguration cfg) throws RepositoryException { log.debug("Creating repo {}", cfg.getId()); ManagedRepository repo = provider.createManagedInstance(cfg); - repo.register(RepositoryEvent.ANY, this); + repo.registerEventHandler(RepositoryEvent.ANY, this); updateRepositoryReferences(provider, repo, cfg, null); return repo; @@ -221,7 +226,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven createIndexingContext(editableRepo); } } - repo.register(RepositoryEvent.ANY, this); + repo.registerEventHandler(RepositoryEvent.ANY, this); } public ArchivaIndexManager getIndexManager(RepositoryType type) { @@ -296,7 +301,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven createIndexingContext(editableRepo); } } - repo.register(RepositoryEvent.ANY, this); + repo.registerEventHandler(RepositoryEvent.ANY, this); } private Map getRepositorGroupsFromConfig() { @@ -331,7 +336,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven private RepositoryGroup createNewRepositoryGroup(RepositoryProvider provider, RepositoryGroupConfiguration config) throws RepositoryException { RepositoryGroup repositoryGroup = provider.createRepositoryGroup(config); - repositoryGroup.register(RepositoryEvent.ANY, this); + repositoryGroup.registerEventHandler(RepositoryEvent.ANY, this); updateRepositoryReferences(provider, repositoryGroup, config); return repositoryGroup; } @@ -1171,7 +1176,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven ManagedRepositoryConfiguration cfg = provider.getManagedConfiguration(repo); cfg.setId(newId); ManagedRepository cloned = provider.createManagedInstance(cfg); - cloned.register(RepositoryEvent.ANY, this); + cloned.registerEventHandler(RepositoryEvent.ANY, this); return cloned; } @@ -1200,7 +1205,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven RemoteRepositoryConfiguration cfg = provider.getRemoteConfiguration(repo); cfg.setId(newId); RemoteRepository cloned = provider.createRemoteInstance(cfg); - cloned.register(RepositoryEvent.ANY, this); + cloned.registerEventHandler(RepositoryEvent.ANY, this); return cloned; } @@ -1215,47 +1220,32 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven @Override - public void register(EventType type, RepositoryEventListener listener) { - List> listeners; - if (typeListenerMap.containsKey(type)) { - listeners = typeListenerMap.get(type); - } else { - listeners = new ArrayList<>(); - typeListenerMap.put(type, listeners); - } - if (!listeners.contains(listener)) { - listeners.add(listener); - } + public void registerEventHandler(EventType type, EventHandler eventHandler) { + eventManager.registerEventHandler(type, eventHandler); } @Override - public void unregister(EventType type, RepositoryEventListener listener) { - for (List> listeners : typeListenerMap.values()) { - listeners.remove(listener); - } + public void unregisterEventHandler(EventType type, EventHandler eventHandler) { + eventManager.unregisterEventHandler(type, eventHandler); } - @Override - public void clearListeners() { - this.typeListenerMap.clear(); - } @Override - public void raise(Event event) { + public void handle(Event event) { // To avoid event cycles: if (sameOriginator(event)) { return; } - if (event instanceof IndexCreationEvent) { - handleIndexCreationEvent((IndexCreationEvent) event); + if (event instanceof RepositoryIndexEvent) { + handleIndexCreationEvent((RepositoryIndexEvent) event); } // We propagate all events to our listeners, but with context of repository registry - pushEvent(event.recreate(this)); + pushEvent(event); } - private void handleIndexCreationEvent(IndexCreationEvent event) { - IndexCreationEvent idxEvent = event; + private void handleIndexCreationEvent(RepositoryIndexEvent event) { + RepositoryIndexEvent idxEvent = event; if (managedRepositories.containsKey(idxEvent.getRepository().getId()) || remoteRepositories.containsKey(idxEvent.getRepository().getId())) { EditableRepository repo = (EditableRepository) idxEvent.getRepository(); @@ -1276,7 +1266,7 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven } private boolean sameOriginator(Event event) { - if (event.getOriginator() == this) { + if (event.getSource() == this) { return true; } else if (event.hasPreviousEvent()) { return sameOriginator(event.getPreviousEvent()); @@ -1286,19 +1276,9 @@ public class RepositoryRegistry implements ConfigurationListener, RepositoryEven } private void pushEvent(Event event) { - final EventType currentType = event.getType(); - for (EventType type : typeListenerMap.keySet()) { - if (EventType.isInstanceOf(currentType, type)) { - callListeners(event, typeListenerMap.get(type)); - } - } + eventManager.fireEvent(event); } - private void callListeners(Event event, List> listeners) { - for (RepositoryEventListener listener : listeners) { - listener.raise(event); - } - } } diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java index 0f7521877..801f5197c 100644 --- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java +++ b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java @@ -261,7 +261,7 @@ public class RepositoryProviderMock implements RepositoryProvider } @Override - public void raise(Event event) { + public void handle(Event event) { } } diff --git a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java index 0a8c57315..04ff8c071 100644 --- a/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java +++ b/archiva-modules/archiva-maven/archiva-maven-proxy/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java @@ -281,7 +281,7 @@ public class RepositoryProviderMock implements RepositoryProvider } @Override - public void raise(Event event) { + public void handle(Event event) { } } diff --git a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenRepositoryProvider.java b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenRepositoryProvider.java index ec78a942f..b477af2ac 100644 --- a/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenRepositoryProvider.java +++ b/archiva-modules/archiva-maven/archiva-maven-repository/src/main/java/org/apache/archiva/repository/maven2/MavenRepositoryProvider.java @@ -509,7 +509,7 @@ public class MavenRepositoryProvider implements RepositoryProvider { } @Override - public void raise(Event event) { + public void handle(Event event) { // }