http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/etcd/src/test/java/org/apache/tamaya/etcd/EtcdAccessorTest.java ---------------------------------------------------------------------- diff --git a/modules/etcd/src/test/java/org/apache/tamaya/etcd/EtcdAccessorTest.java b/modules/etcd/src/test/java/org/apache/tamaya/etcd/EtcdAccessorTest.java new file mode 100644 index 0000000..630a028 --- /dev/null +++ b/modules/etcd/src/test/java/org/apache/tamaya/etcd/EtcdAccessorTest.java @@ -0,0 +1,116 @@ +/* + * 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.etcd; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.net.MalformedURLException; +import java.util.Map; +import java.util.UUID; + +import static org.junit.Assert.*; + +/** + * Tests for the etcd backend integration. You must have setCurrent a system property so, theses tests are executed, e.g. + * {@code -Detcd.url=http://127.0.0.1:4001}. + */ +public class EtcdAccessorTest { + + private static EtcdAccessor accessor; + static boolean execute = false; + + @BeforeClass + public static void setup() throws MalformedURLException { + accessor = new EtcdAccessor("http://192.168.99.105:4001"); + if(!accessor.getVersion().contains("etcd")){ + System.out.println("Disabling etcd tests, etcd not accessible at: " + System.getProperty("etcd.server.urls")); + System.out.println("Configure etcd with -Detcd.server.urls=http://<IP>:<PORT>"); + } + else{ + execute = true; + } + } + + @Test + public void testGetVersion() throws Exception { + if(!execute)return; + assertEquals(accessor.getVersion(), "etcd 0.4.9"); + } + + @Test + public void testGet() throws Exception { + if(!execute)return; + Map<String,String> result = accessor.get("test1"); + assertNotNull(result); + } + + @Test + public void testSetNormal() throws Exception { + if(!execute)return; + String value = UUID.randomUUID().toString(); + Map<String,String> result = accessor.set("testSetNormal", value); + assertNull(result.get("_testSetNormal.ttl")); + assertEquals(value, accessor.get("testSetNormal").get("testSetNormal")); + } + + @Test + public void testSetNormal2() throws Exception { + if(!execute)return; + String value = UUID.randomUUID().toString(); + Map<String,String> result = accessor.set("testSetNormal2", value, null); + assertNull(result.get("_testSetNormal2.ttl")); + assertEquals(value, accessor.get("testSetNormal2").get("testSetNormal2")); + } + + @Test + public void testSetWithTTL() throws Exception { + if(!execute)return; + String value = UUID.randomUUID().toString(); + Map<String,String> result = accessor.set("testSetWithTTL", value, 1); + assertNotNull(result.get("_testSetWithTTL.ttl")); + assertEquals(value, accessor.get("testSetWithTTL").get("testSetWithTTL")); + Thread.sleep(2000L); + result = accessor.get("testSetWithTTL"); + assertNull(result.get("testSetWithTTL")); + } + + @Test + public void testDelete() throws Exception { + if(!execute)return; + String value = UUID.randomUUID().toString(); + Map<String,String> result = accessor.set("testDelete", value, null); + assertEquals(value, accessor.get("testDelete").get("testDelete")); + assertNotNull(result.get("_testDelete.createdIndex")); + result = accessor.delete("testDelete"); + assertEquals(value, result.get("_testDelete.prevNode.createValue")); + assertNull(accessor.get("testDelete").get("testDelete")); + } + + @Test + public void testGetProperties() throws Exception { + if(!execute)return; + String value = UUID.randomUUID().toString(); + accessor.set("testGetProperties1", value); + Map<String,String> result = accessor.getProperties(""); + assertNotNull(result); + assertEquals(value, result.get("testGetProperties1")); + assertNotNull(result.get("_testGetProperties1.createdIndex")); + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/etcd/src/test/java/org/apache/tamaya/etcd/EtcdPropertySourceTest.java ---------------------------------------------------------------------- diff --git a/modules/etcd/src/test/java/org/apache/tamaya/etcd/EtcdPropertySourceTest.java b/modules/etcd/src/test/java/org/apache/tamaya/etcd/EtcdPropertySourceTest.java new file mode 100644 index 0000000..8b6569f --- /dev/null +++ b/modules/etcd/src/test/java/org/apache/tamaya/etcd/EtcdPropertySourceTest.java @@ -0,0 +1,75 @@ +/* + * 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.etcd; + +import org.apache.tamaya.spi.PropertyValue; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +/** + * Created by atsticks on 07.01.16. + */ +public class EtcdPropertySourceTest { + + private final EtcdPropertySource propertySource = new EtcdPropertySource(); + + @BeforeClass + public static void setup(){ + System.setProperty("etcd.server.urls", "http://8.8.8.8:4001,http://192.168.99.105:4001"); + } + + @Test + public void testGetOrdinal() throws Exception { + assertEquals(1000, propertySource.getOrdinal()); + } + + @Test + public void testGetDefaultOrdinal() throws Exception { + assertEquals(1000, propertySource.getDefaultOrdinal()); + } + + @Test + public void testGetName() throws Exception { + assertEquals("etcd", propertySource.getName()); + } + + @Test + public void testGet() throws Exception { + Map<String,PropertyValue> props = propertySource.getProperties(); + for(Map.Entry<String,PropertyValue> en:props.entrySet()){ + assertNotNull("Key not found: " + en.getKey(), propertySource.get(en.getKey())); + } + } + + @Test + public void testGetProperties() throws Exception { + Map<String,PropertyValue> props = propertySource.getProperties(); + assertNotNull(props); + } + + @Test + public void testIsScannable() throws Exception { + assertTrue(propertySource.isScannable()); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/hazelcast/bnd.bnd ---------------------------------------------------------------------- diff --git a/modules/hazelcast/bnd.bnd b/modules/hazelcast/bnd.bnd new file mode 100644 index 0000000..22db283 --- /dev/null +++ b/modules/hazelcast/bnd.bnd @@ -0,0 +1,29 @@ +-buildpath: \ + osgi.annotation; version=6.0.0,\ + osgi.core; version=6.0,\ + osgi.cmpn; version=6.0 + +-testpath: \ + ${junit} + +javac.source: 1.8 +javac.target: 1.8 + +Automatic-Module-Name: org.apache.tamaya.hazelcast +Bundle-Version: ${version}.${tstamp} +Bundle-Name: Apache Tamaya - Hazelcast Config +Bundle-SymbolicName: org.apache.tamaya.hazelcast +Bundle-Description: Apacha Tamaya Config - Hazelcast PropertySource +Bundle-Category: Implementation +Bundle-Copyright: (C) Apache Foundation +Bundle-License: Apache Licence version 2 +Bundle-Vendor: Apache Software Foundation +Bundle-ContactAddress: [email protected] +Bundle-DocURL: http://tamaya.apache.org +Export-Package: \ + org.apache.tamaya.hazelcast +Import-Package: \ + org.apache.tamaya,\ + org.apache.tamaya.spi +Export-Service: \ + org.apache.tamaya.spi.PropertySource http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/hazelcast/pom.xml ---------------------------------------------------------------------- diff --git a/modules/hazelcast/pom.xml b/modules/hazelcast/pom.xml new file mode 100644 index 0000000..af7bced --- /dev/null +++ b/modules/hazelcast/pom.xml @@ -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. + --> +<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.4-incubating-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + + <artifactId>tamaya-hazelcast</artifactId> + <name>Apache Tamaya Modules - Hazelcast PropertySource</name> + <packaging>jar</packaging> + + <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.parent.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-api</artifactId> + <version>${project.parent.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-functions</artifactId> + <version>${project.parent.version}</version> + </dependency> + <dependency> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-spisupport</artifactId> + <version>${project.parent.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.parent.version}</version> + <scope>provided</scope> + <optional>true</optional> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/hazelcast/src/main/java/org/apache/tamaya/hazelcast/AbstractHazelcastPropertySource.java ---------------------------------------------------------------------- diff --git a/modules/hazelcast/src/main/java/org/apache/tamaya/hazelcast/AbstractHazelcastPropertySource.java b/modules/hazelcast/src/main/java/org/apache/tamaya/hazelcast/AbstractHazelcastPropertySource.java new file mode 100644 index 0000000..117bb2c --- /dev/null +++ b/modules/hazelcast/src/main/java/org/apache/tamaya/hazelcast/AbstractHazelcastPropertySource.java @@ -0,0 +1,238 @@ +/* + * 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.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.spi.MutablePropertySource; +import org.apache.tamaya.spi.PropertyValue; +import org.apache.tamaya.spisupport.propertysource.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.concurrent.atomic.AtomicLong; +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 getMeta-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 abstract class AbstractHazelcastPropertySource extends BasePropertySource +implements MutablePropertySource{ + /** The logger. */ + private static final Logger LOG = Logger.getLogger(AbstractHazelcastPropertySource.class.getName()); + /** The Hazelcast config map used. */ + private Map<String, PropertyValue> configMap = new HashMap<>(); + /** The hazelcast map reference ID used, by default {@code tamaya.configuration}. */ + private String mapReference = "tamaya.configuration"; + /** Flag if this property source is read-only. */ + private boolean readOnly = false; + + private AtomicLong timeoutDuration = new AtomicLong(TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES)); + + private AtomicLong timeout = new AtomicLong(); + + /** + * Creates a new instance, hereby using {@code "Hazelcast"} as property source name and + * a default hazelcast backend created by calling {@link Hazelcast#newHazelcastInstance()}. + */ + public AbstractHazelcastPropertySource(){ + super("Hazelcast"); + } + + /** + * Creates a new instance, hereby using the given property source name and + * a default hazelcast backend created by calling {@link Hazelcast#newHazelcastInstance()}. + * @param name the property source name, not null. + */ + public AbstractHazelcastPropertySource(String name){ + super(name); + } + + /** + * Get the current timeout, when a reload will be triggered on access. + * @return the current timeout, or 0 if no data has been loaded at all. + */ + public long getValidUntil(){ + return timeout.get(); + } + + /** + * Get the current cache timeout. + * @return the timeout duration after which data will be reloaded. + */ + public long getCachePeriod(){ + return timeoutDuration.get(); + } + + /** + * Set the duration after which the data cache will be reloaded. + * @param millis the millis + */ + public void setCacheTimeout(long millis){ + this.timeoutDuration.set(millis); + this.refresh(); + } + + + /** + * Setting the read-only flag for this instance. + * @param readOnly if true, the property source will not write back any changes to the + * hazelcast backend. + */ + public void setReadOnly(boolean readOnly){ + this.readOnly = readOnly; + } + + /** + * Flag to check if the property source is read-only. + * @return true, if the instance is read-only. + */ + public boolean isReadOnly(){ + return readOnly; + } + + /** + * Set the Hazelcast reference name for the Tamaya configuration Map. + * @param mapReference the map reference to be used, not null. + */ + public void setMapReference(String mapReference){ + if (!Objects.equals(mapReference, this.mapReference)) { + this.mapReference = Objects.requireNonNull(mapReference); + refresh(); + } + } + + /** + * Get the Hazelcast reference name for the Tamaya configuration Map. + * @return the Hazelcast reference name for the Tamaya configuration Map, never null. + */ + public String getMapReference(){ + return mapReference; + } + + /** + * Get access to the hazelcast instance used. + * @return the hazelcast instance, not null. + */ + protected abstract HazelcastInstance getHazelcastInstance(); + + @Override + public PropertyValue get(String key) { + checkRefresh(); + return this.configMap.get(key); + } + + @Override + public Map<String, PropertyValue> getProperties() { + checkRefresh(); + return this.configMap; + } + + /** + * Checks for a cache timeout and optionally reloads the data. + */ + public void checkRefresh(){ + if(this.timeout.get() < System.currentTimeMillis()){ + refresh(); + } + } + + /** + * Reloads the configuration map from Hazelcast completely. + */ + public void refresh() { + IMap<String,String> config = getHazelcastInstance().getMap(mapReference); + Map<String, PropertyValue> configMap = new HashMap<>(); + config.entrySet().forEach(en -> { + configMap.put(en.getKey(), + PropertyValue.createValue(en.getKey(), en.getValue()) + .setMeta("source", getName()) + .setMeta("backend", "Hazelcast") + .setMeta("instance", getHazelcastInstance().getName()) + .setMeta("mapReference", mapReference) + .immutable()); + }); + this.timeout.set(System.currentTimeMillis() + timeoutDuration.get()); + this.configMap = Collections.unmodifiableMap(configMap); + } + + @Override + public void applyChange(ConfigChangeRequest configChange) { + if(readOnly){ + return; + } + IMap<String,String> config = getHazelcastInstance().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 = getHazelcastInstance().getList("[META]tamaya.transactions"); + taList.add(configChange.getTransactionID()); + config.put("[META]tamaya.transaction.lastId", configChange.getTransactionID(), 1, TimeUnit.DAYS); + config.put("[META]tamaya.transaction.startedAt", String.valueOf(configChange.getStartedAt()), 1, TimeUnit.DAYS); + config.flush(); + refresh(); + } + + @Override + protected String toStringValues() { + return super.toStringValues() + + "\n hazelcastInstance=" + getHazelcastInstance() + + "\n name='" + getName() + '\'' + + "\n mapReference='" + mapReference + '\'' + + "\n readOnly=" + readOnly + '\''; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/hazelcast/src/main/java/org/apache/tamaya/hazelcast/HazelcastPropertySource.java ---------------------------------------------------------------------- diff --git a/modules/hazelcast/src/main/java/org/apache/tamaya/hazelcast/HazelcastPropertySource.java b/modules/hazelcast/src/main/java/org/apache/tamaya/hazelcast/HazelcastPropertySource.java new file mode 100644 index 0000000..58b3617 --- /dev/null +++ b/modules/hazelcast/src/main/java/org/apache/tamaya/hazelcast/HazelcastPropertySource.java @@ -0,0 +1,119 @@ +/* + * 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.spi.MutablePropertySource; +import org.apache.tamaya.spi.PropertyValue; +import org.apache.tamaya.spisupport.propertysource.BasePropertySource; + +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 getMeta-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 AbstractHazelcastPropertySource { + + /** The hazelcast API instance. */ + private HazelcastInstance hazelcastInstance; + + /** + * Creates a new instance, hereby using {@code "Hazelcast"} as property source name and + * a default hazelcast backend created by calling {@link Hazelcast#newHazelcastInstance()}. + */ + public HazelcastPropertySource(){ + this.hazelcastInstance = Hazelcast.newHazelcastInstance(); + } + + /** + * Creates a new instance, hereby using {@code "Hazelcast"} as property source name and the + * given hazelcast instance. + * @param hazelcastInstance the hazelcast instance, not null. + */ + public HazelcastPropertySource(HazelcastInstance hazelcastInstance){ + this("Hazelcast", hazelcastInstance); + } + + /** + * Creates a new instance, hereby using the given property source name and + * a default hazelcast backend created by calling {@link Hazelcast#newHazelcastInstance()}. + * @param name the property source name, not null. + */ + public HazelcastPropertySource(String name){ + super(name); + this.hazelcastInstance = Hazelcast.newHazelcastInstance(); + } + + /** + * Creates a new instance, hereby using the given property source name and + * a creating a new hazelcast backend using the given Hazelcast {@link Config}. + * @param config the hazelcast config, not null. + * @param name the property source name, not null. + */ + public HazelcastPropertySource(String name, Config config){ + super(name); + this.hazelcastInstance = Hazelcast.newHazelcastInstance(config); + } + + /** + * Creates a new instance, hereby using the given property source name and the + * hazelcast instance. + * @param name the property source name, not null. + * @param hazelcastInstance the hazelcast instance, not null. + */ + public HazelcastPropertySource(String name, HazelcastInstance hazelcastInstance){ + super(name); + this.hazelcastInstance = Objects.requireNonNull(hazelcastInstance); + } + + /** + * Get access to the hazelcast instance used. + * @return the hazelcast instance, not null. + */ + @Override + public HazelcastInstance getHazelcastInstance() { + return hazelcastInstance; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/AbstractHzPropertySourceTest.java ---------------------------------------------------------------------- diff --git a/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/AbstractHzPropertySourceTest.java b/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/AbstractHzPropertySourceTest.java new file mode 100644 index 0000000..57d4e59 --- /dev/null +++ b/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/AbstractHzPropertySourceTest.java @@ -0,0 +1,207 @@ +/* + * 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.core.HazelcastInstance; +import com.hazelcast.core.IMap; +import org.apache.tamaya.spi.PropertyValue; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Created by atsticks on 03.11.16. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class AbstractHzPropertySourceTest { + + private static HazelcastInstance hz = HazelcastUtil.getHazelcastInstance(); + private AbstractHazelcastPropertySource hps = new AbstractHazelcastPropertySource() { + @Override + protected HazelcastInstance getHazelcastInstance() { + return HazelcastUtil.getHazelcastInstance(); + } + }; + + @BeforeClass + public static void start() { + IMap<Object, Object> map = hz.getMap("config"); + map.put("k1", "v1"); + map.put("k2", "v2"); + map.put("tamaya.ordinal", "2000"); + map.flush(); + IMap<Object, Object> map2 = hz.getMap("config2"); + map2.put("key1", "val1"); + map2.put("key2", "val2"); + map2.flush(); + } + + @org.junit.Test + public void t01_testGetProperties(){ + hps.setMapReference("config"); + Map<String, PropertyValue> values = hps.getProperties(); + assertNotNull(values); + assertEquals(3, values.size()); + assertNotNull(values.get("k1")); + assertNotNull(values.get("k2")); + assertEquals("v1", values.get("k1").getValue()); + assertEquals("v2", values.get("k2").getValue()); + assertEquals(hps.getOrdinal(), 2000); + + hps.setMapReference("config2"); + Map<String, PropertyValue> values2 = hps.getProperties(); + assertNotNull(values2); + assertEquals(2, values2.size()); + assertNotNull(values2.get("key1")); + assertNotNull(values2.get("key2")); + assertEquals("val1", values2.get("key1").getValue()); + assertEquals("val2", values2.get("key2").getValue()); + assertEquals(hps.getOrdinal(), 0); + + hps.setMapReference("foo"); + hps.setDefaultOrdinal(1500); + Map<String, PropertyValue> values3 = hps.getProperties(); + assertNotNull(values3); + assertEquals(0, values3.size()); + assertEquals(hps.getOrdinal(), 1500); + } + + @org.junit.Test + public void t02_testGetOrdinal(){ + hps.setMapReference("config"); + hps.setDefaultOrdinal(1500); + assertEquals(1500, hps.getDefaultOrdinal()); + assertEquals(hps.getOrdinal(), 2000); + + hps.setMapReference("config2"); + hps.setDefaultOrdinal(0); + assertEquals(0, hps.getDefaultOrdinal()); + assertEquals(hps.getOrdinal(), 0); + + hps.setMapReference("foo"); + hps.setDefaultOrdinal(1500); + assertEquals(1500, hps.getDefaultOrdinal()); + assertEquals(hps.getOrdinal(), 1500); + } + + @org.junit.Test + public void t03_tesGet(){ + hps.setMapReference("config"); + PropertyValue val1 = hps.get("k1"); + assertNotNull(val1); + assertEquals("v1", val1.getValue()); + PropertyValue val2 = hps.get("k2"); + assertNotNull(val2); + assertEquals("v2", val2.getValue()); + + hps.setMapReference("config2"); + val1 = hps.get("key1"); + assertNotNull(val1); + assertEquals("val1", val1.getValue()); + val2 = hps.get("key2"); + assertNotNull(val2); + assertEquals("val2", val2.getValue()); + + hps.setMapReference("foo"); + val1 = hps.get("key1"); + assertNull(val1); + val1 = hps.get("k1"); + assertNull(val1); + } + + @org.junit.Test + public void t03_tesGetMapReference(){ + hps.setMapReference("config"); + assertEquals("config", hps.getMapReference()); + + hps.setMapReference("config2"); + assertEquals("config2", hps.getMapReference()); + } + + @org.junit.Test + public void t03_tesGetSetName(){ + hps.setMapReference("config"); + assertEquals("config", hps.getMapReference()); + assertEquals("Hazelcast", hps.getName()); + + hps.setMapReference("config2"); + hps.setName("foo"); + assertEquals("config2", hps.getMapReference()); + assertEquals("foo", hps.getName()); + } + + @org.junit.Test + public void t04_testCache() throws InterruptedException { + hps.setCacheTimeout(50L); + assertTrue(hps.getValidUntil()>= System.currentTimeMillis()); + assertEquals(50L, hps.getCachePeriod()); + hps.setMapReference("config"); + hps.setDefaultOrdinal(200); + Map<String, PropertyValue> values = hps.getProperties(); + assertNotNull(values); + assertEquals(3, values.size()); + assertNotNull(values.get("k1")); + assertNotNull(values.get("k2")); + assertEquals("v1", values.get("k1").getValue()); + assertEquals("v2", values.get("k2").getValue()); + assertEquals(hps.getOrdinal(), 2000); + + IMap<Object, Object> map = hz.getMap("config"); + map.put("k3", "v3"); + map.remove("tamaya.ordinal"); + map.flush(); + + // Read from cache + assertEquals(50L, hps.getCachePeriod()); + assertTrue(hps.getValidUntil()>= System.currentTimeMillis()); + values = hps.getProperties(); + assertNotNull(values); + assertEquals(3, values.size()); + assertNotNull(values.get("k1")); + assertNotNull(values.get("k2")); + assertEquals("v1", values.get("k1").getValue()); + assertEquals("v2", values.get("k2").getValue()); + assertEquals(hps.getOrdinal(), 2000); + + // Let cache timeout + Thread.sleep(300L); + + // Read updated values + values = hps.getProperties(); + assertNotNull(values); + assertEquals(3, values.size()); + assertNotNull(values.get("k1")); + assertNotNull(values.get("k2")); + assertNotNull(values.get("k3")); + assertEquals("v1", values.get("k1").getValue()); + assertEquals("v2", values.get("k2").getValue()); + assertEquals("v3", values.get("k3").getValue()); + assertEquals(hps.getOrdinal(), 200); + } + + @AfterClass + public static void end(){ + HazelcastUtil.shutdown(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/HazelcastUtil.java ---------------------------------------------------------------------- diff --git a/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/HazelcastUtil.java b/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/HazelcastUtil.java new file mode 100644 index 0000000..87c82ca --- /dev/null +++ b/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/HazelcastUtil.java @@ -0,0 +1,59 @@ +/* + * 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.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Simple test util o manage Hazelcast. + */ +public final class HazelcastUtil { + + private static HazelcastInstance hz; + private static AtomicInteger accessCounter = new AtomicInteger(); + + private HazelcastUtil(){} + + /** + * Get a hazelcast instance. + * @return a hazelcast instance, not null. + */ + public static synchronized HazelcastInstance getHazelcastInstance(){ + accessCounter.incrementAndGet(); + if(hz==null){ + hz = Hazelcast.newHazelcastInstance(); + } + return hz; + } + + /** + * Shut down hazelcast, if we are the last client alive. + */ + public static synchronized void shutdown(){ + if(accessCounter.decrementAndGet()<0){ + if(hz!=null){ + hz.shutdown(); + hz = null; + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/HazelcaszPropertySourceTest.java ---------------------------------------------------------------------- diff --git a/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/HazelcaszPropertySourceTest.java b/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/HazelcaszPropertySourceTest.java new file mode 100644 index 0000000..9986827 --- /dev/null +++ b/modules/hazelcast/src/test/java/org/apache/tamaya/hazelcast/HazelcaszPropertySourceTest.java @@ -0,0 +1,204 @@ +/* + * 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.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.core.IMap; +import org.apache.tamaya.spi.PropertyValue; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * Created by atsticks on 03.11.16. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class HazelcaszPropertySourceTest { + + private static HazelcastInstance hz = HazelcastUtil.getHazelcastInstance(); + private HazelcastPropertySource hps = new HazelcastPropertySource(); + + @BeforeClass + public static void start() { + IMap<Object, Object> map = hz.getMap("config3"); + map.put("k1", "v1"); + map.put("k2", "v2"); + map.put("tamaya.ordinal", "2000"); + map.flush(); + IMap<Object, Object> map2 = hz.getMap("config4"); + map2.put("key1", "val1"); + map2.put("key2", "val2"); + map2.flush(); + } + + @org.junit.Test + public void t01_testGetProperties(){ + hps.setMapReference("config3"); + Map<String, PropertyValue> values = hps.getProperties(); + assertNotNull(values); + assertEquals(3, values.size()); + assertNotNull(values.get("k1")); + assertNotNull(values.get("k2")); + assertEquals("v1", values.get("k1").getValue()); + assertEquals("v2", values.get("k2").getValue()); + assertEquals(hps.getOrdinal(), 2000); + + hps.setMapReference("config4"); + Map<String, PropertyValue> values2 = hps.getProperties(); + assertNotNull(values2); + assertEquals(2, values2.size()); + assertNotNull(values2.get("key1")); + assertNotNull(values2.get("key2")); + assertEquals("val1", values2.get("key1").getValue()); + assertEquals("val2", values2.get("key2").getValue()); + assertEquals(hps.getOrdinal(), 0); + + hps.setMapReference("bar"); + hps.setDefaultOrdinal(1500); + Map<String, PropertyValue> values3 = hps.getProperties(); + assertNotNull(values3); + assertEquals(0, values3.size()); + assertEquals(hps.getOrdinal(), 1500); + } + + @org.junit.Test + public void t02_testGetOrdinal(){ + hps.setMapReference("config3"); + hps.setDefaultOrdinal(1500); + assertEquals(1500, hps.getDefaultOrdinal()); + assertEquals(hps.getOrdinal(), 2000); + + hps.setMapReference("config4"); + hps.setDefaultOrdinal(0); + assertEquals(0, hps.getDefaultOrdinal()); + assertEquals(hps.getOrdinal(), 0); + + hps.setMapReference("bar"); + hps.setDefaultOrdinal(1500); + assertEquals(1500, hps.getDefaultOrdinal()); + assertEquals(hps.getOrdinal(), 1500); + } + + @org.junit.Test + public void t03_tesGet(){ + hps.setMapReference("config3"); + PropertyValue val1 = hps.get("k1"); + assertNotNull(val1); + assertEquals("v1", val1.getValue()); + PropertyValue val2 = hps.get("k2"); + assertNotNull(val2); + assertEquals("v2", val2.getValue()); + + hps.setMapReference("config4"); + val1 = hps.get("key1"); + assertNotNull(val1); + assertEquals("val1", val1.getValue()); + val2 = hps.get("key2"); + assertNotNull(val2); + assertEquals("val2", val2.getValue()); + + hps.setMapReference("bar"); + val1 = hps.get("key1"); + assertNull(val1); + val1 = hps.get("k1"); + assertNull(val1); + } + + @org.junit.Test + public void t03_tesGetMapReference(){ + hps.setMapReference("config3"); + assertEquals("config3", hps.getMapReference()); + + hps.setMapReference("config4"); + assertEquals("config4", hps.getMapReference()); + } + + @org.junit.Test + public void t03_tesGetSetName(){ + hps.setMapReference("config3"); + assertEquals("config3", hps.getMapReference()); + assertEquals("Hazelcast", hps.getName()); + + hps.setMapReference("config4"); + hps.setName("bar"); + assertEquals("config4", hps.getMapReference()); + assertEquals("bar", hps.getName()); + } + + @org.junit.Test + public void t04_testCache() throws InterruptedException { + hps.setCacheTimeout(50L); + assertTrue(hps.getValidUntil()>= System.currentTimeMillis()); + assertEquals(50L, hps.getCachePeriod()); + hps.setMapReference("config3"); + hps.setDefaultOrdinal(200); + Map<String, PropertyValue> values = hps.getProperties(); + assertNotNull(values); + assertEquals(3, values.size()); + assertNotNull(values.get("k1")); + assertNotNull(values.get("k2")); + assertEquals("v1", values.get("k1").getValue()); + assertEquals("v2", values.get("k2").getValue()); + assertEquals(hps.getOrdinal(), 2000); + + IMap<Object, Object> map = hz.getMap("config3"); + map.put("k3", "v3"); + map.remove("tamaya.ordinal"); + map.flush(); + + // Read from cache + assertEquals(50L, hps.getCachePeriod()); + assertTrue(hps.getValidUntil()>= System.currentTimeMillis()); + values = hps.getProperties(); + assertNotNull(values); + assertEquals(3, values.size()); + assertNotNull(values.get("k1")); + assertNotNull(values.get("k2")); + assertEquals("v1", values.get("k1").getValue()); + assertEquals("v2", values.get("k2").getValue()); + assertEquals(hps.getOrdinal(), 2000); + + // Let cache timeout + Thread.sleep(300L); + + // Read updated values + values = hps.getProperties(); + assertNotNull(values); + assertEquals(3, values.size()); + assertNotNull(values.get("k1")); + assertNotNull(values.get("k2")); + assertNotNull(values.get("k3")); + assertEquals("v1", values.get("k1").getValue()); + assertEquals("v2", values.get("k2").getValue()); + assertEquals("v3", values.get("k3").getValue()); + assertEquals(hps.getOrdinal(), 200); + } + + @AfterClass + public static void end(){ + HazelcastUtil.shutdown(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/c8ba9c4c/modules/pom.xml ---------------------------------------------------------------------- diff --git a/modules/pom.xml b/modules/pom.xml index bd7abe0..62c878f 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -45,6 +45,10 @@ under the License. <module>osgi</module> <module>microprofile</module> <module>injection</module> + <module>collections</module> + <module>hazelcast</module> + <module>etcd</module> + <module>consul</module> </modules> </project>
