You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2015/02/27 03:40:50 UTC
[5/8] incubator-tamaya git commit: TAMAYA-69: Added initial revision
of a running event based modules.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/events/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java b/modules/events/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java
new file mode 100644
index 0000000..7cf02fd
--- /dev/null
+++ b/modules/events/src/main/java/org/apache/tamaya/events/folderobserver/ObservingPropertySourceProvider.java
@@ -0,0 +1,225 @@
+/*
+ * 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.events.folderobserver;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.events.EventSupport;
+import org.apache.tamaya.events.delta.ConfigurationContextChange;
+import org.apache.tamaya.events.delta.ConfigurationContextChangeBuilder;
+import org.apache.tamaya.format.ConfigurationData;
+import org.apache.tamaya.format.ConfigurationFormat;
+import org.apache.tamaya.format.FlattenedDefaultPropertySource;
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertySourceProvider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+/**
+ * This implementation run in a folder taking up all file compatible with the given
+ * ConfigurationFormats. When a file is added, deleted or modified the PropertySourceProvider
+ * will adapt the changes automatically and trigger according
+ * {@link org.apache.tamaya.events.delta.PropertySourceChange} events.
+ * The default folder is META-INF/config, but you can change using the absolute path in
+ * "-Dtamaya.configdir" parameter.
+ */
+public class ObservingPropertySourceProvider implements PropertySourceProvider, FileChangeObserver {
+ /**
+ * The logger.
+ */
+ private static final Logger LOG = Logger.getLogger(ObservingPropertySourceProvider.class.getName());
+ /**
+ * The current active property sources of this provider.
+ */
+ private final List<PropertySource> propertySources = Collections.synchronizedList(new LinkedList<>());
+ /**
+ * The supported configuration formats of this provider.
+ */
+ private Collection<ConfigurationFormat> formats = new ArrayList<>();
+ /**
+ * The thread pool used.
+ */
+ private ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ /**
+ * Constructor, reading the config file from classpath resource and system property.
+ */
+ public ObservingPropertySourceProvider(ConfigurationFormat... formats) {
+ this(null, formats);
+ }
+
+ /**
+ * Constructorm using an explicit directory, ignoring all kind of configuration, if set.
+ *
+ * @param directory the target directory. If null, the default configuration and system property are used.
+ * @param formats the formats to be used.
+ */
+ public ObservingPropertySourceProvider(Path directory, ConfigurationFormat... formats) {
+ this.formats = Arrays.asList(formats);
+ if (directory == null) {
+ directory = getDirectory();
+ }
+ if (Objects.nonNull(directory)) {
+ synchronized (this.propertySources) {
+ this.propertySources.addAll(readConfiguration(directory));
+ }
+ Runnable runnable = new FileChangeListener(directory, this);
+ executor.execute(runnable);
+ } else {
+ executor.shutdown();
+ }
+ }
+
+ /**
+ * Read the initial configuration.
+ *
+ * @param directory the target directory, not null.
+ */
+ private List<PropertySource> readConfiguration(Path directory) {
+ List<PropertySource> result = new ArrayList<>();
+ try {
+ synchronized (propertySources) {
+ for (Path path : Files.newDirectoryStream(directory, "*")) {
+ ConfigurationData data = loadFile(path);
+ if (data != null) {
+ result.addAll(getPropertySources(data));
+ }
+ }
+ return result;
+ }
+ } catch (IOException e) {
+ LOG.log(Level.WARNING, e, () -> "Failed to read configuration from dir: " + directory);
+ }
+ return result;
+ }
+
+ protected Collection<PropertySource> getPropertySources(ConfigurationData data) {
+ return Arrays.asList(new PropertySource[]{new FlattenedDefaultPropertySource(data)});
+ }
+
+ /**
+ * Load a single file.
+ *
+ * @param file the file, not null.
+ */
+ protected ConfigurationData loadFile(Path file) {
+ InputStream is = null;
+ for (ConfigurationFormat format : formats) {
+ try {
+ URL url = file.toUri().toURL();
+ if (format.accepts(url)) {
+ is = url.openStream();
+ ConfigurationData data = format.readConfiguration(file.toString(), is);
+ if (data != null) {
+ return data;
+ }
+ }
+ } catch (IOException e) {
+ LOG.log(Level.INFO, e, () -> "Error reading file: " + file.toString() +
+ ", using format: " + format);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ioe) {
+ LOG.log(Level.SEVERE, ioe, () -> "Failed to rea data...");
+ }
+ }
+ }
+ }
+ LOG.warning(() -> "Error reading file: " + file.toString());
+ return null;
+ }
+
+
+ /**
+ * Evaluates the target directory from system property (tamaya.configdir) or classpath.
+ *
+ * @return the directory to be read, or null.
+ */
+ private Path getDirectory() {
+ String absolutePath = System.getProperty("tamaya.configdir");
+ if (Objects.nonNull(absolutePath)) {
+ Path path = Paths.get(absolutePath);
+ if (Files.isDirectory(path)) {
+ return path;
+ }
+ }
+ URL resource = ObservingPropertySourceProvider.class.getResource("/META-INF/config/");
+ if (Objects.nonNull(resource)) {
+ try {
+ return Paths.get(resource.toURI());
+ } catch (URISyntaxException e) {
+ throw new ConfigException("An error to find the directory to watch", e);
+ }
+ }
+ return null;
+ }
+
+
+ @Override
+ public void directoryChanged(Path directory) {
+ synchronized (this.propertySources) {
+ List<PropertySource> existingPropertySources = new ArrayList<>(propertySources);
+ propertySources.clear();
+ Collection<PropertySource> sourcesRead = readConfiguration(directory);
+ this.propertySources.addAll(sourcesRead);
+ triggerConfigChange(existingPropertySources, propertySources);
+ }
+ }
+
+
+ private void triggerConfigChange(List<PropertySource> originalPropertySources,
+ List<PropertySource> newPropertySources) {
+ ConfigurationContextChangeBuilder b = ConfigurationContextChangeBuilder.of();
+ for (PropertySource ps : originalPropertySources) {
+ b.removedPropertySource(ps);
+ }
+ for (PropertySource ps : newPropertySources) {
+ b.newPropertySource(ps);
+ }
+ ConfigurationContextChange changeEvent = b.build();
+ LOG.fine(() -> "Trigger Config Context Change: " + changeEvent);
+ EventSupport.fireEvent(changeEvent);
+ }
+
+ @Override
+ public Collection<PropertySource> getPropertySources() {
+ synchronized (propertySources) {
+ return new ArrayList<>(this.propertySources);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java
----------------------------------------------------------------------
diff --git a/modules/events/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java b/modules/events/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java
new file mode 100644
index 0000000..fe00053
--- /dev/null
+++ b/modules/events/src/main/java/org/apache/tamaya/events/internal/DefaultConfigurationContextChangeListener.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.events.internal;
+
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.events.Listener;
+import org.apache.tamaya.events.delta.ConfigurationContextChange;
+import org.apache.tamaya.spi.ConfigurationContext;
+import org.apache.tamaya.spi.PropertySource;
+
+import java.util.Collection;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+/**
+ * Default Listener for ConfigurationContextChange events that updates the current context, if resources were
+ * affected.
+ */
+public class DefaultConfigurationContextChangeListener implements Listener<ConfigurationContextChange> {
+
+ private static final Logger LOG = Logger.getLogger(DefaultConfigurationContextChangeListener.class.getName());
+
+ @Override
+ public void onEvent(ConfigurationContextChange event) {
+ ConfigurationContext context = ConfigurationProvider.getConfigurationContext();
+ Collection<PropertySource> affectedPropertySources = context.getPropertySources(ps ->
+ event.isAffected(ps));
+ if(!affectedPropertySources.isEmpty()){
+ ConfigurationContext newContext = context.toBuilder()
+ .removePropertySources(event.getRemovedPropertySources().stream()
+ .map(ps -> ps.getName()).collect(Collectors.toSet()))
+ .addPropertySources(event.getAddedPropertySources())
+ .addPropertySources(event.getUpdatedPropertySources())
+ .build();
+ try {
+ ConfigurationProvider.setConfigurationContext(newContext);
+ }
+ catch(Exception e){
+ LOG.log(Level.INFO, "Failed to update the current ConfigurationContext due to config model changes", e);
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/main/java/org/apache/tamaya/events/internal/DefaultEventSupportSpi.java
----------------------------------------------------------------------
diff --git a/modules/events/src/main/java/org/apache/tamaya/events/internal/DefaultEventSupportSpi.java b/modules/events/src/main/java/org/apache/tamaya/events/internal/DefaultEventSupportSpi.java
new file mode 100644
index 0000000..4164363
--- /dev/null
+++ b/modules/events/src/main/java/org/apache/tamaya/events/internal/DefaultEventSupportSpi.java
@@ -0,0 +1,98 @@
+/*
+ * 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.events.internal;
+
+import org.apache.tamaya.TypeLiteral;
+import org.apache.tamaya.events.Listener;
+import org.apache.tamaya.events.spi.EventSupportSpi;
+import org.apache.tamaya.spi.ServiceContext;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Default implementation of {@link org.apache.tamaya.events.internal.DefaultEventSupportSpi} just forwarding all
+ * events synchronously to the listeners.
+ */
+public class DefaultEventSupportSpi implements EventSupportSpi {
+
+ private static final Logger LOG = Logger.getLogger(DefaultEventSupportSpi.class.getName());
+
+ private Map<Type, List<Listener>> listenerMap = new ConcurrentHashMap<>();
+
+
+ /**
+ * Constructor. Also loads all registered listeners.
+ */
+ public DefaultEventSupportSpi() {
+ try {
+ for (Listener<?> l : ServiceContext.getInstance().getServices(Listener.class)) {
+ try{
+ addListener(l);
+ }
+ catch(Exception e){
+ LOG.log(Level.WARNING, e, () -> "Failed to load configured listener: " + l.getClass().getName());
+ }
+ }
+ } catch (Exception e) {
+ LOG.log(Level.WARNING, e, () -> "Failed to load configured listeners.");
+ }
+ }
+
+ @Override
+ public <T> void addListener(Listener<T> l) {
+ Type type = TypeLiteral.getTypeParameter(l.getClass());
+ List<Listener> listeners = listenerMap.computeIfAbsent(type,
+ (k) -> Collections.synchronizedList(new ArrayList<>()));
+ synchronized (listeners) {
+ if (!listeners.contains(l)) {
+ listeners.add(l);
+ }
+ }
+ }
+
+ @Override
+ public <T> void removeListener(Listener<T> l) {
+ Type type = TypeLiteral.getTypeParameter(l.getClass());
+ List<Listener> listeners = listenerMap.get(type);
+ if (listeners != null) {
+ synchronized (listeners) {
+ listeners.remove(l);
+ }
+ }
+ }
+
+ @Override
+ public <T> void fireEvent(T event, Class<T> eventType) {
+ List<Listener> listeners = listenerMap.get(eventType);
+ if (listeners != null) {
+ synchronized (listeners) {
+ for (Listener l : listeners) {
+ l.onEvent(event);
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/main/java/org/apache/tamaya/events/spi/EventSupportSpi.java
----------------------------------------------------------------------
diff --git a/modules/events/src/main/java/org/apache/tamaya/events/spi/EventSupportSpi.java b/modules/events/src/main/java/org/apache/tamaya/events/spi/EventSupportSpi.java
new file mode 100644
index 0000000..0a42286
--- /dev/null
+++ b/modules/events/src/main/java/org/apache/tamaya/events/spi/EventSupportSpi.java
@@ -0,0 +1,54 @@
+/*
+ * 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.events.spi;
+
+import org.apache.tamaya.events.Listener;
+
+/**
+ * SPI interface to implement the {@link org.apache.tamaya.events.EventSupport} singleton.
+ * Implementations of this interface must be registered with the current {@link org.apache.tamaya.spi.ServiceContext},
+ * by default this equals to registering it with {@link java.util.ServiceLoader}. Add {@link javax.annotation.Priority}
+ * annotations for overriding (higher values overriden lower values).
+ */
+public interface EventSupportSpi {
+ /**
+ * Add a listener for observing events. References of this
+ * component to the listeners must be managed as weak references.
+ *
+ * @param l the listener not null.
+ */
+ <T> void addListener(Listener<T> l);
+
+
+ /**
+ * Removes a listener for observing events.
+ *
+ * @param l the listener not null.
+ */
+ <T> void removeListener(Listener<T> l);
+
+ /**
+ * Publishes an event to all interested listeners.
+ *
+ * @param event the event, not null.
+ * @param eventType the event type.
+ */
+ <T> void fireEvent(T event, Class<T> eventType);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.EventSupportSpi
----------------------------------------------------------------------
diff --git a/modules/events/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.EventSupportSpi b/modules/events/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.EventSupportSpi
new file mode 100644
index 0000000..c25632a
--- /dev/null
+++ b/modules/events/src/main/resources/META-INF/services/org.apache.tamaya.events.spi.EventSupportSpi
@@ -0,0 +1,19 @@
+#
+# 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 current 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.
+#
+org.apache.tamaya.events.internal.DefaultEventSupportSpi
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/test/data/test.properties
----------------------------------------------------------------------
diff --git a/modules/events/src/test/data/test.properties b/modules/events/src/test/data/test.properties
new file mode 100644
index 0000000..b8996a5
--- /dev/null
+++ b/modules/events/src/test/data/test.properties
@@ -0,0 +1,21 @@
+#
+# 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 current 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.
+#
+1=val1
+2=val2
+3=val3
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/test/data/test2.properties2
----------------------------------------------------------------------
diff --git a/modules/events/src/test/data/test2.properties2 b/modules/events/src/test/data/test2.properties2
new file mode 100644
index 0000000..2c884b8
--- /dev/null
+++ b/modules/events/src/test/data/test2.properties2
@@ -0,0 +1,21 @@
+#
+# 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 current 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.
+#
+4=val4
+5=val5
+6=val6
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/test/java/org/apache/tamaya/events/tests/ObservedConfigTest.java
----------------------------------------------------------------------
diff --git a/modules/events/src/test/java/org/apache/tamaya/events/tests/ObservedConfigTest.java b/modules/events/src/test/java/org/apache/tamaya/events/tests/ObservedConfigTest.java
new file mode 100644
index 0000000..e8e0b3f
--- /dev/null
+++ b/modules/events/src/test/java/org/apache/tamaya/events/tests/ObservedConfigTest.java
@@ -0,0 +1,31 @@
+package org.apache.tamaya.events.tests;
+
+import org.apache.tamaya.ConfigurationProvider;
+import org.junit.Test;
+
+/**
+ * Created by Anatole on 25.02.2015.
+ */
+public class ObservedConfigTest {
+
+ @Test
+ public void testInitialConfig(){
+ for(int i=0;i<100;i++){
+ System.out.println("1: " + ConfigurationProvider.getConfiguration().get("1"));
+ System.out.println("2: " + ConfigurationProvider.getConfiguration().get("2"));
+ System.out.println("3: " + ConfigurationProvider.getConfiguration().get("3"));
+ System.out.println("4: " + ConfigurationProvider.getConfiguration().get("4"));
+ System.out.println("5: " + ConfigurationProvider.getConfiguration().get("5"));
+ System.out.println("6: " + ConfigurationProvider.getConfiguration().get("6"));
+ System.out.println("=======================================================================");
+ try{
+ Thread.sleep(2000L);
+ }
+ catch(Exception e){
+ // ignore
+ e.printStackTrace();
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/test/java/org/apache/tamaya/events/tests/TestObservingProvider.java
----------------------------------------------------------------------
diff --git a/modules/events/src/test/java/org/apache/tamaya/events/tests/TestObservingProvider.java b/modules/events/src/test/java/org/apache/tamaya/events/tests/TestObservingProvider.java
new file mode 100644
index 0000000..411ac5d
--- /dev/null
+++ b/modules/events/src/test/java/org/apache/tamaya/events/tests/TestObservingProvider.java
@@ -0,0 +1,26 @@
+package org.apache.tamaya.events.tests;
+
+import org.apache.tamaya.events.folderobserver.ObservingPropertySourceProvider;
+import org.apache.tamaya.format.formats.PropertiesFormat;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.util.Iterator;
+
+/**
+ * Created by Anatole on 25.02.2015.
+ */
+public class TestObservingProvider extends ObservingPropertySourceProvider{
+
+ public TestObservingProvider(){
+ super(Paths.get("C:\\Users\\Anatole\\IdeaProjects\\incubator-tamaya\\modules\\events/src/test/data"), new PropertiesFormat());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/test/resources/META-INF/services/org.apache.tamaya.events.Listener
----------------------------------------------------------------------
diff --git a/modules/events/src/test/resources/META-INF/services/org.apache.tamaya.events.Listener b/modules/events/src/test/resources/META-INF/services/org.apache.tamaya.events.Listener
new file mode 100644
index 0000000..f675fd6
--- /dev/null
+++ b/modules/events/src/test/resources/META-INF/services/org.apache.tamaya.events.Listener
@@ -0,0 +1,19 @@
+#
+# 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 current 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.
+#
+org.apache.tamaya.events.internal.DefaultConfigurationContextChangeListener
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/events/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertySourceProvider
----------------------------------------------------------------------
diff --git a/modules/events/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertySourceProvider b/modules/events/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertySourceProvider
new file mode 100644
index 0000000..acb3a45
--- /dev/null
+++ b/modules/events/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertySourceProvider
@@ -0,0 +1,19 @@
+#
+# 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 current 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.
+#
+org.apache.tamaya.events.tests.TestObservingProvider
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/237bbcdc/modules/pom.xml
----------------------------------------------------------------------
diff --git a/modules/pom.xml b/modules/pom.xml
index 5702415..98d2786 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -41,6 +41,7 @@ under the License.
<module>json</module>
<module>resolver</module>
<module>resources</module>
+ <module>events</module>
<!-- module>metamodels</module -->
<!-- module>integration</module -->
</modules>