You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ss...@apache.org on 2013/11/08 17:37:30 UTC
git commit: first version of Zookeeper integration (MARMOTTA-354)
Updated Branches:
refs/heads/develop 1d40d1333 -> eea9f0944
first version of Zookeeper integration (MARMOTTA-354)
Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/eea9f094
Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/eea9f094
Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/eea9f094
Branch: refs/heads/develop
Commit: eea9f0944d2b6fff38424022ebdf318f0869355e
Parents: 1d40d13
Author: Sebastian Schaffert <ss...@apache.org>
Authored: Fri Nov 8 17:37:24 2013 +0100
Committer: Sebastian Schaffert <ss...@apache.org>
Committed: Fri Nov 8 17:37:24 2013 +0100
----------------------------------------------------------------------
launchers/marmotta-webapp/pom.xml | 5 +
.../backend/kiwi/KiWiStoreProvider.java | 23 ++-
.../main/resources/config-defaults.properties | 4 -
.../src/main/resources/kiwi-module.properties | 3 +
.../main/resources/web/admin/configuration.html | 42 ++--
.../src/main/resources/web/admin/console.html | 37 ++++
.../src/main/resources/web/admin/database.html | 63 +++---
.../resources/web/admin/js/widgets/database.js | 21 +-
.../core/api/config/ConfigurationService.java | 13 +-
.../config/ConfigurationServiceImpl.java | 36 +++-
platform/marmotta-zookeeper/pom.xml | 159 +++++++++++++++
.../zookeeper/api/ZookeeperService.java | 33 ++++
.../zookeeper/event/ZookeeperInitEvent.java | 28 +++
.../exception/ConfigurationException.java | 100 ++++++++++
.../listeners/ConfigurationListener.java | 177 +++++++++++++++++
.../services/ZookeeperServiceImpl.java | 193 +++++++++++++++++++
.../src/main/resources/META-INF/beans.xml | 28 +++
.../src/main/resources/kiwi-module.properties | 38 ++++
platform/pom.xml | 2 +
19 files changed, 938 insertions(+), 67 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/launchers/marmotta-webapp/pom.xml
----------------------------------------------------------------------
diff --git a/launchers/marmotta-webapp/pom.xml b/launchers/marmotta-webapp/pom.xml
index c048c35..4c5a0fe 100644
--- a/launchers/marmotta-webapp/pom.xml
+++ b/launchers/marmotta-webapp/pom.xml
@@ -221,6 +221,11 @@
<artifactId>marmotta-versioning-kiwi</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.marmotta</groupId>
+ <artifactId>marmotta-zookeeper</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<!--
<dependency>
<groupId>org.apache.marmotta</groupId>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/backends/marmotta-backend-kiwi/src/main/java/org/apache/marmotta/platform/backend/kiwi/KiWiStoreProvider.java
----------------------------------------------------------------------
diff --git a/platform/backends/marmotta-backend-kiwi/src/main/java/org/apache/marmotta/platform/backend/kiwi/KiWiStoreProvider.java b/platform/backends/marmotta-backend-kiwi/src/main/java/org/apache/marmotta/platform/backend/kiwi/KiWiStoreProvider.java
index 3419578..578ba78 100644
--- a/platform/backends/marmotta-backend-kiwi/src/main/java/org/apache/marmotta/platform/backend/kiwi/KiWiStoreProvider.java
+++ b/platform/backends/marmotta-backend-kiwi/src/main/java/org/apache/marmotta/platform/backend/kiwi/KiWiStoreProvider.java
@@ -58,7 +58,11 @@ import javax.inject.Inject;
@ApplicationScoped
public class KiWiStoreProvider implements StoreProvider {
- public static final String SPARQL_STRATEGY = "sparql.strategy";
+ public static final String SPARQL_STRATEGY = "sparql.strategy";
+ public static final String DATACENTER_ID = "database.datacenter.id";
+ public static final String FULLTEXT_ENABLED = "database.fulltext.enabled";
+ public static final String FULLTEXT_LANGUAGES = "database.fulltext.languages";
+ public static final String DEBUG_SLOWQUERIES = "database.debug.slowqueries";
@Inject
private Logger log;
@@ -94,13 +98,13 @@ public class KiWiStoreProvider implements StoreProvider {
String dbPass = configurationService.getStringConfiguration("database.password");
KiWiConfiguration configuration = new KiWiConfiguration("lmf", jdbcUrl, dbUser, dbPass, dialect, configurationService.getDefaultContext(), configurationService.getInferredContext());
- configuration.setQueryLoggingEnabled(configurationService.getBooleanConfiguration("database.debug.slowqueries", false));
+ configuration.setQueryLoggingEnabled(configurationService.getBooleanConfiguration(DEBUG_SLOWQUERIES, false));
configuration.setTripleBatchCommit(configurationService.getBooleanConfiguration("database.triples.batchcommit", true));
configuration.setTripleBatchSize(configurationService.getIntConfiguration("database.triples.batchsize", 10000));
- configuration.setDatacenterId(configurationService.getIntConfiguration("database.datacenter.id",0));
- configuration.setFulltextEnabled(configurationService.getBooleanConfiguration("database.fulltext.enabled", true));
- configuration.setFulltextLanguages(configurationService.getListConfiguration("database.fulltext.languages", ImmutableList.of("en")));
+ configuration.setDatacenterId(configurationService.getIntConfiguration(DATACENTER_ID,0));
+ configuration.setFulltextEnabled(configurationService.getBooleanConfiguration(FULLTEXT_ENABLED, true));
+ configuration.setFulltextLanguages(configurationService.getListConfiguration(FULLTEXT_LANGUAGES, ImmutableList.of("en")));
if("native".equalsIgnoreCase(configurationService.getStringConfiguration(SPARQL_STRATEGY))) {
return new KiWiSparqlSail(new KiWiStore(configuration));
@@ -142,7 +146,14 @@ public class KiWiStoreProvider implements StoreProvider {
}
public void configurationChanged(@Observes ConfigurationChangedEvent e) {
- if(e.containsChangedKey(SPARQL_STRATEGY)) {
+ if(e.containsChangedKey(SPARQL_STRATEGY) ||
+ e.containsChangedKey(DATACENTER_ID) ||
+ e.containsChangedKey(FULLTEXT_ENABLED) ||
+ e.containsChangedKey(FULLTEXT_LANGUAGES) ||
+ e.containsChangedKey(DEBUG_SLOWQUERIES)
+ ) {
+ log.info("KiWi backend configuration changed, re-initialising triple store");
+
sesameService.restart();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/backends/marmotta-backend-kiwi/src/main/resources/config-defaults.properties
----------------------------------------------------------------------
diff --git a/platform/backends/marmotta-backend-kiwi/src/main/resources/config-defaults.properties b/platform/backends/marmotta-backend-kiwi/src/main/resources/config-defaults.properties
index c39777f..9ff7f78 100644
--- a/platform/backends/marmotta-backend-kiwi/src/main/resources/config-defaults.properties
+++ b/platform/backends/marmotta-backend-kiwi/src/main/resources/config-defaults.properties
@@ -68,7 +68,3 @@ database.postgres.url = jdbc:postgresql://localhost:5432/lmf?prepareThreshold=3
database.mysql.driver = com.mysql.jdbc.Driver
database.mysql.url = jdbc:mysql://localhost:3306/lmf?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true
-# Hibernate-specific configuration for Oracle
-database.oracle.url = jdbc:oracle:thin:@//localhost:1521/XE
-database.oracle.driver = oracle.jdbc.OracleDriver
-
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/backends/marmotta-backend-kiwi/src/main/resources/kiwi-module.properties
----------------------------------------------------------------------
diff --git a/platform/backends/marmotta-backend-kiwi/src/main/resources/kiwi-module.properties b/platform/backends/marmotta-backend-kiwi/src/main/resources/kiwi-module.properties
index de7f308..0454b6c 100644
--- a/platform/backends/marmotta-backend-kiwi/src/main/resources/kiwi-module.properties
+++ b/platform/backends/marmotta-backend-kiwi/src/main/resources/kiwi-module.properties
@@ -37,5 +37,8 @@ adminpage.1.link=/admin/configuration.html
adminpage.2.title=Database
adminpage.2.link=/admin/database.html
+adminpage.3.title=Console
+adminpage.3.link=/admin/console.html
+
webservices=org.apache.marmotta.platform.backend.kiwi.DatabaseWebService
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/configuration.html
----------------------------------------------------------------------
diff --git a/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/configuration.html b/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/configuration.html
index afa5287..3957686 100644
--- a/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/configuration.html
+++ b/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/configuration.html
@@ -16,31 +16,37 @@
-->
<html>
<head>
+<title>Storage Backend: BigData</title>
+<script type="text/javascript">
+ var _SERVER_URL = "http://localhost:8080/LMF/";
+</script>
<!--###BEGIN_HEAD###-->
- <title>Core Module Configuration</title>
- <link type="text/css" rel="stylesheet" href="../../../../../../../marmotta-core/src/main/resources/web/public/js/widgets/configurator/style.css">
<script type="text/javascript" src="../../webjars/jquery/1.8.2/jquery.min.js"></script>
- <script type="text/javascript" src="js/widgets/database.js"></script>
+ <script type="text/javascript" src="../../core/public/js/widgets/configurator/configurator.js"></script>
+ <link rel="stylesheet" href="style.css" />
+ <link type="text/css" rel="stylesheet" href="../../core/public/js/widgets/configurator/style.css">
<script type="text/javascript">
jQuery(document).ready(function(){
- $('#lmf_database').lmf_database({host:_SERVER_URL});
+ var options = {
+ url : _SERVER_URL,
+ container : "kiwi_configurator",
+ prefix : 'database',
+ blacklist: ['database.type','database.url','database.user','database.password','database.h2.','database.postgres.','database.mysql.']
+ }
+ var configurator = new Configurator(options);
});
</script>
<!--###END_HEAD###-->
</head>
<body>
-<div id="main">
-<div id="contents">
-<!--###BEGIN_CONTENT###-->
-<h1>KiWi Storage Backend Configuration</h1>
- <p>
- Here you can configure the database options for the Marmotta KiWi Storage Backend.<br/>
- </p>
- <div id="lmf_database">
- <h4>Loading database manager</h4>
- </div>
-<!--###END_CONTENT###-->
-</div>
-</div>
+ <!--###BEGIN_CONTENT###-->
+ <h1>KiWi Backend Configuration</h1>
+ <p>
+ Here you can configure options offered by the KiWi triple store. The configuration currently contains:
+ </p>
+ <div id="kiwi_configurator">
+ <h4>Loading configurator</h4>
+ </div>
+ <!--###END_CONTENT###-->
</body>
-</html>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/console.html
----------------------------------------------------------------------
diff --git a/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/console.html b/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/console.html
new file mode 100644
index 0000000..87b6835
--- /dev/null
+++ b/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/console.html
@@ -0,0 +1,37 @@
+<!--
+
+ 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.
+
+-->
+<html>
+<head>
+ <!--###BEGIN_HEAD###-->
+ <title>Core Module</title>
+ <script type="text/javascript">
+ (function() {
+ window.open('../../database/');
+ })();
+ </script>
+ <!--###END_HEAD###-->
+</head>
+<body>
+<!--###BEGIN_CONTENT###-->
+<h1>Manage Marmotta database via web-interface</h1>
+<a href="../../database/" target="_blank">Open database administration page in new window.</a>
+<!--###END_CONTENT###-->
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/database.html
----------------------------------------------------------------------
diff --git a/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/database.html b/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/database.html
index 87b6835..afa5287 100644
--- a/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/database.html
+++ b/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/database.html
@@ -1,37 +1,46 @@
<!--
-
- 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.
-
--->
+ ~ 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.
+ -->
<html>
<head>
- <!--###BEGIN_HEAD###-->
- <title>Core Module</title>
+<!--###BEGIN_HEAD###-->
+ <title>Core Module Configuration</title>
+ <link type="text/css" rel="stylesheet" href="../../../../../../../marmotta-core/src/main/resources/web/public/js/widgets/configurator/style.css">
+ <script type="text/javascript" src="../../webjars/jquery/1.8.2/jquery.min.js"></script>
+ <script type="text/javascript" src="js/widgets/database.js"></script>
<script type="text/javascript">
- (function() {
- window.open('../../database/');
- })();
+ jQuery(document).ready(function(){
+ $('#lmf_database').lmf_database({host:_SERVER_URL});
+ });
</script>
- <!--###END_HEAD###-->
+<!--###END_HEAD###-->
</head>
<body>
+<div id="main">
+<div id="contents">
<!--###BEGIN_CONTENT###-->
-<h1>Manage Marmotta database via web-interface</h1>
-<a href="../../database/" target="_blank">Open database administration page in new window.</a>
+<h1>KiWi Storage Backend Configuration</h1>
+ <p>
+ Here you can configure the database options for the Marmotta KiWi Storage Backend.<br/>
+ </p>
+ <div id="lmf_database">
+ <h4>Loading database manager</h4>
+ </div>
<!--###END_CONTENT###-->
+</div>
+</div>
</body>
-</html>
\ No newline at end of file
+</html>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/js/widgets/database.js
----------------------------------------------------------------------
diff --git a/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/js/widgets/database.js b/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/js/widgets/database.js
index 42efb8e..6a0029c 100644
--- a/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/js/widgets/database.js
+++ b/platform/backends/marmotta-backend-kiwi/src/main/resources/web/admin/js/widgets/database.js
@@ -15,6 +15,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+function endsWith(str, suffix) {
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+}
+
(function( $ ){
$.fn.lmf_database = function(options) {
var settings = {
@@ -103,13 +108,15 @@
var values = [];
var databases = new Array();
for(var property in data) {
- property = property.substring(property.indexOf('.')+1);
- property = property.substring(0,property.indexOf('.'));
- if(property!="") {
- if($.inArray(property,databases)==-1) {
- databases.push(property);
- }
- }
+ if(endsWith(property,"url")) {
+ property = property.substring(property.indexOf('.')+1);
+ property = property.substring(0,property.indexOf('.'));
+ if(property!="") {
+ if($.inArray(property,databases)==-1) {
+ databases.push(property);
+ }
+ }
+ }
}
getDBType(databases,new Array());
});
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/api/config/ConfigurationService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/api/config/ConfigurationService.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/api/config/ConfigurationService.java
index 58fdab7..6a00235 100644
--- a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/api/config/ConfigurationService.java
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/api/config/ConfigurationService.java
@@ -20,7 +20,6 @@ package org.apache.marmotta.platform.core.api.config;
import org.apache.commons.configuration.Configuration;
import javax.servlet.ServletContext;
-
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -539,4 +538,16 @@ public interface ConfigurationService {
boolean isInitialising();
void setInitialising(boolean initialising);
+
+
+ /**
+ * Return the context parameter, servlet init parameter, or system property with the given key. This method
+ * provides unified access to properties configured in either the web.xml, the context.xml or via a system property
+ * passed on startup. It can be used by services that cannot read their configuration from the main
+ * system-config.properties.
+ *
+ * @param key
+ * @return
+ */
+ String getContextParam(String key);
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/config/ConfigurationServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/config/ConfigurationServiceImpl.java b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/config/ConfigurationServiceImpl.java
index c42a019..6b9e567 100644
--- a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/config/ConfigurationServiceImpl.java
+++ b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/services/config/ConfigurationServiceImpl.java
@@ -64,7 +64,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
@ApplicationScoped
public class ConfigurationServiceImpl implements ConfigurationService {
- private String home;
+ private String home;
private static Logger log = LoggerFactory.getLogger(ConfigurationService.class);
@@ -176,13 +176,13 @@ public class ConfigurationServiceImpl implements ConfigurationService {
if(!f3.exists()) {
f3.mkdirs();
}
-
+
// ensure directory for importing data
File f4 = new File(getHome() + File.separator + DIR_IMPORT);
if(!f4.exists()) {
f4.mkdirs();
}
-
+
}
// the save configuration will be in the home directory
@@ -299,7 +299,7 @@ public class ConfigurationServiceImpl implements ConfigurationService {
log.info("Apache Marmotta Configuration Service: initialisation completed");
configurationInitEvent.fire(new ConfigurationServiceInitEvent());
-
+
} finally {
lock.writeLock().unlock();
}
@@ -991,6 +991,7 @@ public class ConfigurationServiceImpl implements ConfigurationService {
if (!initialising) {
+ log.debug("firing configuration changed event for key {}", key);
configurationEvent.fire(new ConfigurationChangedEvent(key));
}
}
@@ -1018,6 +1019,8 @@ public class ConfigurationServiceImpl implements ConfigurationService {
Preconditions.checkNotNull(key);
Preconditions.checkState(initialised,"ConfigurationService not yet initialised; call initialise() manually");
+ log.debug("setting configuration {} = {}", key, value);
+
if(!config.containsKey(key) || !ObjectUtils.equals(value,config.getString(key))) {
lock.writeLock().lock();
@@ -1036,6 +1039,7 @@ public class ConfigurationServiceImpl implements ConfigurationService {
if (!initialising) {
+ log.debug("firing configuration changed event for key {}", key);
configurationEvent.fire(new ConfigurationChangedEvent(key));
}
}
@@ -1452,4 +1456,28 @@ public class ConfigurationServiceImpl implements ConfigurationService {
}
}
+ /**
+ * Return the context parameter, servlet init parameter, or system property with the given key. This method
+ * provides unified access to properties configured in either the web.xml, the context.xml or via a system property
+ * passed on startup. It can be used by services that cannot read their configuration from the main
+ * system-config.properties.
+ *
+ * @param key
+ * @return
+ */
+ @Override
+ public String getContextParam(String key) {
+ String value = System.getProperty(key);
+ if(value == null) {
+ if(servletContext != null) {
+ value = servletContext.getInitParameter(key);
+
+ if(value == null) {
+ value = servletContext.getAttribute(key) != null ? servletContext.getAttribute(key).toString() : null;
+ }
+
+ }
+ }
+ return value;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-zookeeper/pom.xml
----------------------------------------------------------------------
diff --git a/platform/marmotta-zookeeper/pom.xml b/platform/marmotta-zookeeper/pom.xml
new file mode 100644
index 0000000..0f4152e
--- /dev/null
+++ b/platform/marmotta-zookeeper/pom.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.marmotta</groupId>
+ <artifactId>marmotta-parent</artifactId>
+ <version>3.2.0-incubating-SNAPSHOT</version>
+ <relativePath>../../parent</relativePath>
+ </parent>
+
+ <artifactId>marmotta-zookeeper</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Apache Marmotta Platform: Zookeeper</name>
+ <description>
+ This module provides integration with Apache Zookeeper for cloud configuration management of clusters of
+ Marmotta installations.
+ </description>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin> <!-- generate JRebel Configuration -->
+ <groupId>org.zeroturnaround</groupId>
+ <artifactId>jrebel-maven-plugin</artifactId>
+ <version>1.1.3</version>
+ <executions>
+ <execution>
+ <id>generate-rebel-xml</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <relativePath>../../</relativePath>
+ <rootPath>$${rebel.root}</rootPath>
+ <classpath>
+ <resources>
+ <resource><!-- default resource --></resource>
+ <resource><directory>src/main/resources</directory></resource>
+ </resources>
+ </classpath>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.marmotta</groupId>
+ <artifactId>buildinfo-maven-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <systemProperty>user.name</systemProperty>
+ <systemProperty>user.timezone</systemProperty>
+ <systemProperty>java.vm.vendor</systemProperty>
+ <systemProperty>java.vm.version</systemProperty>
+ <systemProperty>java.vm.name</systemProperty>
+ <systemProperty>java.runtime.version</systemProperty>
+ <systemProperty>os.name</systemProperty>
+ <systemProperty>os.version</systemProperty>
+ <systemProperty>os.arch</systemProperty>
+ </systemProperties>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>extract</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <executions>
+ <!--
+ <execution>
+ <id>aggregate</id>
+ <goals>
+ <goal>aggregate</goal>
+ </goals>
+ <phase>site</phase>
+ </execution>
+ -->
+ <execution>
+ <!-- configure how the REST API documentation will be produced -->
+ <id>restapi</id>
+ <configuration>
+ <doclet>com.lunatech.doclets.jax.jaxrs.JAXRSDoclet</doclet>
+
+ <name>REST API</name>
+ <description>REST API for LMF Webservices</description>
+
+ <outputDirectory>${project.build.outputDirectory}/doc</outputDirectory>
+ <reportOutputDirectory>${project.build.outputDirectory}/web/doc</reportOutputDirectory>
+ <destDir>rest</destDir>
+
+ <docletArtifact>
+ <groupId>com.lunatech.jax-doclets</groupId>
+ <artifactId>doclets</artifactId>
+ <version>0.10.0</version>
+ </docletArtifact>
+ <additionalparam>
+ -jaxrscontext {BASE}
+ -charset UTF-8
+ </additionalparam>
+
+ <!--
+ <stylesheetfile>${project.parent.basedir}/config/doc/doclet.css</stylesheetfile>
+ -->
+
+ <header><![CDATA[<!--###BEGIN_CONTENT###--><div class="javadoc">]]></header>
+ <footer><![CDATA[</div><!--###END_CONTENT###-->]]></footer>
+ <encoding>UTF-8</encoding>
+ <detectOfflineLinks>false</detectOfflineLinks>
+
+ <!-- For the project-reports page -->
+ </configuration>
+ <goals>
+ <goal>javadoc</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.marmotta</groupId>
+ <artifactId>marmotta-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>at.salzburgresearch.nodekeeper</groupId>
+ <artifactId>nodekeeper-java</artifactId>
+ <version>1.0</version>
+
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.fileinstall</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/api/ZookeeperService.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/api/ZookeeperService.java b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/api/ZookeeperService.java
new file mode 100644
index 0000000..b28b14e
--- /dev/null
+++ b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/api/ZookeeperService.java
@@ -0,0 +1,33 @@
+/*
+ * 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.marmotta.platform.zookeeper.api;
+
+/**
+ * Add file description here!
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public interface ZookeeperService {
+
+ public static final String ZK_SERVER = "zookeeper.server";
+ public static final String ZK_TIMEOUT = "zookeeper.timeout";
+ public static final String ZK_INSTANCE = "zookeeper.instance";
+ public static final String ZK_CLUSTER = "zookeeper.cluster";
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/event/ZookeeperInitEvent.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/event/ZookeeperInitEvent.java b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/event/ZookeeperInitEvent.java
new file mode 100644
index 0000000..cf7c904
--- /dev/null
+++ b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/event/ZookeeperInitEvent.java
@@ -0,0 +1,28 @@
+/*
+ * 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.marmotta.platform.zookeeper.event;
+
+/**
+ * Thrown when Zookeeper connection is initialised.
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class ZookeeperInitEvent {
+ public ZookeeperInitEvent() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/exception/ConfigurationException.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/exception/ConfigurationException.java b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/exception/ConfigurationException.java
new file mode 100644
index 0000000..03ba686
--- /dev/null
+++ b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/exception/ConfigurationException.java
@@ -0,0 +1,100 @@
+/*
+ * 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.marmotta.platform.zookeeper.exception;
+
+/**
+ * Add file description here!
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class ConfigurationException extends Exception {
+
+ /**
+ * Constructs a new exception with {@code null} as its detail message.
+ * The cause is not initialized, and may subsequently be initialized by a
+ * call to {@link #initCause}.
+ */
+ public ConfigurationException() {
+ }
+
+ /**
+ * Constructs a new exception with the specified cause and a detail
+ * message of <tt>(cause==null ? null : cause.toString())</tt> (which
+ * typically contains the class and detail message of <tt>cause</tt>).
+ * This constructor is useful for exceptions that are little more than
+ * wrappers for other throwables (for example, {@link
+ * java.security.PrivilegedActionException}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public ConfigurationException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message. The
+ * cause is not initialized, and may subsequently be initialized by
+ * a call to {@link #initCause}.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ */
+ public ConfigurationException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause. <p>Note that the detail message associated with
+ * {@code cause} is <i>not</i> automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public ConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message,
+ * cause, suppression enabled or disabled, and writable stack
+ * trace enabled or disabled.
+ *
+ * @param message the detail message.
+ * @param cause the cause. (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @param enableSuppression whether or not suppression is enabled
+ * or disabled
+ * @param writableStackTrace whether or not the stack trace should
+ * be writable
+ * @since 1.7
+ */
+ public ConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/listeners/ConfigurationListener.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/listeners/ConfigurationListener.java b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/listeners/ConfigurationListener.java
new file mode 100644
index 0000000..ffbf52f
--- /dev/null
+++ b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/listeners/ConfigurationListener.java
@@ -0,0 +1,177 @@
+/*
+ * 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.marmotta.platform.zookeeper.listeners;
+
+import at.salzburgresearch.nodekeeper.NodeKeeper;
+import at.salzburgresearch.nodekeeper.NodeListener;
+import at.salzburgresearch.nodekeeper.exception.NodeKeeperException;
+import at.salzburgresearch.nodekeeper.model.Node;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.zookeeper.api.ZookeeperService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * Add file description here!
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class ConfigurationListener extends NodeListener<String> {
+
+ private static Logger log = LoggerFactory.getLogger(ConfigurationListener.class);
+
+ private ConfigurationService configurationService;
+
+ public ConfigurationListener(ConfigurationService configurationService, NodeKeeper nodekeeper) {
+ this.configurationService = configurationService;
+ this.nodekeeper = nodekeeper;
+ }
+
+ @Override
+ public void onNodeCreated(Node<String> node) {
+ ConfigurationLevel level = getConfigurationLevel(node);
+
+ String key = node.getPath().substring(node.getPath().lastIndexOf("/")+1);
+ String value = node.getData();
+
+ try {
+ // look if there is a more specific existing configuration; if yes, issue a message and return
+ for(ConfigurationLevel existing : new ConfigurationLevel[]{ConfigurationLevel.GLOBAL, ConfigurationLevel.CLUSTER, ConfigurationLevel.INSTANCE}) {
+ if(existing.compareTo(level) > 0) {
+ String exvalue = getConfiguration(key,existing);
+ if(exvalue != null) {
+ log.info("ZOOKEEPER: ignoring configuration option {}, because there is a more specific configuration on level {}", key, existing);
+ return;
+ }
+ }
+ }
+
+ log.info("ZOOKEEPER: setting configuration option {} = {}", key, value);
+ configurationService.setConfiguration(key,value);
+ } catch (InterruptedException | NodeKeeperException | IOException e) {
+ log.error("ZOOKEEPER: error reading Zookeeper configuration",e);
+ }
+ }
+
+ @Override
+ public void onNodeUpdated(Node<String> node) {
+ onNodeCreated(node);
+ }
+
+ @Override
+ public void onNodeDeleted(Node<String> node) {
+ ConfigurationLevel level = getConfigurationLevel(node);
+ String key = node.getPath().substring(node.getPath().lastIndexOf("/")+1);
+
+ try {
+ // look if there is a more specific existing configuration; if yes, issue a message and return
+ for(ConfigurationLevel existing : new ConfigurationLevel[]{ConfigurationLevel.GLOBAL, ConfigurationLevel.CLUSTER, ConfigurationLevel.INSTANCE}) {
+ if(existing.compareTo(level) > 0) {
+ String exvalue = getConfiguration(key,existing);
+ if(exvalue != null) {
+ log.info("ZOOKEEPER: ignoring delete option {}, because there is a more specific configuration on level {}", key, existing);
+ return;
+ }
+ }
+ }
+
+ // look if there is a more generic existing configuration; if yes, use this configuration instead and return
+ for(ConfigurationLevel existing : new ConfigurationLevel[]{ConfigurationLevel.INSTANCE, ConfigurationLevel.CLUSTER, ConfigurationLevel.GLOBAL}) {
+ if(existing.compareTo(level) < 0) {
+ String exvalue = getConfiguration(key,existing);
+ if(exvalue != null) {
+ log.info("ZOOKEEPER: iupdating option {} to its more generic value {} at level {}", key, exvalue, existing);
+ configurationService.setConfiguration(key,exvalue);
+ return;
+ }
+ }
+ }
+
+
+ log.info("ZOOKEEPER: deleting configuration option {}", key);
+ configurationService.removeConfiguration(key);
+ } catch (InterruptedException | NodeKeeperException | IOException e) {
+ log.error("ZOOKEEPER: error reading Zookeeper configuration",e);
+ }
+ }
+
+ @Override
+ public Class<String> getType() {
+ return String.class;
+ }
+
+ /**
+ * Return the configuration value for the given key at the given level if it exists, or return null otherwise.
+ *
+ * @param key
+ * @param level
+ * @return
+ */
+ private String getConfiguration(String key, ConfigurationLevel level) throws InterruptedException, IOException, NodeKeeperException {
+ String uuid = configurationService.getStringConfiguration(ZookeeperService.ZK_INSTANCE, UUID.randomUUID().toString());
+ String cluster = configurationService.getStringConfiguration(ZookeeperService.ZK_CLUSTER, "default");
+
+ String path;
+ switch (level) {
+ case INSTANCE:
+ path = String.format("/marmotta/clusters/%s/instances/%s/config/%s", cluster, uuid, key);
+ break;
+ case CLUSTER:
+ path = String.format("/marmotta/clusters/%s/config/%s", cluster, key);
+ break;
+ default:
+ path = String.format("/marmotta/config/%s", key);
+ break;
+ }
+
+ Node<String> node = nodekeeper.readNode(path, String.class);
+
+ if(node != null) {
+ return node.getData();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the configuration level of the node
+ *
+ * @param node
+ * @return
+ */
+ private ConfigurationLevel getConfigurationLevel(Node<String> node) {
+ if(node.getPath().contains("instances")) {
+ return ConfigurationLevel.INSTANCE;
+ } else if(node.getPath().contains("clusters")) {
+ return ConfigurationLevel.CLUSTER;
+ } else {
+ return ConfigurationLevel.GLOBAL;
+ }
+ }
+
+ /**
+ * Used for representing the different levels at which a configuration event can happen; if there is an
+ * INSTANCE level configuration, it will override CLUSTER and GLOBAL and so on.
+ */
+ private static enum ConfigurationLevel {
+ GLOBAL, CLUSTER, INSTANCE
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/services/ZookeeperServiceImpl.java
----------------------------------------------------------------------
diff --git a/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/services/ZookeeperServiceImpl.java b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/services/ZookeeperServiceImpl.java
new file mode 100644
index 0000000..4370c69
--- /dev/null
+++ b/platform/marmotta-zookeeper/src/main/java/org/apache/marmotta/platform/zookeeper/services/ZookeeperServiceImpl.java
@@ -0,0 +1,193 @@
+/*
+ * 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.marmotta.platform.zookeeper.services;
+
+import at.salzburgresearch.nodekeeper.NodeKeeper;
+import at.salzburgresearch.nodekeeper.exception.NodeKeeperException;
+import org.apache.commons.lang.StringUtils;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.events.ConfigurationServiceInitEvent;
+import org.apache.marmotta.platform.zookeeper.api.ZookeeperService;
+import org.apache.marmotta.platform.zookeeper.event.ZookeeperInitEvent;
+import org.apache.marmotta.platform.zookeeper.listeners.ConfigurationListener;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs;
+import org.slf4j.Logger;
+
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Event;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Any;
+import javax.inject.Inject;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.UUID;
+
+/**
+ * Add file description here!
+ *
+ * @author Sebastian Schaffert (sschaffert@apache.org)
+ */
+@ApplicationScoped
+public class ZookeeperServiceImpl implements ZookeeperService {
+
+ @Inject
+ private Logger log;
+
+ @Inject
+ private ConfigurationService configurationService;
+
+ @Inject
+ @Any
+ private Event<ZookeeperInitEvent> zookeeperInitEvent;
+
+ private NodeKeeper nodeKeeper;
+
+ private Properties properties;
+
+
+ public void initialise(@Observes ConfigurationServiceInitEvent event) throws IOException, InterruptedException {
+ log.warn("Activating Marmotta Zookeeper Bridge");
+
+ //read configuration
+ final String connectionString = configurationService.getContextParam(ZK_SERVER);
+
+ if(connectionString != null) {
+
+ log.info(" - connection string: {}",connectionString);
+
+ this.properties = new Properties();
+ File nkProperties = new File(configurationService.getHome() + File.separator + "nodekeeper.properties");
+ if(nkProperties.exists()) {
+ properties.load(new FileInputStream(nkProperties));
+ }
+
+ // get instance id (if not configured), first try from context parameters, if not given create random
+ if(StringUtils.isBlank(configurationService.getStringConfiguration(ZK_INSTANCE))) {
+ String instanceId;
+ if(StringUtils.isBlank(configurationService.getContextParam(ZK_INSTANCE))) {
+ instanceId = UUID.randomUUID().toString();
+ } else {
+ instanceId = configurationService.getContextParam(ZK_INSTANCE);
+ }
+
+ configurationService.setConfiguration(ZK_INSTANCE, instanceId);
+ }
+
+ // get cluster name (if not configured), first try from context parameters, if not given use "default"
+ if(StringUtils.isBlank(configurationService.getStringConfiguration(ZK_CLUSTER))) {
+ String clusterId;
+ if(StringUtils.isBlank(configurationService.getContextParam(ZK_CLUSTER))) {
+ clusterId = "default";
+ } else {
+ clusterId = configurationService.getContextParam(ZK_CLUSTER);
+ }
+
+ configurationService.setConfiguration(ZK_CLUSTER, clusterId);
+ }
+
+
+ log.info(" - initialize nodekeeper connection for instance {} (cluster {})",configurationService.getStringConfiguration(ZK_INSTANCE), configurationService.getStringConfiguration(ZK_CLUSTER));
+
+
+
+ try {
+ nodeKeeper = new NodeKeeper(connectionString,configurationService.getIntConfiguration(ZK_TIMEOUT, 60000),properties, null);
+
+ initZooKeeper();
+
+ String uuid = configurationService.getStringConfiguration(ZK_INSTANCE, UUID.randomUUID().toString());
+ String cluster = configurationService.getStringConfiguration(ZK_CLUSTER, "default");
+
+ ConfigurationListener listener = new ConfigurationListener(configurationService, nodeKeeper);
+
+ nodeKeeper.addListener("/marmotta/config/[^/]+", listener );
+ nodeKeeper.addListener(String.format("/marmotta/clusters/%s/config/[^/]+", cluster), listener );
+ nodeKeeper.addListener(String.format("/marmotta/clusters/%s/instances/%s/config/[^/]+", cluster, uuid), listener );
+
+ nodeKeeper.startListeners();
+
+ log.info("... running");
+
+ zookeeperInitEvent.fire(new ZookeeperInitEvent());
+ } catch (KeeperException ex) {
+ log.error("could not initialise Zookeeper: {}", ex.getMessage());
+ } catch (NodeKeeperException e) {
+ log.error("could not initialise NodeKeeper: {}", e.getMessage());
+ }
+ } else {
+ log.warn("no Zookeeper servers configured, Zookeeper Integration not available");
+ }
+
+ }
+
+ @PreDestroy
+ private void shutdown() throws InterruptedException, IOException {
+ log.info("deactivating Zookeeper Bridge ...");
+ if(nodeKeeper != null) {
+ log.info(" - closing nodekeeper connection");
+ nodeKeeper.shutdown();
+ log.info(" ... closed");
+ }
+ File nkProperties = new File(configurationService.getHome() + File.separator + "nodekeeper.properties");
+ properties.store(new FileOutputStream(nkProperties), "automatic nodekeeper state");
+ }
+
+ /**
+ * init zookeeper if necessary
+ * @throws org.apache.zookeeper.KeeperException
+ * @throws InterruptedException
+ */
+ private void initZooKeeper() throws KeeperException, InterruptedException, IOException {
+
+ if (nodeKeeper == null || nodeKeeper.getZooKeeper() == null) {
+ log.error("ZooKeeper not available");
+ } else {
+ String uuid = configurationService.getStringConfiguration(ZK_INSTANCE, UUID.randomUUID().toString());
+ String cluster = configurationService.getStringConfiguration(ZK_CLUSTER, "default");
+
+ //create base paths
+ createNodeIfNotExists("/marmotta");
+ createNodeIfNotExists("/marmotta/config");
+
+ createNodeIfNotExists("/marmotta/clusters");
+ createNodeIfNotExists(String.format("/marmotta/clusters/%s", cluster));
+ createNodeIfNotExists(String.format("/marmotta/clusters/%s/config", cluster));
+
+ createNodeIfNotExists(String.format("/marmotta/clusters/%s/instances", cluster));
+ createNodeIfNotExists(String.format("/marmotta/clusters/%s/instances/%s", cluster, uuid));
+ createNodeIfNotExists(String.format("/marmotta/clusters/%s/instances/%s/config", cluster, uuid));
+ }
+ }
+
+
+ private void createNodeIfNotExists(String path) throws KeeperException, InterruptedException {
+ if (nodeKeeper.getZooKeeper().exists(path,false) == null) {
+ String uuid = configurationService.getStringConfiguration(ZK_INSTANCE, UUID.randomUUID().toString());
+
+ nodeKeeper.getZooKeeper().create(path,new String("creator:"+uuid).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-zookeeper/src/main/resources/META-INF/beans.xml
----------------------------------------------------------------------
diff --git a/platform/marmotta-zookeeper/src/main/resources/META-INF/beans.xml b/platform/marmotta-zookeeper/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..461858e
--- /dev/null
+++ b/platform/marmotta-zookeeper/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+
+</beans>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/marmotta-zookeeper/src/main/resources/kiwi-module.properties
----------------------------------------------------------------------
diff --git a/platform/marmotta-zookeeper/src/main/resources/kiwi-module.properties b/platform/marmotta-zookeeper/src/main/resources/kiwi-module.properties
new file mode 100644
index 0000000..dd81f71
--- /dev/null
+++ b/platform/marmotta-zookeeper/src/main/resources/kiwi-module.properties
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+name=Zookeeper Integration
+
+container=Cloud
+container.weight = 10
+
+subtitle = Configure Zookeeper
+weight = 10
+
+icon_small = /admin/img/config_small.png
+
+#do not change!!!
+baseurl=/zookeeper
+
+adminpage.0.title=About
+adminpage.0.link=/admin/about.html
+
+adminpage.1.title=Configuration
+adminpage.1.link=/admin/configuration.html
+
+
+webservices=
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/eea9f094/platform/pom.xml
----------------------------------------------------------------------
diff --git a/platform/pom.xml b/platform/pom.xml
index 4561bc5..20f3325 100644
--- a/platform/pom.xml
+++ b/platform/pom.xml
@@ -70,6 +70,8 @@
<module>marmotta-reasoner-kiwi</module>
<module>marmotta-versioning-kiwi</module>
+ <!-- Cloud Integration -->
+ <module>marmotta-zookeeper</module>
</modules>