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
|