git-svn-id: https://svn.apache.org/repos/asf/archiva/branches/MRM-976@706263 13f79535-47bb-0310-9956-ffa450edef68MRM-976
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!-- | |||||
~ 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. | |||||
--> | |||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | |||||
<parent> | |||||
<groupId>org.apache.archiva</groupId> | |||||
<artifactId>archiva-base</artifactId> | |||||
<version>1.2-SNAPSHOT</version> | |||||
</parent> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<groupId>org.apache.archiva</groupId> | |||||
<artifactId>archiva-event</artifactId> | |||||
<packaging>jar</packaging> | |||||
<version>1.2-SNAPSHOT</version> | |||||
<name>Archiva Base :: Event</name> | |||||
</project> |
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.Collections; | |||||
import java.util.HashSet; | |||||
import java.util.Set; | |||||
import java.util.concurrent.BlockingQueue; | |||||
import java.util.concurrent.ExecutorService; | |||||
import java.util.concurrent.Executors; | |||||
import java.util.concurrent.LinkedBlockingQueue; | |||||
/** | |||||
* Simple Async Event Bus implementation | |||||
* | |||||
* @author jdumay | |||||
*/ | |||||
public class AsynchronousEventBus implements EventBus | |||||
{ | |||||
private final Set<EventObserver> observers = Collections.synchronizedSet(new HashSet()); | |||||
private final BlockingQueue<Event> events = new LinkedBlockingQueue<Event>(); | |||||
private final Thread workerThread; | |||||
private final int threads; | |||||
public AsynchronousEventBus(int threads) | |||||
{ | |||||
this.threads = threads; | |||||
workerThread = new Thread(new WorkerRunnable()); | |||||
workerThread.start(); | |||||
} | |||||
public void emit(EventEmitter emitter, EventMessage message) | |||||
{ | |||||
events.offer(new Event(emitter, message)); | |||||
} | |||||
public void subscribe(EventObserver observer) | |||||
{ | |||||
observers.add(observer); | |||||
} | |||||
public void unsubscribe(EventObserver observer) | |||||
{ | |||||
observers.remove(observer); | |||||
} | |||||
public Set<EventObserver> getObservers() { | |||||
return new HashSet<EventObserver>(observers); | |||||
} | |||||
class WorkerRunnable implements Runnable | |||||
{ | |||||
private final ExecutorService service; | |||||
public WorkerRunnable() | |||||
{ | |||||
service = Executors.newFixedThreadPool(threads); | |||||
} | |||||
public void run() | |||||
{ | |||||
while (true) | |||||
{ | |||||
dequeueAndExecute(); | |||||
} | |||||
} | |||||
private void dequeueAndExecute() | |||||
{ | |||||
try | |||||
{ | |||||
final Event event = events.take(); | |||||
for (final EventObserver observer : observers) | |||||
{ | |||||
service.execute(new Runnable() | |||||
{ | |||||
public void run() | |||||
{ | |||||
try | |||||
{ | |||||
observer.observe(event); | |||||
} | |||||
finally | |||||
{ | |||||
//log me | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
} | |||||
catch (InterruptedException e) | |||||
{ | |||||
//Do nothing | |||||
} | |||||
} | |||||
} | |||||
} |
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. | |||||
*/ | |||||
/** | |||||
* Encaptulation of both the EventEmitter and the EventMessage | |||||
* to represent a single event | |||||
*/ | |||||
public final class Event | |||||
{ | |||||
private final EventEmitter emitter; | |||||
private final EventMessage message; | |||||
public Event(EventEmitter emitter, EventMessage message) | |||||
{ | |||||
this.emitter = emitter; | |||||
this.message = message; | |||||
} | |||||
/** | |||||
* Get the Emitter who emitted the Event | |||||
* @return emitter | |||||
*/ | |||||
public EventEmitter getEmitter() | |||||
{ | |||||
return emitter; | |||||
} | |||||
/** | |||||
* Get the EventMessage | |||||
* @return message | |||||
*/ | |||||
public EventMessage getMessage() | |||||
{ | |||||
return message; | |||||
} | |||||
} |
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.Set; | |||||
/** | |||||
* Allows implementer to emit to, subscribe and unsubscribe EventObservers | |||||
*/ | |||||
public interface EventBus | |||||
{ | |||||
/** | |||||
* Emit a event | |||||
* @param emitter | |||||
* @param message | |||||
*/ | |||||
void emit(EventEmitter emitter, EventMessage message); | |||||
/** | |||||
* Allows the subscriber to receive messages from this event bus | |||||
* @param observer | |||||
*/ | |||||
void subscribe(EventObserver observer); | |||||
/** | |||||
* Stops the observer from receiving any messages | |||||
* @param observer | |||||
*/ | |||||
void unsubscribe(EventObserver observer); | |||||
/** | |||||
* Get the set of registered EventObservers | |||||
* @return | |||||
*/ | |||||
Set<EventObserver> getObservers(); | |||||
} |
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. | |||||
*/ | |||||
public interface EventEmitter | |||||
{ | |||||
} |
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. | |||||
*/ | |||||
public interface EventMessage | |||||
{ | |||||
} |
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. | |||||
*/ | |||||
public interface EventObserver | |||||
{ | |||||
void observe(Event event); | |||||
} |
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.ArrayList; | |||||
import java.util.Collections; | |||||
import java.util.List; | |||||
import junit.framework.TestCase; | |||||
public class AsynchronousEventBusTest extends TestCase | |||||
{ | |||||
public void testSubscribeUnsubscribe() throws Exception | |||||
{ | |||||
AsynchronousEventBus bus = new AsynchronousEventBus(1); | |||||
MockObserver observer = new MockObserver(); | |||||
assertEquals(0, bus.getObservers().size()); | |||||
bus.subscribe(observer); | |||||
assertTrue(bus.getObservers().contains(observer)); | |||||
bus.unsubscribe(observer); | |||||
assertFalse(bus.getObservers().contains(bus)); | |||||
} | |||||
public void testAllEventsAreObserved() throws Exception | |||||
{ | |||||
AsynchronousEventBus bus = new AsynchronousEventBus(1); | |||||
MockObserver observer = new MockObserver(); | |||||
bus.subscribe(observer); | |||||
for (int i = 0; i < 10; i++) | |||||
{ | |||||
bus.emit(new EventEmitter() {}, new EventMessage() {}); | |||||
} | |||||
while (observer.observedEvents.size() != 10) | |||||
{ | |||||
} | |||||
assertEquals(10, observer.observedEvents.size()); | |||||
} | |||||
class MockObserver implements EventObserver | |||||
{ | |||||
final List<Event> observedEvents = Collections.synchronizedList(new ArrayList()); | |||||
public void observe(Event event) | |||||
{ | |||||
observedEvents.add(event); | |||||
} | |||||
} | |||||
} |
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 junit.framework.TestCase; | |||||
public class EventTest extends TestCase | |||||
{ | |||||
public void testEvent() | |||||
{ | |||||
EventEmitter emitter = new EventEmitter() {}; | |||||
EventMessage message = new EventMessage() {}; | |||||
Event event = new Event(emitter, message); | |||||
assertEquals(emitter, event.getEmitter()); | |||||
assertEquals(message, event.getMessage()); | |||||
} | |||||
} |
<module>archiva-transaction</module> | <module>archiva-transaction</module> | ||||
<module>archiva-artifact-converter</module> | <module>archiva-artifact-converter</module> | ||||
<module>archiva-converter</module> | <module>archiva-converter</module> | ||||
<module>archiva-event</module> | |||||
</modules> | </modules> | ||||
</project> | </project> |
Stage 1: remove use of database and index from core consumers (move implementation into respective database and index modules) | |||||
Done! | |||||
Stage 2: separate model from JPOX annotated classes, centralising JPOX use in database | |||||
* archiva-model to be reviewed, possibly split into a basic model with extensible parts. See metadata proposal | |||||
* add consumer to generate Archiva metadata at same time as database model | |||||
Stage 3: add a basic repository querying API for base artifact information and retrieval of metadata | |||||
* RSS, browse | |||||
* consider repository-api refactorings | |||||
* at this point, should be able to have functional Archiva without a database | |||||
* note that metadata need not be stored with the artifacts themselves, but will be by default | |||||
Stage 4: incorporation of event API | |||||
* used to centralise arrival, removal, etc of files/artifacts in the repository | |||||
* errors should be events as well to avoid exceptions in the logs and instead meaningful handling/reporting | |||||
* could also be used for configuration events | |||||
* consider hooking the audit log to this as well | |||||
Stage 5: isolate scanning code | |||||
* Repository should operate without scanning code, it should push events if enabled | |||||
* better assessment of its progress, performance | |||||
* removal of database / repository scanning duality - all operations are driven by the event bus | |||||
* move some database operations to a housekeeping scheduled task (same for index), make scheduled tasks a listable item based on available plugins | |||||