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 2016/02/18 00:43:14 UTC
[6/8] incubator-tamaya git commit: Redesigned component slightly.
Redesigned component slightly.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/1547d4a9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/1547d4a9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/1547d4a9
Branch: refs/heads/master
Commit: 1547d4a9c0c05b50a605f2e44ae871b77a467266
Parents: 89bf981
Author: anatole <an...@apache.org>
Authored: Thu Feb 18 00:38:01 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Thu Feb 18 00:38:01 2016 +0100
----------------------------------------------------------------------
...aya.mutableconfig.spi.ConfigChangeManagerSpi | 19 --
...g.spi.MutableConfigurationBackendProviderSpi | 19 ++
.../mutableconfig/ConfigChangeManager.java | 238 -------------------
.../mutableconfig/ConfigChangeRequest.java | 164 -------------
.../mutableconfig/MutableConfiguration.java | 164 +++++++++++++
.../MutableConfigurationQuery.java | 238 +++++++++++++++++++
.../internal/DefaultConfigChangeManagerSpi.java | 52 ----
.../DefaultConfigurationBackendSpi.java | 52 ++++
.../PropertiesFileConfigBackendSpi.java | 114 +++++++++
.../PropertiesFileConfigChangeRequest.java | 116 ---------
.../XmlPropertiesFileConfigBackendSpi.java | 114 +++++++++
.../XmlPropertiesFileConfigChangeRequest.java | 116 ---------
.../spi/AbstractConfigChangeRequest.java | 167 -------------
.../spi/AbstractMutableConfiguration.java | 167 +++++++++++++
...stractMutableConfigurationBackendSpiSpi.java | 107 +++++++++
.../spi/ConfigChangeManagerSpi.java | 39 ---
.../MutableConfigurationBackendProviderSpi.java | 40 ++++
.../spi/MutableConfigurationBackendSpi.java | 143 +++++++++++
...aya.mutableconfig.spi.ConfigChangeManagerSpi | 19 --
...g.spi.MutableConfigurationBackendProviderSpi | 19 ++
.../mutableconfig/ConfigChangeManagerTest.java | 78 ------
.../MutableConfigurationQueryTest.java | 78 ++++++
.../PropertiesFileConfigBackendTest.java | 161 +++++++++++++
.../PropertiesFileConfigChangeRequestTest.java | 161 -------------
24 files changed, 1416 insertions(+), 1169 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi b/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi
deleted file mode 100644
index 2189807..0000000
--- a/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.etcd.internal.MutableConfigSupport
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi
----------------------------------------------------------------------
diff --git a/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi b/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi
new file mode 100644
index 0000000..2189807
--- /dev/null
+++ b/modules/integration/etcd/src/main/resources/META-INF/services/org.apache.tamaya.mutableconfig.spi.MutableConfigurationBackendProviderSpi
@@ -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.etcd.internal.MutableConfigSupport
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
deleted file mode 100644
index 8142fcc..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeManager.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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.mutableconfig;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
-import org.apache.tamaya.spi.ServiceContextManager;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.UUID;
-
-
-/**
- * Accessor for creating {@link ConfigChangeRequest} instances to change and commit configuration.
- */
-public final class ConfigChangeManager {
-
- /** Singleton constructor. */
- private ConfigChangeManager(){}
-
- /**
- * Creates a new change request for the given configurationSource
- *
- * @param configurationTargets the configuration targets (String to create URIs) to use to write the changes/config. By passing multiple
- * URIs you can write back changes into multiple configuration backends, e.g.
- * one for redistributing changes using multicast mechanism, a local property file
- * for failover as well as the shared etcd server.
- * @return a new ChangeRequest
- * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
- */
- public static ConfigChangeRequest createChangeRequest(String... configurationTargets){
- try {
- URI[] uris = new URI[configurationTargets.length];
- for (int i = 0; i < configurationTargets.length; i++) {
- uris[i] = new URI(configurationTargets[i]);
- }
- return createChangeRequest(uris);
- } catch(URISyntaxException e){
- throw new ConfigException("Invalid URIs enocuntered in " + Arrays.toString(configurationTargets));
- }
- }
-
- /**
- * Creates a new change request for the given configurationSource
- *
- * @param configurationTargets the configuration targets to use to write the changes/config. By passing multiple
- * URIs you can write back changes into multiple configuration backends, e.g.
- * one for redistributing changes using multicast mechanism, a local property file
- * for failover as well as the shared etcd server.
- * @return a new ChangeRequest
- * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
- */
- public static ConfigChangeRequest createChangeRequest(URI... configurationTargets){
- if(Objects.requireNonNull(configurationTargets).length==0){
- throw new IllegalArgumentException("At least one target URI is required.");
- }
- List<ConfigChangeRequest> targets = new ArrayList<>();
- for(ConfigChangeManagerSpi spi:ServiceContextManager.getServiceContext()
- .getServices(ConfigChangeManagerSpi.class)){
- for(URI target:configurationTargets) {
- ConfigChangeRequest req = spi.createChangeRequest(target);
- if (req != null) {
- targets.add(req);
- }
- }
- }
- if(targets.isEmpty()) {
- throw new ConfigException("Not an editable configuration target for: " +
- Arrays.toString(configurationTargets));
- }
- if(targets.size()==1){
- return targets.get(0);
- }
- return new CompoundConfigChangeRequest(targets);
- }
-
-
- /**
- * Compound request that contains internally multiple change requests. Changes are committed to all members.
- */
- private static final class CompoundConfigChangeRequest implements ConfigChangeRequest{
-
- private final List<ConfigChangeRequest> targets;
- private final List<URI> backendURIs = new ArrayList<>();
- private String requestId = UUID.randomUUID().toString();
-
- CompoundConfigChangeRequest(List<ConfigChangeRequest> targets){
- this.targets = targets;
- for(ConfigChangeRequest req:targets){
- req.setRequestId(requestId);
- backendURIs.addAll(req.getBackendURIs());
- }
- }
-
- @Override
- public String getRequestID() {
- return requestId;
- }
-
- @Override
- public List<URI> getBackendURIs() {
- return Collections.unmodifiableList(backendURIs);
- }
-
- @Override
- public boolean isWritable(String keyExpression) {
- for(ConfigChangeRequest req:targets){
- if(req.isWritable(keyExpression)){
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean isRemovable(String keyExpression) {
- for(ConfigChangeRequest req:targets){
- if(req.isRemovable(keyExpression)){
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean exists(String keyExpression) {
- for(ConfigChangeRequest req:targets){
- if(req.exists(keyExpression)){
- return true;
- }
- }
- return false;
- }
-
- @Override
- public ConfigChangeRequest put(String key, String value) {
- for(ConfigChangeRequest req:targets){
- if(req.isWritable(key)){
- req.put(key, value);
- }
- }
- return this;
- }
-
- @Override
- public ConfigChangeRequest putAll(Map<String, String> properties) {
- for(ConfigChangeRequest req:targets){
- for(Map.Entry<String,String> en:properties.entrySet()) {
- if (req.isWritable(en.getKey())) {
- req.put(en.getKey(), en.getValue());
- }
- }
- }
- return this;
- }
-
- @Override
- public ConfigChangeRequest remove(String... keys) {
- for(ConfigChangeRequest req:targets){
- for(String key:keys){
- if (req.isRemovable(key)) {
- req.remove(key);
- }
- }
- }
- return this;
- }
-
- @Override
- public ConfigChangeRequest remove(Collection<String> keys) {
- for(ConfigChangeRequest req:targets){
- for(String key:keys){
- if (req.isRemovable(key)) {
- req.remove(key);
- }
- }
- }
- return this;
- }
-
- @Override
- public void commit() {
- for(ConfigChangeRequest req:targets){
- req.commit();
- }
- }
-
- @Override
- public void cancel() {
- for(ConfigChangeRequest req:targets){
- req.cancel();
- }
- }
-
- @Override
- public boolean isClosed() {
- for(ConfigChangeRequest req:targets){
- if(req.isClosed()){
- return true;
- }
- }
- return false;
- }
-
- @Override
- public void setRequestId(String requestId) {
- if(isClosed()){
- throw new IllegalStateException("Cannot set requestId, already closed.");
- }
- this.requestId = Objects.requireNonNull(requestId);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
deleted file mode 100644
index a192f50..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/ConfigChangeRequest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.mutableconfig;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.Map;
-
-
-/**
- * This interface extends the Configuration interface hereby adding methods to change configuration entries.
- * Hereby not all configuration entries are necessarily mutable, since some entries may be read from non
- * mutable areas of configuration. Of course, it is always possible to add a mutable shadow layer on top of all
- * configuration to enable whatever changes applied. The exact management and storage persistence algorithm should be
- * transparent.<br>
- * As a consequence clients should first check, using the corresponding methods, if entries are to edited or removed
- * actually are eligible for change/creation or removal.
- */
-public interface ConfigChangeRequest {
-
- /**
- * Get the unique id of this change request (UUID).
- *
- * @return the unique id of this change request (UUID).
- */
- String getRequestID();
-
- /**
- * Identifies the configuration backends that participate in this request instance and which are
- * also responsible for writing back the changes applied.
- *
- * @return the backend URI, never null.
- */
- Collection<URI> getBackendURIs();
-
- /**
- * Checks if a configuration key is writable (or it can be added).
- *
- * @param keyExpression the key to be checked for write access (including creation), not null. Here this could also
- * be a regular expression, such "as a.b.c.*".
- * @return the boolean
- */
- boolean isWritable(String keyExpression);
-
- /**
- * Checks if a configuration key is removable. This also implies that it is writable, but there might be writable
- * keys that cannot be removed.
- *
- * @param keyExpression the keyExpression the key to be cheched for write access (including creation), not null.
- * Here this could also
- * be a regulat expression, such "as a.b.c.*".
- * @return the boolean
- */
- boolean isRemovable(String keyExpression);
-
- /**
- * Checks if any keys of the given type already exist in the backend. <b>NOTE:</b> there may be backends that
- * are not able to support lookups with regular expressions. In most such cases you should pass the keys to
- * lookup explicitly.
- *
- * @param keyExpression the key to be checked for write access (including creation), not null. Here this could
- * also be a regular expression, such "as a.b.c.*".
- * @return true, if there is any key found matching the expression.
- */
- boolean exists(String keyExpression);
-
- /**
- * Sets a property.
- *
- * @param key the property's key, not null.
- * @param value the property's value, not null.
- * @return the former property value, or null.
- * @throws org.apache.tamaya.ConfigException if the key/value cannot be added, or the request is read-only.
- */
- ConfigChangeRequest put(String key, String value);
-
- /**
- * Puts all given configuration entries. This method should check that all given properties are
- * basically removable, as defined by #isWritable. If any of the passed keys is not writable during this initial
- * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
- * occur afterwards, when the properties are effectively written back to the backends, the errors should be
- * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
- * remove all entries as far as possible and abort the writing operation.
- *
- * @param properties the properties tobe written, not null.
- * @return the config change request
- * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request is read-only.
- */
- ConfigChangeRequest putAll(Map<String, String> properties);
-
- /**
- * Removes all given configuration entries. This method should check that all given properties are
- * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
- * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
- * occur afterwards, when the properties are effectively written back to the backends, the errors should be
- * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
- * remove all entries as far as possible and abort the writing operation.
- *
- * @param keys the property's keys to be removed, not null.
- * @return the config change request
- * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
- */
- ConfigChangeRequest remove(Collection<String> keys);
-
- /**
- * Removes all given configuration entries. This method should check that all given properties are
- * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
- * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
- * occur afterwards, when the properties are effectively written back to the backends, the errors should be
- * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
- * remove all entries as far as possible and abort the writing operation.
- *
- * @param keys the property's keys to be removed, not null.
- * @return the config change request
- * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
- */
- ConfigChangeRequest remove(String... keys);
-
- /**
- * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
- * the corresponding configuration backend.
- * " @throws ConfigException if the request already has been committed or cancelled, or the commit fails.
- */
- void commit();
-
- /**
- * Cancel the given request, leaving everything unchanged. Cancelled requests are read-only and can not be used
- * for preparing/submitting any configuration changes.
- *
- * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled.
- */
- void cancel();
-
- /**
- * Operation to check, if the current request is closed (either commited or cancelled). Closed requests are
- * read-only and can not be used for preparing/submitting any configuration changes.
- *
- * @return true, if this instance is closed.
- */
- boolean isClosed();
-
- /**
- * Method to set the request id to be used.
- * @param requestId the id to be used, not null
- * @throws IllegalStateException if the request is already closed.
- */
- void setRequestId(String requestId);
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
new file mode 100644
index 0000000..fed3151
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfiguration.java
@@ -0,0 +1,164 @@
+/*
+ * 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.mutableconfig;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Map;
+
+
+/**
+ * This interface extends the Configuration interface hereby adding methods to change configuration entries.
+ * Hereby not all configuration entries are necessarily mutable, since some entries may be read from non
+ * mutable areas of configuration. Of course, it is always possible to add a mutable shadow layer on top of all
+ * configuration to enable whatever changes applied. The exact management and storage persistence algorithm should be
+ * transparent.<br>
+ * As a consequence clients should first check, using the corresponding methods, if entries are to edited or removed
+ * actually are eligible for change/creation or removal.
+ */
+public interface MutableConfiguration {
+
+ /**
+ * Get the unique id of this change request (UUID).
+ *
+ * @return the unique id of this change request (UUID).
+ */
+ String getRequestID();
+
+ /**
+ * Identifies the configuration backends that participate in this request instance and which are
+ * also responsible for writing back the changes applied.
+ *
+ * @return the backend URI, never null.
+ */
+ Collection<URI> getBackendURIs();
+
+ /**
+ * Checks if a configuration key is writable (or it can be added).
+ *
+ * @param keyExpression the key to be checked for write access (including creation), not null. Here this could also
+ * be a regular expression, such "as a.b.c.*".
+ * @return the boolean
+ */
+ boolean isWritable(String keyExpression);
+
+ /**
+ * Checks if a configuration key is removable. This also implies that it is writable, but there might be writable
+ * keys that cannot be removed.
+ *
+ * @param keyExpression the keyExpression the key to be cheched for write access (including creation), not null.
+ * Here this could also
+ * be a regulat expression, such "as a.b.c.*".
+ * @return the boolean
+ */
+ boolean isRemovable(String keyExpression);
+
+ /**
+ * Checks if any keys of the given type already exist in the backend. <b>NOTE:</b> there may be backends that
+ * are not able to support lookups with regular expressions. In most such cases you should pass the keys to
+ * lookup explicitly.
+ *
+ * @param keyExpression the key to be checked for write access (including creation), not null. Here this could
+ * also be a regular expression, such "as a.b.c.*".
+ * @return true, if there is any key found matching the expression.
+ */
+ boolean exists(String keyExpression);
+
+ /**
+ * Sets a property.
+ *
+ * @param key the property's key, not null.
+ * @param value the property's value, not null.
+ * @return the former property value, or null.
+ * @throws org.apache.tamaya.ConfigException if the key/value cannot be added, or the request is read-only.
+ */
+ MutableConfiguration put(String key, String value);
+
+ /**
+ * Puts all given configuration entries. This method should check that all given properties are
+ * basically removable, as defined by #isWritable. If any of the passed keys is not writable during this initial
+ * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+ * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+ * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+ * remove all entries as far as possible and abort the writing operation.
+ *
+ * @param properties the properties tobe written, not null.
+ * @return the config change request
+ * @throws org.apache.tamaya.ConfigException if any of the given properties could not be written, or the request is read-only.
+ */
+ MutableConfiguration putAll(Map<String, String> properties);
+
+ /**
+ * Removes all given configuration entries. This method should check that all given properties are
+ * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
+ * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+ * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+ * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+ * remove all entries as far as possible and abort the writing operation.
+ *
+ * @param keys the property's keys to be removed, not null.
+ * @return the config change request
+ * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
+ */
+ MutableConfiguration remove(Collection<String> keys);
+
+ /**
+ * Removes all given configuration entries. This method should check that all given properties are
+ * basically removable, as defined by #isRemovable. If any of the passed keys is not removable during this initial
+ * check, the operation should not perform any configuration changes and throw a {@link org.apache.tamaya.ConfigException}. If errors
+ * occur afterwards, when the properties are effectively written back to the backends, the errors should be
+ * collected and returned as part of the ConfigException payload. Nevertheless the operation should in that case
+ * remove all entries as far as possible and abort the writing operation.
+ *
+ * @param keys the property's keys to be removed, not null.
+ * @return the config change request
+ * @throws org.apache.tamaya.ConfigException if any of the given keys could not be removed, or the request is read-only.
+ */
+ MutableConfiguration remove(String... keys);
+
+ /**
+ * Commits the request. After a commit the change is not editable anymore. All changes applied will be written to
+ * the corresponding configuration backend.
+ * " @throws ConfigException if the request already has been committed or cancelled, or the commit fails.
+ */
+ void commit();
+
+ /**
+ * Cancel the given request, leaving everything unchanged. Cancelled requests are read-only and can not be used
+ * for preparing/submitting any configuration changes.
+ *
+ * @throws org.apache.tamaya.ConfigException if the request already has been committed or cancelled.
+ */
+ void cancel();
+
+ /**
+ * Operation to check, if the current request is closed (either commited or cancelled). Closed requests are
+ * read-only and can not be used for preparing/submitting any configuration changes.
+ *
+ * @return true, if this instance is closed.
+ */
+ boolean isClosed();
+
+ /**
+ * Method to set the request id to be used.
+ * @param requestId the id to be used, not null
+ * @throws IllegalStateException if the request is already closed.
+ */
+ void setRequestId(String requestId);
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.java
new file mode 100644
index 0000000..7aaf2bf
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/MutableConfigurationQuery.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.mutableconfig;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
+import org.apache.tamaya.spi.ServiceContextManager;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+
+/**
+ * Accessor for creating {@link MutableConfiguration} instances to change and commit configuration.
+ */
+public final class MutableConfigurationQuery {
+
+ /** Singleton constructor. */
+ private MutableConfigurationQuery(){}
+
+ /**
+ * Creates a new change request for the given configurationSource
+ *
+ * @param configurationTargets the configuration targets (String to create URIs) to use to write the changes/config. By passing multiple
+ * URIs you can write back changes into multiple configuration backends, e.g.
+ * one for redistributing changes using multicast mechanism, a local property file
+ * for failover as well as the shared etcd server.
+ * @return a new ChangeRequest
+ * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
+ */
+ public static MutableConfiguration createChangeRequest(String... configurationTargets){
+ try {
+ URI[] uris = new URI[configurationTargets.length];
+ for (int i = 0; i < configurationTargets.length; i++) {
+ uris[i] = new URI(configurationTargets[i]);
+ }
+ return createChangeRequest(uris);
+ } catch(URISyntaxException e){
+ throw new ConfigException("Invalid URIs enocuntered in " + Arrays.toString(configurationTargets));
+ }
+ }
+
+ /**
+ * Creates a new change request for the given configurationSource
+ *
+ * @param configurationTargets the configuration targets to use to write the changes/config. By passing multiple
+ * URIs you can write back changes into multiple configuration backends, e.g.
+ * one for redistributing changes using multicast mechanism, a local property file
+ * for failover as well as the shared etcd server.
+ * @return a new ChangeRequest
+ * @throws org.apache.tamaya.ConfigException if the given configurationSource cannot be edited.
+ */
+ public static MutableConfiguration createChangeRequest(URI... configurationTargets){
+ if(Objects.requireNonNull(configurationTargets).length==0){
+ throw new IllegalArgumentException("At least one target URI is required.");
+ }
+ List<MutableConfiguration> targets = new ArrayList<>();
+ for(ConfigChangeManagerSpi spi:ServiceContextManager.getServiceContext()
+ .getServices(ConfigChangeManagerSpi.class)){
+ for(URI target:configurationTargets) {
+ MutableConfiguration req = spi.createChangeRequest(target);
+ if (req != null) {
+ targets.add(req);
+ }
+ }
+ }
+ if(targets.isEmpty()) {
+ throw new ConfigException("Not an editable configuration target for: " +
+ Arrays.toString(configurationTargets));
+ }
+ if(targets.size()==1){
+ return targets.get(0);
+ }
+ return new CompoundConfigChangeRequest(targets);
+ }
+
+
+ /**
+ * Compound request that contains internally multiple change requests. Changes are committed to all members.
+ */
+ private static final class CompoundConfigChangeRequest implements MutableConfiguration {
+
+ private final List<MutableConfiguration> targets;
+ private final List<URI> backendURIs = new ArrayList<>();
+ private String requestId = UUID.randomUUID().toString();
+
+ CompoundConfigChangeRequest(List<MutableConfiguration> targets){
+ this.targets = targets;
+ for(MutableConfiguration req:targets){
+ req.setRequestId(requestId);
+ backendURIs.addAll(req.getBackendURIs());
+ }
+ }
+
+ @Override
+ public String getRequestID() {
+ return requestId;
+ }
+
+ @Override
+ public List<URI> getBackendURIs() {
+ return Collections.unmodifiableList(backendURIs);
+ }
+
+ @Override
+ public boolean isWritable(String keyExpression) {
+ for(MutableConfiguration req:targets){
+ if(req.isWritable(keyExpression)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isRemovable(String keyExpression) {
+ for(MutableConfiguration req:targets){
+ if(req.isRemovable(keyExpression)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean exists(String keyExpression) {
+ for(MutableConfiguration req:targets){
+ if(req.exists(keyExpression)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public MutableConfiguration put(String key, String value) {
+ for(MutableConfiguration req:targets){
+ if(req.isWritable(key)){
+ req.put(key, value);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public MutableConfiguration putAll(Map<String, String> properties) {
+ for(MutableConfiguration req:targets){
+ for(Map.Entry<String,String> en:properties.entrySet()) {
+ if (req.isWritable(en.getKey())) {
+ req.put(en.getKey(), en.getValue());
+ }
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public MutableConfiguration remove(String... keys) {
+ for(MutableConfiguration req:targets){
+ for(String key:keys){
+ if (req.isRemovable(key)) {
+ req.remove(key);
+ }
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public MutableConfiguration remove(Collection<String> keys) {
+ for(MutableConfiguration req:targets){
+ for(String key:keys){
+ if (req.isRemovable(key)) {
+ req.remove(key);
+ }
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public void commit() {
+ for(MutableConfiguration req:targets){
+ req.commit();
+ }
+ }
+
+ @Override
+ public void rollback() {
+ for(MutableConfiguration req:targets){
+ req.rollback();
+ }
+ }
+
+ @Override
+ public boolean isClosed() {
+ for(MutableConfiguration req:targets){
+ if(req.isClosed()){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void setRequestId(String requestId) {
+ if(isClosed()){
+ throw new IllegalStateException("Cannot set requestId, already closed.");
+ }
+ this.requestId = Objects.requireNonNull(requestId);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
deleted file mode 100644
index d1d8371..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigChangeManagerSpi.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.mutableconfig.internal;
-
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-import org.apache.tamaya.mutableconfig.spi.ConfigChangeManagerSpi;
-
-import java.io.File;
-import java.net.URI;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Mutable Config Request factory that tries to convert given URIs to file references, if successful, it returns
- * ConfigChangeRequests fir .properties and .xml files.
- */
-public class DefaultConfigChangeManagerSpi implements ConfigChangeManagerSpi{
-
- private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
-
- @Override
- public ConfigChangeRequest createChangeRequest(URI uri) {
- try{
- File f = new File(uri);
- if(f.getName().endsWith(".properties")){
- return new PropertiesFileConfigChangeRequest(f);
- }else if(f.getName().endsWith(".xml")){
- return new XmlPropertiesFileConfigChangeRequest(f);
- }
- } catch(Exception e){
- LOG.log(Level.FINEST, "URI not convertible to file, ignoring " + uri, e);
- }
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
new file mode 100644
index 0000000..e5def2e
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/DefaultConfigurationBackendSpi.java
@@ -0,0 +1,52 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.spi.ConfigurationBackendSpi;
+
+import java.io.File;
+import java.net.URI;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Mutable Config Request factory that tries to convert given URIs to file references, if successful, it returns
+ * ConfigChangeRequests fir .properties and .xml files.
+ */
+public class DefaultConfigurationBackendSpi implements ConfigurationBackendSpi {
+
+ private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
+
+ @Override
+ public MutableConfiguration getBackend(URI uri) {
+ try{
+ File f = new File(uri);
+ if(f.getName().endsWith(".properties")){
+ return new PropertiesFileConfigChangeRequest(f);
+ }else if(f.getName().endsWith(".xml")){
+ return new XmlPropertiesFileConfigChangeRequest(f);
+ }
+ } catch(Exception e){
+ LOG.log(Level.FINEST, "URI not convertible to file, ignoring " + uri, e);
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
new file mode 100644
index 0000000..15a68cb
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigBackendSpi.java
@@ -0,0 +1,114 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.AbstractMutableConfigurationBackendSpiSpi;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Change Request implementation based on .properties file.
+ */
+class PropertiesFileConfigBackendSpi extends AbstractMutableConfigurationBackendSpiSpi {
+
+ private static final Logger LOG = Logger.getLogger(PropertiesFileConfigBackendSpi.class.getName());
+
+ private final File file;
+
+ private final Properties properties = new Properties();
+
+ /**
+ * Instantiates a new Properties file config change request.
+ *
+ * @param file the file
+ */
+ PropertiesFileConfigBackendSpi(File file){
+ super(file.toURI());
+ this.file = file;
+ if(file.exists()) {
+ try (InputStream is = getBackendURI().toURL().openStream()) {
+ properties.load(is);
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
+ }
+ }
+ }
+
+ @Override
+ public boolean isExisting(String keyExpression) {
+ if(properties.containsKey(keyExpression)){
+ return true;
+ }
+ for(Object key:properties.keySet()){
+ if(key.toString().matches(keyExpression)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ @Override
+ protected void commitInternal() {
+ if(!file.exists()){
+ try {
+ if(!file.createNewFile()){
+ throw new ConfigException("Failed to create config file " + file);
+ }
+ } catch (IOException e) {
+ throw new ConfigException("Failed to create config file " + file, e);
+ }
+ }
+ for(Map.Entry<String,String> en:super.addedProperties.entrySet()){
+ int index = en.getKey().indexOf('?');
+ if(index>0){
+ this.properties.put(en.getKey().substring(0, index), en.getValue());
+ }else{
+ this.properties.put(en.getKey(), en.getValue());
+ }
+ }
+ for(String rmKey:super.removedProperties){
+ this.properties.remove(rmKey);
+ }
+ try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
+ properties.store(bos, "Properties written from Tamaya on : " + new Date());
+ bos.flush();
+ }
+ catch(Exception e){
+ throw new ConfigException("Failed to write config to " + file, e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "PropertiesFileConfigBackend{" +
+ "file=" + file +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
deleted file mode 100644
index 94d3f2e..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/PropertiesFileConfigChangeRequest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.mutableconfig.internal;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.AbstractConfigChangeRequest;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Map;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Change Request implementation based on .properties file.
- */
-class PropertiesFileConfigChangeRequest extends AbstractConfigChangeRequest{
-
- private static final Logger LOG = Logger.getLogger(PropertiesFileConfigChangeRequest.class.getName());
-
- private final File file;
-
- private final Properties properties = new Properties();
-
- /**
- * Instantiates a new Properties file config change request.
- *
- * @param file the file
- */
- PropertiesFileConfigChangeRequest(File file){
- super(file.toURI());
- this.file = file;
- if(file.exists()) {
- for(URI uri:getBackendURIs()) {
- try (InputStream is = uri.toURL().openStream()) {
- properties.load(is);
- } catch (Exception e) {
- LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
- }
- }
- }
- }
-
- @Override
- public boolean exists(String keyExpression) {
- if(properties.containsKey(keyExpression)){
- return true;
- }
- for(Object key:properties.keySet()){
- if(key.toString().matches(keyExpression)){
- return true;
- }
- }
- return false;
- }
-
-
- @Override
- protected void commitInternal() {
- if(!file.exists()){
- try {
- if(!file.createNewFile()){
- throw new ConfigException("Failed to create config file " + file);
- }
- } catch (IOException e) {
- throw new ConfigException("Failed to create config file " + file, e);
- }
- }
- for(Map.Entry<String,String> en:super.properties.entrySet()){
- int index = en.getKey().indexOf('?');
- if(index>0){
- this.properties.put(en.getKey().substring(0, index), en.getValue());
- }else{
- this.properties.put(en.getKey(), en.getValue());
- }
- }
- for(String rmKey:super.removed){
- this.properties.remove(rmKey);
- }
- try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
- properties.store(bos, "Properties written from Tamaya, request: " + getRequestID());
- bos.flush();
- }
- catch(Exception e){
- throw new ConfigException("Failed to write config to " + file, e);
- }
- }
-
- @Override
- public String toString() {
- return "PropertiesFileConfigChangeRequest{" +
- "file=" + file +
- '}';
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
new file mode 100644
index 0000000..cdca80d
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigBackendSpi.java
@@ -0,0 +1,114 @@
+/*
+ * 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.mutableconfig.internal;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.spi.AbstractMutableConfigurationBackendSpiSpi;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Change Request implementation based on .xml properties file.
+ */
+class XmlPropertiesFileConfigBackendSpi extends AbstractMutableConfigurationBackendSpiSpi {
+
+ private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigBackendSpi.class.getName());
+
+ private final File file;
+
+ private final Properties properties = new Properties();
+
+ /**
+ * Instantiates a new Xml properties file config change request.
+ *
+ * @param file the file
+ */
+ XmlPropertiesFileConfigBackendSpi(File file){
+ super(file.toURI());
+ this.file = file;
+ if(file.exists()) {
+ try (InputStream is = getBackendURI().toURL().openStream()) {
+ properties.loadFromXML(is);
+ } catch (Exception e) {
+ LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
+ }
+ }
+ }
+
+ @Override
+ public boolean isExisting(String keyExpression) {
+ if(properties.containsKey(keyExpression)){
+ return true;
+ }
+ for(Object key:properties.keySet()){
+ if(key.toString().matches(keyExpression)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ @Override
+ protected void commitInternal() {
+ if(!file.exists()){
+ try {
+ if(!file.createNewFile()){
+ throw new ConfigException("Failed to create config file " + file);
+ }
+ } catch (IOException e) {
+ throw new ConfigException("Failed to create config file " + file, e);
+ }
+ }
+ for(Map.Entry<String,String> en:super.addedProperties.entrySet()){
+ int index = en.getKey().indexOf('?');
+ if(index>0){
+ this.properties.put(en.getKey().substring(0, index), en.getValue());
+ }else{
+ this.properties.put(en.getKey(), en.getValue());
+ }
+ }
+ for(String rmKey:super.removedProperties){
+ this.properties.remove(rmKey);
+ }
+ try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
+ properties.storeToXML(bos, "Properties written from Tamaya on " + new Date());
+ bos.flush();
+ }
+ catch(Exception e){
+ throw new ConfigException("Failed to write config to " + file, e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "XmlPropertiesFileConfigBackend{" +
+ "file=" + file +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
deleted file mode 100644
index 9211641..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/internal/XmlPropertiesFileConfigChangeRequest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.mutableconfig.internal;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.spi.AbstractConfigChangeRequest;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Map;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Change Request implementation based on .xml properties file.
- */
-class XmlPropertiesFileConfigChangeRequest extends AbstractConfigChangeRequest{
-
- private static final Logger LOG = Logger.getLogger(XmlPropertiesFileConfigChangeRequest.class.getName());
-
- private final File file;
-
- private final Properties properties = new Properties();
-
- /**
- * Instantiates a new Xml properties file config change request.
- *
- * @param file the file
- */
- XmlPropertiesFileConfigChangeRequest(File file){
- super(file.toURI());
- this.file = file;
- if(file.exists()) {
- for(URI uri:getBackendURIs()) {
- try (InputStream is = uri.toURL().openStream()) {
- properties.loadFromXML(is);
- } catch (Exception e) {
- LOG.log(Level.SEVERE, "Failed to load properties from " + file, e);
- }
- }
- }
- }
-
- @Override
- public boolean exists(String keyExpression) {
- if(properties.containsKey(keyExpression)){
- return true;
- }
- for(Object key:properties.keySet()){
- if(key.toString().matches(keyExpression)){
- return true;
- }
- }
- return false;
- }
-
-
- @Override
- protected void commitInternal() {
- if(!file.exists()){
- try {
- if(!file.createNewFile()){
- throw new ConfigException("Failed to create config file " + file);
- }
- } catch (IOException e) {
- throw new ConfigException("Failed to create config file " + file, e);
- }
- }
- for(Map.Entry<String,String> en:super.properties.entrySet()){
- int index = en.getKey().indexOf('?');
- if(index>0){
- this.properties.put(en.getKey().substring(0, index), en.getValue());
- }else{
- this.properties.put(en.getKey(), en.getValue());
- }
- }
- for(String rmKey:super.removed){
- this.properties.remove(rmKey);
- }
- try(BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))){
- properties.storeToXML(bos, "Properties written from Tamaya, request: " + getRequestID());
- bos.flush();
- }
- catch(Exception e){
- throw new ConfigException("Failed to write config to " + file, e);
- }
- }
-
- @Override
- public String toString() {
- return "XmlPropertiesFileConfigChangeRequest{" +
- "file=" + file +
- '}';
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
deleted file mode 100644
index 5e319db..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractConfigChangeRequest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.mutableconfig.spi;
-
-import org.apache.tamaya.ConfigException;
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Base class for implementing a ConfigChangeRequest.
- */
-public abstract class AbstractConfigChangeRequest implements ConfigChangeRequest {
-
- private final List<URI> uris = new ArrayList<>();
- private String requestID = UUID.randomUUID().toString();
- /**
- * The Properties.
- */
- protected final Map<String,String> properties = new HashMap<>();
- /**
- * The Removed.
- */
- protected final Set<String> removed = new HashSet<>();
- private boolean closed = false;
-
- protected Set<String> getRemoved() {
- return removed;
- }
-
- protected Map<String,String> getProperties() {
- return properties;
- }
-
- /**
- * Instantiates a new Abstract config change request.
- *
- * @param uris the uris
- */
- protected AbstractConfigChangeRequest(URI... uris){
- for(URI uri:uris){
- this.uris.add(Objects.requireNonNull(uri));
- }
- if(this.uris.isEmpty()){
- throw new IllegalArgumentException("At least one URI should be provided.");
- }
- }
-
- /**
- * Get the unique id of this change request (UUID).
- * @return the unique id of this change request (UUID).
- */
- @Override
- public String getRequestID(){
- return requestID;
- }
-
- @Override
- public final Collection<URI> getBackendURIs() {
- return Collections.unmodifiableCollection(uris);
- }
-
- @Override
- public boolean isWritable(String keyExpression) {
- return true;
- }
-
- @Override
- public boolean isRemovable(String keyExpression) {
- return true;
- }
-
- @Override
- public abstract boolean exists(String keyExpression);
-
- @Override
- public void setRequestId(String requestId) {
- checkClosed();
- this.requestID = Objects.requireNonNull(requestId);
- }
-
- @Override
- public ConfigChangeRequest put(String key, String value) {
- checkClosed();
- this.properties.put(key, value);
- return this;
- }
-
- @Override
- public ConfigChangeRequest putAll(Map<String, String> properties) {
- checkClosed();
- this.properties.putAll(properties);
- return this;
- }
-
- @Override
- public ConfigChangeRequest remove(String... keys) {
- checkClosed();
- Collections.addAll(this.removed, keys);
- return this;
- }
-
- @Override
- public ConfigChangeRequest remove(Collection<String> keys) {
- checkClosed();
- this.removed.addAll(keys);
- return this;
- }
-
- @Override
- public final void commit() {
- checkClosed();
- commitInternal();
- closed = true;
- }
-
- /**
- * Commit internal.
- */
- protected abstract void commitInternal();
-
- @Override
- public final void cancel() {
- checkClosed();
- closed = true;
- }
-
- @Override
- public final boolean isClosed() {
- return closed;
- }
-
- /**
- * Check closed.
- */
- protected void checkClosed(){
- if(closed){
- throw new ConfigException("Change request already closed.");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
new file mode 100644
index 0000000..2dd9a20
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfiguration.java
@@ -0,0 +1,167 @@
+/*
+ * 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.mutableconfig.spi;
+
+import org.apache.tamaya.ConfigException;
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Base class for implementing a ConfigChangeRequest.
+ */
+public abstract class AbstractMutableConfiguration implements MutableConfiguration {
+
+ private final List<URI> uris = new ArrayList<>();
+ private String requestID = UUID.randomUUID().toString();
+ /**
+ * The Properties.
+ */
+ protected final Map<String,String> properties = new HashMap<>();
+ /**
+ * The Removed.
+ */
+ protected final Set<String> removed = new HashSet<>();
+ private boolean closed = false;
+
+ protected Set<String> getRemoved() {
+ return removed;
+ }
+
+ protected Map<String,String> getProperties() {
+ return properties;
+ }
+
+ /**
+ * Instantiates a new Abstract config change request.
+ *
+ * @param uris the uris
+ */
+ protected AbstractMutableConfiguration(URI... uris){
+ for(URI uri:uris){
+ this.uris.add(Objects.requireNonNull(uri));
+ }
+ if(this.uris.isEmpty()){
+ throw new IllegalArgumentException("At least one URI should be provided.");
+ }
+ }
+
+ /**
+ * Get the unique id of this change request (UUID).
+ * @return the unique id of this change request (UUID).
+ */
+ @Override
+ public String getRequestID(){
+ return requestID;
+ }
+
+ @Override
+ public final Collection<URI> getBackendURIs() {
+ return Collections.unmodifiableCollection(uris);
+ }
+
+ @Override
+ public boolean isWritable(String keyExpression) {
+ return true;
+ }
+
+ @Override
+ public boolean isRemovable(String keyExpression) {
+ return true;
+ }
+
+ @Override
+ public abstract boolean exists(String keyExpression);
+
+ @Override
+ public void setRequestId(String requestId) {
+ checkClosed();
+ this.requestID = Objects.requireNonNull(requestId);
+ }
+
+ @Override
+ public MutableConfiguration put(String key, String value) {
+ checkClosed();
+ this.properties.put(key, value);
+ return this;
+ }
+
+ @Override
+ public MutableConfiguration putAll(Map<String, String> properties) {
+ checkClosed();
+ this.properties.putAll(properties);
+ return this;
+ }
+
+ @Override
+ public MutableConfiguration remove(String... keys) {
+ checkClosed();
+ Collections.addAll(this.removed, keys);
+ return this;
+ }
+
+ @Override
+ public MutableConfiguration remove(Collection<String> keys) {
+ checkClosed();
+ this.removed.addAll(keys);
+ return this;
+ }
+
+ @Override
+ public final void commit() {
+ checkClosed();
+ commitInternal();
+ closed = true;
+ }
+
+ /**
+ * Commit internal.
+ */
+ protected abstract void commitInternal();
+
+ @Override
+ public final void rollback() {
+ checkClosed();
+ closed = true;
+ }
+
+ @Override
+ public final boolean isClosed() {
+ return closed;
+ }
+
+ /**
+ * Check closed.
+ */
+ protected void checkClosed(){
+ if(closed){
+ throw new ConfigException("Change request already closed.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java
new file mode 100644
index 0000000..15cbe87
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/AbstractMutableConfigurationBackendSpiSpi.java
@@ -0,0 +1,107 @@
+/*
+ * 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.mutableconfig.spi;
+
+import java.net.URI;
+import java.util.*;
+
+/**
+ * Base class for implementing a MutableConfigurationBackend.
+ */
+public abstract class AbstractMutableConfigurationBackendSpiSpi implements MutableConfigurationBackendSpi {
+
+ private final URI backendURI;
+
+ /**
+ * The Properties.
+ */
+ protected final Map<String,String> addedProperties = new HashMap<>();
+ /**
+ * The Removed.
+ */
+ protected final Set<String> removedProperties = new HashSet<>();
+
+ protected Set<String> getRemovedProperties() {
+ return removedProperties;
+ }
+
+ protected Map<String,String> getAddedProperties() {
+ return addedProperties;
+ }
+
+ protected AbstractMutableConfigurationBackendSpiSpi(URI backendURI){
+ this.backendURI = Objects.requireNonNull(backendURI);
+ }
+
+ @Override
+ public URI getBackendURI() {
+ return backendURI;
+ }
+
+ @Override
+ public boolean isWritable(String keyExpression) {
+ return true;
+ }
+
+ @Override
+ public boolean isRemovable(String keyExpression) {
+ return true;
+ }
+
+ @Override
+ public abstract boolean isExisting(String keyExpression);
+
+ @Override
+ public void put(String key, String value) {
+ this.addedProperties.put(key, value);
+ }
+
+ @Override
+ public void putAll(Map<String, String> properties) {
+ this.addedProperties.putAll(properties);
+ }
+
+ @Override
+ public void remove(String... keys) {
+ Collections.addAll(this.removedProperties, keys);
+ }
+
+ @Override
+ public void remove(Collection<String> keys) {
+ this.removedProperties.addAll(keys);
+ }
+
+ @Override
+ public final void commit() {
+ commitInternal();
+ this.removedProperties.clear();
+ this.addedProperties.clear();
+ }
+
+ /**
+ * Commit internal.
+ */
+ protected abstract void commitInternal();
+
+ @Override
+ public final void rollback() {
+ this.removedProperties.clear();
+ this.addedProperties.clear();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
deleted file mode 100644
index fa78708..0000000
--- a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/ConfigChangeManagerSpi.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.mutableconfig.spi;
-
-import org.apache.tamaya.mutableconfig.ConfigChangeRequest;
-
-import java.net.URI;
-
-/**
- * Provider SPI for the {@link org.apache.tamaya.mutableconfig.ConfigChangeManager}. Providers may override
- * other providers registering with a higher {@link javax.annotation.Priority} value annotated.
- */
-public interface ConfigChangeManagerSpi {
-
- /**
- * Creates a new change request for the given Configuration.
- *
- * @param backendURI the backend uri
- * @return a new ChangeRequest, or null if the given backend URI cannot be edited.
- */
- ConfigChangeRequest createChangeRequest(URI backendURI);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1547d4a9/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
----------------------------------------------------------------------
diff --git a/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
new file mode 100644
index 0000000..98d4eb7
--- /dev/null
+++ b/modules/mutable-config/src/main/java/org/apache/tamaya/mutableconfig/spi/MutableConfigurationBackendProviderSpi.java
@@ -0,0 +1,40 @@
+/*
+ * 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.mutableconfig.spi;
+
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.MutableConfigurationQuery;
+
+import java.net.URI;
+
+/**
+ * Provider SPI used by {@link MutableConfigurationQuery}. Providers may override
+ * other providers registering with a higher {@link javax.annotation.Priority} value annotated.
+ */
+public interface MutableConfigurationBackendProviderSpi {
+
+ /**
+ * Creates a new configuration backend for applying changes to.
+ *
+ * @param backendURI the backend uri
+ * @return the requested backend, or null if the given backend URI is not supported by the given SPI.
+ */
+ MutableConfigurationBackend getBackend(URI backendURI);
+
+}