Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 89984200B85 for ; Thu, 15 Sep 2016 19:26:35 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 88054160ADA; Thu, 15 Sep 2016 17:26:35 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 33B4F160ABA for ; Thu, 15 Sep 2016 19:26:33 +0200 (CEST) Received: (qmail 24717 invoked by uid 500); 15 Sep 2016 17:26:32 -0000 Mailing-List: contact commits-help@tamaya.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tamaya.incubator.apache.org Delivered-To: mailing list commits@tamaya.incubator.apache.org Received: (qmail 24708 invoked by uid 99); 15 Sep 2016 17:26:32 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 15 Sep 2016 17:26:32 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id D1A43182411 for ; Thu, 15 Sep 2016 17:26:31 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -2.646 X-Spam-Level: X-Spam-Status: No, score=-2.646 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_BADIPHTTP=2, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-1.426] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id mbGfy45IzRXj for ; Thu, 15 Sep 2016 17:26:22 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id F25145FB25 for ; Thu, 15 Sep 2016 17:26:19 +0000 (UTC) Received: (qmail 23576 invoked by uid 99); 15 Sep 2016 17:26:19 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 15 Sep 2016 17:26:19 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id EF0F7E094C; Thu, 15 Sep 2016 17:26:18 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: plexus@apache.org To: commits@tamaya.incubator.apache.org Date: Thu, 15 Sep 2016 17:26:19 -0000 Message-Id: <8b4f2f61ca7d424483d932bacb6c1a57@git.apache.org> In-Reply-To: <601e12b1c9f64d208a03247b1439c1ca@git.apache.org> References: <601e12b1c9f64d208a03247b1439c1ca@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [02/24] incubator-tamaya git commit: Removed all modules from the main repository. They will be reborn in separate ASF repository. archived-at: Thu, 15 Sep 2016 17:26:35 -0000 http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java deleted file mode 100644 index 52a0d11..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfiguration.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.spisupport; - -import org.apache.tamaya.ConfigException; -import org.apache.tamaya.ConfigOperator; -import org.apache.tamaya.ConfigQuery; -import org.apache.tamaya.Configuration; -import org.apache.tamaya.TypeLiteral; -import org.apache.tamaya.spi.ConfigurationContext; -import org.apache.tamaya.spi.ConversionContext; -import org.apache.tamaya.spi.PropertyConverter; -import org.apache.tamaya.spi.PropertySource; -import org.apache.tamaya.spi.PropertyValue; -import org.apache.tamaya.spi.PropertyValueCombinationPolicy; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Implementation of the Configuration API. This class uses the current {@link ConfigurationContext} to evaluate the - * chain of {@link PropertySource} and {@link org.apache.tamaya.spi.PropertyFilter} - * instance to evaluate the current Configuration. - */ -public class DefaultConfiguration implements Configuration { - /** - * The logger. - */ - private static final Logger LOG = Logger.getLogger(DefaultConfiguration.class.getName()); - - /** - * The current {@link ConfigurationContext} of the current instance. - */ - private final ConfigurationContext configurationContext; - - - /** - * Constructor. - * @param configurationContext The configuration Context to be used. - */ - public DefaultConfiguration(ConfigurationContext configurationContext){ - this.configurationContext = Objects.requireNonNull(configurationContext); - } - - /** - * Get a given value, filtered with the context's filters as needed. - * @param key the property's key, not null. - * @return the filtered value, or null. - */ - @Override - public String get(String key) { - PropertyValue configData = evaluteRawValue(key); - if(configData==null){ - return null; - } - return PropertyFiltering.applyFilter(key, configData.getConfigEntries(), configurationContext); - } - - /** - * Evaluates the raw value using the context's PropertyValueCombinationPolicy. - * @param key the key, not null. - * @return the value, before filtering is applied. - */ - protected PropertyValue evaluteRawValue(String key) { - List propertySources = configurationContext.getPropertySources(); - Map unfilteredValue = null; - PropertyValueCombinationPolicy combinationPolicy = this.configurationContext - .getPropertyValueCombinationPolicy(); - for (PropertySource propertySource : propertySources) { - unfilteredValue = combinationPolicy.collect(unfilteredValue, key, propertySource); - } - if(unfilteredValue==null){ - return null; - } - return PropertyValue.of(key, unfilteredValue.get(key), unfilteredValue.get("_"+key+".source")); - } - - - @Override - public String getOrDefault(String key, String defaultValue) { - String val = get(key); - if(val==null){ - return defaultValue; - } - return val; - } - - @Override - public T getOrDefault(String key, Class type, T defaultValue) { - T val = get(key, type); - if(val==null){ - return defaultValue; - } - return val; - } - - /** - * Get the current properties, composed by the loaded {@link PropertySource} and filtered - * by registered {@link org.apache.tamaya.spi.PropertyFilter}. - * - * @return the final properties. - */ - @Override - public Map getProperties() { - return PropertyFiltering.applyFilters(evaluateUnfilteredMap(), configurationContext); - } - - /** - * Evaluate all properties, but do not apply filtering on the output. - * @return the unfiltered key, value map. - */ - protected Map evaluateUnfilteredMap() { - List propertySources = new ArrayList<>(configurationContext.getPropertySources()); - Collections.reverse(propertySources); - Map result = new HashMap<>(); - for (PropertySource propertySource : propertySources) { - try { - int origSize = result.size(); - Map otherMap = propertySource.getProperties(); - LOG.log(Level.FINEST, null, "Overriding with properties from " + propertySource.getName()); - result.putAll(otherMap); - LOG.log(Level.FINEST, null, "Handled properties from " + propertySource.getName() + "(new: " + - (result.size() - origSize) + ", overrides: " + origSize + ", total: " + result.size()); - } catch (Exception e) { - LOG.log(Level.SEVERE, "Error adding properties from PropertySource: " + propertySource + ", ignoring PropertySource.", e); - } - } - return result; - } - - /** - * Accesses the current String value for the given key and tries to convert it - * using the {@link PropertyConverter} instances provided by the current - * {@link ConfigurationContext}. - * - * @param key the property's absolute, or relative path, e.g. @code - * a/b/c/d.myProperty}. - * @param type The target type required, not null. - * @param the value type - * @return the converted value, never null. - */ - @Override - public T get(String key, Class type) { - return get(key, (TypeLiteral)TypeLiteral.of(type)); - } - - /** - * Accesses the current String value for the given key and tries to convert it - * using the {@link PropertyConverter} instances provided by the current - * {@link ConfigurationContext}. - * - * @param key the property's absolute, or relative path, e.g. @code - * a/b/c/d.myProperty}. - * @param type The target type required, not null. - * @param the value type - * @return the converted value, never null. - */ - @Override - public T get(String key, TypeLiteral type) { - return convertValue(key, get(key), type); - } - - protected T convertValue(String key, String value, TypeLiteral type) { - if (value != null) { - List> converters = configurationContext.getPropertyConverters(type); - ConversionContext context = new ConversionContext.Builder(this, configurationContext, key, type).build(); - for (PropertyConverter converter : converters) { - try { - T t = converter.convert(value, context); - if (t != null) { - return t; - } - } catch (Exception e) { - LOG.log(Level.FINEST, "PropertyConverter: " + converter + " failed to convert value: " + value, e); - } - } - throw new ConfigException("Unparseable config value for type: " + type.getRawType().getName() + ": " + key + - ", supported formats: "+context.getSupportedFormats()); - } - return null; - } - - @Override - public T getOrDefault(String key, TypeLiteral type, T defaultValue) { - T val = get(key, type); - if(val==null){ - return defaultValue; - } - return val; - } - - @Override - public Configuration with(ConfigOperator operator) { - return operator.operate(this); - } - - @Override - public T query(ConfigQuery query) { - return query.query(this); - } - - @Override - public ConfigurationContext getContext() { - return configurationContext; - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java deleted file mode 100644 index 76f254b..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/DefaultConfigurationContext.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.spisupport; - -import org.apache.tamaya.ConfigurationProvider; -import org.apache.tamaya.TypeLiteral; -import org.apache.tamaya.spi.ConfigurationContext; -import org.apache.tamaya.spi.ConfigurationContextBuilder; -import org.apache.tamaya.spi.PropertyConverter; -import org.apache.tamaya.spi.PropertyFilter; -import org.apache.tamaya.spi.PropertySource; -import org.apache.tamaya.spi.PropertySourceProvider; -import org.apache.tamaya.spi.PropertyValueCombinationPolicy; -import org.apache.tamaya.spi.ServiceContextManager; - -import javax.annotation.Priority; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.logging.Logger; - -/** - * Default Implementation of a simple ConfigurationContext. - */ -public class DefaultConfigurationContext implements ConfigurationContext { - /** The logger used. */ - private final static Logger LOG = Logger.getLogger(DefaultConfigurationContext.class.getName()); - /** - * Cubcomponent handling {@link PropertyConverter} instances. - */ - private final PropertyConverterManager propertyConverterManager = new PropertyConverterManager(); - - /** - * The current unmodifiable list of loaded {@link PropertySource} instances. - */ - private List immutablePropertySources; - - /** - * The current unmodifiable list of loaded {@link PropertyFilter} instances. - */ - private List immutablePropertyFilters; - - /** - * The overriding policy used when combining PropertySources registered to evalute the final configuration - * values. - */ - private PropertyValueCombinationPolicy propertyValueCombinationPolicy; - - /** - * Lock for internal synchronization. - */ - private final ReentrantReadWriteLock propertySourceLock = new ReentrantReadWriteLock(); - - /** Comparator used for ordering property sources. */ - private final PropertySourceComparator propertySourceComparator = new PropertySourceComparator(); - - /** Comparator used for ordering property filters. */ - private final PropertyFilterComparator propertyFilterComparator = new PropertyFilterComparator(); - - - /** - * The first time the Configuration system gets invoked we do initialize - * all our {@link PropertySource}s and - * {@link PropertyFilter}s which are known at startup. - */ - public DefaultConfigurationContext() { - List propertySources = new ArrayList<>(); - - // first we load all PropertySources which got registered via java.util.ServiceLoader - propertySources.addAll(ServiceContextManager.getServiceContext().getServices(PropertySource.class)); - - // after that we add all PropertySources which get dynamically registered via their PropertySourceProviders - propertySources.addAll(evaluatePropertySourcesFromProviders()); - - // now sort them according to their ordinal values - Collections.sort(propertySources, new PropertySourceComparator()); - - immutablePropertySources = Collections.unmodifiableList(propertySources); - LOG.info("Registered " + immutablePropertySources.size() + " property sources: " + - immutablePropertySources); - - // as next step we pick up the PropertyFilters pretty much the same way - List propertyFilters = new ArrayList<>(); - propertyFilters.addAll(ServiceContextManager.getServiceContext().getServices(PropertyFilter.class)); - Collections.sort(propertyFilters, new PropertyFilterComparator()); - immutablePropertyFilters = Collections.unmodifiableList(propertyFilters); - LOG.info("Registered " + immutablePropertyFilters.size() + " property filters: " + - immutablePropertyFilters); - - immutablePropertyFilters = Collections.unmodifiableList(propertyFilters); - LOG.info("Registered " + immutablePropertyFilters.size() + " property filters: " + - immutablePropertyFilters); - propertyValueCombinationPolicy = ServiceContextManager.getServiceContext().getService(PropertyValueCombinationPolicy.class); - if(propertyValueCombinationPolicy==null) { - propertyValueCombinationPolicy = PropertyValueCombinationPolicy.DEFAULT_OVERRIDING_COLLECTOR; - } - LOG.info("Using PropertyValueCombinationPolicy: " + propertyValueCombinationPolicy); - } - - /** - * Pick up all {@link PropertySourceProvider}s and return all the - * {@link PropertySource}s they like to register. - */ - private Collection evaluatePropertySourcesFromProviders() { - List propertySources = new ArrayList<>(); - Collection propertySourceProviders = ServiceContextManager.getServiceContext().getServices(PropertySourceProvider.class); - for (PropertySourceProvider propertySourceProvider : propertySourceProviders) { - Collection sources = propertySourceProvider.getPropertySources(); - LOG.finer("PropertySourceProvider " + propertySourceProvider.getClass().getName() + - " provided the following property sources: " + sources); - propertySources.addAll(sources); - } - - return propertySources; - } - - @Override - public void addPropertySources(PropertySource... propertySourcesToAdd) { - Lock writeLock = propertySourceLock.writeLock(); - try { - writeLock.lock(); - List newPropertySources = new ArrayList<>(this.immutablePropertySources); - newPropertySources.addAll(Arrays.asList(propertySourcesToAdd)); - Collections.sort(newPropertySources, new PropertySourceComparator()); - - this.immutablePropertySources = Collections.unmodifiableList(newPropertySources); - } finally { - writeLock.unlock(); - } - } - - /** - * Comparator used for comparing PropertySources. - */ - private static class PropertySourceComparator implements Comparator, Serializable { - - private static final long serialVersionUID = 1L; - - /** - * Order property source reversely, the most important come first. - * - * @param source1 the first PropertySource - * @param source2 the second PropertySource - * @return the comparison result. - */ - private int comparePropertySources(PropertySource source1, PropertySource source2) { - if (source1.getOrdinal() < source2.getOrdinal()) { - return -1; - } else if (source1.getOrdinal() > source2.getOrdinal()) { - return 1; - } else { - return source1.getClass().getName().compareTo(source2.getClass().getName()); - } - } - - @Override - public int compare(PropertySource source1, PropertySource source2) { - return comparePropertySources(source1, source2); - } - } - - /** - * Comparator used for comparing PropertyFilters. - */ - private static class PropertyFilterComparator implements Comparator, Serializable{ - - private static final long serialVersionUID = 1L; - - /** - * Compare 2 filters for ordering the filter chain. - * - * @param filter1 the first filter - * @param filter2 the second filter - * @return the comparison result - */ - private int comparePropertyFilters(PropertyFilter filter1, PropertyFilter filter2) { - Priority prio1 = filter1.getClass().getAnnotation(Priority.class); - Priority prio2 = filter2.getClass().getAnnotation(Priority.class); - int ord1 = prio1 != null ? prio1.value() : 0; - int ord2 = prio2 != null ? prio2.value() : 0; - - if (ord1 < ord2) { - return -1; - } else if (ord1 > ord2) { - return 1; - } else { - return filter1.getClass().getName().compareTo(filter2.getClass().getName()); - } - } - - @Override - public int compare(PropertyFilter filter1, PropertyFilter filter2) { - return comparePropertyFilters(filter1, filter2); - } - } - - @Override - public List getPropertySources() { - return immutablePropertySources; - } - - @Override - public void addPropertyConverter(TypeLiteral typeToConvert, PropertyConverter propertyConverter) { - propertyConverterManager.register(typeToConvert, propertyConverter); - LOG.info("Added PropertyConverter: " + propertyConverter.getClass().getName()); - } - - @Override - public Map, List>> getPropertyConverters() { - return propertyConverterManager.getPropertyConverters(); - } - - @Override - public List> getPropertyConverters(TypeLiteral targetType) { - return propertyConverterManager.getPropertyConverters(targetType); - } - - @Override - public List getPropertyFilters() { - return immutablePropertyFilters; - } - - @Override - public PropertyValueCombinationPolicy getPropertyValueCombinationPolicy(){ - return propertyValueCombinationPolicy; - } - - @Override - public ConfigurationContextBuilder toBuilder() { - return ConfigurationProvider.getConfigurationContextBuilder().setContext(this); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java deleted file mode 100644 index d003ccb..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/EnumConverter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.spisupport; - -import org.apache.tamaya.ConfigException; -import org.apache.tamaya.spi.ConversionContext; -import org.apache.tamaya.spi.PropertyConverter; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Locale; -import java.util.Objects; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Converter, converting from String to tge given enum type. - * @param the enum type. - */ -public class EnumConverter implements PropertyConverter { - private final Logger LOG = Logger.getLogger(EnumConverter.class.getName()); - private Class enumType; - private Method factory; - - public EnumConverter(Class enumType) { - if (!Enum.class.isAssignableFrom(enumType)) { - throw new IllegalArgumentException("Not an Enum: " + enumType.getName()); - } - this.enumType = Objects.requireNonNull(enumType); - try { - this.factory = enumType.getMethod("valueOf", String.class); - } catch (NoSuchMethodException e) { - throw new ConfigException("Uncovertible enum type without valueOf method found, please provide a custom " + - "PropertyConverter for: " + enumType.getName()); - } - } - - @Override - public T convert(String value, ConversionContext context) { - try { - return (T) factory.invoke(null, value); - } catch (InvocationTargetException | IllegalAccessException e) { - LOG.log(Level.FINEST, "Invalid enum value '" + value + "' for " + enumType.getName(), e); - } - try { - return (T) factory.invoke(null, value.toUpperCase(Locale.ENGLISH)); - } catch (InvocationTargetException | IllegalAccessException e) { - LOG.log(Level.FINEST, "Invalid enum value '" + value + "' for " + enumType.getName(), e); - } - return null; - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/MapPropertySource.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/MapPropertySource.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/MapPropertySource.java deleted file mode 100644 index ec4abc9..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/MapPropertySource.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tamaya.spisupport; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Properties; - -/** - * Simple PropertySource implementation that just takes a Map and an (optional) priority. - * Optionally the entries passed can be mapped to a different rootContext. - */ -public class MapPropertySource extends BasePropertySource { - - /** The unique name of the PropertySource. */ - private final String name; - - /** - * The Property Sources priority, a fixed priority should be used. - */ - private final Integer priority; - - /** - * The current properties. - */ - private final Map props = new HashMap<>(); - - /** - * Creates a new instance, hereby using the default mechanism for evaluating the property source's - * priority. - * - * @param name unique name of this source. - * @param props the properties - */ - public MapPropertySource(String name, Map props) { - this(name, props, null, null); - } - - /** - * Creates a new instance, hereby using the default mechanism for evaluating the property source's - * priority, but applying a custom mapping {@code rootContext} to the entries provided. - * - * @param name unique name of this source. - * @param props the properties - * @param rootContext the root context mapping, or null (for no mapping). - */ - public MapPropertySource(String name, Map props, String rootContext) { - this(name, props, rootContext, null); - } - - /** - * Creates a new instance, hereby using the default mechanism for evaluating the property source's - * priority, but applying a custom mapping {@code rootContext} to the entries provided. - * - * @param name unique name of this source. - * @param props the properties - * @param rootContext the root context mapping, or null (for no mapping). - * @param priority the (optional) fixed priority. If null, the default priority - * evaluation is used. - */ - public MapPropertySource(String name, Map props, String rootContext, Integer priority) { - this.priority = priority; - this.name = Objects.requireNonNull(name); - if (rootContext == null) { - this.props.putAll(props); - } else { - for (Map.Entry en : props.entrySet()) { - String prefix = rootContext; - if (!prefix.endsWith(".") && prefix.length() > 0) { - prefix += "."; - } - this.props.put(prefix + en.getKey(), en.getValue()); - } - } - } - - /** - * Creates a new instance, hereby using the default mechanism for evaluating the property source's - * priority, but applying a custom mapping {@code rootContext} to the entries provided. - * - * @param name unique name of this source. - * @param props the properties - * @param rootContext the root context mapping, or null (for no mapping). - * @param priority the (optional) fixed priority. If null, the default priority - * evaluation is used. - */ - public MapPropertySource(String name, Properties props, String rootContext, Integer priority) { - this(name, getMap(props), rootContext, priority); - } - - /** - * Simple method to convert Properties into a Map instance. - * @param props the properties, not null. - * @return the corresponding Map instance. - */ - public static Map getMap(Properties props) { - Map result = new HashMap<>(); - for (Map.Entry en : props.entrySet()) { - result.put(en.getKey().toString(), en.getValue().toString()); - } - return result; - } - - - @Override - public String getName() { - return name; - } - - @Override - public Map getProperties() { - return Collections.unmodifiableMap(this.props); - } - - @Override - public int getOrdinal() { - if(priority!=null) { - return priority; - } - return super.getOrdinal(); - } - - @Override - public String toString() { - return "SimplePropertiesPropertySource{" + - "name=" + name + ", " + - "priority=" + priority + - '}'; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java deleted file mode 100644 index 8f15696..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PriorityServiceComparator.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.spisupport; - -import javax.annotation.Priority; -import java.io.Serializable; -import java.util.Comparator; - -/** - * Comparator implementation for odering services loaded based on their increasing priority values. - */ -public class PriorityServiceComparator implements Comparator, Serializable { - - private static final long serialVersionUID = 1L; - - @Override - public int compare(Object o1, Object o2) { - int prio = getPriority(o1) - getPriority(o2); - if (prio < 0) { - return 1; - } else if (prio > 0) { - return -1; - } else { - return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName()); - } - } - - /** - * 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; - Priority priority = o.getClass().getAnnotation(Priority.class); - if (priority != null) { - prio = priority.value(); - } - return prio; - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertiesResourcePropertySource.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertiesResourcePropertySource.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertiesResourcePropertySource.java deleted file mode 100644 index bb8ba0b..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertiesResourcePropertySource.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.spisupport; - -import java.io.InputStream; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Simple PropertySource, with a fixed ordinal that reads a .properties file from a given URL. - */ -public class PropertiesResourcePropertySource extends MapPropertySource { - /** The logger used. */ - private static final Logger LOGGER = Logger.getLogger(PropertiesResourcePropertySource.class.getName()); - /** The resource loaded. */ - private final URL url; - - /** - * Creates a new instance. - * @param url the resource URL, not null. - * @param priority the optional (fixed) priority ordinal. - */ - public PropertiesResourcePropertySource(URL url, Integer priority){ - this(null, url, priority); - } - - /** - * Creates a new instance. - * @param rootContext the (optional) root context for mapping (prefixing) the properties loaded. - * @param url the resource URL, not null. - * @param priority the optional (fixed) priority ordinal. - */ - public PropertiesResourcePropertySource(String rootContext, URL url, Integer priority){ - super(url.toExternalForm(), loadProps(url), rootContext, priority); - this.url = url; - } - - /** - * Loads the properties using the JDK's Property loading mechanism. - * @param url the resource URL, not null. - * @return the loaded properties. - */ - private static Map loadProps(URL url) { - Map result = new HashMap<>(); - try(InputStream is = url.openStream()){ - Properties props = new Properties(); - props.load(is); - for(Map.Entry en: props.entrySet()){ - result.put(en.getKey().toString(), en.getValue().toString()); - } - } - catch(Exception e){ - LOGGER.log(Level.WARNING, "Failed to read properties from " + url, e); - } - return result; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java deleted file mode 100644 index 2be6313..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyConverterManager.java +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.spisupport; - -import org.apache.tamaya.ConfigException; -import org.apache.tamaya.TypeLiteral; -import org.apache.tamaya.spi.ConversionContext; -import org.apache.tamaya.spi.PropertyConverter; -import org.apache.tamaya.spi.ServiceContextManager; - -import javax.annotation.Priority; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.logging.Logger; - -/** - * Manager that deals with {@link PropertyConverter} instances. - * This class is thread-safe. - */ -public class PropertyConverterManager { - /** - * The logger used. - */ - private static final Logger LOG = Logger.getLogger(PropertyConverterManager.class.getName()); - /** - * The registered converters. - */ - private final Map, List>> converters = new ConcurrentHashMap<>(); - /** - * The transitive converters. - */ - private final Map, List>> transitiveConverters = new ConcurrentHashMap<>(); - /** - * The lock used. - */ - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - - private static final Comparator PRIORITY_COMPARATOR = new Comparator() { - - @Override - public int compare(Object o1, Object o2) { - int prio = getPriority(o1) - getPriority(o2); - if (prio < 0) { - return 1; - } else if (prio > 0) { - return -1; - } else { - return o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName()); - } - } - }; - - /** - * 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; - Priority priority = o.getClass().getAnnotation(Priority.class); - if (priority != null) { - prio = priority.value(); - } - return prio; - } - - /** - * Constructor. - */ - public PropertyConverterManager() { - this(true); - } - - public PropertyConverterManager(boolean init) { - if (init) { - initConverters(); - } - } - - /** - * Registers the default converters provided out of the box. - */ - protected void initConverters() { - for (PropertyConverter conv : ServiceContextManager.getServiceContext().getServices(PropertyConverter.class)) { - Type type = TypeLiteral.getGenericInterfaceTypeParameters(conv.getClass(), PropertyConverter.class)[0]; - register(TypeLiteral.of(type), conv); - } - } - - /** - * Registers a ew converter instance. - * - * @param targetType the target type, not null. - * @param converter the converter, not null. - * @param the type. - */ - public void register(TypeLiteral targetType, PropertyConverter converter) { - Objects.requireNonNull(converter); - Lock writeLock = lock.writeLock(); - try { - writeLock.lock(); - List converters = List.class.cast(this.converters.get(targetType)); - List> newConverters = new ArrayList<>(); - if (converters != null) { - newConverters.addAll(converters); - } - newConverters.add(converter); - Collections.sort(newConverters, PRIORITY_COMPARATOR); - this.converters.put(targetType, Collections.unmodifiableList(newConverters)); - // evaluate transitive closure for all inherited supertypes and implemented interfaces - // direct implemented interfaces - for (Class ifaceType : targetType.getRawType().getInterfaces()) { - converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType))); - newConverters = new ArrayList<>(); - if (converters != null) { - newConverters.addAll(converters); - } - newConverters.add(converter); - Collections.sort(newConverters, PRIORITY_COMPARATOR); - this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters)); - } - Class superClass = targetType.getRawType().getSuperclass(); - while (superClass != null && !superClass.equals(Object.class)) { - converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(superClass))); - newConverters = new ArrayList<>(); - if (converters != null) { - newConverters.addAll(converters); - } - newConverters.add(converter); - Collections.sort(newConverters, PRIORITY_COMPARATOR); - this.transitiveConverters.put(TypeLiteral.of(superClass), Collections.unmodifiableList(newConverters)); - for (Class ifaceType : superClass.getInterfaces()) { - converters = List.class.cast(this.transitiveConverters.get(TypeLiteral.of(ifaceType))); - newConverters = new ArrayList<>(); - if (converters != null) { - newConverters.addAll(converters); - } - newConverters.add(converter); - Collections.sort(newConverters, PRIORITY_COMPARATOR); - this.transitiveConverters.put(TypeLiteral.of(ifaceType), Collections.unmodifiableList(newConverters)); - } - superClass = superClass.getSuperclass(); - } - } finally { - writeLock.unlock(); - } - } - - /** - * Allows to evaluate if a given target type is supported. - * - * @param targetType the target type, not null. - * @return true, if a converter for the given type is registered, or a default one can be created. - */ - public boolean isTargetTypeSupported(TypeLiteral targetType) { - return converters.containsKey(targetType) || transitiveConverters.containsKey(targetType) - || createDefaultPropertyConverter(targetType) != null; - } - - /** - * Get a map of all property converters currently registered. This will not contain the converters that - * may be created, when an instance is adapted, which provides a String constructor or compatible - * factory methods taking a single String instance. - * - * @return the current map of instantiated and registered converters. - * @see #createDefaultPropertyConverter(TypeLiteral) - */ - public Map, List>> getPropertyConverters() { - Lock readLock = lock.readLock(); - try { - readLock.lock(); - return new HashMap<>(this.converters); - } finally { - readLock.unlock(); - } - } - - /** - * Get the list of all current registered converters for the given target type. - * If not converters are registered, they component tries to create and register a dynamic - * converter based on String costructor or static factory methods available. - * - *

The converters provided are of the following type and returned in the following order:

- * - *
    - *
  • Converters mapped explicitly to the required target type are returned first, ordered - * by decreasing priority. This means, if explicit converters are registered these are used - * primarly for converting a value.
  • - *
  • The target type of each explicitly registered converter also can be transitively mapped to - * 1) all directly implemented interfaces, 2) all its superclasses (except Object), 3) all the interfaces - * implemented by its superclasses. These groups of transitive converters is returned similarly in the - * order as mentioned, whereas also here a priority based decreasing ordering is applied.
  • - *
  • java.lang wrapper classes and native types are automatically mapped.
  • - *
  • If no explicit converters are registered, for Enum types a default implementation is provided that - * compares the configuration values with the different enum members defined (cases sensitive mapping).
  • - *
- * - * - * So given that list above directly registered mappings always are tried first, before any transitive mapping - * should be used. Also in all cases @Priority annotations are honored for ordering of the converters in place. - * Transitive conversion is supported for all directly implemented interfaces (including inherited ones) and - * the inheritance hierarchy (exception Object). Superinterfaces of implemented interfaces are ignored. - * - * - * @param targetType the target type, not null. - * @param the type class - * @return the ordered list of converters (may be empty for not convertible types). - * @see #createDefaultPropertyConverter(TypeLiteral) - */ - public List> getPropertyConverters(TypeLiteral targetType) { - Lock readLock = lock.readLock(); - List> converterList = new ArrayList<>(); - List> converters; - // direct mapped converters - try { - readLock.lock(); - converters = List.class.cast(this.converters.get(targetType)); - } finally { - readLock.unlock(); - } - if (converters != null) { - converterList.addAll(converters); - } - // transitive converter - try { - readLock.lock(); - converters = List.class.cast(this.transitiveConverters.get(targetType)); - } finally { - readLock.unlock(); - } - if (converters != null) { - converterList.addAll(converters); - } - // handling of java.ui.lang wrapper classes - TypeLiteral boxedType = mapBoxedType(targetType); - if (boxedType != null) { - try { - readLock.lock(); - converters = List.class.cast(this.converters.get(boxedType)); - } finally { - readLock.unlock(); - } - if (converters != null) { - converterList.addAll(converters); - } - } - if (converterList.isEmpty()) { - // adding any converters created on the fly, e.g. for enum types. - PropertyConverter defaultConverter = createDefaultPropertyConverter(targetType); - if (defaultConverter != null) { - register(targetType, defaultConverter); - try { - readLock.lock(); - converters = List.class.cast(this.converters.get(targetType)); - } finally { - readLock.unlock(); - } - } - if (converters != null) { - converterList.addAll(converters); - } - } - return converterList; - } - - /** - * Maps native types to the corresponding boxed types. - * - * @param targetType the native type. - * @param the type - * @return the boxed type, or null. - */ - @SuppressWarnings("all") - private TypeLiteral mapBoxedType(TypeLiteral targetType) { - Type parameterType = targetType.getType(); - if (parameterType == int.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Integer.class)); - } - if (parameterType == short.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Short.class)); - } - if (parameterType == byte.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Byte.class)); - } - if (parameterType == long.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Long.class)); - } - if (parameterType == boolean.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class)); - } - if (parameterType == char.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Character.class)); - } - if (parameterType == float.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Float.class)); - } - if (parameterType == double.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Double.class)); - } - if (parameterType == int[].class) { - return TypeLiteral.class.cast(TypeLiteral.of(Integer[].class)); - } - if (parameterType == short[].class) { - return TypeLiteral.class.cast(TypeLiteral.of(Short[].class)); - } - if (parameterType == byte[].class) { - return TypeLiteral.class.cast(TypeLiteral.of(Byte[].class)); - } - if (parameterType == long[].class) { - return TypeLiteral.class.cast(TypeLiteral.of(Long[].class)); - } - if (parameterType == boolean.class) { - return TypeLiteral.class.cast(TypeLiteral.of(Boolean.class)); - } - if (parameterType == char[].class) { - return TypeLiteral.class.cast(TypeLiteral.of(Character[].class)); - } - if (parameterType == float[].class) { - return TypeLiteral.class.cast(TypeLiteral.of(Float[].class)); - } - if (parameterType == double[].class) { - return TypeLiteral.class.cast(TypeLiteral.of(Double[].class)); - } - return null; - } - - /** - * Creates a dynamic PropertyConverter for the given target type. - * - * @param targetType the target type - * @param the type class - * @return a new converter, or null. - */ - protected PropertyConverter createDefaultPropertyConverter(final TypeLiteral targetType) { - if (Enum.class.isAssignableFrom(targetType.getRawType())) { - return new EnumConverter<>(targetType.getRawType()); - } - PropertyConverter converter = null; - final Method factoryMethod = getFactoryMethod(targetType.getRawType(), "of", "valueOf", "instanceOf", "getInstance", "from", "fromString", "parse"); - if (factoryMethod != null) { - converter = new PropertyConverter() { - @Override - public T convert(String value, ConversionContext context) { - try { - if (!Modifier.isStatic(factoryMethod.getModifiers())) { - throw new ConfigException(factoryMethod.toGenericString() + - " is not a static method. Only static " + - "methods can be used as factory methods."); - } - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - factoryMethod.setAccessible(true); - return null; - } - }); - Object invoke = factoryMethod.invoke(null, value); - return targetType.getRawType().cast(invoke); - } catch (Exception e) { - throw new ConfigException("Failed to decode '" + value + "'", e); - } - } - }; - } - if (converter == null) { - try { - final Constructor constr = targetType.getRawType().getDeclaredConstructor(String.class); - converter = new PropertyConverter() { - @Override - public T convert(String value, ConversionContext context) { - try { - constr.setAccessible(true); - return constr.newInstance(value); - } catch (Exception e) { - throw new ConfigException("Failed to decode '" + value + "'", e); - } - } - }; - } catch (Exception e) { - LOG.finest("Failed to construct instance of type: " + targetType.getRawType().getName() + ": " + e); - } - } - return converter; - } - - /** - * Tries to evaluate a factory method that can be used to create an instance based on a String. - * - * @param type the target type - * @param methodNames the possible static method names - * @return the first method found, or null. - */ - private Method getFactoryMethod(Class type, String... methodNames) { - Method m; - for (String name : methodNames) { - try { - m = type.getDeclaredMethod(name, String.class); - return m; - } catch (NoSuchMethodException | RuntimeException e) { - LOG.finest("No such factory method found on type: " + type.getName() + ", methodName: " + name); - } - } - return null; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java deleted file mode 100644 index eef758b..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertyFiltering.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.spisupport; - -import org.apache.tamaya.spi.ConfigurationContext; -import org.apache.tamaya.spi.FilterContext; -import org.apache.tamaya.spi.PropertyFilter; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Implementation of the Configuration API. This class uses the current {@link ConfigurationContext} to evaluate the - * chain of {@link org.apache.tamaya.spi.PropertySource} and {@link PropertyFilter} - * instance to evaluate the current Configuration. - */ -public final class PropertyFiltering{ - /** - * The logger. - */ - private static final Logger LOG = Logger.getLogger(PropertyFiltering.class.getName()); - /** - * The maximal number of filter cycles performed before aborting. - */ - private static final int MAX_FILTER_LOOPS = 10; - - /** - * Private singleton constructor. - */ - private PropertyFiltering(){} - - public static String applyFilter(String key, Map configData, ConfigurationContext configurationContext) { - // Apply filters to values, prevent values filtered to null! - String unfilteredValue = configData.get(key); - for (int i = 0; i < MAX_FILTER_LOOPS; i++) { - boolean changed = false; - // Apply filters to values, prevent values filtered to null! - for (PropertyFilter filter : configurationContext.getPropertyFilters()) { - String newValue = filter.filterProperty(unfilteredValue, new FilterContext(key, configData, true)); - if (newValue != null && !newValue.equals(unfilteredValue)) { - changed = true; - if (LOG.isLoggable(Level.FINEST)) { - LOG.finest("Filter - " + key + ": " + unfilteredValue + " -> " + newValue + " by " + filter); - } - } else if (unfilteredValue != null && !unfilteredValue.equals(newValue)) { - changed = true; - if (LOG.isLoggable(Level.FINEST)) { - LOG.finest("Filter - " + key + ": " + unfilteredValue + " -> " + newValue + " by " + filter); - } - } - unfilteredValue = newValue; - } - if (!changed) { - LOG.finest("Finishing filter loop, no changes detected."); - break; - } else { - if (i == (MAX_FILTER_LOOPS - 1)) { - if (LOG.isLoggable(Level.WARNING)) { - LOG.warning("Maximal filter loop count reached, aborting filter evaluation after cycles: " + i); - } - } else { - LOG.finest("Repeating filter loop, changes detected."); - } - } - } - return unfilteredValue; - } - - public static Map applyFilters(Map inputMap, ConfigurationContext configurationContext) { - Map resultMap = new HashMap<>(inputMap); - // Apply filters to values, prevent values filtered to null! - for (int i = 0; i < MAX_FILTER_LOOPS; i++) { - AtomicInteger changes = new AtomicInteger(); - for (PropertyFilter filter : configurationContext.getPropertyFilters()) { - for (Map.Entry entry : inputMap.entrySet()) { - final String k = entry.getKey(); - final String v = entry.getValue(); - - String newValue = filter.filterProperty(v, new FilterContext(k, inputMap, false)); - if (newValue != null && !newValue.equals(v)) { - changes.incrementAndGet(); - LOG.finest("Filter - " + k + ": " + v + " -> " + newValue + " by " + filter); - } else if (v != null && !v.equals(newValue)) { - changes.incrementAndGet(); - LOG.finest("Filter - " + k + ": " + v + " -> " + newValue + " by " + filter); - } - // Remove null values - if (null != newValue) { - resultMap.put(k, newValue); - }else{ - resultMap.remove(k); - } - } - } - if (changes.get() == 0) { - LOG.finest("Finishing filter loop, no changes detected."); - break; - } else { - if (i == (MAX_FILTER_LOOPS - 1)) { - if (LOG.isLoggable(Level.WARNING)) { - LOG.warning("Maximal filter loop count reached, aborting filter evaluation after cycles: " + i); - } - } else { - LOG.finest("Repeating filter loop, changes detected: " + changes.get()); - } - changes.set(0); - } - } - return resultMap; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java ---------------------------------------------------------------------- diff --git a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java b/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java deleted file mode 100644 index 6554167..0000000 --- a/modules/spi-support/src/main/java/org/apache/tamaya/spisupport/PropertySourceComparator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.spisupport; - -import org.apache.tamaya.spi.PropertySource; - -import java.io.Serializable; -import java.util.Comparator; - -/** - * Comparator for ordering of PropertySources based on their ordinal method and class name. - */ -public class PropertySourceComparator implements Comparator, Serializable { - /** serial version UID. */ - private static final long serialVersionUID = 1L; - - /** - * Order property source reversely, the most important come first. - * - * @param source1 the first PropertySource - * @param source2 the second PropertySource - * @return the comparison result. - */ - private int comparePropertySources(PropertySource source1, PropertySource source2) { - if (source1.getOrdinal() < source2.getOrdinal()) { - return -1; - } else if (source1.getOrdinal() > source2.getOrdinal()) { - return 1; - } else { - return source1.getClass().getName().compareTo(source2.getClass().getName()); - } - } - - @Override - public int compare(PropertySource source1, PropertySource source2) { - return comparePropertySources(source1, source2); - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/yaml/pom.xml ---------------------------------------------------------------------- diff --git a/modules/yaml/pom.xml b/modules/yaml/pom.xml deleted file mode 100644 index 483b6a9..0000000 --- a/modules/yaml/pom.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - - 4.0.0 - - - org.apache.tamaya.ext - tamaya-extensions - 0.3-incubating-SNAPSHOT - .. - - tamaya-yaml - Apache Tamaya Modules - YAML Support - bundle - 2016 - - - 1.7 - 1.17 - - - - - org.apache.tamaya - tamaya-api - ${project.version} - provided - - - - org.apache.tamaya - tamaya-core - ${project.version} - provided - - - - org.apache.tamaya.ext - tamaya-formats - ${project.version} - - - org.yaml - snakeyaml - ${snakeyaml.version} - - - junit - junit - - - org.hamcrest - java-hamcrest - - - - - - - maven-dependency-plugin - - - copyMain - process-test-sources - - copy - - - ${project.build.directory} - false - false - true - true - - - org.jboss.arquillian.daemon - arquillian-daemon-main - - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - - org.apache.tamaya.json - - - - - - - - - http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/yaml/src/main/java/org/apache/tamaya/json/YAMLFormat.java ---------------------------------------------------------------------- diff --git a/modules/yaml/src/main/java/org/apache/tamaya/json/YAMLFormat.java b/modules/yaml/src/main/java/org/apache/tamaya/json/YAMLFormat.java deleted file mode 100644 index 06e431e..0000000 --- a/modules/yaml/src/main/java/org/apache/tamaya/json/YAMLFormat.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.json; - -import org.apache.tamaya.ConfigException; -import org.apache.tamaya.format.ConfigurationData; -import org.apache.tamaya.format.ConfigurationDataBuilder; -import org.apache.tamaya.format.ConfigurationFormat; -import org.yaml.snakeyaml.Yaml; - -import java.io.InputStream; -import java.net.URL; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static java.lang.String.format; - - -/** - * Implementation of the {@link org.apache.tamaya.format.ConfigurationFormat} - * able to read configuration properties represented in JSON - * - * @see JSON format specification - */ -public class YAMLFormat implements ConfigurationFormat { - /** - * THe logger. - */ - private static final Logger LOG = Logger.getLogger(YAMLFormat.class.getName()); - - /** - * Constructor, itniaitlizing zhe JSON reader factory. - */ - public YAMLFormat(){ - } - - @Override - public String getName() { - return "yaml"; - } - - @Override - public boolean accepts(URL url) { - return Objects.requireNonNull(url).getPath().endsWith(".yaml"); - } - - @Override - public ConfigurationData readConfiguration(String resource, InputStream inputStream) { - try( InputStream in = inputStream;) { - Map values = readConfig(resource, inputStream); - return ConfigurationDataBuilder.of(resource, this).addProperties(values) - .build(); - } catch (Exception e) { - throw new ConfigException("Failed to read data from " + resource, e); - } - } - - /** - * Reads the configuration. - * @param inputStream the input stream, not null. - * @param resource resource URI, not null. - * @return the configuration read from the given resource URI. - * @throws ConfigException if resource URI cannot be read. - */ - protected Map readConfig(String resource, InputStream inputStream) { - try{ - Yaml yaml = new Yaml(); - HashMap values = new HashMap<>(); - Object config = yaml.load(inputStream); - mapYamlIntoProperties(config, values); - if(LOG.isLoggable(Level.FINEST)){ - LOG.finest("Read data from " + resource + " : " + values); - } - return values; - }catch (Throwable t) { - throw new ConfigException(format("Failed to read properties from %s", resource), t); - } - } - /** - * Reads the configuration. - * @param urlResource soure of the configuration. - * @return the configuration read from the given resource URL. - * @throws ConfigException if resource URL cannot be read. - */ - protected Map readConfig(URL urlResource) { - try (InputStream is = urlResource.openStream()) { - return readConfig(urlResource.toExternalForm(), is); - } - catch (Throwable t) { - throw new ConfigException(format("Failed to read properties from %s", urlResource.toExternalForm()), t); - } - } - - private void mapYamlIntoProperties(Object config, HashMap values) { - mapYamlIntoProperties("", config, values); - } - - /** - * Maps the given config item (could be a String, a collection type or something else returned by the yaml parser - * to a key/value pair and adds it to {@code values} (hereby honoring the prefix as a key to be used.). - * Collection types are recursively to remapped hereby extending the given prefix as needed and recursively - * delegate mapping of values contained. - * @param prefix the prefix or key evaluated so far, never null (but can be empty for root entries). - * @param config the config value. Could be a single value or a collection type. - * @param values the properties where items identified must be written into. These properties are going to be - * returned as result of the format reading operation ans integrated into the overall configuration - * map. - */ - protected void mapYamlIntoProperties(String prefix, Object config, HashMap values) { - // add further data types supported by yaml, e.g. date, ... - if(config instanceof List){ - StringBuilder b = new StringBuilder(); - for(Object val:((List)config)){ - b.append(mapValueToString(val)); - b.append(","); - } - if(b.length()>0){ - b.setLength(b.length()-1); - } - values.put(prefix, b.toString()); - values.put("_"+prefix+".collection-type", "List"); - } else if(config instanceof Map){ - for(Map.Entry en:((Map)config).entrySet()){ - String newPrefix = prefix.isEmpty()?en.getKey():prefix +"."+en.getKey(); - mapYamlIntoProperties(newPrefix, en.getValue(), values); - } - } else{ - values.put(prefix, mapValueToString(config)); - } - } - - protected String mapValueToString(Object val) { - return String.valueOf(val); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/yaml/src/main/java/org/apache/tamaya/json/YAMLPropertySource.java ---------------------------------------------------------------------- diff --git a/modules/yaml/src/main/java/org/apache/tamaya/json/YAMLPropertySource.java b/modules/yaml/src/main/java/org/apache/tamaya/json/YAMLPropertySource.java deleted file mode 100644 index e29d2e7..0000000 --- a/modules/yaml/src/main/java/org/apache/tamaya/json/YAMLPropertySource.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.json; - -import org.apache.tamaya.spi.PropertySource; -import org.apache.tamaya.spi.PropertyValue; - -import java.net.URL; -import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; - - - -/** - * Property source based on a JSON file. - */ -public class YAMLPropertySource implements PropertySource { - /** The underlying resource. */ - private final URL urlResource; - /** The values read. */ - private final Map values; - /** The evaluated ordinal. */ - private int ordinal; - /** The format implementation used for parsing. */ - private YAMLFormat format = new YAMLFormat(); - - /** - * Constructor, hereby using 0 as the default ordinal. - * @param resource the resource modelled as URL, not null. - */ - public YAMLPropertySource(URL resource) { - this(resource, 0); - } - - /** - * Constructor. - * @param resource the resource modelled as URL, not null. - * @param defaultOrdinal the defaultOrdinal to be used. - */ - public YAMLPropertySource(URL resource, int defaultOrdinal) { - urlResource = Objects.requireNonNull(resource); - this.ordinal = defaultOrdinal; // may be overriden by read... - this.values = format.readConfig(urlResource); - if (this.values.containsKey(TAMAYA_ORDINAL)) { - this.ordinal = Integer.parseInt(this.values.get(TAMAYA_ORDINAL)); - } - } - - @Override - public int getOrdinal() { - PropertyValue configuredOrdinal = get(TAMAYA_ORDINAL); - if(configuredOrdinal!=null){ - try{ - return Integer.parseInt(configuredOrdinal.getValue()); - } catch(Exception e){ - Logger.getLogger(getClass().getName()).log(Level.WARNING, - "Configured Ordinal is not an int number: " + configuredOrdinal, e); - } - } - return ordinal; - } - - @Override - public String getName() { - return urlResource.toExternalForm(); - } - - @Override - public PropertyValue get(String key) { - return PropertyValue.of(key, getProperties().get(key), getName()); - } - - @Override - public Map getProperties() { - return Collections.unmodifiableMap(values); - } - - - @Override - public boolean isScannable() { - return true; - } -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/yaml/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat ---------------------------------------------------------------------- diff --git a/modules/yaml/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat b/modules/yaml/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat deleted file mode 100644 index 1b5d57d..0000000 --- a/modules/yaml/src/main/resources/META-INF/services/org.apache.tamaya.format.ConfigurationFormat +++ /dev/null @@ -1,19 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy current the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -org.apache.tamaya.json.YAMLFormat \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/yaml/src/test/java/org/apache/tamaya/json/YAMLFormatTest.java ---------------------------------------------------------------------- diff --git a/modules/yaml/src/test/java/org/apache/tamaya/json/YAMLFormatTest.java b/modules/yaml/src/test/java/org/apache/tamaya/json/YAMLFormatTest.java deleted file mode 100644 index 0f0e589..0000000 --- a/modules/yaml/src/test/java/org/apache/tamaya/json/YAMLFormatTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.json; - - -import org.apache.tamaya.format.ConfigurationData; -import org.apache.tamaya.format.FlattenedDefaultPropertySource; -import org.apache.tamaya.spi.PropertySource; -import org.junit.Test; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Map; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -public class YAMLFormatTest { - private final YAMLFormat format = new YAMLFormat(); - - @Test - public void testAcceptURL() throws MalformedURLException { - assertTrue(format.accepts(new URL("http://127.0.0.1/anyfile.yaml"))); - } - - @Test - public void testAcceptURL_BC1() throws MalformedURLException { - assertFalse(format.accepts(new URL("http://127.0.0.1/anyfile.YAML"))); - } - - @Test(expected = NullPointerException.class) - public void testAcceptURL_BC2() throws MalformedURLException { - assertFalse(format.accepts(null)); - } - - @Test - public void testAcceptURL_BC3() throws MalformedURLException { - assertFalse(format.accepts(new URL("http://127.0.0.1/anyfile.docx"))); - } - - @Test - public void testRead() throws IOException { - URL configURL = YAMLPropertySourceTest.class.getResource("/configs/valid/contact.yaml"); - assertTrue(format.accepts(configURL)); - ConfigurationData data = format.readConfiguration(configURL.toString(), configURL.openStream()); - assertNotNull(data); - for(Map.Entry en:data.getDefaultProperties().entrySet()) { - System.out.println(en.getKey() + " -> " + en.getValue()); - } - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/yaml/src/test/java/org/apache/tamaya/json/YAMLPropertySourceTest.java ---------------------------------------------------------------------- diff --git a/modules/yaml/src/test/java/org/apache/tamaya/json/YAMLPropertySourceTest.java b/modules/yaml/src/test/java/org/apache/tamaya/json/YAMLPropertySourceTest.java deleted file mode 100644 index 7f1c7a3..0000000 --- a/modules/yaml/src/test/java/org/apache/tamaya/json/YAMLPropertySourceTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.tamaya.json; - -import org.apache.tamaya.ConfigException; -import org.apache.tamaya.spi.PropertySource; -import org.hamcrest.CoreMatchers; -import org.junit.Test; - -import java.net.URL; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; - -public class YAMLPropertySourceTest { - - @Test - public void testYamlWithOrdinal() throws Exception { - URL configURL = YAMLPropertySourceTest.class.getResource("/configs/valid/test-with-prio.yaml"); - - assertThat(configURL, CoreMatchers.notNullValue()); - - YAMLPropertySource source = new YAMLPropertySource(configURL, 4); - assertEquals(source.getOrdinal(), 16784); - } - - @Test - public void testYamlDefaultOrdinal() throws Exception { - URL configURL = YAMLPropertySourceTest.class.getResource("/configs/valid/test.yaml"); - - assertThat(configURL, CoreMatchers.notNullValue()); - - YAMLPropertySource source = new YAMLPropertySource(configURL, 4); - assertEquals(source.getOrdinal(), 4); - } - - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/359d3e4a/modules/yaml/src/test/resources/configs/valid/contact.yaml ---------------------------------------------------------------------- diff --git a/modules/yaml/src/test/resources/configs/valid/contact.yaml b/modules/yaml/src/test/resources/configs/valid/contact.yaml deleted file mode 100644 index 95d5a03..0000000 --- a/modules/yaml/src/test/resources/configs/valid/contact.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy current the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -invoice: 34843 -date : 2001-01-23 -bill-to: &id001 - given : Chris - family : Dumars - address: - lines: | - 458 Walkman Dr. - Suite #292 - city : Royal Oak - state : MI - postal : 48046 -ship-to: *id001 -product: - - sku : BL394D - quantity : 4 - description : Basketball - price : 450.00 - - sku : BL4438H - quantity : 1 - description : Super Hoop - price : 2392.00 -tax : 251.42 -total: 4443.52 -comments: > - Late afternoon is best. - Backup contact is Nancy - Billsmer @ 338-4338. \ No newline at end of file