TAMAYA-195: Added hazelcast support.

Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/commit/003dc040
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/tree/003dc040
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/diff/003dc040

Branch: refs/heads/master
Commit: 003dc040646632260dd3b55ab3fcb8316ea8bf24
Parents: a61f874
Author: anatole <[email protected]>
Authored: Sun Nov 13 22:52:42 2016 +0100
Committer: anatole <[email protected]>
Committed: Sun Nov 13 22:52:42 2016 +0100

----------------------------------------------------------------------
 hazelcast/pom.xml                               |  89 +++++++++
 .../hazelcast/HazelcastPropertySource.java      | 183 +++++++++++++++++++
 2 files changed, 272 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/003dc040/hazelcast/pom.xml
----------------------------------------------------------------------
diff --git a/hazelcast/pom.xml b/hazelcast/pom.xml
new file mode 100644
index 0000000..b150010
--- /dev/null
+++ b/hazelcast/pom.xml
@@ -0,0 +1,89 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing,
+  ~  software distributed under the License is distributed on an
+  ~  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~  KIND, either express or implied.  See the License for the
+  ~  specific language governing permissions and limitations
+  ~  under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.tamaya.ext</groupId>
+        <artifactId>tamaya-sandbox</artifactId>
+        <version>0.3-incubating-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+
+    <artifactId>tamaya-hazelcast</artifactId>
+    <name>Apache Tamaya Modules - Hazelcast PropertySource</name>
+    <packaging>bundle</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.tamaya.etcd
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>java-hamcrest</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya</groupId>
+            <artifactId>tamaya-core</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya</groupId>
+            <artifactId>tamaya-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-functions</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.hazelcast</groupId>
+            <artifactId>hazelcast</artifactId>
+            <version>3.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-mutable-config</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/003dc040/hazelcast/src/main/java/org/apache/tamaya/hazelcast/HazelcastPropertySource.java
----------------------------------------------------------------------
diff --git 
a/hazelcast/src/main/java/org/apache/tamaya/hazelcast/HazelcastPropertySource.java
 
b/hazelcast/src/main/java/org/apache/tamaya/hazelcast/HazelcastPropertySource.java
new file mode 100644
index 0000000..facd642
--- /dev/null
+++ 
b/hazelcast/src/main/java/org/apache/tamaya/hazelcast/HazelcastPropertySource.java
@@ -0,0 +1,183 @@
+/*
+ * 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.tamaya.hazelcast;
+
+import com.hazelcast.config.Config;
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.core.IList;
+import com.hazelcast.core.IMap;
+import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
+import org.apache.tamaya.mutableconfig.Refreshable;
+import org.apache.tamaya.mutableconfig.spi.MutablePropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+import org.apache.tamaya.spisupport.BasePropertySource;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Distributed Propertysource using a in-memory hazelcast cluster.
+ * Created by atsticks on 03.11.16.
+ *
+ * Basically all kind of property entris can be stored. Additionally this 
property source allows
+ * to pass additional meta-entries to control the TTL of the data in 
milliseconds. For illustration
+ * the following map will store {@code my.entry} with a TLL of 20000 
milliseconds (20 seconds) and
+ * store {@code my.otherEntry} with infinite lifetime (as long as the cluster 
is alive):
+ *
+ * {@code
+ *     my.entry=myvalue
+ *     _my.entry.ttl=20000
+ *     my.otherEntry=1234
+ * }
+ *
+ * By default a new hazelcast instance is created, but it is also possible to 
reuse an existing
+ * instance of pass a Hazelcast configuration instance.
+ */
+public class HazelcastPropertySource extends BasePropertySource
+implements Refreshable, MutablePropertySource{
+
+    private static final Logger LOG = 
Logger.getLogger(HazelcastPropertySource.class.getName());
+    private Map<String, String> configMap = new HashMap<>();
+    private HazelcastInstance hazelcastInstance;
+    private String mapReference = "tamaya.configuration";
+    private boolean readOnly = false;
+
+    public HazelcastPropertySource(){
+        super("Hazelcast");
+        this.hazelcastInstance = Hazelcast.newHazelcastInstance();
+    }
+
+    public HazelcastPropertySource(HazelcastInstance hazelcastInstance){
+        this("Hazelcast", hazelcastInstance);
+    }
+
+    public HazelcastPropertySource(String name){
+        super(name);
+        this.hazelcastInstance = Hazelcast.newHazelcastInstance();
+    }
+
+    public HazelcastPropertySource(String name, Config config){
+        super(name);
+        this.hazelcastInstance = Hazelcast.newHazelcastInstance(config);
+    }
+
+    public HazelcastPropertySource(String name, HazelcastInstance 
hazelcastInstance){
+        super(name);
+        this.hazelcastInstance = Objects.requireNonNull(hazelcastInstance);
+    }
+
+    public void setReadOnly(boolean readOnly){
+        this.readOnly = readOnly;
+    }
+
+    public boolean isReadOnly(){
+        return readOnly;
+    }
+
+    public void setMapReference(String mapReference){
+        this.mapReference = Objects.requireNonNull(mapReference);
+    }
+
+    public String getMapReference(){
+        return mapReference;
+    }
+
+    @Override
+    public PropertyValue get(String key) {
+        Config hcConfig = hazelcastInstance.getConfig();
+        String value = hcConfig.getProperty(key);
+        if(value==null){
+            return null;
+        }
+        return PropertyValue.builder(key, value, getName())
+                .addContextData("backend", "Hazelcast")
+                .addContextData("instance", hcConfig.getInstanceName())
+                .addContextData("mapReference", mapReference)
+                .build();
+    }
+
+    @Override
+    public Map<String, String> getProperties() {
+        return Collections.unmodifiableMap(this.configMap);
+    }
+
+    @Override
+    public boolean isScannable() {
+        return true;
+    }
+
+    @Override
+    public void refresh() {
+        IMap<String,String> config = hazelcastInstance.getMap(mapReference);
+        Map<String, String> configMap = new HashMap<>(config);
+        this.configMap = configMap;
+    }
+
+    @Override
+    public void applyChange(ConfigChangeRequest configChange) {
+        if(readOnly){
+            return;
+        }
+        IMap<String,String> config = hazelcastInstance.getMap(mapReference);
+        for(Map.Entry<String, String> en: 
configChange.getAddedProperties().entrySet()){
+            String metaVal = configChange.getAddedProperties().get("_" + 
en.getKey()+".ttl");
+            if(metaVal!=null){
+                try {
+                    long ms = Long.parseLong(metaVal);
+                    config.put(en.getKey(), en.getValue(), ms, 
TimeUnit.MILLISECONDS);
+                }catch(Exception e){
+                    LOG.log(Level.WARNING, "Failed to parse TTL in millis: " + 
metaVal +
+                            " for '"+ en.getKey()+"'", e);
+                    config.put(en.getKey(), en.getValue());
+                }
+            }else {
+                config.put(en.getKey(), en.getValue());
+            }
+        }
+        for(String key: configChange.getRemovedProperties()){
+            config.remove(key);
+        }
+        IList<String> taList = 
hazelcastInstance.getList("_tamaya.transactions");
+        taList.add(configChange.getTransactionID());
+        config.put("_tamaya.transaction.lastId", 
configChange.getTransactionID(), 1, TimeUnit.DAYS);
+        config.put("_tamaya.transaction.startedAt", 
String.valueOf(configChange.getStartedAt()), 1, TimeUnit.DAYS);
+        config.flush();
+        refresh();
+    }
+
+    @Override
+    public String toString() {
+        return "HazelcastPropertySource{" +
+                "\n  hazelcastInstance=" + hazelcastInstance +
+                "\n  name='" + getName() + '\'' +
+                "\n  mapReference='" + mapReference + '\'' +
+                "\n  readOnly=" + readOnly +
+                "\n}";
+    }
+
+    public HazelcastInstance getHazelcastInstance() {
+        return hazelcastInstance;
+    }
+}

Reply via email to