ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject svn commit: r1465924 [1/3] - in /ace/trunk/org.apache.ace.log: ./ src/ src/org/ src/org/apache/ src/org/apache/ace/ src/org/apache/ace/log/ src/org/apache/ace/log/listener/ src/org/apache/ace/log/server/ src/org/apache/ace/log/server/servlet/ src/org/a...
Date Tue, 09 Apr 2013 08:18:48 GMT
Author: marrs
Date: Tue Apr  9 08:18:47 2013
New Revision: 1465924

URL: http://svn.apache.org/r1465924
Log:
ACE-333 Added the new log project.

Added:
    ace/trunk/org.apache.ace.log/
    ace/trunk/org.apache.ace.log/.classpath
    ace/trunk/org.apache.ace.log/.project
    ace/trunk/org.apache.ace.log/api.bnd
    ace/trunk/org.apache.ace.log/bnd.bnd
    ace/trunk/org.apache.ace.log/build.xml
    ace/trunk/org.apache.ace.log/listener.bnd
    ace/trunk/org.apache.ace.log/server.servlet.bnd
    ace/trunk/org.apache.ace.log/server.store.api.bnd
    ace/trunk/org.apache.ace.log/server.store.file.bnd
    ace/trunk/org.apache.ace.log/server.store.mongo.bnd
    ace/trunk/org.apache.ace.log/server.task.bnd
    ace/trunk/org.apache.ace.log/src/
    ace/trunk/org.apache.ace.log/src/org/
    ace/trunk/org.apache.ace.log/src/org/apache/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/AuditEvent.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/Log.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogDescriptor.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogEvent.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogSync.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/Activator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/ListenerImpl.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogCache.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogProxy.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogTracker.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/packageinfo
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/Activator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/LogServlet.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/LogStore.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/impl/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/impl/Activator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/impl/LogStoreImpl.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/mongo/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/mongo/Activator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/mongo/MongoLogStore.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/packageinfo
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/task/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/task/Activator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/task/LogSyncTask.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/Activator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/LogConfigurator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/LogImpl.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/LogSyncConfigurator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/store/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/store/LogStore.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/store/impl/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/store/impl/Activator.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/store/impl/LogStoreImpl.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/store/packageinfo
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/task/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/target/task/LogSyncTask.java
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/util/
    ace/trunk/org.apache.ace.log/src/org/apache/ace/log/util/Codec.java
    ace/trunk/org.apache.ace.log/target.bnd
    ace/trunk/org.apache.ace.log/target.store.impl.bnd
    ace/trunk/org.apache.ace.log/test/
    ace/trunk/org.apache.ace.log/test/org/
    ace/trunk/org.apache.ace.log/test/org/apache/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/LogDescriptorTest.java
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/LogEventTest.java
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/listener/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/listener/LogTest.java
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/listener/MockLog.java
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/server/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/server/servlet/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/server/servlet/LogServletTest.java
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/server/store/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/server/store/impl/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/server/store/impl/ServerLogStoreTester.java
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/server/task/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/server/task/LogTaskTest.java
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/target/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/target/store/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/target/store/impl/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/target/store/impl/GatewayLogStoreTest.java
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/target/task/
    ace/trunk/org.apache.ace.log/test/org/apache/ace/log/target/task/LogSyncTaskTest.java

Added: ace/trunk/org.apache.ace.log/.classpath
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/.classpath?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/.classpath (added)
+++ ace/trunk/org.apache.ace.log/.classpath Tue Apr  9 08:18:47 2013
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: ace/trunk/org.apache.ace.log/.project
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/.project?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/.project (added)
+++ ace/trunk/org.apache.ace.log/.project Tue Apr  9 08:18:47 2013
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.ace.log</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>

Added: ace/trunk/org.apache.ace.log/api.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/api.bnd?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/api.bnd (added)
+++ ace/trunk/org.apache.ace.log/api.bnd Tue Apr  9 08:18:47 2013
@@ -0,0 +1,3 @@
+Private-Package: org.apache.ace.log.util
+Export-Package: org.apache.ace.log
+Bundle-Version: 1.0.0
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/bnd.bnd?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/bnd.bnd (added)
+++ ace/trunk/org.apache.ace.log/bnd.bnd Tue Apr  9 08:18:47 2013
@@ -0,0 +1,15 @@
+-buildpath: osgi.core,\
+	osgi.cmpn,\
+	javax.servlet,\
+	org.apache.felix.dependencymanager,\
+	org.apache.ace.range.api;version=latest,\
+	org.apache.ace.test;version=latest,\
+	org.apache.ace.identification.api;version=latest,\
+	org.apache.ace.discovery.api;version=latest,\
+	org.apache.ace.scheduler.api;version=latest,\
+	org.apache.ace.connectionfactory;version=latest,\
+	org.apache.ace.authentication.api;version=latest,\
+	org.amdatu.mongo,\
+	com.mongodb
+
+-sub: *.bnd
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/build.xml
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/build.xml?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/build.xml (added)
+++ ace/trunk/org.apache.ace.log/build.xml Tue Apr  9 08:18:47 2013
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build"> 
+	<import file="../cnf/build.xml"/>
+</project>

Added: ace/trunk/org.apache.ace.log/listener.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/listener.bnd?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/listener.bnd (added)
+++ ace/trunk/org.apache.ace.log/listener.bnd Tue Apr  9 08:18:47 2013
@@ -0,0 +1,3 @@
+Private-Package: org.apache.ace.log.listener
+Bundle-Activator: org.apache.ace.log.listener.Activator
+Bundle-Version: 1.0.0

Added: ace/trunk/org.apache.ace.log/server.servlet.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/server.servlet.bnd?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/server.servlet.bnd (added)
+++ ace/trunk/org.apache.ace.log/server.servlet.bnd Tue Apr  9 08:18:47 2013
@@ -0,0 +1,3 @@
+Private-Package: org.apache.ace.log.server.servlet
+Bundle-Activator: org.apache.ace.log.server.servlet.Activator
+Bundle-Version: 1.0.0

Added: ace/trunk/org.apache.ace.log/server.store.api.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/server.store.api.bnd?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/server.store.api.bnd (added)
+++ ace/trunk/org.apache.ace.log/server.store.api.bnd Tue Apr  9 08:18:47 2013
@@ -0,0 +1 @@
+Export-Package: org.apache.ace.log.server.store
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/server.store.file.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/server.store.file.bnd?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/server.store.file.bnd (added)
+++ ace/trunk/org.apache.ace.log/server.store.file.bnd Tue Apr  9 08:18:47 2013
@@ -0,0 +1,3 @@
+Bundle-Activator: org.apache.ace.log.server.store.impl.Activator
+Private-Package: org.apache.ace.log.server.store.impl
+Bundle-Version: 1.0.0
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/server.store.mongo.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/server.store.mongo.bnd?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/server.store.mongo.bnd (added)
+++ ace/trunk/org.apache.ace.log/server.store.mongo.bnd Tue Apr  9 08:18:47 2013
@@ -0,0 +1,2 @@
+Private-Package: org.apache.ace.log.server.store.mongo
+Bundle-Activator: org.apache.ace.log.server.store.mongo.Activator
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/server.task.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/server.task.bnd?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/server.task.bnd (added)
+++ ace/trunk/org.apache.ace.log/server.task.bnd Tue Apr  9 08:18:47 2013
@@ -0,0 +1,3 @@
+Bundle-Version: 1.0.0
+Private-Package: org.apache.ace.log.server.task
+Bundle-Activator: org.apache.ace.log.server.task.Activator

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/AuditEvent.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/AuditEvent.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/AuditEvent.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/AuditEvent.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log;
+
+/**
+ * Audit log event. These events are recorded in the audit log, which keeps track of
+ * all life cycle events that occur on a target.
+ */
+public interface AuditEvent
+{
+
+    public static final String KEY_ID = "id";
+    public static final String KEY_NAME = "name";
+    public static final String KEY_VERSION = "version";
+    public static final String KEY_LOCATION = "location";
+    public static final String KEY_MSG = "msg";
+    public static final String KEY_TYPE = "type";
+    public static final String KEY_SUCCESS = "success";
+
+    public static final int BUNDLE_BASE = 0;
+
+    /**
+     * When a bundle is installed, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * <dt>name</dt>
+     * <dd>symbolic name (if present)</dd>
+     * <dt>version</dt>
+     * <dd>bundle version</dd>
+     * <dt>location</dt>
+     * <dd>bundle location</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_INSTALLED = (BUNDLE_BASE + 1);
+
+    /**
+     * When a bundle is resolved, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_RESOLVED = (BUNDLE_BASE + 2);
+
+    /**
+     * When a bundle is started, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_STARTED = (BUNDLE_BASE + 3);
+
+    /**
+     * When a bundle is stopped, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_STOPPED = (BUNDLE_BASE + 4);
+
+    /**
+     * When a bundle is unresolved, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_UNRESOLVED = (BUNDLE_BASE + 5);
+
+    /**
+     * When a bundle is updated, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * <dt>version</dt>
+     * <dd>bundle version</dd>
+     * <dt>location</dt>
+     * <dd>bundle location</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_UPDATED = (BUNDLE_BASE + 6);
+
+    /**
+     * When a bundle is uninstalled, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_UNINSTALLED = (BUNDLE_BASE + 7);
+
+    /**
+     * When a bundle is starting, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_STARTING = (BUNDLE_BASE + 8);
+
+    /**
+     * When a bundle is stopping, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier</dd>
+     * </dl>
+     */
+    public static final int BUNDLE_STOPPING = (BUNDLE_BASE + 9);
+
+
+
+    public static final int FRAMEWORK_BASE = 1000;
+
+    /**
+     * When a framework info message occurs, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier (if present)</dd>
+     * <dt>msg</dt>
+     * <dd>the error message (if present)</dd>
+     * <dt>type</dt>
+     * <dd>the fully qualified error type (if present)</dd>
+     * </dl>
+     */
+    public static final int FRAMEWORK_INFO = (FRAMEWORK_BASE + 1);
+
+    /**
+     * When a framework warning message occurs, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier (if present)</dd>
+     * <dt>msg</dt>
+     * <dd>the error message (if present)</dd>
+     * <dt>type</dt>
+     * <dd>the fully qualified error type (if present)</dd>
+     * </dl>
+     */
+    public static final int FRAMEWORK_WARNING = (FRAMEWORK_BASE + 2);
+
+    /**
+     * When a framework error message occurs, this event is logged with the following properties:
+     * <dl>
+     * <dt>id</dt>
+     * <dd>bundle identifier (if present)</dd>
+     * <dt>msg</dt>
+     * <dd>the error message (if present)</dd>
+     * <dt>type</dt>
+     * <dd>the fully qualified error type (if present)</dd>
+     * </dl>
+     */
+    public static final int FRAMEWORK_ERROR = (FRAMEWORK_BASE + 3);
+
+    /**
+     * When a framework refresh occurs, this event is logged.
+     */
+    public static final int FRAMEWORK_REFRESH = (FRAMEWORK_BASE + 4);
+
+    /**
+     * When a framework start occurs, this event is logged.
+     */
+    public static final int FRAMEWORK_STARTED = (FRAMEWORK_BASE + 5);
+
+    /**
+     * When a framework start level change occurs, this event is logged.
+     */
+    public static final int FRAMEWORK_STARTLEVEL = (FRAMEWORK_BASE + 6);
+
+    public static final int DEPLOYMENTADMIN_BASE = 2000;
+
+    /**
+     * When a deployment package is installed, this event is logged with the following properties:
+     * <dl>
+     * <dt>name</dt>
+     * <dd>deployment package symbolic name</dd>
+     * </dl>
+     */
+    public static final int DEPLOYMENTADMIN_INSTALL = (DEPLOYMENTADMIN_BASE + 1);
+
+    /**
+     * When a deployment package is uninstalled, this event is logged with the following properties:
+     * <dl>
+     * <dt>name</dt>
+     * <dd>deployment package symbolic name</dd>
+     * </dl>
+     */
+    public static final int DEPLOYMENTADMIN_UNINSTALL = (DEPLOYMENTADMIN_BASE + 2);
+
+    /**
+     * When a deployment package operation has completed, this event is logged with the following properties:
+     * <dl>
+     * <dt>name</dt>
+     * <dd>deployment package symbolic name</dd>
+     * <dt>success</dt>
+     * <dd>whether the operation was successful or not</dd>
+     * <dt>version</dt>
+     * <dd>deployment package version</dd>
+     * </dl>
+     */
+    public static final int DEPLOYMENTADMIN_COMPLETE = (DEPLOYMENTADMIN_BASE + 3);
+
+    public static final int DEPLOYMENTCONTROL_BASE = 3000;
+
+    /**
+     * Before a deployment package install begins, this event is logged with the following properties:
+     * <dl>
+     * <dt>url</dt>
+     * <dd>deployment package url</dd>
+     * <dt>version</dt>
+     * <dd>deployment package version</dd>
+     * </dl>
+     */
+    public static final int DEPLOYMENTCONTROL_INSTALL = (DEPLOYMENTCONTROL_BASE + 1);
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/Log.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/Log.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/Log.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/Log.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log;
+
+import java.util.Dictionary;
+
+/**
+ * Log interface for a fairly generic logging mechanism, where each log entry has a type
+ * and a dictionary of properties.
+ */
+public interface Log
+{
+    /**
+     * Logs a new message to the log.
+     *
+     * @param type
+     * @param properties
+     */
+    public void log(int type, Dictionary properties);
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogDescriptor.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogDescriptor.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogDescriptor.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogDescriptor.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log;
+
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+import org.apache.ace.range.SortedRangeSet;
+import org.apache.ace.log.util.Codec;
+
+/**
+ * Instances of this class represent a range of log events. Such a range is defined by:
+ * <ul>
+ * <li>A unique target ID</li>
+ * <li>A log ID unique for this target</li>
+ * <li>A set of event IDs</li>
+ * </ul>
+ */
+public class LogDescriptor {
+    private final SortedRangeSet m_rangeSet;
+    private final long m_logID;
+    private final String m_targetID;
+
+    /**
+     * Create a log event range.
+     *
+     * @param targetID The unique target ID
+     * @param logID The unique log ID for this target
+     * @param rangeSet The set of event IDs
+     */
+    public LogDescriptor(String targetID, long logID, SortedRangeSet rangeSet) {
+        m_targetID = targetID;
+        m_logID = logID;
+        m_rangeSet = rangeSet;
+    }
+
+    /**
+     * Create a log event range from a string representation. String representations
+     * should be formatted as "targetID,logID,eventIDs" where each substring is formatted
+     * using <code>Codec.encode(string)</code> method.
+     *
+     * Throws an <code>IllegalArgumentException</code> when the string representation is not correctly formatted.
+     *
+     * @param representation String representation of the log event range
+     */
+    public LogDescriptor(String representation) {
+        try {
+            StringTokenizer st = new StringTokenizer(representation, ",");
+            m_targetID = Codec.decode(st.nextToken());
+            m_logID = Long.parseLong(st.nextToken());
+            String rangeSet = "";
+            if (st.hasMoreTokens()) {
+                rangeSet = st.nextToken();
+            }
+            m_rangeSet = new SortedRangeSet(Codec.decode(rangeSet));
+        }
+        catch (NoSuchElementException e) {
+            throw new IllegalArgumentException("Could not create range from: " + representation);
+        }
+    }
+
+    /**
+     * Get the unique target identifier.
+     *
+     * @return Unique target identifier.
+     */
+    public String getTargetID() {
+        return m_targetID;
+    }
+
+    /**
+     * Get the unique log identifier for this target.
+     *
+     * @return Unique log identifier for this target.
+     */
+    public long getLogID() {
+        return m_logID;
+    }
+
+    /**
+     * Get the range set of the log event range.
+     *
+     * @return The range set
+     */
+    public SortedRangeSet getRangeSet() {
+        return m_rangeSet;
+    }
+
+    /**
+     * Get a string representation of the log event range. String representations
+     * generated by this method can be used to construct new <code>LogDescriptor</code> instances.
+     *
+     * @return A string representation of the log event range
+     */
+    public String toRepresentation() {
+        StringBuffer result = new StringBuffer();
+        result.append(Codec.encode(m_targetID));
+        result.append(',');
+        result.append(m_logID);
+        result.append(',');
+        result.append(Codec.encode(m_rangeSet.toRepresentation()));
+        return result.toString();
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogEvent.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogEvent.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogEvent.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogEvent.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import org.apache.ace.log.util.Codec;
+
+/**
+ * Log event from a specific target and log.
+ */
+public class LogEvent implements Comparable {
+    private final String m_targetID;
+    private final long m_logID;
+    private final long m_id;
+    private final long m_time;
+    private final int m_type;
+    private final Dictionary m_properties;
+
+    public LogEvent(String targetID, long logID, long id, long time, int type, Dictionary properties) {
+        m_targetID = targetID;
+        m_logID = logID;
+        m_id = id;
+        m_time = time;
+        m_type = type;
+        m_properties = properties;
+    }
+
+    public LogEvent(String targetID, LogEvent source) {
+        this(targetID, source.getLogID(), source.getID(), source.getTime(), source.getType(), source.getProperties());
+    }
+
+    public LogEvent(String representation) {
+        try {
+            StringTokenizer st = new StringTokenizer(representation, ",");
+            m_targetID = Codec.decode(st.nextToken());
+            m_logID = Long.parseLong(st.nextToken());
+            m_id = Long.parseLong(st.nextToken());
+            m_time = Long.parseLong(st.nextToken());
+            m_type = Integer.parseInt(st.nextToken());
+            m_properties = new Properties();
+            while (st.hasMoreTokens()) {
+                m_properties.put(st.nextToken(), Codec.decode(st.nextToken()));
+            }
+        }
+        catch (Exception e) {
+            throw new IllegalArgumentException(
+                "Could not create log event from: " + representation);
+        }
+    }
+
+    public String toRepresentation() {
+        StringBuffer result = new StringBuffer();
+        result.append(Codec.encode(m_targetID));
+        result.append(',');
+        result.append(m_logID);
+        result.append(',');
+        result.append(m_id);
+        result.append(',');
+        result.append(m_time);
+        result.append(',');
+        result.append(m_type);
+        Enumeration e = m_properties.keys();
+        while (e.hasMoreElements()) {
+            String key = (String) e.nextElement();
+            result.append(',');
+            result.append(key);
+            result.append(',');
+            result.append(Codec.encode((String) m_properties.get(key)));
+        }
+        return result.toString();
+    }
+
+    /**
+     * Returns the unique ID of the target that created this event.
+     */
+    public String getTargetID() {
+        return m_targetID;
+    }
+
+    /**
+     * Returns the unique log ID of the log. This ID is unique within a target.
+     */
+    public long getLogID() {
+        return m_logID;
+    }
+
+    /**
+     * Return the ID or sequence number of the event.
+     */
+    public long getID() {
+        return m_id;
+    }
+
+    /**
+     * Returns the timestamp of the event.
+     */
+    public long getTime() {
+        return m_time;
+    }
+
+    /**
+     * Returns the type of the event. Valid types are defined in this interface.
+     */
+    public int getType() {
+        return m_type;
+    }
+
+    /**
+     * Returns the properties of the event. Properties are restricted to simple key value pairs, only a couple of types are allowed: String, int, long, boolean (TODO what do we need?).
+     */
+    public Dictionary getProperties() {
+        return m_properties;
+    }
+
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (o instanceof LogEvent) {
+            LogEvent event = (LogEvent) o;
+            return m_targetID.equals(event.m_targetID)
+                && m_logID == event.m_logID && m_id == event.m_id;
+        }
+
+        return false;
+    }
+
+    public int hashCode() {
+        return (int) (m_targetID.hashCode() + m_logID + m_id);
+    }
+
+    public int compareTo(Object o) {
+        LogEvent e = (LogEvent) o;
+        final int cmp = m_targetID.compareTo(e.m_targetID);
+        if (cmp != 0) {
+            return cmp;
+        }
+        if (m_logID < e.m_logID) {
+            return -1;
+        }
+        if (m_logID > e.m_logID) {
+            return 1;
+        }
+        if (m_id < e.m_id) {
+            return -1;
+        }
+        if (m_id > e.m_id) {
+            return 1;
+        }
+        return 0;
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogSync.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogSync.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogSync.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/LogSync.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log;
+
+import java.io.IOException;
+
+/**
+ * Log synchronizing interface. It is intended to give direct access to the synchronizing
+ * possibilities of the server side log.
+ */
+public interface LogSync
+{
+
+    /**
+     * Pushes local changes and updates them in the remote repository.
+     * @throws java.io.IOException when there is an error communicating with the server.
+     * @return <code>true</code> when changes have been made the local log store,
+     * <code>false</code> otherwise.
+     */
+    public boolean push() throws IOException;
+
+    /**
+     * Pulls remote changes and updates them in the local repository.
+     * @throws java.io.IOException when there is an error communicating with the server.
+     * @return <code>true</code> when changes have been made the local log store,
+     * <code>false</code> otherwise.
+     */
+    public boolean pull() throws IOException;
+
+    /**
+     * Both pushes and pulls changes, and updates them in the both repositories.
+     * @throws java.io.IOException when there is an error communicating with the server.
+     * @return <code>true</code> when changes have been made the local log store,
+     * <code>false</code> otherwise.
+     */
+    public boolean pushpull() throws IOException;
+
+    /**
+     * Returns the name of the log 'channel' this log sync task is assigned to.
+     *
+     * @return The name of the log 'channel' this log sync task is assigned to.
+     */
+    public String getName();
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/Activator.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/Activator.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/Activator.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log.listener;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import org.apache.ace.log.Log;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * Activator for the bundle that listens to all life-cycle events, and logs them to the
+ * log service. The BundleEvents, FrameworkEvents and the events related to
+ * Deployment Packages are relevant for the audit log.
+ * <p>
+ * Furthermore this bundle takes care of the situation when the real log is not
+ * yet available within the framework, by using a cache that temporarily stores the
+ * log entries, and flushing those when the real log service comes up.
+ * BundleEvents and Framework events are always available, but events related to
+ * Deployment Packages will only be available when the EventAdmin is present.
+ */
+public class Activator implements BundleActivator {
+
+    private static final String LOG_NAME = "auditlog";
+
+    private final static String [] topics = new String[] { "org/osgi/service/deployment/*", "org/apache/ace/deployment/*" };
+    private ServiceTracker m_logTracker;
+    private ListenerImpl m_listener;
+
+    public synchronized void start(BundleContext context) throws Exception {
+        LogProxy logProxy = new LogProxy();
+        m_listener = new ListenerImpl(context, logProxy);
+        m_listener.startInternal();
+        // listen for bundle and framework events
+        context.addBundleListener(m_listener);
+        context.addFrameworkListener(m_listener);
+
+        // listen for deployment events
+        Dictionary dict = new Hashtable();
+        dict.put(EventConstants.EVENT_TOPIC, topics);
+        context.registerService(EventHandler.class.getName(), m_listener, dict);
+
+        // keep track of when the real log is available
+        ServiceTrackerCustomizer logTrackerCust = new LogTracker(context, logProxy);
+        m_logTracker = new ServiceTracker(context, context.createFilter("(&(" + Constants.OBJECTCLASS + "=" + Log.class.getName() + ")(name=" + LOG_NAME + "))"), logTrackerCust);
+        m_logTracker.open();
+    }
+
+    public synchronized void stop(BundleContext context) throws Exception {
+        // cleanup
+        m_logTracker.close();
+        context.removeFrameworkListener(m_listener);
+        context.removeBundleListener(m_listener);
+        m_listener.stopInternal();
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/ListenerImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/ListenerImpl.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/ListenerImpl.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/ListenerImpl.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log.listener;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+import org.apache.ace.log.AuditEvent;
+import org.apache.ace.log.Log;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.service.deploymentadmin.DeploymentAdmin;
+import org.osgi.service.deploymentadmin.DeploymentPackage;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * This class implements all listening actions to be done. It listens for BundleEvents, FrameworkEvents and events related to
+ * Deployment Packages. Whenever an event is received, it is transformed as defined in AuditEvent, and consequently logged in
+ * the AuditLog.
+ */
+public class ListenerImpl implements BundleListener, FrameworkListener, EventHandler {
+
+    private final String TOPIC_INSTALL = "org/osgi/service/deployment/INSTALL";
+    private final String TOPIC_UNINSTALL = "org/osgi/service/deployment/UNINSTALL";
+    private final String TOPIC_COMPLETE = "org/osgi/service/deployment/COMPLETE";
+
+    private final String TOPIC_DEPLOYMENTPACKAGE_INSTALL = "org/apache/ace/deployment/INSTALL";
+
+    volatile BundleContext m_context;
+    volatile Log m_auditLog;
+
+    private final List m_queue = new ArrayList();
+
+    public ListenerImpl(BundleContext context, Log log) {
+        m_context = context;
+        m_auditLog = log;
+    }
+
+    /**
+     * Whenever a BundleEvent is received, an event is logged on the AuditLog. The event details logged are first transformed as
+     * defined in AuditEvent before actually being logged.
+     */
+    public void bundleChanged(final BundleEvent event) {
+        synchronized (m_queue) {
+            m_queue.add(new Runnable() {
+                public void run() {
+                    int eventType = AuditEvent.BUNDLE_BASE;
+                    Properties props = new Properties();
+                    Bundle bundle = event.getBundle();
+                    props.put(AuditEvent.KEY_ID, Long.toString(bundle.getBundleId()));
+
+                    switch (event.getType()) {
+                        case BundleEvent.INSTALLED:
+                            eventType = AuditEvent.BUNDLE_INSTALLED;
+                            if (bundle.getSymbolicName() != null) {
+                                props.put(AuditEvent.KEY_NAME, bundle.getSymbolicName());
+                            }
+                            String version = (String) bundle.getHeaders().get(Constants.BUNDLE_VERSION);
+                            if (version != null) {
+                                props.put(AuditEvent.KEY_VERSION, version);
+                            }
+                            props.put(AuditEvent.KEY_LOCATION, bundle.getLocation());
+                            break;
+                        case BundleEvent.RESOLVED:
+                            eventType = AuditEvent.BUNDLE_RESOLVED;
+                            break;
+                        case BundleEvent.STARTED:
+                            eventType = AuditEvent.BUNDLE_STARTED;
+                            break;
+                        case BundleEvent.STOPPED:
+                            eventType = AuditEvent.BUNDLE_STOPPED;
+                            break;
+                        case BundleEvent.UNRESOLVED:
+                            eventType = AuditEvent.BUNDLE_UNRESOLVED;
+                            break;
+                        case BundleEvent.UPDATED:
+                            eventType = AuditEvent.BUNDLE_UPDATED;
+                            version = (String) bundle.getHeaders().get(Constants.BUNDLE_VERSION);
+                            if (version != null) {
+                                props.put(AuditEvent.KEY_VERSION, version);
+                            }
+                            props.put(AuditEvent.KEY_LOCATION, bundle.getLocation());
+                            break;
+                        case BundleEvent.UNINSTALLED:
+                            eventType = AuditEvent.BUNDLE_UNINSTALLED;
+                            break;
+                        case BundleEvent.STARTING:
+                            eventType = AuditEvent.BUNDLE_STARTING;
+                            break;
+                        case BundleEvent.STOPPING:
+                            eventType = AuditEvent.BUNDLE_STOPPING;
+                            break;
+                    }
+                    m_auditLog.log(eventType, props);
+                }
+            });
+            m_queue.notifyAll();
+        }
+    }
+
+    /**
+     * Whenever a FrameworkEvent is received, an event is logged on the AuditLog. The event details logged are first transformed
+     * as defined in AuditEvent before actually being logged.
+     */
+    public void frameworkEvent(final FrameworkEvent event) {
+        synchronized (m_queue) {
+            m_queue.add(new Runnable() {
+                public void run() {
+                    int eventType = AuditEvent.FRAMEWORK_BASE;
+                    Properties props = new Properties();
+                    Bundle bundle = event.getBundle();
+
+                    if (bundle != null) {
+                        props.put(AuditEvent.KEY_ID, Long.toString(bundle.getBundleId()));
+                    }
+
+                    String msg = null;
+                    String type = null;
+                    Throwable exception = event.getThrowable();
+                    if (exception != null) {
+                        msg = exception.getMessage();
+                        type = exception.getClass().getName();
+                    }
+
+                    switch (event.getType()) {
+                        case FrameworkEvent.INFO:
+                            eventType = AuditEvent.FRAMEWORK_INFO;
+                            if (msg != null) {
+                                props.put(AuditEvent.KEY_MSG, msg);
+                            }
+                            if (type != null) {
+                                props.put(AuditEvent.KEY_TYPE, type);
+                            }
+                            break;
+                        case FrameworkEvent.WARNING:
+                            eventType = AuditEvent.FRAMEWORK_WARNING;
+                            if (msg != null) {
+                                props.put(AuditEvent.KEY_MSG, msg);
+                            }
+                            if (type != null) {
+                                props.put(AuditEvent.KEY_TYPE, type);
+                            }
+                            break;
+                        case FrameworkEvent.ERROR:
+                            eventType = AuditEvent.FRAMEWORK_ERROR;
+                            if (msg != null) {
+                                props.put(AuditEvent.KEY_MSG, msg);
+                            }
+                            if (type != null) {
+                                props.put(AuditEvent.KEY_TYPE, type);
+                            }
+                            break;
+                        case FrameworkEvent.PACKAGES_REFRESHED:
+                            eventType = AuditEvent.FRAMEWORK_REFRESH;
+                            break;
+                        case FrameworkEvent.STARTED:
+                            eventType = AuditEvent.FRAMEWORK_STARTED;
+                            break;
+                        case FrameworkEvent.STARTLEVEL_CHANGED:
+                            eventType = AuditEvent.FRAMEWORK_STARTLEVEL;
+                            break;
+                    }
+                    m_auditLog.log(eventType, props);
+                }
+            });
+            m_queue.notifyAll();
+        }
+    }
+
+    /**
+     * Only expects events related to Deployment Packages. Whenever an event is received, the event is logged on the AuditLog.
+     * The event details logged are first transformed as defined in AuditEvent before actually being logged.
+     */
+    public void handleEvent(final Event event) {
+        synchronized (m_queue) {
+            m_queue.add(new Runnable() {
+                public void run() {
+                    int eventType = AuditEvent.DEPLOYMENTADMIN_BASE;
+                    Dictionary props = new Properties();
+
+                    String topic = event.getTopic();
+
+                    if (topic.equals(TOPIC_DEPLOYMENTPACKAGE_INSTALL)) {
+                        String url = (String) event.getProperty("deploymentpackage.url");
+                        String version = (String) event.getProperty("deploymentpackage.version");
+
+                        eventType = AuditEvent.DEPLOYMENTCONTROL_INSTALL;
+                        props.put(AuditEvent.KEY_VERSION, version);
+                        props.put(AuditEvent.KEY_NAME, url);
+                    }
+                    else if (topic.equals(TOPIC_INSTALL)) {
+                        String deplPackName = (String) event.getProperty("deploymentpackage.name");
+                        eventType = AuditEvent.DEPLOYMENTADMIN_INSTALL;
+                        props.put(AuditEvent.KEY_NAME, deplPackName);
+                    }
+
+                    else if (topic.equals(TOPIC_UNINSTALL)) {
+                        String deplPackName = (String) event.getProperty("deploymentpackage.name");
+                        eventType = AuditEvent.DEPLOYMENTADMIN_UNINSTALL;
+                        props.put(AuditEvent.KEY_NAME, deplPackName);
+                    }
+                    else if (topic.equals(TOPIC_COMPLETE)) {
+                        String deplPackName = (String) event.getProperty("deploymentpackage.name");
+
+                        // to retrieve the version, DeploymentAdmin has to be used
+                        ServiceReference ref = m_context.getServiceReference(DeploymentAdmin.class.getName());
+                        if (ref != null) {
+                            DeploymentAdmin deplAdmin = (DeploymentAdmin) m_context.getService(ref);
+                            if (deplAdmin != null) {
+                                DeploymentPackage dp = deplAdmin.getDeploymentPackage(deplPackName);
+                                if (dp != null) {
+                                    Version version = dp.getVersion();
+                                    if (version != null) {
+                                        props.put(AuditEvent.KEY_VERSION, version.toString());
+                                    }
+                                }
+                                // after use, release the service as is it not needed anymore
+                                m_context.ungetService(ref);
+                            }
+                        }
+
+                        eventType = AuditEvent.DEPLOYMENTADMIN_COMPLETE;
+                        props.put(AuditEvent.KEY_NAME, deplPackName);
+                        Boolean success = (Boolean) event.getProperty("successful");
+                        props.put(AuditEvent.KEY_SUCCESS, success.toString());
+                    }
+
+                    m_auditLog.log(eventType, props);
+                }
+            });
+            m_queue.notifyAll();
+        }
+    }
+
+    synchronized void startInternal() {
+        initInternal();
+        if (!m_thread.isAlive()) {
+            m_thread.start();
+        }
+    }
+
+    synchronized void stopInternal() {
+        if (m_thread != null) {
+            m_thread.interrupt();
+            try {
+                m_thread.join();
+            }
+            catch (InterruptedException e) {
+                // Not much we can do
+            }
+            m_thread = null;
+        }
+    }
+
+    private Thread m_thread = null;
+
+    synchronized void initInternal() {
+        if ((m_thread == null) || (!m_thread.isAlive())) {
+            m_thread = new Thread("AuditLogListenerThread") {
+                public void run() {
+
+                    Runnable next = null;
+                    do {
+                        synchronized (m_queue) {
+                            while (m_queue.isEmpty() && !isInterrupted()) {
+                                try {
+                                    m_queue.wait();
+                                }
+                                catch (InterruptedException ex) {
+                                    interrupt();
+                                }
+                            }
+                            if (!m_queue.isEmpty()) {
+                                next = (Runnable) m_queue.remove(0);
+                            }
+                            else {
+                                next = null;
+                            }
+                        }
+                        if (next != null) {
+                            try {
+                                next.run();
+                            }
+                            catch (Exception ex) {
+                                // Not much we can do
+                                // FIXME:
+                                ex.printStackTrace(System.err);
+                            }
+                        }
+                    }
+                    while (next != null);
+                }
+            };
+            m_thread.setDaemon(true);
+        }
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogCache.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogCache.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogCache.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogCache.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log.listener;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ace.log.Log;
+
+/**
+ * This cache is used whenever the real log service is not available. When
+ * the real log becomes available, all cached log entries should be flushed
+ * to the real log service and leaving the cache empty afterwards.
+ */
+public class LogCache implements Log {
+
+    private final List m_logEntries = new ArrayList();
+
+    /**
+     * Log the entry in the cache for flushing to the real log service later on.
+     */
+    public synchronized void log(int type, Dictionary properties) {
+        m_logEntries.add(new LogEntry(type, properties));
+    }
+
+    /**
+     * Flushes all cached log entries to the specified Log and leaves the cache empty
+     * after flushing. Will do nothing when a null is passed as parameter.
+     * @param log  The log service to flush the cached log entries to
+     */
+    public synchronized void flushTo(Log log) {
+        if (log != null) {
+            for (Iterator iterator = m_logEntries.iterator(); iterator.hasNext();) {
+                LogEntry entry = (LogEntry) iterator.next();
+                log.log(entry.getType(), entry.getProperties());
+            }
+            m_logEntries.clear();
+        }
+        else {
+            // do nothing, as you want to keep using the cache
+        }
+    }
+
+    private class LogEntry {
+        private int m_type;
+        private Dictionary m_properties;
+        public LogEntry(int type, Dictionary properties) {
+            m_type = type;
+            m_properties = properties;
+        }
+
+        public int getType() {
+            return m_type;
+        }
+
+        public Dictionary getProperties() {
+            return m_properties;
+        }
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogProxy.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogProxy.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogProxy.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogProxy.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log.listener;
+
+import java.util.Dictionary;
+import org.apache.ace.log.Log;
+
+/**
+ * Class responsible for being the object to talk to when trying to log events. This class
+ * will decide whether to log it to cache, or to the actual log.
+ */
+public class LogProxy implements Log {
+
+    private Log m_log;
+    private LogCache m_logCache;
+
+    public LogProxy() {
+        m_logCache = new LogCache();
+    }
+
+    /**
+     * Logs the log entry either to the real log service or to the cache, depending on
+     * whether the real service is available.
+     */
+    public synchronized void log(int type, Dictionary properties) {
+        if (m_log != null) {
+            m_log.log(type, properties);
+        }
+        else {
+            m_logCache.log(type, properties);
+        }
+    }
+
+    /**
+     * Sets the log, and flushes the cached log entries when a log service
+     * is passed into this method. When null is passed as parameter, the log service
+     * is not available anymore, and the cache should be used instead.
+     * @param log  the log service to use, when null the cache will be used instead
+     */
+    public synchronized void setLog(Log log) {
+        m_log = log;
+        // flush content of the cache to the real log
+        m_logCache.flushTo(m_log);
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogTracker.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogTracker.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogTracker.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/listener/LogTracker.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log.listener;
+
+import org.apache.ace.log.Log;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * Keep track of whether the log is available. If available, use the real log,
+ * else use the cache version. When the real log becomes available, flush all events
+ * from the cache to the real log.
+ *
+ */
+public class LogTracker implements ServiceTrackerCustomizer {
+
+    private BundleContext m_context;
+    private LogProxy m_proxy;
+
+    public LogTracker(BundleContext context, LogProxy proxy) {
+        m_context = context;
+        m_proxy = proxy;
+    }
+
+    /**
+     * Called when the log service has been added. As result, the real
+     * log service will be used instead of the cache.
+     */
+    public Object addingService(ServiceReference ref) {
+        // get the service based upon the reference, and return it
+        // make sure the real Log will be used, and all events in the
+        // cache are being flushed to the real Log.
+        Log externalLog = (Log) m_context.getService(ref);
+        m_proxy.setLog(externalLog);
+        return externalLog;
+    }
+
+    /**
+     * Called when the Log service is not available anymore. As result,
+     * the cache version of the Log will be used until the Log
+     * service is added again.
+     */
+    public void removedService(ServiceReference ref, Object log) {
+        // make sure the LogCache is used instead of the real Log
+        m_proxy.setLog(null);
+        // unget the service again
+        m_context.ungetService(ref);
+    }
+
+    public void modifiedService(ServiceReference ref, Object log) {
+        // do nothing
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/packageinfo
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/packageinfo?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/packageinfo (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/packageinfo Tue Apr  9 08:18:47 2013
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/Activator.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/Activator.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/Activator.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log.server.servlet;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.Servlet;
+
+import org.apache.ace.authentication.api.AuthenticationService;
+import org.apache.ace.log.server.store.LogStore;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.log.LogService;
+
+public class Activator extends DependencyActivatorBase implements ManagedServiceFactory {
+
+    private static final String KEY_LOG_NAME = "name";
+
+    /** A boolean denoting whether or not authentication is enabled. */
+    private static final String KEY_USE_AUTHENTICATION = "authentication.enabled";
+
+    private final Map<String, Component> m_instances = new HashMap<String, Component>(); // String -> Service
+    private DependencyManager m_manager;
+    private volatile LogService m_log;
+
+    @Override
+    public void init(BundleContext context, DependencyManager manager) throws Exception {
+        m_manager = manager;
+        Properties props = new Properties();
+        props.put(Constants.SERVICE_PID, "org.apache.ace.server.log.servlet.factory");
+        manager.add(createComponent()
+            .setInterface(ManagedServiceFactory.class.getName(), props)
+            .setImplementation(this)
+            .add(createServiceDependency().setService(LogService.class).setRequired(false)));    }
+
+    @Override
+    public void destroy(BundleContext context, DependencyManager manager) throws Exception {
+    }
+
+    public void deleted(String pid) {
+        Component log = m_instances.remove(pid);
+        if (log != null) {
+            m_manager.remove(log);
+        }
+    }
+
+    public String getName() {
+        return "Log Servlet Factory";
+    }
+
+    @SuppressWarnings("unchecked")
+    public void updated(String pid, Dictionary dict) throws ConfigurationException {
+        String name = (String) dict.get(KEY_LOG_NAME);
+        if ((name == null) || "".equals(name)) {
+            throw new ConfigurationException(KEY_LOG_NAME, "Log name has to be specified.");
+        }
+        
+        String useAuthString = (String) dict.get(KEY_USE_AUTHENTICATION);
+        if (useAuthString == null
+            || !("true".equalsIgnoreCase(useAuthString) || "false".equalsIgnoreCase(useAuthString))) {
+            throw new ConfigurationException(KEY_USE_AUTHENTICATION, "Missing or invalid value!");
+        }
+        boolean useAuth = Boolean.parseBoolean(useAuthString);
+
+        Component service = m_instances.get(pid);
+        if (service == null) {
+            service = m_manager.createComponent()
+                .setInterface(Servlet.class.getName(), dict)
+                .setImplementation(new LogServlet(name, useAuth))
+                .add(createServiceDependency().setService(AuthenticationService.class).setRequired(useAuth))
+                .add(createServiceDependency().setService(LogService.class).setRequired(false))
+                .add(createServiceDependency().setService(LogStore.class, "(&("+Constants.OBJECTCLASS+"="+LogStore.class.getName()+")(name=" + name + "))").setRequired(true));
+
+            m_instances.put(pid, service);
+            m_manager.add(service);
+        } else {
+            m_log.log(LogService.LOG_INFO, "Ignoring configuration update because factory instance was already configured: " + name);
+        }
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/LogServlet.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/LogServlet.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/LogServlet.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/servlet/LogServlet.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log.server.servlet;
+
+import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.ace.authentication.api.AuthenticationService;
+import org.apache.ace.log.LogDescriptor;
+import org.apache.ace.log.LogEvent;
+import org.apache.ace.log.server.store.LogStore;
+import org.apache.ace.range.SortedRangeSet;
+import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.User;
+
+/**
+ * This class acts as a servlet and handles the log protocol. This means a number of requests will be handled:
+ *
+ * The endpoint is configured externally, 'auditlog' is used as an example here.
+ *
+ * Querying existing audit log event id's:
+ * http://host:port/auditlog/query - Return all known event ranges
+ * http://host:port/auditlog/query?tid=myid&logid=123712636323 - Return the event range belonging to the specified target and log id
+ *
+ * Accepting new audit log events:
+ * http://host:port/auditlog/send - Gets a new log event and puts it in the store, the event is inside the request and should be a formatted as done in <code>LogEvent.toRepresentation()</code>.
+ *
+ * Querying existing audit log events:
+ * http://host:port/auditlog/receive - Return all known events
+ * http://host:port/auditlog/receive?tid=myid - Return all known events belonging to the specified target ID
+ * http://host:port/auditlog/receive?tid=myid&logid=2374623874 - Return all known events belonging to the specified target ID
+ *
+ * If the request is not correctly formatted or other problems arise error code <code>HttpServletResponse.SC_NOT_FOUND</code> will be sent in the response.
+ */
+public class LogServlet extends HttpServlet {
+
+    private static final long serialVersionUID = 1L;
+
+    // response mime type
+    private static final String TEXT_MIMETYPE = "text/plain";
+
+    // url path names available on the endpoint
+    private static final String QUERY = "/query";
+    private static final String SEND = "/send";
+    private static final String RECEIVE = "/receive";
+
+    // url parameter keys
+    private static final String TARGETID_KEY = "tid";
+    private static final String FILTER_KEY = "filter";
+    private static final String LOGID_KEY = "logid";
+    private static final String RANGE_KEY = "range";
+    
+    // injected by Dependency Manager
+    private volatile LogService m_log;
+    private volatile LogStore m_store;
+    private volatile AuthenticationService m_authService;
+
+    private final String m_name;
+    private final boolean m_useAuth;
+
+    public LogServlet(String name, boolean useAuth) {
+        m_name = name;
+        m_useAuth = useAuth;
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
+        // 'send' calls are POST calls
+        String path = request.getPathInfo();
+        response.setContentType(TEXT_MIMETYPE);
+        try {
+            if (SEND.equals(path) && !handleSend(request.getInputStream())) {
+                sendError(response, HttpServletResponse.SC_BAD_REQUEST, "Could not construct a log event for all events received");
+            }
+        }
+        catch (IOException e) {
+            sendError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error processing received log events");
+        }
+    }
+
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
+        // 'query' and 'receive' calls are GET calls
+
+        String path = request.getPathInfo();
+        String targetID = request.getParameter(TARGETID_KEY);
+        String logID = request.getParameter(LOGID_KEY);
+        String filter = request.getParameter(FILTER_KEY);
+        String range = request.getParameter(RANGE_KEY);
+
+        m_log.log(LogService.LOG_DEBUG, "Log servlet called: path(" + path + ") targetID(" + targetID + ") logID(" + logID + ") range( " + range + ") filter(" + filter +")");
+        response.setContentType(TEXT_MIMETYPE);
+
+        ServletOutputStream output = null;
+        try {
+            output = response.getOutputStream();
+            if (QUERY.equals(path) && !handleQuery(targetID, logID, filter, output)) {
+                sendError(response, HttpServletResponse.SC_BAD_REQUEST, "Unable to interpret query");
+            }
+            else if (RECEIVE.equals(path) && !handleReceive(targetID, logID, range, filter, output)) {
+                sendError(response, HttpServletResponse.SC_BAD_REQUEST, "Unable to interpret receive query");
+            }
+        }
+        catch (IOException e) {
+            sendError(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unable to process query");
+        }
+        finally {
+            try {
+                if (output != null) {
+                    output.close();
+                }
+            }
+            catch (Exception ex) {
+                m_log.log(LogService.LOG_WARNING, "Exception trying to close stream after request: " + request.getRequestURL(), ex);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        if (!authenticate(req)) {
+            // Authentication failed; don't proceed with the original request...
+            resp.sendError(SC_UNAUTHORIZED);
+        } else {
+            // Authentication successful, proceed with original request...
+            super.service(req, resp);
+        }
+    }
+
+    /**
+     * Authenticates, if needed the user with the information from the given request.
+     * 
+     * @param request the request to obtain the credentials from, cannot be <code>null</code>.
+     * @return <code>true</code> if the authentication was successful, <code>false</code> otherwise.
+     */
+    private boolean authenticate(HttpServletRequest request) {
+        if (m_useAuth) {
+            User user = m_authService.authenticate(request);
+            if (user == null) {
+                m_log.log(LogService.LOG_INFO, "Authentication failure!");
+            }
+            return (user != null);
+        }
+        return true;
+    }
+
+    // Handle a call to the query 'command'
+    protected boolean handleQuery(String targetID, String logID, String filter, ServletOutputStream output) throws IOException {
+        if ((targetID != null) && (logID != null)) {
+            // target and log id are specified, return only the range that matches these id's
+            LogDescriptor range = m_store.getDescriptor(targetID, Long.parseLong(logID));
+            output.print(range.toRepresentation());
+            return true;
+        }
+        else if ((targetID == null) && (logID == null)) {
+            // no target or log id has been specified, return all ranges
+            List<LogDescriptor> ranges = m_store.getDescriptors();
+            for (LogDescriptor range : ranges) {
+                output.print(range.toRepresentation() + "\n");
+            }
+            return true;
+        }
+        return false;
+    }
+
+    // Handle a call to the receive 'command'
+    protected boolean handleReceive(String targetID, String logID, String range, String filter, ServletOutputStream output) throws IOException {
+        if ((targetID != null) && (logID != null)) {
+            // target and log id are specified, return only the events that are in the range that matches these id's
+            if (range != null) {
+                LogDescriptor storeDescriptor = m_store.getDescriptor(targetID, Long.parseLong(logID));
+                outputRange(output, new LogDescriptor(storeDescriptor.getTargetID(), storeDescriptor.getLogID(), new SortedRangeSet(range)));
+            }
+            else {
+                outputRange(output, m_store.getDescriptor(targetID, Long.parseLong(logID)));
+            }
+            return true;
+        }
+        else if ((targetID != null) && (logID == null)) {
+            // target id is specified, log id is not, return all events that belong to the specified target id
+            List<LogDescriptor> descriptors = m_store.getDescriptors(targetID);
+            for (LogDescriptor descriptor : descriptors) {
+                outputRange(output, descriptor);
+            }
+            return true;
+        }
+        else if ((targetID == null) && (logID == null)) {
+            // no target or log id has been specified, return all events
+            List<LogDescriptor> descriptors = m_store.getDescriptors();
+            for (LogDescriptor descriptor : descriptors) {
+                outputRange(output, descriptor);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    // Handle a call to the send 'command'
+    protected boolean handleSend(ServletInputStream input) throws IOException {
+        List<LogEvent> events = new ArrayList<LogEvent>();
+        boolean success = true;
+
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new InputStreamReader(input));
+
+            String eventString;
+            while ((eventString = reader.readLine()) != null) {
+                try {
+                    m_log.log(LogService.LOG_DEBUG, "Log event received: '" + eventString +"'");
+                    LogEvent event = new LogEvent(eventString);
+                    events.add(event);
+                }
+                catch (IllegalArgumentException iae) {
+                    success = false;
+                    m_log.log(LogService.LOG_WARNING, "Could not construct LogEvent from string: '" + eventString + "'");
+                }
+            }
+        }
+        finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                }
+                catch (Exception ex) {
+                    // not much we can do
+                }
+            }
+        }
+        m_store.put(events);
+        return success;
+    }
+
+    // print string representations of all events in the specified range to the specified output
+    private void outputRange(ServletOutputStream output, LogDescriptor range) throws IOException {
+        List<LogEvent> events = m_store.get(range);
+        for (LogEvent event : events) {
+            output.print(event.toRepresentation() + "\n");
+        }
+    }
+
+    // send an error response
+    private void sendError(HttpServletResponse response, int statusCode, String description) {
+        m_log.log(LogService.LOG_WARNING, "Log request failed: " + description);
+        try {
+            response.sendError(statusCode, description);
+        }
+        catch (IOException e) {
+            m_log.log(LogService.LOG_WARNING, "Unable to send error response", e);
+        }
+    }
+
+    @Override
+    public String getServletInfo() {
+        return "Log Endpoint (channel=" + m_name + ")";
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/LogStore.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/LogStore.java?rev=1465924&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/LogStore.java (added)
+++ ace/trunk/org.apache.ace.log/src/org/apache/ace/log/server/store/LogStore.java Tue Apr  9 08:18:47 2013
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+package org.apache.ace.log.server.store;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.ace.log.LogDescriptor;
+import org.apache.ace.log.LogEvent;
+
+/**
+ * Log store interface. Implementation of this service interface provide a persisted storage for LogEvent logs.
+ */
+public interface LogStore
+{
+
+    /**
+     * Event topic that indicates a new LogEvent that has been added to the store. The name
+     * of the log is available as EVENT_PROP_LOGNAME, the original LogEvent as EVENT_PROP_LOG_EVENT.
+     */
+    public static final String EVENT_TOPIC = LogStore.class.getName().replace('.', '/') + "/LogEvent";
+
+    /**
+     * Event property key containing the name of the log on which the LogEvent has been added.
+     */
+    public static final String EVENT_PROP_LOGNAME = "name";
+
+    /**
+     * Event property key containing the LogEvent that has been added.
+     */
+    public static final String EVENT_PROP_LOG_EVENT = "logEvent";
+
+    /**
+     * Return all events in a given range.
+     *
+     * @param range the range to filter events by.
+     * @return a list of all events in this store that are in the given range.
+     * @throws java.io.IOException in case of any error.
+     */
+    public List<LogEvent> get(LogDescriptor range) throws IOException;
+
+    /**
+     * Get the range for the given id and the given log.
+     *
+     * @param targetID the id for which to return the log range.
+     * @param logID the log id for which to return the range.
+     * @return the range for the given id and the given log.
+     * @throws java.io.IOException in case of any error.
+     */
+    public LogDescriptor getDescriptor(String targetID, long logID) throws IOException;
+
+    /**
+     * Store the given events. The implementation does not have to be transactional i.e., it might throw an exception and still
+     * store part of the events. However, individual events should be either stored or not.
+     *
+     * @param events a list of events to store.
+     * @throws java.io.IOException in case of any error. It might be possible that only part of the events get stored.
+     */
+    public void put(List<LogEvent> events) throws IOException;
+
+    /**
+     * Get the ranges of all logs of the given id.
+     *
+     * @param targetID the id for which to return the log ranges.
+     * @return a list of the ranges of all logs for the given id.
+     * @throws java.io.IOException in case of any error.
+     */
+    public List<LogDescriptor> getDescriptors(String targetID) throws IOException;
+
+    /**
+     * Get the ranges of all logs of all ids in this store.
+     *
+     * @return a list of ranges of all logs for all ids in this store.
+     * @throws java.io.IOException in case of any error.
+     */
+    public List<LogDescriptor> getDescriptors() throws IOException;
+}
\ No newline at end of file



Mime
View raw message