blob: a97cf77215a63339e950341c5d1cf09ef73c3500 [file] [log] [blame]
/*
* 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.builder.internal;
import org.apache.tamaya.builder.PropertySourceBasedConfiguration;
import org.apache.tamaya.builder.spi.FilterContext;
import org.apache.tamaya.builder.spi.PropertyFilter;
import org.apache.tamaya.builder.spi.PropertySource;
import java.util.Collections;
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 PropertySourceBasedConfiguration} to evaluate the
* chain of {@link 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<String,String> configData, PropertySourceBasedConfiguration configurationContext) {
// Apply filters to values, prevent values filtered to null!
String result = configData.get(key);
for (int i = 0; i < MAX_FILTER_LOOPS; i++) {
boolean changed = false;
// Apply filters to values, prevent values filtered to null!
FilterContext filterContext = new FilterContext(key, configData, true);
for (PropertyFilter filter : configurationContext.getPropertyFilters()) {
String newValue = filter.filterProperty(result, filterContext);
if (newValue != null && !newValue.equals(result)) {
changed = true;
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("Filter - " + key + ": " + result + " -> " + newValue + " by " + filter);
}
} else if (result != null && !result.equals(newValue)) {
changed = true;
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("Filter - " + key + ": " + result + " -> " + newValue + " by " + filter);
}
}
result = 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 result;
}
public static Map<String, String> applyFilters(Map<String, String> inputMap, PropertySourceBasedConfiguration configurationContext) {
Map<String, String> resultMap = new HashMap<>(inputMap);
// Apply filters to values, prevent values filtered to null!
Map<String, String> metaData = filterMetadata(inputMap);
for (int i = 0; i < MAX_FILTER_LOOPS; i++) {
AtomicInteger changes = new AtomicInteger();
for (Map.Entry<String, String> entry : inputMap.entrySet()) {
FilterContext filterContext = new FilterContext(entry.getKey(), inputMap, false);
for (PropertyFilter filter : configurationContext.getPropertyFilters()) {
final String k = entry.getKey();
final String v = entry.getValue();
String newValue = filter.filterProperty(v, filterContext);
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;
}
private static Map<String, String> filterMetadata(Map<String, String> inputMap) {
Map<String,String> result = new HashMap<>();
for(Map.Entry<String,String> en:inputMap.entrySet()){
if(en.getKey().startsWith("_")){
result.put(en.getKey(), en.getValue());
}
}
return Collections.unmodifiableMap(result);
}
}