/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package org.codice.ddf.configuration.persistence.felix; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Abstract base class used to convert a Felix property value into a different format. */ abstract class PropertyValueConverter { protected static final Logger LOGGER = LoggerFactory.getLogger(PropertyValueConverter.class); private static final String SINGLE_VALUE_REGEX = "(\"[^\"]*\")"; private static final String ARRAY_REGEX = "\\[\\s*(\"[^\"]*\")(\\s*,\\s*\"[^\"]*\")*\\s*\\]"; private static final String VECTOR_REGEX = "\\(\\s*(\"[^\"]*\")(\\s*,\\s*\"[^\"]*\")*\\s*\\)"; private static final Pattern PROPERTY_VALUE_PATTERN = Pattern.compile(String.format("%s|%s|%s", SINGLE_VALUE_REGEX, ARRAY_REGEX, VECTOR_REGEX)); /** * Converts a property value (which can be a single value or an array or list of values) to a * different format. Sub-classes are responsible for the conversion of individual values by * implementing the {@link #convertSingleValue(String, StringBuilder)}. * <p/> * Note that values will be converted only if their format follows the Felix format for values * which can be "value", ["value1", "value2", ...] or ("value1", "value2", ...). Any value * that doesn't match that format will just be output as-is and not converted. * * @param propertyValue property value to convert. Assumes that the value provided has been * trimmed, starts with a quote ("), square bracket ([) or parenthesis * and is not {@code null}. * @param output {@link StringBuilder} to append the value to. Assumes that this is * never {@code null}. */ public void convert(String propertyValue, StringBuilder output) { Matcher matcher = PROPERTY_VALUE_PATTERN.matcher(propertyValue); if (!matcher.matches()) { LOGGER.debug("Property value {} doesn't seem valid, skipping", propertyValue); output.append(propertyValue); return; } if (propertyValue.startsWith("\"")) { LOGGER.debug("Converting single value {}", propertyValue); output.append('"'); convertSingleValue(propertyValue.trim() .replaceAll("\"", ""), output); output.append('"'); } else if (propertyValue.startsWith("[") && propertyValue.endsWith("]")) { LOGGER.debug("Converting values in array {}", propertyValue); processMultipleValues("[", propertyValue, "]", output); } else if (propertyValue.startsWith("(") && propertyValue.endsWith(")")) { LOGGER.debug("Converting values in vector {}", propertyValue); processMultipleValues("(", propertyValue, ")", output); } LOGGER.debug("Configuration property after value conversion: {}", output.toString()); } /** * Converts a single property value to a new format if needed. If the conversion * fails or the value cannot or does not need to be converted, the original value * should be appended back. Unless part of the conversion logic, the returned * value should not be quoted. * * @param value value to convert. The value will never have any leading or trailing white * spaces or quotes (") and will never be {@code null}. * @param output {@link StringBuilder} to use to output the converted value. Will never be * {@code null}. */ protected abstract void convertSingleValue(String value, StringBuilder output); private void processMultipleValues(String openingBracket, String propertyValues, String closingBracket, StringBuilder output) { output.append(openingBracket); String propertyValuesWithoutBrackets = removeSurroundingCharacters(propertyValues, openingBracket, closingBracket); for (String value : propertyValuesWithoutBrackets.split("\"\\s*,\\s*\"")) { String trimmedValue = value.trim(); String unquotedValue = removeSurroundingCharacters(trimmedValue, "\"", "\""); output.append('"'); convertSingleValue(unquotedValue, output); output.append("\","); } output.deleteCharAt(output.length() - 1); output.append(closingBracket); } private String removeSurroundingCharacters(String value, String left, String right) { String cleanedUpValue = value.trim(); if (cleanedUpValue.startsWith(left)) { cleanedUpValue = cleanedUpValue.substring(1); } if (cleanedUpValue.endsWith(right)) { cleanedUpValue = cleanedUpValue.substring(0, cleanedUpValue.length() - 1); } return cleanedUpValue; } }