merge remaining changes from archiva-database-decoupling branch


git-svn-id: https://svn.apache.org/repos/asf/archiva/branches/MRM-976@706263 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/archiva-modules/archiva-base/archiva-event/pom.xml b/archiva-modules/archiva-base/archiva-event/pom.xml
new file mode 100644
index 0000000..139cfc1
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/pom.xml
@@ -0,0 +1,34 @@
+<?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>

diff --git a/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/AsynchronousEventBus.java b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/AsynchronousEventBus.java
new file mode 100644
index 0000000..2087085
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/AsynchronousEventBus.java
@@ -0,0 +1,117 @@
+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
+            }
+        }
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/Event.java b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/Event.java
new file mode 100644
index 0000000..e41d19e
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/Event.java
@@ -0,0 +1,55 @@
+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;
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventBus.java b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventBus.java
new file mode 100644
index 0000000..6445cb9
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventBus.java
@@ -0,0 +1,53 @@
+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();
+}
diff --git a/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventEmitter.java b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventEmitter.java
new file mode 100644
index 0000000..4cdab91
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventEmitter.java
@@ -0,0 +1,24 @@
+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
+{
+}
diff --git a/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventMessage.java b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventMessage.java
new file mode 100644
index 0000000..8f39dec
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventMessage.java
@@ -0,0 +1,24 @@
+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
+{
+}
diff --git a/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventObserver.java b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventObserver.java
new file mode 100644
index 0000000..bb5f07d
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/src/main/java/org/apache/archiva/event/EventObserver.java
@@ -0,0 +1,25 @@
+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);
+}
diff --git a/archiva-modules/archiva-base/archiva-event/src/test/java/org/apache/archiva/event/AsynchronousEventBusTest.java b/archiva-modules/archiva-base/archiva-event/src/test/java/org/apache/archiva/event/AsynchronousEventBusTest.java
new file mode 100644
index 0000000..b688389
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/src/test/java/org/apache/archiva/event/AsynchronousEventBusTest.java
@@ -0,0 +1,70 @@
+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);
+        }
+    }
+}
diff --git a/archiva-modules/archiva-base/archiva-event/src/test/java/org/apache/archiva/event/EventTest.java b/archiva-modules/archiva-base/archiva-event/src/test/java/org/apache/archiva/event/EventTest.java
new file mode 100644
index 0000000..5710f07
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-event/src/test/java/org/apache/archiva/event/EventTest.java
@@ -0,0 +1,35 @@
+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());
+    }
+}
diff --git a/archiva-modules/archiva-base/pom.xml b/archiva-modules/archiva-base/pom.xml
index f95c75f..c6b7de9 100644
--- a/archiva-modules/archiva-base/pom.xml
+++ b/archiva-modules/archiva-base/pom.xml
@@ -42,5 +42,6 @@
     <module>archiva-transaction</module>
     <module>archiva-artifact-converter</module>
     <module>archiva-converter</module>
+    <module>archiva-event</module>
   </modules>
 </project>
diff --git a/branch-working-notes.txt b/branch-working-notes.txt
new file mode 100644
index 0000000..495464e
--- /dev/null
+++ b/branch-working-notes.txt
@@ -0,0 +1,30 @@
+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
+