http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ConfigurationExtension.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ConfigurationExtension.java b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ConfigurationExtension.java new file mode 100644 index 0000000..4524461 --- /dev/null +++ b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ConfigurationExtension.java @@ -0,0 +1,290 @@ +/* + * 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.integration.cdi; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.ConfigOperator; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.ConfigurationProvider; +import org.apache.tamaya.inject.api.Config; +import org.apache.tamaya.inject.api.ConfigDefaultSections; +import org.apache.tamaya.inject.api.WithConfigOperator; +import org.apache.tamaya.inject.api.WithPropertyConverter; +import org.apache.tamaya.spi.PropertyConverter; + +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.spi.AfterBeanDiscovery; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.Extension; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.enterprise.inject.spi.ProcessBean; +import javax.enterprise.inject.spi.ProcessProducerMethod; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; + + +/** + * CDI Extension module that adds injection mechanism for configuration. + * + * @see org.apache.tamaya.inject.api.Config + * @see org.apache.tamaya.inject.api.ConfigDefaultSections + * @see ConfigException + */ +public class ConfigurationExtension implements Extension { + + private static final Logger LOG = Logger.getLogger(ConfigurationExtension.class.getName()); + + static final Map<Class, ConfigOperator> CUSTOM_OPERATORS = new ConcurrentHashMap<>(); + static final Map<Class, PropertyConverter> CUSTOM_CONVERTERS = new ConcurrentHashMap<>(); + + private final Set<Type> types = new HashSet<>(); + private Bean<?> convBean; + + /** + * Constructor for loading logging its load. + */ + public ConfigurationExtension(){ + LOG.finest("Loading Tamaya CDI Support..."); + } + + /** + * Method that checks the configuration injection points during deployment for available configuration. + * @param pb the bean to process. + * @param beanManager the bean manager to notify about new injections. + */ + public void retrieveTypes(@Observes final ProcessBean<?> pb, BeanManager beanManager) { + + final Set<InjectionPoint> ips = pb.getBean().getInjectionPoints(); + CDIConfiguredType configuredType = new CDIConfiguredType(pb.getBean().getBeanClass()); + + boolean configured = false; + boolean logged = false; + for (InjectionPoint injectionPoint : ips) { + if (injectionPoint.getAnnotated().isAnnotationPresent(Config.class)) { + final Config annotation = injectionPoint.getAnnotated().getAnnotation(Config.class); + final ConfigDefaultSections typeAnnot = injectionPoint.getAnnotated().getAnnotation(ConfigDefaultSections.class); + final List<String> keys = evaluateKeys(injectionPoint.getMember().getName(), + annotation!=null?annotation.value():null, + typeAnnot!=null?typeAnnot.value():null); + + final WithConfigOperator withOperatorAnnot = injectionPoint.getAnnotated().getAnnotation(WithConfigOperator.class); + if(withOperatorAnnot!=null){ + tryLoadOpererator(withOperatorAnnot.value()); + } + final WithPropertyConverter withConverterAnnot = injectionPoint.getAnnotated().getAnnotation(WithPropertyConverter.class); + if(withConverterAnnot!=null){ + tryLoadConverter(withConverterAnnot.value()); + } + + // We don't want to wait until the injection really fails at runtime. + // If there is a non resolvable configuration, we want to know at startup. + Configuration config = ConfigurationProvider.getConfiguration(); + String value = null; + for(String key:keys) { + value = config.get(key); + if(value!=null){ + break; + } + } + if(value==null && !annotation.defaultValue().isEmpty()){ + value = annotation.defaultValue(); + } + if(value==null){ + throw new ConfigException(String.format( + "Cannot resolve any of the possible configuration keys: %s. Please provide one of the given keys " + + "with a value in your configuration sources.", + keys.toString())); + } + types.add(injectionPoint.getType()); + if(annotation!=null){ + configured = true; + if(!logged) { + LOG.finest("Enabling Tamaya CDI Configuration on bean: " + configuredType.getName()); + } + configuredType.addConfiguredMember(injectionPoint, keys); + } + } + } + if(configured) { + beanManager.fireEvent(configuredType); + } + } + + + public void captureConvertBean(@Observes final ProcessProducerMethod<?, ?> ppm) { + if (ppm.getAnnotated().isAnnotationPresent(Config.class)) { + convBean = ppm.getBean(); + } + + } + + public void addConverter(@Observes final AfterBeanDiscovery abd, final BeanManager bm) { + if(!types.isEmpty()) { + abd.addBean(new ConverterBean(convBean, types)); + } + } + + private void tryLoadOpererator(Class<? extends ConfigOperator> operatorClass) { + Objects.requireNonNull(operatorClass); + if(ConfigOperator.class == operatorClass){ + return; + } + try{ + if(!CUSTOM_OPERATORS.containsKey(operatorClass)) { + CUSTOM_OPERATORS.put(operatorClass, operatorClass.newInstance()); + } + } catch(Exception e){ + throw new ConfigException("Custom ConfigOperator could not be loaded: " + operatorClass.getName(), e); + } + } + + private void tryLoadConverter(Class<? extends PropertyConverter> converterClass) { + Objects.requireNonNull(converterClass); + if(PropertyConverter.class == converterClass){ + return; + } + try{ + if(!CUSTOM_CONVERTERS.containsKey(converterClass)) { + CUSTOM_CONVERTERS.put(converterClass, converterClass.newInstance()); + } + } catch(Exception e){ + throw new ConfigException("Custom PropertyConverter could not be loaded: " + converterClass.getName(), e); + } + } + + /** + * Evaluates the effective keys to be used. if no {@code keys} are defined, {@code memberName} is used. + * The effective keys are then combined with the sections given (if any) and only, if the given keys are not + * absolute keys (surrounded by brackets). + * @param memberName the default member name, not null. + * @param keys the keys, may be empty, or null. + * @param sections the default sections, may be empty. May also be null. + * @return the list of keys to be finally used for configuration resolution in order of + * precedence. The first keys in the list that could be successfully resolved define the final + * configuration value. + */ + public static List<String> evaluateKeys(String memberName, String[] keys, String[] sections) { + List<String> effKeys = new ArrayList<>(); + if(keys!=null){ + effKeys.addAll(Arrays.asList(keys)); + } + if (effKeys.isEmpty()) { + effKeys.add(memberName); + } + ListIterator<String> iterator = effKeys.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 (sections != null && sections.length>0) { + // 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 : sections) { + iterator.add(area.isEmpty() ? next : area + '.' + next); + } + } + } + } + return effKeys; + } + + + /** + * Internally used conversion bean. + */ + private static class ConverterBean implements Bean<Object> { + + private final Bean<Object> delegate; + private final Set<Type> types; + + public ConverterBean(final Bean convBean, final Set<Type> types) { + this.types = types; + this.delegate = convBean; + } + + @Override + public Set<Type> getTypes() { + return types; + } + + @Override + public Class<?> getBeanClass() { + return delegate.getBeanClass(); + } + + @Override + public Set<InjectionPoint> getInjectionPoints() { + return delegate.getInjectionPoints(); + } + + @Override + public String getName() { + return delegate.getName(); + } + + @Override + public Set<Annotation> getQualifiers() { + return delegate.getQualifiers(); + } + + @Override + public Class<? extends Annotation> getScope() { + return delegate.getScope(); + } + + @Override + public Set<Class<? extends Annotation>> getStereotypes() { + return delegate.getStereotypes(); + } + + @Override + public boolean isAlternative() { + return delegate.isAlternative(); + } + + @Override + public boolean isNullable() { + return delegate.isNullable(); + } + + @Override + public Object create(CreationalContext<Object> creationalContext) { + return delegate.create(creationalContext); + } + + @Override + public void destroy(Object instance, CreationalContext<Object> creationalContext) { + delegate.destroy(instance, creationalContext); + } + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ConfigurationProducer.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ConfigurationProducer.java b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ConfigurationProducer.java new file mode 100644 index 0000000..bfbb51a --- /dev/null +++ b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ConfigurationProducer.java @@ -0,0 +1,147 @@ +/* + * 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.integration.cdi; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.ConfigOperator; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.ConfigurationProvider; +import org.apache.tamaya.TypeLiteral; +import org.apache.tamaya.inject.api.Config; +import org.apache.tamaya.inject.api.ConfigDefaultSections; +import org.apache.tamaya.inject.api.DynamicValue; +import org.apache.tamaya.inject.api.WithConfigOperator; +import org.apache.tamaya.inject.api.WithPropertyConverter; +import org.apache.tamaya.spi.ConversionContext; +import org.apache.tamaya.spi.PropertyConverter; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Producer bean for configuration properties. + */ +@ApplicationScoped +public class ConfigurationProducer { + + private static final Logger LOGGER = Logger.getLogger(ConfigurationProducer.class.getName()); + + private DynamicValue createynamicValue(final InjectionPoint injectionPoint) { + Member member = injectionPoint.getMember(); + if (member instanceof Field) { + return DefaultDynamicValue.of((Field) member, ConfigurationProvider.getConfiguration()); + } else if (member instanceof Method) { + return DefaultDynamicValue.of((Method) member, ConfigurationProvider.getConfiguration()); + } + return null; + } + + @Produces + @Config + public Object resolveAndConvert(final InjectionPoint injectionPoint) { + if (DynamicValue.class.equals(injectionPoint.getAnnotated().getBaseType())) { + return createynamicValue(injectionPoint); + } + final Config annotation = injectionPoint.getAnnotated().getAnnotation(Config.class); + final ConfigDefaultSections typeAnnot = injectionPoint.getAnnotated().getAnnotation(ConfigDefaultSections.class); + final List<String> keys = ConfigurationExtension.evaluateKeys(injectionPoint.getMember().getName(), + annotation != null ? annotation.value() : null, + typeAnnot != null ? typeAnnot.value() : null); + + final WithConfigOperator withOperatorAnnot = injectionPoint.getAnnotated().getAnnotation(WithConfigOperator.class); + ConfigOperator operator = null; + if (withOperatorAnnot != null) { + operator = ConfigurationExtension.CUSTOM_OPERATORS.get(withOperatorAnnot.value()); + } + PropertyConverter customConverter = null; + final WithPropertyConverter withConverterAnnot = injectionPoint.getAnnotated().getAnnotation(WithPropertyConverter.class); + if (withConverterAnnot != null) { + customConverter = ConfigurationExtension.CUSTOM_CONVERTERS.get(withConverterAnnot.value()); + } + + // unless the extension is not installed, this should never happen because the extension + // enforces the resolvability of the config + Configuration config = ConfigurationProvider.getConfiguration(); + if (operator != null) { + config = operator.operate(config); + } + final Class<?> toType = (Class<?>) injectionPoint.getAnnotated().getBaseType(); + String textValue = null; + String defaultTextValue = annotation.defaultValue().isEmpty() ? null : annotation.defaultValue(); + String keyFound = null; + for (String key : keys) { + textValue = config.get(key); + if (textValue != null) { + keyFound = key; + break; + } + } + ConversionContext.Builder builder = new ConversionContext.Builder(config, + ConfigurationProvider.getConfiguration().getContext(), keyFound, TypeLiteral.of(toType)); + if (injectionPoint.getMember() instanceof AnnotatedElement) { + builder.setAnnotatedElement((AnnotatedElement) injectionPoint.getMember()); + } + ConversionContext conversionContext = builder.build(); + Object value = null; + if (keyFound != null) { + if (customConverter != null) { + value = customConverter.convert(textValue, conversionContext); + } + if (value == null) { + value = config.get(keyFound, toType); + } + } else if (defaultTextValue != null) { + value = defaultTextValue; + if (customConverter != null) { + value = customConverter.convert((String)value, conversionContext); + } + if (value != null) { + List<PropertyConverter<Object>> converters = ConfigurationProvider.getConfiguration().getContext() + .getPropertyConverters(TypeLiteral.of(toType)); + for (PropertyConverter<Object> converter : converters) { + try { + value = converter.convert(defaultTextValue, conversionContext); + if (value != null) { + LOGGER.log(Level.FINEST, "Parsed default value from '" + defaultTextValue + "' into " + + injectionPoint); + break; + } + } catch (Exception e) { + LOGGER.log(Level.FINEST, "Failed to convert default value '" + defaultTextValue + "' for " + + injectionPoint, e); + } + } + } + } + if (value == null) { + throw new ConfigException(String.format( + "Can't resolve any of the possible config keys: %s to the required target type: %s, supported formats: %s", + keys.toString(), toType.getName(), conversionContext.getSupportedFormats().toString())); + } + LOGGER.finest(String.format("Injecting %s for key %s in class %s", keyFound, value.toString(), injectionPoint.toString())); + return value; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/DefaultDynamicValue.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/DefaultDynamicValue.java b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/DefaultDynamicValue.java new file mode 100644 index 0000000..98ee05a --- /dev/null +++ b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/DefaultDynamicValue.java @@ -0,0 +1,499 @@ +/* + * 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.integration.cdi; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.Configuration; +import org.apache.tamaya.TypeLiteral; +import org.apache.tamaya.inject.api.BaseDynamicValue; +import org.apache.tamaya.inject.api.DynamicValue; +import org.apache.tamaya.inject.api.InjectionUtils; +import org.apache.tamaya.inject.api.LoadPolicy; +import org.apache.tamaya.inject.api.UpdatePolicy; +import org.apache.tamaya.inject.api.WithPropertyConverter; +import org.apache.tamaya.spi.ConversionContext; +import org.apache.tamaya.spi.PropertyConverter; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.logging.Logger; + +/** + * A accessor for a single configured value. This can be used to support values that may change during runtime, + * reconfigured or final. Hereby external code (could be Tamaya configuration listners or client code), can set a + * new value. Depending on the {@link UpdatePolicy} the new value is immedeately active or it requires an active commit + * by client code. Similarly an instance also can ignore all later changes to the value. + * <h3>Implementation Details</h3> + * This class is + * <ul> + * <li>Serializable, when also the item stored is serializable</li> + * <li>Thread safe</li> + * </ul> + * + * @param <T> The type of the value. + */ +final class DefaultDynamicValue<T> extends BaseDynamicValue<T> { + + private static final long serialVersionUID = -2071172847144537443L; + + /** + * The property name of the entry. + */ + private final String propertyName; + /** + * The keys to be resolved. + */ + private final String[] keys; + /** + * Back reference to the base configuration instance. This reference is used reevalaute the given property and + * compare the result with the previous value after a configuration change was triggered. + */ + private final Configuration configuration; + /** + * The target type of the property used to lookup a matching {@link PropertyConverter}. + * If null, {@code propertyConverter} is set and used instead. + */ + private final TypeLiteral<T> targetType; + /** + * The property converter to be applied, may be null. In the ladder case targetType is not null. + */ + private final PropertyConverter<T> propertyConverter; + /** + * Policy that defines how new values are applied, be default it is applied initially once, but never updated + * anymore. + */ + private UpdatePolicy updatePolicy; + /** + * Load policy. + */ + private final LoadPolicy loadPolicy; + + /** + * The current value, never null. + */ + private transient T value; + /** + * The new value, or null. + */ + private transient Object[] newValue; + /** + * List of listeners that listen for changes. + */ + private transient WeakList<PropertyChangeListener> listeners; + + /** + * Constructor. + * + * @param propertyName the name of the fields' property/method. + * @param keys the keys of the property, not null. + * @param configuration the configuration, not null. + * @param targetType the target type, not null. + * @param propertyConverter the optional converter to be used. + */ + private DefaultDynamicValue(String propertyName, Configuration configuration, TypeLiteral<T> targetType, + PropertyConverter<T> propertyConverter, List<String> keys, LoadPolicy loadPolicy, + UpdatePolicy updatePolicy) { + this.propertyName = Objects.requireNonNull(propertyName); + this.keys = keys.toArray(new String[keys.size()]); + this.configuration = Objects.requireNonNull(configuration); + this.propertyConverter = propertyConverter; + this.targetType = targetType; + this.loadPolicy = Objects.requireNonNull(loadPolicy); + this.updatePolicy = Objects.requireNonNull(updatePolicy); + if(loadPolicy == LoadPolicy.INITIAL){ + this.value = evaluateValue(); + } + } + + public static DynamicValue of(Field annotatedField, Configuration configuration) { + return of(annotatedField, configuration, LoadPolicy.ALWAYS, UpdatePolicy.IMMEDEATE); + } + + public static DynamicValue of(Field annotatedField, Configuration configuration, LoadPolicy loadPolicy) { + return of(annotatedField, configuration, loadPolicy, UpdatePolicy.IMMEDEATE); + } + + public static DynamicValue of(Field annotatedField, Configuration configuration, UpdatePolicy updatePolicy) { + return of(annotatedField, configuration, LoadPolicy.ALWAYS, updatePolicy); + } + + public static DynamicValue of(Field annotatedField, Configuration configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) { + // Check for adapter/filter + Type targetType = annotatedField.getGenericType(); + if (targetType == null) { + throw new ConfigException("Failed to evaluate target type for " + annotatedField.getDeclaringClass().getName() + + '.' + annotatedField.getName()); + } + if (targetType instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) targetType; + Type[] types = pt.getActualTypeArguments(); + if (types.length != 1) { + throw new ConfigException("Failed to evaluate target type for " + annotatedField.getDeclaringClass().getName() + + '.' + annotatedField.getName()); + } + targetType = types[0]; + } + PropertyConverter<?> propertyConverter = null; + WithPropertyConverter annot = annotatedField.getAnnotation(WithPropertyConverter.class); + if (annot != null) { + try { + propertyConverter = annot.value().newInstance(); + } catch (Exception e) { + throw new ConfigException("Failed to instantiate annotated PropertyConverter on " + + annotatedField.getDeclaringClass().getName() + + '.' + annotatedField.getName(), e); + } + } + List<String> keys = InjectionUtils.getKeys(annotatedField); + return new DefaultDynamicValue(annotatedField.getName(), configuration, + TypeLiteral.of(targetType), propertyConverter, keys, loadPolicy, updatePolicy); + } + + public static DynamicValue of(Method method, Configuration configuration) { + return of(method, configuration, LoadPolicy.ALWAYS, UpdatePolicy.IMMEDEATE); + } + + public static DynamicValue of(Method method, Configuration configuration, UpdatePolicy updatePolicy) { + return of(method, configuration, LoadPolicy.ALWAYS, updatePolicy); + } + + public static DynamicValue of(Method method, Configuration configuration, LoadPolicy loadPolicy) { + return of(method, configuration, loadPolicy, UpdatePolicy.IMMEDEATE); + } + + public static DynamicValue of(Method method, Configuration configuration, LoadPolicy loadPolicy, UpdatePolicy updatePolicy) { + // Check for adapter/filter + Type targetType = method.getGenericReturnType(); + if (targetType == null) { + throw new ConfigException("Failed to evaluate target type for " + method.getDeclaringClass() + .getName() + '.' + method.getName()); + } + if (targetType instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) targetType; + Type[] types = pt.getActualTypeArguments(); + if (types.length != 1) { + throw new ConfigException("Failed to evaluate target type for " + method.getDeclaringClass() + .getName() + '.' + method.getName()); + } + targetType = types[0]; + } + PropertyConverter<Object> propertyConverter = null; + WithPropertyConverter annot = method.getAnnotation(WithPropertyConverter.class); + if (annot != null) { + try { + propertyConverter = (PropertyConverter<Object>) annot.value().newInstance(); + } catch (Exception e) { + throw new ConfigException("Failed to instantiate annotated PropertyConverter on " + + method.getDeclaringClass().getName() + + '.' + method.getName(), e); + } + } + return new DefaultDynamicValue<>(method.getName(), + configuration, TypeLiteral.of(targetType), propertyConverter, InjectionUtils.getKeys(method), + loadPolicy, updatePolicy); + } + + + /** + * Commits a new value that has not been committed yet, make it the new value of the instance. On change any + * registered listeners will be triggered. + */ + public void commit() { + T oldValue = value; + value = newValue==null?null:(T)newValue[0]; + newValue = null; + informListeners(oldValue, value); + } + + private void informListeners(T value, T newValue) { + synchronized (this) { + PropertyChangeEvent evt = new PropertyChangeEvent(this, propertyName, value, + newValue); + if (listeners != null) { + for (PropertyChangeListener consumer : listeners.get()) { + consumer.propertyChange(evt); + } + } + } + } + + /** + * Discards a new value that was published. No listeners will be informed. + */ + public void discard() { + newValue = null; + } + + + /** + * Access the {@link UpdatePolicy} used for updating this value. + * + * @return the update policy, never null. + */ + public UpdatePolicy getUpdatePolicy() { + return updatePolicy; + } + + /** + * Sets a new {@link UpdatePolicy}. + * + * @param updatePolicy the new policy, not null. + */ + public void setUpdatePolicy(UpdatePolicy updatePolicy) { + this.updatePolicy = Objects.requireNonNull(updatePolicy); + } + + /** + * Add a listener to be called as weak reference, when this value has been changed. + * + * @param l the listener, not null + */ + public void addListener(PropertyChangeListener l) { + if (listeners == null) { + listeners = new WeakList<>(); + } + listeners.add(l); + } + + /** + * Removes a listener to be called, when this value has been changed. + * + * @param l the listner to be removed, not null + */ + public void removeListener(PropertyChangeListener l) { + if (listeners != null) { + listeners.remove(l); + } + } + + /** + * If a value is present in this {@code DynamicValue}, returns the value, + * otherwise throws {@code ConfigException}. + * + * @return the non-null value held by this {@code Optional} + * @throws ConfigException if there is no value present + * @see DefaultDynamicValue#isPresent() + */ + public T get() { + T newLocalValue; + if(loadPolicy!=LoadPolicy.INITIAL) { + newLocalValue = evaluateValue(); + if (this.value == null) { + this.value = newLocalValue; + } + if(!Objects.equals(this.value, newLocalValue)){ + switch (updatePolicy){ + case IMMEDEATE: + commit(); + break; + case EXPLCIT: + this.newValue = new Object[]{newLocalValue}; + break; + case LOG_ONLY: + informListeners(this.value, newLocalValue); + this.newValue = null; + break; + case NEVER: + this.newValue = null; + break; + default: + this.newValue = null; + break; + } + } + } + return value; + } + + /** + * Method to check for and apply a new value. Depending on the {@link UpdatePolicy} + * the value is immediately or deferred visible (or it may even be ignored completely). + * + * @return true, if a new value has been detected. The value may not be visible depending on the current + * {@link UpdatePolicy} in place. + */ + public boolean updateValue() { + if(this.value==null && this.newValue==null){ + this.value = evaluateValue(); + return false; + } + T newValue = evaluateValue(); + if (Objects.equals(newValue, this.value)) { + return false; + } + switch (this.updatePolicy) { + case LOG_ONLY: + Logger.getLogger(getClass().getName()).info("Discard change on " + this + ", newValue=" + newValue); + informListeners(value, newValue); + this.newValue = null; + break; + case NEVER: + this.newValue = null; + break; + case EXPLCIT: + case IMMEDEATE: + default: + this.newValue = new Object[]{newValue}; + commit(); + break; + } + return true; + } + + /** + * Evaluates the current value dynamically from the underlying configuration. + * + * @return the current actual value, or null. + */ + public T evaluateValue() { + T value = null; + + for (String key : keys) { + if (propertyConverter == null) { + value = configuration.get(key, targetType); + } else { + String source = configuration.get(key); + ConversionContext ctx = new ConversionContext.Builder(configuration, + configuration.getContext(), key, targetType).build(); + value = propertyConverter.convert(source, ctx); + } + + if (value != null) { + break; + } + } + + return value; + } + + /** + * Access a new value that has not yet been committed. + * + * @return the uncommitted new value, or null. + */ + public T getNewValue() { + T nv = newValue==null?null:(T)newValue[0]; + if (nv != null) { + return nv; + } + return null; + } + + + /** + * Serialization implementation that strips away the non serializable Optional part. + * + * @param oos the output stream + * @throws IOException if serialization fails. + */ + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.writeObject(getUpdatePolicy()); + oos.writeObject(get()); + } + + /** + * Reads an instance from the input stream. + * + * @param ois the object input stream + * @throws IOException if deserialization fails. + * @throws ClassNotFoundException + */ + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + this.updatePolicy = (UpdatePolicy) ois.readObject(); + if (isPresent()) { + this.value = (T) ois.readObject(); + } + newValue = null; + } + + + /** + * Simple helper that allows keeping the listeners registered as weak references, hereby avoiding any + * memory leaks. + * + * @param <I> the type + */ + private class WeakList<I> { + final List<WeakReference<I>> refs = new LinkedList<>(); + + /** + * Adds a new instance. + * + * @param t the new instance, not null. + */ + void add(I t) { + refs.add(new WeakReference<>(t)); + } + + /** + * Removes a instance. + * + * @param t the instance to be removed. + */ + void remove(I t) { + synchronized (refs) { + for (Iterator<WeakReference<I>> iterator = refs.iterator(); iterator.hasNext(); ) { + WeakReference<I> ref = iterator.next(); + I instance = ref.get(); + if (instance == null || instance == t) { + iterator.remove(); + break; + } + } + } + } + + + /** + * Access a list (copy) of the current instances that were not discarded by the GC. + * + * @return the list of accessible items. + */ + public List<I> get() { + synchronized (refs) { + List<I> res = new ArrayList<>(); + for (Iterator<WeakReference<I>> iterator = refs.iterator(); iterator.hasNext(); ) { + WeakReference<I> ref = iterator.next(); + I instance = ref.get(); + if (instance == null) { + iterator.remove(); + } else { + res.add(instance); + } + } + return res; + } + } + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ServiceLoaderServiceContext.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ServiceLoaderServiceContext.java b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ServiceLoaderServiceContext.java new file mode 100644 index 0000000..5171d91 --- /dev/null +++ b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/ServiceLoaderServiceContext.java @@ -0,0 +1,151 @@ +/* + * 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.integration.cdi; + +import org.apache.tamaya.ConfigException; +import org.apache.tamaya.spi.ServiceContext; + +import javax.annotation.Priority; +import java.text.MessageFormat; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class implements the (default) {@link ServiceContext} interface and hereby uses the JDK + * {@link ServiceLoader} to load the services required. + */ +final class ServiceLoaderServiceContext implements ServiceContext { + /** + * List current services loaded, per class. + */ + private final ConcurrentHashMap<Class<?>, List<Object>> servicesLoaded = new ConcurrentHashMap<>(); + /** + * Singletons. + */ + private final Map<Class<?>, Object> singletons = new ConcurrentHashMap<>(); + + @Override + public <T> T getService(Class<T> serviceType) { + Object cached = singletons.get(serviceType); + if (cached == null) { + Collection<T> services = getServices(serviceType); + if (services.isEmpty()) { + cached = null; + } else { + cached = getServiceWithHighestPriority(services, serviceType); + } + if(cached!=null) { + singletons.put(serviceType, cached); + } + } + return serviceType.cast(cached); + } + + /** + * Loads and registers services. + * + * @param <T> the concrete type. + * @param serviceType The service type. + * @return the items found, never {@code null}. + */ + @Override + public <T> List<T> getServices(final Class<T> serviceType) { + List<T> found = (List<T>) servicesLoaded.get(serviceType); + if (found != null) { + return found; + } + List<T> services = new ArrayList<>(); + try { + for (T t : ServiceLoader.load(serviceType)) { + services.add(t); + } + services = Collections.unmodifiableList(services); + } catch (Exception e) { + Logger.getLogger(ServiceLoaderServiceContext.class.getName()).log(Level.WARNING, + "Error loading services current type " + serviceType, e); + } + final List<T> previousServices = List.class.cast(servicesLoaded.putIfAbsent(serviceType, (List<Object>) services)); + return previousServices != null ? previousServices : services; + } + + /** + * Checks the given instance for a @Priority annotation. If present the annotation's value s evaluated. If no such + * annotation is present, a default priority is returned (1); + * @param o the instance, not null. + * @return a priority, by default 1. + */ + public static int getPriority(Object o){ + int prio = 1; //X TODO discuss default priority + Priority priority = o.getClass().getAnnotation(Priority.class); + if (priority != null) { + prio = priority.value(); + } + return prio; + } + + /** + * @param services to scan + * @param <T> type of the service + * + * @return the service with the highest {@link Priority#value()} + * + * @throws ConfigException if there are multiple service implementations with the maximum priority + */ + private <T> T getServiceWithHighestPriority(Collection<T> services, Class<T> serviceType) { + + // we do not need the priority stuff if the list contains only one element + if (services.size() == 1) { + return services.iterator().next(); + } + + Integer highestPriority = null; + int highestPriorityServiceCount = 0; + T highestService = null; + + for (T service : services) { + int prio = getPriority(service); + if (highestPriority == null || highestPriority < prio) { + highestService = service; + highestPriorityServiceCount = 1; + highestPriority = prio; + } else if (highestPriority == prio) { + highestPriorityServiceCount++; + } + } + + if (highestPriorityServiceCount > 1) { + throw new ConfigException(MessageFormat.format("Found {0} implementations for Service {1} with Priority {2}: {3}", + highestPriorityServiceCount, + serviceType.getName(), + highestPriority, + services)); + } + + return highestService; + } + + @Override + public int ordinal() { + return 1; + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/TamayaCDIIntegration.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/TamayaCDIIntegration.java b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/TamayaCDIIntegration.java new file mode 100644 index 0000000..3f62039 --- /dev/null +++ b/modules/injection/cdi-ee/src/main/java/org/apache/tamaya/integration/cdi/TamayaCDIIntegration.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.integration.cdi; + +import javax.enterprise.event.Observes; +import javax.enterprise.inject.spi.AfterDeploymentValidation; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.Extension; + +/** + * Tamaya main integration with CDI, storing the BeanManager reference for implementation, where no + * JNDI is available or {@code java:comp/env/BeanManager} is not set correctly. + */ +public class TamayaCDIIntegration implements Extension { + /** The BeanManager references stored. */ + private static BeanManager beanManager; + + /** + * Initializes the current BeanManager with the instance passed. + * @param validation the event + * @param beanManager the BeanManager instance + */ + @SuppressWarnings("all") + public void initBeanManager(@Observes AfterDeploymentValidation validation, BeanManager beanManager){ + TamayaCDIIntegration.beanManager = beanManager; + } + + /** + * Get the current {@link BeanManager} instance. + * @return the currently used bean manager. + */ + public static BeanManager getBeanManager(){ + return beanManager; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/main/resources/META-INF/beans.xml ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/main/resources/META-INF/beans.xml b/modules/injection/cdi-ee/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..562647f --- /dev/null +++ b/modules/injection/cdi-ee/src/main/resources/META-INF/beans.xml @@ -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. +--> +<beans></beans> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/modules/injection/cdi-ee/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension new file mode 100644 index 0000000..e82118a --- /dev/null +++ b/modules/injection/cdi-ee/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension @@ -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.integration.cdi.ConfigurationExtension \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/main/resources/META-INF/services/org.apache.tamaya.spi.ServiceContext ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/main/resources/META-INF/services/org.apache.tamaya.spi.ServiceContext b/modules/injection/cdi-ee/src/main/resources/META-INF/services/org.apache.tamaya.spi.ServiceContext new file mode 100644 index 0000000..782b0ce --- /dev/null +++ b/modules/injection/cdi-ee/src/main/resources/META-INF/services/org.apache.tamaya.spi.ServiceContext @@ -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. +# + +# +# 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.integration.cdi.CDIAwareServiceContext \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationProducerFailedInjectionTest.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationProducerFailedInjectionTest.java b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationProducerFailedInjectionTest.java new file mode 100644 index 0000000..6bfda3a --- /dev/null +++ b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationProducerFailedInjectionTest.java @@ -0,0 +1,33 @@ +/* + * 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.integration.cdi; + +import org.apache.openejb.OpenEjbContainer; +import org.junit.Test; + +import javax.ejb.embeddable.EJBContainer; + +public class ConfigurationProducerFailedInjectionTest { + + @Test(expected = OpenEjbContainer.AssembleApplicationException.class) + public void notFoundShouldNotDeploy() { + // this explicitly tests that a non resolvable config makes + // the deployment fail and we won't have any failure at runtime + EJBContainer.createEJBContainer(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationProducerTest.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationProducerTest.java b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationProducerTest.java new file mode 100644 index 0000000..d128191 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationProducerTest.java @@ -0,0 +1,168 @@ +/* + * 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.integration.cdi; + +import org.apache.openejb.jee.EjbJar; +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.testing.Classes; +import org.apache.openejb.testing.Module; +import org.apache.tamaya.inject.api.Config; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.tomitribe.util.Duration; + +import javax.inject.Inject; +import java.io.File; + +import static org.junit.Assert.*; + +@RunWith(ApplicationComposer.class) +public class ConfigurationProducerTest { + + @Module + @Classes(cdi = true, value = { + AllTypes.class, + ConfigurationExtension.class, + ConfigurationProducer.class + }) + public EjbJar jar() { + return new EjbJar("config"); + } + + @Inject + private AllTypes allTypes; + + @Test + public void defaultValues() { + assertNotNull(allTypes); + assertEquals("defaultString", allTypes.getDefaultString()); + assertEquals(new File("./"), allTypes.getDefaultFile()); + assertEquals(new Duration("2 hours and 54 minutes"), allTypes.getDefaultDuration()); + assertEquals(true, allTypes.getDefaultBoolean()); + assertEquals(45, (int) allTypes.getDefaultInteger()); + } + + @Test + public void actualPropertyValues() { + assertNotNull(allTypes); + assertEquals("hello", allTypes.getString()); + assertEquals(new File("./conf"), allTypes.getFile()); + assertEquals(new Duration("10 minutes and 57 seconds"), allTypes.getDuration()); + assertEquals(true, allTypes.getaBoolean()); + assertEquals(123, (int) allTypes.getInteger()); + } + + static class AllTypes { + + @Inject + @Config(value = "string.value", defaultValue = "defaultString") + private String string; + + @Inject + @Config(value = "defaultString.value", defaultValue = "defaultString") + private String defaultString; + + @Inject + @Config(value = "file.value", defaultValue = "./") + private File file; + + @Inject + @Config(value = "defaultFile.value", defaultValue = "./") + private File defaultFile; + + @Inject + @Config(value = "duration.value", defaultValue = "2 hours and 54 minutes") + private Duration duration; + + @Inject + @Config(value = "defaultDuration.value", defaultValue = "2 hours and 54 minutes") + private Duration defaultDuration; + + @Inject + @Config(value = "boolean.value", defaultValue = "true") + private Boolean aBoolean; + + @Inject + @Config(value = "defaultBoolean.value", defaultValue = "true") + private Boolean defaultBoolean; + + @Inject + @Config(value = "integer.value", defaultValue = "45") + private Integer integer; + + @Inject + @Config(value = "defaultInteger.value", defaultValue = "45") + private Integer defaultInteger; + + public String getString() { + return string; + } + + public File getFile() { + return file; + } + + public Duration getDuration() { + return duration; + } + + public Boolean getaBoolean() { + return aBoolean; + } + + public Integer getInteger() { + return integer; + } + + public String getDefaultString() { + return defaultString; + } + + public File getDefaultFile() { + return defaultFile; + } + + public Duration getDefaultDuration() { + return defaultDuration; + } + + public Boolean getDefaultBoolean() { + return defaultBoolean; + } + + public Integer getDefaultInteger() { + return defaultInteger; + } + + @Override + public String toString() { + return "AllTypes{" + + "string='" + string + '\'' + + ", defaultString='" + defaultString + '\'' + + ", file=" + file + + ", defaultFile=" + defaultFile + + ", duration=" + duration + + ", defaultDuration=" + defaultDuration + + ", aBoolean=" + aBoolean + + ", defaultBoolean=" + defaultBoolean + + ", integer=" + integer + + ", defaultInteger=" + defaultInteger + + '}'; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationResolverTest.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationResolverTest.java b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationResolverTest.java new file mode 100644 index 0000000..1c551b2 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/ConfigurationResolverTest.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.integration.cdi; +// +//import org.apache.openejb.loader.SystemInstance; +//import org.junit.Before; +//import org.junit.Test; +// +//import static org.junit.Assert.*; +// +//public class ConfigurationResolverTest { +// +// private ConfigurationResolver resolver; +// +// @Before +// public void cleanEnv() { +// SystemInstance.reset(); +// System.clearProperty("environment"); +// +// resolver = new ConfigurationResolver(); +// } +// +// @Test +// public void defaultEnvironment() { +// assertEquals("test", resolver.getEnvironment()); +// } +// +// @Test +// public void overrideDefaultEnvironment() { +// System.setProperty("environment", "dev"); +// +// // don't use the field cause before is invoked before we have a chance to set the environment +// assertEquals("dev", new ConfigurationResolver().getEnvironment()); +// } +// +// @Test +// public void isResolvable() { +// +// { // precondition +// try { +// resolver.isResolvableConfig(null, "value"); +// fail("a null key is not resolvable"); +// +// } catch (final NullPointerException e) { +// // expected +// } +// } +// { // precondition +// try { +// resolver.isResolvableConfig("key", null); +// fail("a null default value is not resolvable"); +// +// } catch (final NullPointerException e) { +// // expected +// } +// } +// +// // loaded from test.properties +// assertTrue(resolver.isResolvableConfig("remote.wsdl.location", "")); +// assertFalse(resolver.isResolvableConfig("something", "")); +// +// // loaded from base.properties +// assertTrue(resolver.isResolvableConfig("remote.username", "")); +// assertFalse(resolver.isResolvableConfig("bla", "")); +// } +// +// @Test +// public void found() { +// +// { // precondition +// try { +// resolver.isResolvableConfig(null, "value"); +// fail("a null key is not resolvable"); +// +// } catch (final NullPointerException e) { +// // expected +// } +// } +// { // precondition +// try { +// resolver.isResolvableConfig("key", null); +// fail("a null default value is not resolvable"); +// +// } catch (final NullPointerException e) { +// // expected +// } +// } +// +// // loaded from test.properties +// assertEquals("classpath:/service-wsdl.xml", resolver.resolve("remote.wsdl.location", "")); +// assertEquals("something-else", resolver.resolve("something", "something-else")); +// +// // loaded from base.properties +// assertEquals("joecool", resolver.resolve("remote.username", "")); +// assertEquals("blabla", resolver.resolve("bla", "blabla")); +// } +// +//} http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/EnvironmentsTest.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/EnvironmentsTest.java b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/EnvironmentsTest.java new file mode 100644 index 0000000..cb60307 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/EnvironmentsTest.java @@ -0,0 +1,83 @@ +/* + * 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.integration.cdi; +// +//import org.junit.Test; +// +//import java.util.Map; +//import java.util.Properties; +// +//import static org.junit.Assert.assertEquals; +// +///** +// * Tests the related environment properties exist +// */ +//public class EnvironmentsTest { +// +// @Test +// public void testGetProperties() throws Exception { +// +// final Properties test = Environments.getProperties("test"); +// +// // loaded from test.properties +// assertEquals("classpath:/test-service-wsdl.xml", test.getProperty("remote.wsdl.location")); +// +// // loaded from base.properties +// assertEquals("joecool", test.getProperty("remote.username")); +// } +// +// @Test(expected = IllegalArgumentException.class) +// public void noEnvFound() { +// Environments.getProperties("does not exists"); +// } +// +// @Test +// public void dev() throws Exception { +// +// final Properties test = Environments.getProperties("dev"); +// +// assertEquals("org.apache.openejb.cipher.StaticDESPasswordCipher", test.getProperty("cipher")); +// assertEquals("NjAq6q2agYVnvSMz+eYUZg==", test.getProperty("remote.password")); +// assertEquals("1443", test.getProperty("remote.port")); +// assertEquals("https://srv1114.supertribe.org:1443/remote/service/url", test.getProperty("remote.target.url")); +// assertEquals("srv1114.supertribe.org:1443", test.getProperty("remote.address")); +// assertEquals("srv1114.supertribe.org", test.getProperty("remote.host")); +// assertEquals("classpath:/service-wsdl.xml", test.getProperty("remote.wsdl.location")); +// assertEquals("joecool", test.getProperty("remote.username")); +// } +// +// @Test +// public void cert() throws Exception { +// final Properties test = Environments.getProperties("cert"); +// assertEquals("srv1016.supertribe.org", test.getProperty("remote.host")); +// assertEquals("joecool", test.getProperty("remote.username")); +// } +// +// @Test +// public void prod() throws Exception { +// final Properties test = Environments.getProperties("prod"); +// assertEquals("remotedb001.supertribe.org", test.getProperty("remote.host")); +// assertEquals("joecool", test.getProperty("remote.username")); +// } +// +// +// private static void generateAsserts(Properties test) { +// for (Map.Entry<Object, Object> entry : test.entrySet()) { +// System.out.printf("assertEquals(\"%s\", test.getProperty(\"%s\"));%n", entry.getValue(), entry.getKey()); +// } +// } +//} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/InterpolationTest.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/InterpolationTest.java b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/InterpolationTest.java new file mode 100644 index 0000000..56cc8c9 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/InterpolationTest.java @@ -0,0 +1,62 @@ +/* + * 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.integration.cdi; +// +//import org.junit.Test; +//import org.tomitribe.util.IO; +// +//import java.net.URL; +//import java.util.Properties; +// +//import static org.junit.Assert.assertEquals; +// +//public class InterpolationTest { +// +// @Test +// public void testInterpolate() throws Exception { +// final Properties interpolated; +// { +// final Properties properties = new Properties(); +// properties.setProperty("foo.host", "localhost"); +// properties.setProperty("foo.port", "1234"); +// properties.setProperty("address", "http://${foo.host}:${foo.port}"); +// properties.setProperty("url", "${address}/webapp"); +// properties.setProperty("urlUnchanged", "${not an address}/webapp"); +// +// interpolated = Interpolation.interpolate(properties); +// } +// +// assertEquals("localhost", interpolated.getProperty("foo.host")); +// assertEquals("1234", interpolated.getProperty("foo.port")); +// assertEquals("http://localhost:1234", interpolated.getProperty("address")); +// assertEquals("http://localhost:1234/webapp", interpolated.getProperty("url")); +// assertEquals("${not an address}/webapp", interpolated.getProperty("urlUnchanged")); +// } +// +// @Test +// public void test() throws Exception { +// +// final ClassLoader loader = Thread.currentThread().getContextClassLoader(); +// +// final URL resource = loader.getResource("test.properties"); +// final Properties properties = Interpolation.interpolate(IO.readProperties(resource)); +// +// //remote.wsdl.location = classpath:/lx01116-zhr-active-partner-service-wsdl.xml +// assertEquals("classpath:/test-service-wsdl.xml", properties.getProperty("remote.wsdl.location")); +// } +// +//} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/NotFoundNoDefault.java ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/NotFoundNoDefault.java b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/NotFoundNoDefault.java new file mode 100644 index 0000000..afeeb84 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/java/org/apache/tamaya/integration/cdi/NotFoundNoDefault.java @@ -0,0 +1,78 @@ +/* + * 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.integration.cdi; + +import org.apache.tamaya.inject.api.Config; +import org.tomitribe.util.Duration; + +import javax.inject.Inject; +import java.io.File; + +public class NotFoundNoDefault { + + @Inject + @Config("string.bla") + private String string; + + @Inject + @Config("file.bla") + private File file; + + @Inject + @Config("duration.bla") + private Duration duration; + + @Inject + @Config("boolean.bla") + private Boolean aBoolean; + + @Inject + @Config("integer.bla") + private Integer integer; + + public String getString() { + return string; + } + + public File getFile() { + return file; + } + + public Duration getDuration() { + return duration; + } + + public Boolean getaBoolean() { + return aBoolean; + } + + public Integer getInteger() { + return integer; + } + + @Override + public String toString() { + return "NotFoundNoDefault{" + + "string='" + string + '\'' + + ", file=" + file + + ", duration=" + duration + + ", aBoolean=" + aBoolean + + ", integer=" + integer + + '}'; + } + + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/resources/META-INF/beans.xml ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/resources/META-INF/beans.xml b/modules/injection/cdi-ee/src/test/resources/META-INF/beans.xml new file mode 100644 index 0000000..562647f --- /dev/null +++ b/modules/injection/cdi-ee/src/test/resources/META-INF/beans.xml @@ -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. +--> +<beans></beans> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/resources/META-INF/javaconfiguration.properties ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/resources/META-INF/javaconfiguration.properties b/modules/injection/cdi-ee/src/test/resources/META-INF/javaconfiguration.properties new file mode 100644 index 0000000..8d3c5c8 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/resources/META-INF/javaconfiguration.properties @@ -0,0 +1,32 @@ +# +# 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. +# +remote.wsdl.location = classpath:/service-wsdl.xml +remote.port=1443 +remote.address=${remote.host}:${remote.port} +remote.target.url = https://${remote.address}/remote/service/url +remote.username = joecool +# ciphered using built in StaticDESPasswordCipher +remote.password = NjAq6q2agYVnvSMz+eYUZg== +cipher=org.apache.openejb.cipher.StaticDESPasswordCipher + +string.value = hello +file.value = ./conf +duration.value = 10 minutes and 57 seconds +boolean.value = true +integer.value = 123 http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/resources/base.properties ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/resources/base.properties b/modules/injection/cdi-ee/src/test/resources/base.properties new file mode 100644 index 0000000..a4d9896 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/resources/base.properties @@ -0,0 +1,32 @@ +# +# 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. +# +remote.wsdl.location = classpath:/service-wsdl.xml +remote.port=1443 +remote.address=${remote.host}:${remote.port} +remote.target.url = https://${remote.address}/remote/service/url +remote.username = joecool +# ciphered using built in StaticDESPasswordCipher +remote.password = NjAq6q2agYVnvSMz+eYUZg== +cipher=org.apache.openejb.cipher.StaticDESPasswordCipher + +string.value = hello +file.value = ./conf +duration.value = 10 minutes and 57 seconds +boolean.value = true +integer.value = 123 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/resources/cert.properties ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/resources/cert.properties b/modules/injection/cdi-ee/src/test/resources/cert.properties new file mode 100644 index 0000000..c2c3712 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/resources/cert.properties @@ -0,0 +1,20 @@ +# +# 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. +# +remote.host=srv1016.supertribe.org +remote.password=vm9oNWJpN8Y= http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/resources/dev.properties ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/resources/dev.properties b/modules/injection/cdi-ee/src/test/resources/dev.properties new file mode 100644 index 0000000..abd3e03 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/resources/dev.properties @@ -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. +# +remote.host=srv1114.supertribe.org http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/resources/prod.properties ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/resources/prod.properties b/modules/injection/cdi-ee/src/test/resources/prod.properties new file mode 100644 index 0000000..9f1ad67 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/resources/prod.properties @@ -0,0 +1,20 @@ +# +# 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. +# +remote.host=remotedb001.supertribe.org +remote.password=vm9oNWJpN8Y= http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/resources/qa.properties ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/resources/qa.properties b/modules/injection/cdi-ee/src/test/resources/qa.properties new file mode 100644 index 0000000..3f43795 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/resources/qa.properties @@ -0,0 +1,20 @@ +# +# 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. +# +remote.host=srv1115.supertribe.org +remote.password=vm9oNWJpN8Y= http://git-wip-us.apache.org/repos/asf/incubator-tamaya-extensions/blob/fe7cd8f1/modules/injection/cdi-ee/src/test/resources/test.properties ---------------------------------------------------------------------- diff --git a/modules/injection/cdi-ee/src/test/resources/test.properties b/modules/injection/cdi-ee/src/test/resources/test.properties new file mode 100644 index 0000000..8e08405 --- /dev/null +++ b/modules/injection/cdi-ee/src/test/resources/test.properties @@ -0,0 +1,20 @@ +# +# 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. +# +remote.wsdl.location = classpath:/test-service-wsdl.xml +
