http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/main/java/org/apache/tamaya/inject/internal/InjectionUtils.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/main/java/org/apache/tamaya/inject/internal/InjectionUtils.java b/modules/injection/src/main/java/org/apache/tamaya/inject/internal/InjectionUtils.java new file mode 100644 index 0000000..d80ee80 --- /dev/null +++ b/modules/injection/src/main/java/org/apache/tamaya/inject/internal/InjectionUtils.java @@ -0,0 +1,221 @@ +package org.apache.tamaya.core.internal.inject; + +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.PropertyAdapter; +import org.apache.tamaya.annotation.*; +import org.apache.tamaya.annotation.WithPropertyAdapter; +import org.apache.tamaya.core.internal.Utils; +import org.apache.tamaya.spi.PropertyAdapterSpi; + +/** + * Created by Anatole on 19.12.2014. + */ +@SuppressWarnings("unchecked") +final class InjectionUtils { + + private InjectionUtils(){} + + /** + * This method evaluates the {@link org.apache.tamaya.Configuration} that currently is valid for the given target field/method. + * + * @return the {@link org.apache.tamaya.Configuration} instance to be used, never null. + */ + public static Configuration getConfiguration(ConfiguredProperty prop, Configuration... configuration) { + String name = prop.config(); + if (name != null && !name.trim().isEmpty()) { + return Configuration.current(name.trim()); + } + return Configuration.current(); + } + + /** + * Evaluates all absolute configuration key based on the annotations found on a class. + * + * @param areasAnnot the (optional) annotation definining areas to be looked up. + * @param propertyAnnotation the annotation on field/method level that may defined one or + * several keys to be looked up (in absolute or relative form). + * @return the list current keys in order how they should be processed/looked up. + */ + public static List<String> evaluateKeys(Member member, DefaultAreas areasAnnot, ConfiguredProperty propertyAnnotation) { + List<String> keys = new ArrayList<>(Arrays.asList(propertyAnnotation.keys())); + if (keys.isEmpty()) //noinspection UnusedAssignment + keys.add(member.getName()); + ListIterator<String> iterator = keys.listIterator(); + while (iterator.hasNext()) { + String next = iterator.next(); + if (next.startsWith("[") && next.endsWith("]")) { + // absolute key, strip away brackets, take key as is + iterator.set(next.substring(1, next.length() - 1)); + } else { + if (areasAnnot != null) { + // Remove original entry, since it will be replaced with prefixed entries + iterator.remove(); + // Add prefixed entries, including absolute (root) entry for "" area keys. + for (String area : areasAnnot.value()) { + iterator.add(area.isEmpty() ? next : area + '.' + next); + } + } + } + } + return keys; + } + + /** + * Evaluates all absolute configuration key based on the member name found. + * + * @param areasAnnot the (optional) annotation definining areas to be looked up. + * @return the list current keys in order how they should be processed/looked up. + */ + public static List<String> evaluateKeys(Member member, DefaultAreas areasAnnot) { + List<String> keys = new ArrayList<>(); + String name = member.getName(); + String mainKey; + if(name.startsWith("get") || name.startsWith("set")){ + mainKey = Character.toLowerCase(name.charAt(3)) + name.substring(4); + } + else{ + mainKey = Character.toLowerCase(name.charAt(0)) + name.substring(1); + } + keys.add(mainKey); + if (areasAnnot != null) { + // Add prefixed entries, including absolute (root) entry for "" area keys. + for (String area : areasAnnot.value()) { + if(!area.isEmpty()) { + keys.add(area + '.' + mainKey); + } + } + } + else{ // add package name + keys.add(member.getDeclaringClass().getName()+'.'+mainKey); + } + return keys; + } + + /** + * Internally evaluated the current valid configuration keys based on the given annotations present. + * + * @return the keys to be returned, or null. + */ + public static String getConfigValue(Method method, Configuration... configurations) { + DefaultAreas areasAnnot = method.getDeclaringClass().getAnnotation(DefaultAreas.class); + WithLoadPolicy loadPolicy = Utils.getAnnotation(WithLoadPolicy.class, method, method.getDeclaringClass()); + return getConfigValueInternal(method, areasAnnot, loadPolicy, configurations); + } + + + /** + * Internally evaluated the current valid configuration keys based on the given annotations present. + * + * @return the keys to be returned, or null. + */ + public static String getConfigValue(Field field, Configuration... configurations) { + DefaultAreas areasAnnot = field.getDeclaringClass().getAnnotation(DefaultAreas.class); + WithLoadPolicy loadPolicy = Utils.getAnnotation(WithLoadPolicy.class, field, field.getDeclaringClass()); + return getConfigValueInternal(field, areasAnnot, loadPolicy, configurations); + } + + /** + * Internally evaluated the current valid configuration keys based on the given annotations present. + * + * @return the keys to be returned, or null. + */ + private static String getConfigValueInternal(AnnotatedElement element, DefaultAreas areasAnnot, WithLoadPolicy loadPolicy, Configuration... configurations) { + Collection<ConfiguredProperty> configuredProperties = Utils.getAnnotations( + element, ConfiguredProperty.class, ConfiguredProperties.class); + DefaultValue defaultAnnot = element.getAnnotation(DefaultValue.class); + String configValue = null; + if(configuredProperties.isEmpty()){ + List<String> keys = InjectionUtils.evaluateKeys((Member)element, areasAnnot); + Configuration config = InjectionUtils.getConfiguration("default", configurations); + configValue = evaluteConfigValue(configValue, keys, config); + } + else { + for (ConfiguredProperty prop : configuredProperties) { + List<String> keys = InjectionUtils.evaluateKeys((Member) element, areasAnnot, prop); + Configuration config = InjectionUtils.getConfiguration(prop, configurations); + configValue = evaluteConfigValue(configValue, keys, config); + } + } + if (configValue == null && defaultAnnot != null) { + return defaultAnnot.value(); + } + return configValue; + } + + private static String evaluteConfigValue(String configValue, List<String> keys, Configuration config) { + for (String key : keys) { + configValue = config.get(key).orElse(null); + if (configValue != null) { + break; + } + } + if (configValue != null) { + // net step perform expression resolution, if any + configValue = Configuration.evaluateValue(configValue, config); + } + return configValue; + } + + + @SuppressWarnings("rawtypes") + public static <T> T adaptValue(AnnotatedElement element, Class<T> targetType, String configValue){ + try { + // Check for adapter/filter +// T adaptedValue = null; + WithPropertyAdapter codecAnnot = element.getAnnotation(WithPropertyAdapter.class); + Class<? extends PropertyAdapter> codecType; + if (codecAnnot != null) { + codecType = codecAnnot.value(); + if (!codecType.equals(PropertyAdapter.class)) { + // TODO cache here... +// Codec<String> codec = codecType.newInstance(); +// adaptedValue = (T) codec.adapt(configValue); + } + } + if (String.class.equals(targetType)) { + return (T)configValue; + } else { + PropertyAdapter<?> adapter = PropertyAdapter.getInstance(targetType); + return (T)adapter.adapt(configValue); + } + } catch (Exception e) { + throw new ConfigException("Failed to annotate configured member: " + element, e); + } + } + + /** + * This method evaluates the {@link Configuration} that currently is valid for the given target field/method. + * @param configurations Configuration instances that replace configuration served by services. This allows + * more easily testing and adaption. + * @return the {@link Configuration} instance to be used, never null. + */ + public static Configuration getConfiguration(String name, Configuration... configurations) { + if(name!=null) { + for(Configuration conf: configurations){ + if(name.equals(conf.getName())){ + return conf; + } + } + return Configuration.current(name); + } + else{ + for(Configuration conf: configurations){ + if("default".equals(conf.getName())){ + return conf; + } + } + } + return Configuration.current(); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/main/java/org/apache/tamaya/inject/internal/WeakConfigListenerManager.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/main/java/org/apache/tamaya/inject/internal/WeakConfigListenerManager.java b/modules/injection/src/main/java/org/apache/tamaya/inject/internal/WeakConfigListenerManager.java new file mode 100644 index 0000000..e9b9ec3 --- /dev/null +++ b/modules/injection/src/main/java/org/apache/tamaya/inject/internal/WeakConfigListenerManager.java @@ -0,0 +1,117 @@ +/* + * 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.core.internal.inject; + +import org.apache.tamaya.core.properties.PropertyChangeSet; + +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.StampedLock; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Simple listener container that only holds weak references on the listeners. + */ +public final class WeakConfigListenerManager{ + + private static final WeakConfigListenerManager INSTANCE = new WeakConfigListenerManager(); + + private static final Logger LOG = Logger.getLogger(WeakConfigListenerManager.class.getName()); + private StampedLock lock = new StampedLock(); + private Map<Object,Consumer<PropertyChangeSet>> listenerReferences = new WeakHashMap<>(); + + /** Private singleton constructor. */ + private WeakConfigListenerManager(){} + + public static WeakConfigListenerManager of(){ + return INSTANCE; + } + + /** + * Registers the given consumer for the instance. If a consumer already exists for this instance the given + * consumer is appended. + * @param instance the instance, not null. + * @param listener the consumer. + */ + public void registerConsumer(Object instance, Consumer<PropertyChangeSet> listener){ + Lock writeLock = lock.asWriteLock(); + try { + writeLock.lock(); + Consumer<PropertyChangeSet> l = listenerReferences.get(instance); + if (l == null) { + listenerReferences.put(instance, listener); + } else { + listenerReferences.put(instance, l.andThen(listener)); + } + } + finally{ + writeLock.unlock(); + } + } + + /** + * Unregisters all consumers for the given instance. + * @param instance the instance, not null. + */ + public void unregisterConsumer(Object instance) { + Lock writeLock = lock.asWriteLock(); + try { + writeLock.lock(); + listenerReferences.remove(instance); + } + finally{ + writeLock.unlock(); + } + } + + /** + * Publishes a change event to all consumers registered. + * @param change the change event, not null. + */ + public void publishChangeEvent(PropertyChangeSet change){ + Lock readLock = lock.asReadLock(); + try{ + readLock.lock(); + listenerReferences.values().parallelStream().forEach(l -> { + try{ + l.accept(change); + } + catch(Exception e){ + LOG.log(Level.SEVERE, "ConfigChangeListener failed: " + l.getClass().getName(), e); + } + }); + } + finally{ + readLock.unlock(); + } + } + + + @Override + public String toString(){ + return "WeakConfigListenerManager{" + + "listenerReferences=" + listenerReferences + + '}'; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/main/java/org/apache/tamaya/inject/spi/ConfigurationFactorySpi.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/main/java/org/apache/tamaya/inject/spi/ConfigurationFactorySpi.java b/modules/injection/src/main/java/org/apache/tamaya/inject/spi/ConfigurationFactorySpi.java new file mode 100644 index 0000000..3b167cc --- /dev/null +++ b/modules/injection/src/main/java/org/apache/tamaya/inject/spi/ConfigurationFactorySpi.java @@ -0,0 +1,60 @@ +/* + * 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.spi; + +import org.apache.tamaya.Configuration; +import org.apache.tamaya.PropertySource; + +import java.util.Map; +import java.util.Optional; + +/** + * Factory to create configurations from property sources. If not defines a default is used. + */ +public interface ConfigurationFactorySpi { + /** + * Creates a configuration from a {@link org.apache.tamaya.PropertySource}. + * + * @param propertySource the property source + * @return the corresponding Configuration instance, never null. + */ + default Configuration from(PropertySource propertySource){ + return new Configuration() { + @Override + public String getName() { + return propertySource.getName(); + } + + @Override + public Optional<String> get(String key) { + return propertySource.get(key); + } + + @Override + public Map<String, String> getProperties() { + return propertySource.getProperties(); + } + + @Override + public String toString(){ + return "Configuration, based on " + propertySource; + } + }; + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/main/java/org/apache/tamaya/inject/spi/ConfigurationSpi.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/main/java/org/apache/tamaya/inject/spi/ConfigurationSpi.java b/modules/injection/src/main/java/org/apache/tamaya/inject/spi/ConfigurationSpi.java new file mode 100644 index 0000000..5891dc2 --- /dev/null +++ b/modules/injection/src/main/java/org/apache/tamaya/inject/spi/ConfigurationSpi.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tamaya.spi; + +import org.apache.tamaya.Configuration; +import org.apache.tamaya.PropertyAdapter; +import org.apache.tamaya.PropertySource; +import org.apache.tamaya.annotation.WithPropertyAdapter; + +import java.util.Map; +import java.util.Optional; + + +/** + * Manager for {@link org.apache.tamaya.Configuration} instances. Implementations must register an instance + * using the {@link ServiceContextManager} mechanism in place (by default this is based on the {@link java.util.ServiceLoader}. + * The {@link org.apache.tamaya.Configuration} Singleton in the API delegates its corresponding calls to the + * instance returned by the current bootstrap service in place. + * + * @see org.apache.tamaya.Configuration + * @see ServiceContextManager + */ +public interface ConfigurationSpi { + + /** + * Allows to check if a configuration with a given name is defined. + * @param name the configuration's name, not null, not empty. + * @return true, if such a configuration is defined. + */ + boolean isConfigurationAvailable(String name); + + /** + * Access a configuration by name. + * @param name the configuration's name, not null, not empty. + * @return the corresponding Configuration instance, never null. + * @throws org.apache.tamaya.ConfigException if no such configuration is defined. + */ + Configuration getConfiguration(String name); + + /** + * Access the default configuration. + * @return the corresponding Configuration instance, never null. + * @throws org.apache.tamaya.ConfigException if no such configuration is defined. + */ + default Configuration getConfiguration(){ + return getConfiguration("default"); + } + + /** + * Configures an instance, by resolving and injecting the configuration + * entries. + * + * @param instance the instance with configuration annotations, not null. + * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}. + * If no such config is passed, the default configurationa provided by the current + * registered providers are used. + * @throws org.apache.tamaya.ConfigException if any required configuration could not be resolved/injected. + */ + void configure(Object instance, Configuration... configurations); + + /** + * Access a configuration by name. + * + * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}, not null. + * If no such config is passed, the default configurationa provided by the current + * registered providers are used. + * @return the corresponding Configuration instance, never null. + * @throws org.apache.tamaya.ConfigException if no such configuration is defined. + */ + <T> T createTemplate(Class<T> template, Configuration... configurations); + + /** + * Evaluate the current expression based on the current configuration valid. + * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}, not null. + * If no such config is passed, the default configurationa provided by the current + * registered providers are used. + * @param expression the expression, not null. + * @return the evaluated config expression. + */ + String evaluateValue(String expression, Configuration... configurations); + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/main/java/org/apache/tamaya/inject/spi/PropertyAdapterSpi.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/main/java/org/apache/tamaya/inject/spi/PropertyAdapterSpi.java b/modules/injection/src/main/java/org/apache/tamaya/inject/spi/PropertyAdapterSpi.java new file mode 100644 index 0000000..a1222a4 --- /dev/null +++ b/modules/injection/src/main/java/org/apache/tamaya/inject/spi/PropertyAdapterSpi.java @@ -0,0 +1,72 @@ +/* + * 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.spi; + +import org.apache.tamaya.Configuration; +import org.apache.tamaya.PropertyAdapter; +import org.apache.tamaya.annotation.WithPropertyAdapter; + + +/** + * Manager for {@link org.apache.tamaya.Configuration} instances. Implementations must register an instance + * using the {@link org.apache.tamaya.spi.ServiceContextManager} mechanism in place (by default this is based on the {@link java.util.ServiceLoader}. + * The {@link org.apache.tamaya.Configuration} Singleton in the API delegates its corresponding calls to the + * instance returned by the current bootstrap service in place. + * + * @see org.apache.tamaya.Configuration + * @see org.apache.tamaya.spi.ServiceContextManager + */ +public interface PropertyAdapterSpi { + + + /** + * Registers a new PropertyAdapter for the given target type, hereby replacing any existing adapter for + * this type. + * @param targetType The target class, not null. + * @param adapter The adapter, not null. + * @param <T> The target type + * @return any adapter replaced with the new adapter, or null. + */ + <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> adapter); + + /** + * Get an adapter converting to the given target type. + * @param targetType the target type class + * @return true, if the given target type is supported. + */ + default <T> PropertyAdapter<T> getAdapter(Class<T> targetType){ + return getPropertyAdapter(targetType, null); + } + + /** + * Get an adapter converting to the given target type. + * @param targetType the target type class + * @param <T> the target type + * @return the corresponding adapter, never null. + * @throws org.apache.tamaya.ConfigException if the target type is not supported. + */ + <T> PropertyAdapter<T> getPropertyAdapter(Class<T> targetType, WithPropertyAdapter annotation); + + /** + * Checks if the given target type is supported, i.e. a adapter is registered and accessible. + * @param targetType the target type class + * @return true, if the given target type is supported. + */ + boolean isTargetTypeSupported(Class<?> targetType); +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/test/java/annottext/AnnotatedConfig.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/test/java/annottext/AnnotatedConfig.java b/modules/injection/src/test/java/annottext/AnnotatedConfig.java new file mode 100644 index 0000000..b9160e3 --- /dev/null +++ b/modules/injection/src/test/java/annottext/AnnotatedConfig.java @@ -0,0 +1,51 @@ +/* + * 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 annottext; + +import org.apache.tamaya.annotation.ConfiguredProperty; +import org.apache.tamaya.annotation.WithLoadPolicy; +import org.apache.tamaya.annotation.DefaultValue; +import org.apache.tamaya.annotation.LoadPolicy; + +/** + * An example showing some basic annotations, using an interface to be proxied by the + * configuration system. + * Created by Anatole on 15.02.14. + */ +@WithLoadPolicy(LoadPolicy.INITIAL) +public interface AnnotatedConfig { + + @ConfiguredProperty(keys = "foo.bar.myprop") + @ConfiguredProperty(keys = "mp") + @ConfiguredProperty(keys = "common.testdata.myProperty") + @DefaultValue("myValue_$[env.stage]") + // @ConfigLoadPolicy(listener = MyListener.class) + String myParameter(); + + @ConfiguredProperty(keys = "simple_value") + @WithLoadPolicy(LoadPolicy.LAZY) + String simpleValue(); + + @ConfiguredProperty + String simplestValue(); + + @ConfiguredProperty(keys = "env.host.name") + String hostName(); + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/test/java/annottext/AnnotatedFullConfig.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/test/java/annottext/AnnotatedFullConfig.java b/modules/injection/src/test/java/annottext/AnnotatedFullConfig.java new file mode 100644 index 0000000..c59fb82 --- /dev/null +++ b/modules/injection/src/test/java/annottext/AnnotatedFullConfig.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 annottext; + +import org.apache.tamaya.Configuration; +import org.apache.tamaya.annotation.ConfiguredProperty; +import org.apache.tamaya.annotation.WithLoadPolicy; +import org.apache.tamaya.annotation.DefaultValue; +import org.apache.tamaya.annotation.LoadPolicy; + +/** + * An example showing some basic annotations, using an interface to be proxied by the + * configuration system, nevertheless extending the overall Configuration interface. + * Created by Anatole on 15.02.14. + */ +@WithLoadPolicy(LoadPolicy.INITIAL) +public interface AnnotatedFullConfig extends Configuration{ + + @ConfiguredProperty(keys = "foo.bar.myprop") + @ConfiguredProperty(keys = "mp") + @ConfiguredProperty(keys = "common.testdata.myProperty") + @DefaultValue("myValue_$[env.stage]") + // @ConfigLoadPolicy(listener = MyListener.class) + String myParameter(); + + @ConfiguredProperty(keys = "simple_value") + @WithLoadPolicy(LoadPolicy.LAZY) + String simpleValue(); + + @ConfiguredProperty + String simplestValue(); + + @ConfiguredProperty(keys = "env.host.name") + String hostName(); + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java b/modules/injection/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java new file mode 100644 index 0000000..3245877 --- /dev/null +++ b/modules/injection/src/test/java/org/apache/tamaya/TestConfigServiceSingletonSpi.java @@ -0,0 +1,90 @@ +/* + * 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; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + +import org.apache.tamaya.spi.ConfigurationSpi; + +/** + * Created by Anatole on 09.09.2014. + */ +public class TestConfigServiceSingletonSpi implements ConfigurationSpi { + + + private Map<String, Configuration> configs = new ConcurrentHashMap<>(); + + public TestConfigServiceSingletonSpi(){ + Map<String,String> config = new HashMap<>(); + config.put("a.b.c.key1", "keys current a.b.c.key1"); + config.put("a.b.c.key2", "keys current a.b.c.key2"); + config.put("a.b.key3", "keys current a.b.key3"); + config.put("a.b.key4", "keys current a.b.key4"); + config.put("a.key5", "keys current a.key5"); + config.put("a.key6", "keys current a.key6"); + config.put("int1", "123456"); + config.put("int2", "111222"); + config.put("booleanT", "true"); + config.put("double1", "1234.5678"); + config.put("BD", "123456789123456789123456789123456789.123456789123456789123456789123456789"); + config.put("testProperty", "keys current testProperty"); + config.put("runtimeVersion", "${java.version}"); + // configs.put("testdata", new MapConfiguration(MetaInfoBuilder.current().setName("testdata").build(), config)); + } + + + + @Override + public boolean isConfigurationAvailable(String name){ + return configs.containsKey(name); + } + + @Override + public Configuration getConfiguration(String name) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public <T> T createTemplate(Class<T> type, Configuration... configurations) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void configure(Object instance, Configuration... configurations) { + // TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public String evaluateValue(String expression, Configuration... configurations) { + // TODO improve this ugly implementation... + for (Configuration config : configurations) { + for (Map.Entry<String, String> en : config.getProperties().entrySet()) { + expression = expression.replaceAll("\\$\\{" + en.getKey() + "\\}", en.getValue()); + } + } + return expression; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java ---------------------------------------------------------------------- diff --git a/modules/injection/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java b/modules/injection/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java new file mode 100644 index 0000000..65e6c1d --- /dev/null +++ b/modules/injection/src/test/java/org/apache/tamaya/TestPropertyAdaptersSingletonSpi.java @@ -0,0 +1,99 @@ +/* + * 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; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.util.Currency; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tamaya.annotation.WithPropertyAdapter; +import org.apache.tamaya.spi.PropertyAdapterSpi; + +/** + * Test implementation current {@link org.apache.tamaya.spi.PropertyAdapterSpi}, which provides propertyAdapters + * for some basic types. + */ +@SuppressWarnings({"unchecked", "rawtypes"}) +public final class TestPropertyAdaptersSingletonSpi implements PropertyAdapterSpi { + + private Map<Class, PropertyAdapter<?>> propertyAdapters = new ConcurrentHashMap<>(); + + private TestPropertyAdaptersSingletonSpi(){ + register(char.class, (s) -> s.charAt(0)); + register(int.class, Integer::parseInt); + register(byte.class, Byte::parseByte); + register(short.class, Short::parseShort); + register(boolean.class, Boolean::parseBoolean); + register(float.class, Float::parseFloat); + register(double.class, Double::parseDouble); + + register(Character.class, (s) -> s.charAt(0)); + register(Integer.class, Integer::valueOf); + register(Byte.class, Byte::valueOf); + register(Short.class, Short::valueOf); + register(Boolean.class, Boolean::valueOf); + register(Float.class, Float::valueOf); + register(Double.class, Double::valueOf); + register(BigDecimal.class, BigDecimal::new); + register(BigInteger.class, BigInteger::new); + + register(Currency.class, Currency::getInstance); + + register(LocalDate.class, LocalDate::parse); + register(LocalTime.class, LocalTime::parse); + register(LocalDateTime.class, LocalDateTime::parse); + register(ZoneId.class, ZoneId::of); + } + + + @Override + public <T> PropertyAdapter<T> register(Class<T> targetType, PropertyAdapter<T> codec){ + Objects.requireNonNull(targetType); + Objects.requireNonNull(codec); + return (PropertyAdapter<T>) propertyAdapters.put(targetType, codec); + } + + @Override + public <T> PropertyAdapter<T> getPropertyAdapter(Class<T> targetType, WithPropertyAdapter annotation){ + if(annotation!=null){ + Class<?> adapterType = annotation.value(); + if(!adapterType.equals(PropertyAdapter.class)){ + try{ + return (PropertyAdapter<T>)adapterType.newInstance(); + } + catch(Exception e){ + throw new ConfigException("Failed to load PropertyAdapter: " + adapterType, e); + } + } + } + return (PropertyAdapter<T>) propertyAdapters.get(targetType); + } + + @Override + public boolean isTargetTypeSupported(Class<?> targetType){ + return propertyAdapters.containsKey(targetType); + } +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/test/resources/META-INF/beans.xml ---------------------------------------------------------------------- diff --git a/modules/injection/src/test/resources/META-INF/beans.xml b/modules/injection/src/test/resources/META-INF/beans.xml new file mode 100644 index 0000000..5207c9a --- /dev/null +++ b/modules/injection/src/test/resources/META-INF/beans.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +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. +--> +<beans xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://java.sun.com/xml/ns/javaee + http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> +</beans> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/test/resources/META-INF/services/org.apache.tamaya.spi.ConfigurationSpi ---------------------------------------------------------------------- diff --git a/modules/injection/src/test/resources/META-INF/services/org.apache.tamaya.spi.ConfigurationSpi b/modules/injection/src/test/resources/META-INF/services/org.apache.tamaya.spi.ConfigurationSpi new file mode 100644 index 0000000..1b0cdd4 --- /dev/null +++ b/modules/injection/src/test/resources/META-INF/services/org.apache.tamaya.spi.ConfigurationSpi @@ -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.TestConfigServiceSingletonSpi http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/injection/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi ---------------------------------------------------------------------- diff --git a/modules/injection/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi b/modules/injection/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi new file mode 100644 index 0000000..e9b04b4 --- /dev/null +++ b/modules/injection/src/test/resources/META-INF/services/org.apache.tamaya.spi.PropertyAdapterSpi @@ -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.TestPropertyAdaptersSingletonSpi http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/integration/pom.xml ---------------------------------------------------------------------- diff --git a/modules/integration/pom.xml b/modules/integration/pom.xml new file mode 100644 index 0000000..efc019d --- /dev/null +++ b/modules/integration/pom.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>tamaya-extensions-all</artifactId> + <groupId>org.apache.tamaya.ext</groupId> + <version>0.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <packaging>pom</packaging> + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.tamaya.ext.integration</groupId> + <artifactId>tamaya-integrations</artifactId> + + <modules> + <module>cdi</module> + <module>se</module> + </modules> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/management/pom.xml ---------------------------------------------------------------------- diff --git a/modules/management/pom.xml b/modules/management/pom.xml new file mode 100644 index 0000000..6d6e441 --- /dev/null +++ b/modules/management/pom.xml @@ -0,0 +1,41 @@ +<!-- +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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-extensions</artifactId> + <version>0.2-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>tamaya-management</artifactId> + <name>Apache Tamaya Modules Integration - Java Management Extensions</name> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>tamaya-core</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/metamodels/environment/pom.xml ---------------------------------------------------------------------- diff --git a/modules/metamodels/environment/pom.xml b/modules/metamodels/environment/pom.xml new file mode 100644 index 0000000..85a45ee --- /dev/null +++ b/modules/metamodels/environment/pom.xml @@ -0,0 +1,34 @@ +<!-- +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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya.ext.metamodels</groupId> + <artifactId>tamaya-metamodels</artifactId> + <version>0.2-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>tamaya-metamodel-environment</artifactId> + <name>Apache Tamaya Modules Metamodels - environment</name> + <description>Environment Tamaya Metamodel</description> + <packaging>jar</packaging> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/metamodels/pom.xml ---------------------------------------------------------------------- diff --git a/modules/metamodels/pom.xml b/modules/metamodels/pom.xml new file mode 100644 index 0000000..2631d94 --- /dev/null +++ b/modules/metamodels/pom.xml @@ -0,0 +1,39 @@ +<!-- +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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya.ext</groupId> + <artifactId>tamaya-extensions</artifactId> + <version>0.2-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <groupId>org.apache.tamaya.ext.metamodels</groupId> + <artifactId>tamaya-metamodels</artifactId> + <name>Apache Tamaya Extension Modules: Metamodels</name> + <packaging>pom</packaging> + + <modules> + <module>simple</module> + <module>environment</module> + </modules> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/metamodels/simple/pom.xml ---------------------------------------------------------------------- diff --git a/modules/metamodels/simple/pom.xml b/modules/metamodels/simple/pom.xml new file mode 100644 index 0000000..898ab2f --- /dev/null +++ b/modules/metamodels/simple/pom.xml @@ -0,0 +1,34 @@ +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya.ext.metamodels</groupId> + <artifactId>tamaya-metamodels</artifactId> + <version>0.1-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>tamaya-metamodel-simple</artifactId> + <name>Apache Tamaya Modules Metamodels - Simple</name> + <description>Simple Tamaya Metamodel, e.g. feasible for SE commandline tools and simple use cases.</description> + <packaging>jar</packaging> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/pom.xml ---------------------------------------------------------------------- diff --git a/modules/pom.xml b/modules/pom.xml new file mode 100644 index 0000000..c2aa0b2 --- /dev/null +++ b/modules/pom.xml @@ -0,0 +1,42 @@ +<!-- +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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.tamaya</groupId> + <artifactId>tamaya-all</artifactId> + <version>0.2-SNAPSHOT</version> + <relativePath>..</relativePath> + </parent> + <artifactId>tamaya-extensions</artifactId> + <groupId>org.apache.tamaya.ext</groupId> + <name>Apache Tamaya Extension Modules</name> + <description>This project contains the several extensions that can be used with Tamaya.</description> + <packaging>pom</packaging> + + <modules> + <module>injection</module> + <module>resolver</module> + <module>metamodels</module> + <module>integration</module> + </modules> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/resolver/src/main/java/org/apache/tamaya/resolver/ExpressionEvaluator.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/ExpressionEvaluator.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/ExpressionEvaluator.java new file mode 100644 index 0000000..5baa956 --- /dev/null +++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/ExpressionEvaluator.java @@ -0,0 +1,38 @@ +/* + * 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.core.spi; + +import org.apache.tamaya.Configuration; + +/** + * This interfaces provides a model for expression evaluation. This enables transparently plugin expression languages + * as needed. In a Java EE context full fledged EL may be used, whereas in ME only simple replacement mechanisms + * are better suited to the runtime requirements. + */ +@FunctionalInterface +public interface ExpressionEvaluator { + /** + * Evaluates the given expression. + * @param expression the expression to be evaluated, not null. + * @param configurations the configurations to be used for evaluating the values for injection into {@code instance}. + * If no items are passed, the default configuration is used. + * @return the evaluated expression. + */ + String evaluate(String expression, Configuration... configurations); +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java new file mode 100644 index 0000000..457aa6c --- /dev/null +++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java @@ -0,0 +1,144 @@ +/* + * 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.core.internal.el; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.spi.ServiceContext; +import org.apache.tamaya.core.spi.ExpressionEvaluator; +import org.apache.tamaya.core.spi.ExpressionResolver; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Default expression evaluator that manages several instances of {@link org.apache.tamaya.core.spi.ExpressionResolver}. + * Each resolver is identified by a resolver id. Each expression passed has the form resolverId:resolverExpression, which + * has the advantage that different resolvers can be active in parallel. + */ +public final class DefaultExpressionEvaluator implements ExpressionEvaluator{ + + private Map<String, ExpressionResolver> resolvers = new ConcurrentHashMap<>(); + + private ExpressionResolver defaultResolver; + + public DefaultExpressionEvaluator() { + for(ExpressionResolver resolver: ServiceContext.getInstance().getServices(ExpressionResolver.class)){ + resolvers.put(resolver.getResolverId(), resolver); + } + defaultResolver = ServiceContext.getInstance().getSingleton(ExpressionResolver.class); + } + + /** + * Resolves an expression in the form current <code>${resolverId:expression}</code>. The expression can be + * part current any type current literal text. Also multiple expression, with different resolver ids are supported. + * All control characters (${}\) can be escaped.<br> + * So all the following are valid expressions: + * <ul> + * <li><code>${resolverId:expression}</code></li> + * <li><code>bla bla ${resolverId:expression}</code></li> + * <li><code>${resolverId:expression} bla bla</code></li> + * <li><code>bla bla ${resolverId:expression} bla bla</code></li> + * <li><code>${resolverId:expression}${resolverId2:expression2}</code></li> + * <li><code>foo ${resolverId:expression}${resolverId2:expression2}</code></li> + * <li><code>foo ${resolverId:expression} bar ${resolverId2:expression2}</code></li> + * <li><code>${resolverId:expression}foo${resolverId2:expression2}bar</code></li> + * <li><code>foor${resolverId:expression}bar${resolverId2:expression2}more</code></li> + * <li><code>\${resolverId:expression}foo${resolverId2:expression2}bar</code> (first expression is escaped).</li> + * </ul> + * + * @param expression the expression to be evaluated, not null + * @param configurations overriding configurations to be used for evaluating the values for injection into {@code instance}. + * If no such config is passed, the default configurations provided by the current + * registered providers are used. + * @return the evaluated expression. + * @throws org.apache.tamaya.ConfigException if resolution fails. + */ + @Override + public String evaluate(String expression, Configuration... configurations) { + StringTokenizer tokenizer = new StringTokenizer(expression, "${}\\", true); + boolean escaped = false; + StringBuilder resolvedValue = new StringBuilder(); + StringBuilder current = new StringBuilder(); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (escaped) { + switch (token) { + case "n": + current.append("\n"); + break; + case "r": + current.append("\r"); + break; + case "t": + current.append("\t"); + break; + default: + current.append(token); + break; + } + escaped = false; + continue; + } + switch (token) { + case "\\": + escaped = true; + break; + case "$": + if (current.length() > 0) { + resolvedValue.append(current); + current.setLength(0); + } + if (!"{".equals(tokenizer.nextToken())) { + throw new ConfigException("Invalid expression encountered: " + expression); + } + String subExpression = tokenizer.nextToken(); + if (!"}".equals(tokenizer.nextToken())) { + throw new ConfigException("Invalid expression encountered: " + expression); + } + // evaluate sub-expression + current.append(evaluteInternal(subExpression)); + break; + default: + current.append(token); + } + } + if (current.length() > 0) { + resolvedValue.append(current); + } + return resolvedValue.toString(); + } + + private String evaluteInternal(String subExpression) { + int sepPos = subExpression.indexOf(':'); + if (sepPos > 0) { + String refID = subExpression.substring(0, sepPos); + String expression = subExpression.substring(sepPos + 1); + return Optional.ofNullable(this.resolvers.get(refID)).orElseThrow( + () -> new ConfigException("Resolver not found: " + refID + " in " + subExpression) + ).resolve(expression); + } else { + return Optional.ofNullable(this.defaultResolver).orElseThrow( + () -> new ConfigException("No default Resolver set, but required by " + subExpression) + ).resolve(subExpression); + } + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/EnvironmentPropertyResolver.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/EnvironmentPropertyResolver.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/EnvironmentPropertyResolver.java new file mode 100644 index 0000000..68d37a4 --- /dev/null +++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/EnvironmentPropertyResolver.java @@ -0,0 +1,44 @@ +/* + * 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.core.internal.el; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.core.spi.ExpressionResolver; + +import java.util.Optional; + +/** + * Property resolver implementation that interprets the resolver expressions as environment properties. + */ +public final class EnvironmentPropertyResolver implements ExpressionResolver{ + + @Override + public String getResolverId() { + return "env"; + } + + @Override + public String resolve(String expression, Configuration... configurations){ + return Optional.ofNullable(System.getenv(expression)).orElseThrow( + () -> new ConfigException("No such environment property: " + expression) + ); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/SystemPropertyResolver.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/SystemPropertyResolver.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/SystemPropertyResolver.java new file mode 100644 index 0000000..c6eb298 --- /dev/null +++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/SystemPropertyResolver.java @@ -0,0 +1,44 @@ +/* + * 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.core.internal.el; + +import java.util.Optional; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.core.spi.ExpressionResolver; + +/** + * Property resolver implementation that interprets the resolver expression as system property name. + */ +public final class SystemPropertyResolver implements ExpressionResolver{ + + @Override + public String getResolverId() { + return "sys"; + } + + @Override + public String resolve(String expression, Configuration... configurations){ + return Optional.ofNullable(System.getProperty(expression)).orElseThrow( + () -> new ConfigException("No such system property: " + expression) + ); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/modules/resolver/src/main/java/org/apache/tamaya/resolver/spi/ExpressionResolver.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/spi/ExpressionResolver.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/spi/ExpressionResolver.java new file mode 100644 index 0000000..5ec7b52 --- /dev/null +++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/spi/ExpressionResolver.java @@ -0,0 +1,53 @@ +/* + * 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.core.spi; + +import org.apache.tamaya.Configuration; + +/** + * This interface defines a small plugin for resolving current expressions within configuration. + * Resolver expression always have the form current <code>${resolverId:expression}</code>. The + * {@code resolverId} hereby references the resolver to be used to replace the according + * {@code expression}. Also it is well possible to mix different resolvers, e.g. using + * an expression like <code>${ref1:expression1} bla bla ${ref2:expression2}</code>. + * Finally when no resolver id is passed, the default resolver should be used. + */ +public interface ExpressionResolver { + + /** + * Get a (unique) resolver id used as a prefix for qualifying the resolver to be used for + * resolving an expression. + * + * @return the (unique) resolver id, never null, not empty. + */ + String getResolverId(); + + /** + * Resolve the expression. The expression should be stripped fromMap any surrounding parts. + * E.g. <code>${myresolver:blabla to be interpreted AND executed.}</code> should be passed + * as {@code blabla to be interpreted AND executed.} only. + * + * @param expression the stripped expression. + * @param configuration the configuration for which the value must be resolved. + * @return the resolved expression. + * @throws org.apache.tamaya.ConfigException when the expression passed is not resolvable, e.g. due to syntax issues + * or data not present or valid. + */ + String resolve(String expression, Configuration configuration); +}