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/12/22 21:19:32 UTC
[2/4] incubator-tamaya-sandbox git commit: TAMAYA-145: Added support
for Refreshable and property source level filtering.
TAMAYA-145: Added support for Refreshable and property source level filtering.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/commit/20c558d0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/tree/20c558d0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/diff/20c558d0
Branch: refs/heads/master
Commit: 20c558d0771a07da54fe26a9a8f28b80cb06014e
Parents: 7b9971d
Author: anatole <an...@apache.org>
Authored: Wed Dec 21 16:58:40 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Wed Dec 21 16:58:40 2016 +0100
----------------------------------------------------------------------
.../org/apache/tamaya/metamodel/Enabled.java | 37 +++++
.../tamaya/metamodel/EnabledPropertySource.java | 135 +++++++++++++++++++
.../EnabledPropertySourceProvider.java | 112 +++++++++++++++
.../apache/tamaya/metamodel/MetaContext.java | 10 ++
.../metamodel/internal/ContextReader.java | 4 +-
.../DSLLoadingConfigurationProviderSpi.java | 10 +-
.../internal/PropertySourceReader.java | 78 +++++++++++
7 files changed, 375 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/20c558d0/metamodel/src/main/java/org/apache/tamaya/metamodel/Enabled.java
----------------------------------------------------------------------
diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/Enabled.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/Enabled.java
new file mode 100644
index 0000000..b3051d3
--- /dev/null
+++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/Enabled.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tamaya.metamodel;
+
+/**
+ * Common interface for items that can be enabled or disabled.
+ */
+public interface Enabled {
+
+ /**
+ * Returns the enabled property.
+ * @return the enabled value.
+ */
+ boolean isEnabled();
+
+ /**
+ * Enables/disables this property source.
+ * @param enabled the enabled value.
+ */
+ void setEnabled(boolean enabled);
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/20c558d0/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java
----------------------------------------------------------------------
diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java
new file mode 100644
index 0000000..e231930
--- /dev/null
+++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySource.java
@@ -0,0 +1,135 @@
+/*
+ * 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.metamodel;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertyValue;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+
+/**
+ * Wrapped property source that allows enabling a property source using an
+ * {@code enabled} expression.
+ */
+public final class EnabledPropertySource
+ implements PropertySource, Enabled {
+
+ private static final Logger LOG = Logger.getLogger(EnabledPropertySource.class.getName());
+ private String enabledExpression;
+ private PropertySource wrapped;
+ private boolean enabled;
+
+ public EnabledPropertySource(PropertySource wrapped, Map<String,String> context, String expression) {
+ this.enabledExpression = Objects.requireNonNull(expression);
+ this.wrapped = Objects.requireNonNull(wrapped);
+ this.enabled = calculateEnabled(context);
+ }
+
+ protected boolean calculateEnabled(Map<String, String> context) {
+ try {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine engine = manager.getEngineByName("nashorn");
+ if(engine==null){
+ engine = manager.getEngineByName("rhino");
+ }
+ // init script engine
+ for(Map.Entry<String,String> entry: context.entrySet()) {
+ engine.put(entry.getKey(), entry.getValue());
+ }
+ Object o = engine.eval(enabledExpression);
+ if(!(o instanceof Boolean)){
+ LOG.severe("Enabled expression must evaluate to Boolean: '"
+ +enabledExpression+"', but was " + o +
+ ", property source will be disabled: " +
+ wrapped.getName());
+ return false;
+ }
+ return (Boolean)o;
+ } catch (ScriptException e) {
+ LOG.severe("Invalid Boolean expression: '"
+ +enabledExpression+"': " + e + ", property source will be disabled: " +
+ wrapped.getName());
+ }
+ return false;
+ }
+
+ /**
+ * Returns the enabled property.
+ * @return the enabled value.
+ */
+ @Override
+ public boolean isEnabled(){
+ return enabled;
+ }
+
+ /**
+ * Enables/disables this property source.
+ * @param enabled the enabled value.
+ */
+ @Override
+ public void setEnabled(boolean enabled){
+ this.enabled = enabled;
+ }
+
+ @Override
+ public int getOrdinal() {
+ return this.wrapped.getOrdinal();
+ }
+
+ @Override
+ public String getName() {
+ return this.wrapped.getName();
+ }
+
+ @Override
+ public PropertyValue get(String key) {
+ if(!isEnabled()){
+ return null;
+ }
+ return this.wrapped.get(key);
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ if(!isEnabled()){
+ return Collections.emptyMap();
+ }
+ return this.wrapped.getProperties();
+ }
+
+ @Override
+ public boolean isScannable() {
+ return this.wrapped.isScannable();
+ }
+
+ @Override
+ public String toString() {
+ return "DynamicPropertySource{" +
+ "\n enabled=" + enabledExpression +
+ "\n wrapped=" + wrapped +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/20c558d0/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySourceProvider.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySourceProvider.java
new file mode 100644
index 0000000..5dfed10
--- /dev/null
+++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/EnabledPropertySourceProvider.java
@@ -0,0 +1,112 @@
+/*
+ * 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.metamodel;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertySourceProvider;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Wrapped property source provider that allows enabling a property source using an
+ * {@code enabled} expression.
+ */
+public final class EnabledPropertySourceProvider
+ implements PropertySourceProvider, Enabled {
+
+ private static final Logger LOG = Logger.getLogger(EnabledPropertySourceProvider.class.getName());
+ private String enabledExpression;
+ private PropertySourceProvider wrapped;
+ private boolean enabled;
+
+ public EnabledPropertySourceProvider(PropertySourceProvider wrapped, Map<String,String> context, String expression) {
+ this.enabledExpression = Objects.requireNonNull(expression);
+ this.wrapped = Objects.requireNonNull(wrapped);
+ this.enabled = calculateEnabled(context);
+ }
+
+ protected boolean calculateEnabled(Map<String, String> context) {
+ try {
+ ScriptEngineManager manager = new ScriptEngineManager();
+ ScriptEngine engine = manager.getEngineByName("nashorn");
+ if(engine==null){
+ engine = manager.getEngineByName("rhino");
+ }
+ // init script engine
+ for(Map.Entry<String,String> entry: context.entrySet()) {
+ engine.put(entry.getKey(), entry.getValue());
+ }
+ Object o = engine.eval(enabledExpression);
+ if(!(o instanceof Boolean)){
+ LOG.severe("Enabled expression must evaluate to Boolean: '"
+ +enabledExpression+"', but was " + o +
+ ", property source provider will be disabled: " +
+ wrapped.getClass().getName());
+ return false;
+ }
+ return (Boolean)o;
+ } catch (ScriptException e) {
+ LOG.severe("Invalid Boolean expression: '"
+ +enabledExpression+"': " + e + ", property source provider will be disabled: " +
+ wrapped.getClass().getName());
+ }
+ return false;
+ }
+
+ /**
+ * Returns the enabled property.
+ * @return the enabled value.
+ */
+ @Override
+ public boolean isEnabled(){
+ return enabled;
+ }
+
+ /**
+ * Enables/disables this property source.
+ * @param enabled the enabled value.
+ */
+ @Override
+ public void setEnabled(boolean enabled){
+ this.enabled = enabled;
+ }
+
+ @Override
+ public Collection<PropertySource> getPropertySources() {
+ if(!isEnabled()){
+ return Collections.emptySet();
+ }
+ return this.wrapped.getPropertySources();
+ }
+
+ @Override
+ public String toString() {
+ return "DynamicPropertySourceProvider{" +
+ "\n enabled=" + enabledExpression +
+ "\n wrapped=" + wrapped +
+ '}';
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/20c558d0/metamodel/src/main/java/org/apache/tamaya/metamodel/MetaContext.java
----------------------------------------------------------------------
diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/MetaContext.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/MetaContext.java
index 4032c03..c4fa25a 100644
--- a/metamodel/src/main/java/org/apache/tamaya/metamodel/MetaContext.java
+++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/MetaContext.java
@@ -52,6 +52,7 @@ public final class MetaContext {
return new MetaContext();
}
};
+ public static final String DEFAULT_CONTEXT_NAME = "<DEFAULT>";
private String id;
@@ -72,6 +73,15 @@ public final class MetaContext {
}
/**
+ * Access the default context. Contexts are managed as weak references in this class. If no
+ * such context exists, a new instance is created.
+ * @return the context instance, never null.
+ */
+ public static MetaContext getDefaultInstance(){
+ return getInstance(DEFAULT_CONTEXT_NAME);
+ }
+
+ /**
* Access a context by name. Contexts are managed as weak references in this class. If no
* such valid context exists, a new instance is created, using the given {@code validSupplier}.
* @param contextName the context name, not null.
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/20c558d0/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/ContextReader.java
----------------------------------------------------------------------
diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/ContextReader.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/ContextReader.java
index 5754e4f..db72f13 100644
--- a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/ContextReader.java
+++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/ContextReader.java
@@ -39,7 +39,7 @@ public class ContextReader implements MetaConfigurationReader {
@Override
public void read(Document document, ConfigurationContextBuilder contextBuilder) {
NodeList nodeList = document.getDocumentElement().getElementsByTagName("context");
- String contextName = "DEFAULT";
+ String contextName = null;
LOG.finer("Reading " + nodeList.getLength() + " meta context entries...");
for(int i=0;i<nodeList.getLength();i++){
Node node = nodeList.item(i);
@@ -48,7 +48,7 @@ public class ContextReader implements MetaConfigurationReader {
if(nameNode!=null){
contextName = nameNode.getTextContent();
}
- MetaContext context = MetaContext.getInstance(contextName);
+ MetaContext context = contextName!=null?MetaContext.getInstance(contextName):MetaContext.getDefaultInstance();
NodeList entryNodes = node.getChildNodes();
for(int c=0;c<entryNodes.getLength();c++){
Node entryNode = entryNodes.item(c);
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/20c558d0/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DSLLoadingConfigurationProviderSpi.java
----------------------------------------------------------------------
diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DSLLoadingConfigurationProviderSpi.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DSLLoadingConfigurationProviderSpi.java
index 266ed5a..47ce7f0 100644
--- a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DSLLoadingConfigurationProviderSpi.java
+++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/DSLLoadingConfigurationProviderSpi.java
@@ -23,18 +23,10 @@ import org.apache.tamaya.spi.*;
import org.apache.tamaya.Configuration;
import org.apache.tamaya.spisupport.DefaultConfiguration;
import org.apache.tamaya.spisupport.DefaultConfigurationContextBuilder;
-import org.w3c.dom.Document;
-import org.xml.sax.InputSource;
import javax.annotation.Priority;
-import javax.xml.parsers.DocumentBuilderFactory;
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.util.Comparator;
import java.util.Objects;
-import java.util.logging.Level;
-import java.util.logging.Logger;
/**
* ConfigurationContext that uses {@link MetaConfiguration} to configure the
@@ -48,7 +40,7 @@ public class DSLLoadingConfigurationProviderSpi implements ConfigurationProvider
@Override
public ConfigurationContextBuilder getConfigurationContextBuilder() {
- return ServiceContextManager.getServiceContext().getService(ConfigurationContextBuilder.class);
+ return ServiceContextManager.getServiceContext().create(ConfigurationContextBuilder.class);
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/20c558d0/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/PropertySourceReader.java
----------------------------------------------------------------------
diff --git a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/PropertySourceReader.java b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/PropertySourceReader.java
index 8f42a3b..b3f107c 100644
--- a/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/PropertySourceReader.java
+++ b/metamodel/src/main/java/org/apache/tamaya/metamodel/internal/PropertySourceReader.java
@@ -18,10 +18,12 @@
*/
package org.apache.tamaya.metamodel.internal;
+import org.apache.tamaya.metamodel.*;
import org.apache.tamaya.metamodel.spi.ItemFactory;
import org.apache.tamaya.metamodel.spi.ItemFactoryManager;
import org.apache.tamaya.metamodel.spi.MetaConfigurationReader;
import org.apache.tamaya.spi.ConfigurationContextBuilder;
+import org.apache.tamaya.spi.PropertyFilter;
import org.apache.tamaya.spi.PropertySource;
import org.apache.tamaya.spi.PropertySourceProvider;
import org.w3c.dom.Document;
@@ -66,6 +68,7 @@ public class PropertySourceReader implements MetaConfigurationReader{
PropertySource ps = sourceFactory.create(params);
if(ps!=null) {
ComponentConfigurator.configure(ps, params);
+ ps = decoratePropertySource(ps, contextBuilder, node, params);
LOG.finer("Adding configured property source: " + ps.getName());
contextBuilder.addPropertySources(ps);
}
@@ -84,6 +87,7 @@ public class PropertySourceReader implements MetaConfigurationReader{
PropertySourceProvider prov = providerFactory.create(params);
if(prov!=null) {
ComponentConfigurator.configure(prov, node);
+ prov = decoratePropertySourceProvider(prov, contextBuilder, node, params);
LOG.finer("Adding configured property source provider: " + prov.getClass().getName());
contextBuilder.addPropertySources(prov.getPropertySources());
}
@@ -100,4 +104,78 @@ public class PropertySourceReader implements MetaConfigurationReader{
}
}
+ /**
+ * Decorates a property source to be refreshable or filtered.
+ * @param ps the wrapped property source
+ * @param contextBuilder
+ *@param configNode the XML config node
+ * @param params the extracted parameter list @return the property source to be added to the context.
+ */
+ private PropertySource decoratePropertySource(PropertySource ps, ConfigurationContextBuilder contextBuilder, Node configNode, Map<String, String> params){
+ Node refreshableVal = configNode.getAttributes().getNamedItem("refreshable");
+ if(refreshableVal!=null && Boolean.parseBoolean(refreshableVal.getNodeValue())){
+ if(!(ps instanceof Refreshable)){
+ ps = RefreshablePropertySource.of(params, ps);
+ }
+ }
+ NodeList childNodes = configNode.getChildNodes();
+ for(int i=0;i<childNodes.getLength();i++){
+ Node node = childNodes.item(i);
+ if("filter".equals(node.getNodeName())) {
+ ps = FilteredPropertySource.of(ps);
+ configureFilter((FilteredPropertySource) ps, node);
+ }
+ }
+ Node enabledVal = configNode.getAttributes().getNamedItem("enabled");
+ if(enabledVal!=null){
+ ps = new EnabledPropertySource(ps,
+ MetaContext.getDefaultInstance().getProperties(),
+ enabledVal.getNodeValue());
+ }
+ return ps;
+ }
+
+ private void configureFilter(FilteredPropertySource ps, Node filterNode) {
+ try {
+ String type = filterNode.getAttributes().getNamedItem("type").getNodeValue();
+ ItemFactory<PropertyFilter> filterFactory = ItemFactoryManager.getInstance().getFactory(PropertyFilter.class, type);
+ if(filterFactory==null){
+ LOG.severe("No such property filter: " + type);
+ return;
+ }
+ Map<String,String> params = ComponentConfigurator.extractParameters(filterNode);
+ PropertyFilter filter = filterFactory.create(params);
+ if(filter!=null) {
+ ComponentConfigurator.configure(filter, params);
+ LOG.finer("Adding configured property filter: " + filter.getClass().getName());
+ ps.addPropertyFilter(filter);
+ }
+ }catch(Exception e){
+ LOG.log(Level.SEVERE, "Failed to read property filter configuration: " + filterNode, e);
+ }
+ }
+
+ /**
+ * Decorates a property source provider to be refreshable or filtered.
+ * @param prov the property source provider to be wrapped.
+ * @param contextBuilder
+ *@param configNode the XML config node
+ * @param params the extracted parameter list @return the property source provider to be added to the context.
+ */
+ private PropertySourceProvider decoratePropertySourceProvider(PropertySourceProvider prov, ConfigurationContextBuilder contextBuilder, Node configNode, Map<String, String> params){
+ Node refreshableVal = configNode.getAttributes().getNamedItem("refreshable");
+ if(refreshableVal!=null && Boolean.parseBoolean(refreshableVal.getNodeValue())){
+ if(!(prov instanceof Refreshable)){
+ prov = RefreshablePropertySourceProvider.of(params, prov);
+ }
+ }
+ Node enabledVal = configNode.getAttributes().getNamedItem("enabled");
+ if(enabledVal!=null){
+ prov = new EnabledPropertySourceProvider(prov,
+ MetaContext.getDefaultInstance().getProperties(),
+ enabledVal.getNodeValue());
+ }
+ return prov;
+ }
+
}