blob: 00d6934f74146ca58f799abdc03815b67f690043 [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.qpid.server.model;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConfiguredSettableInjectedAttribute<C extends ConfiguredObject, T>
extends ConfiguredObjectInjectedAttributeOrStatistic<C,T> implements ConfiguredSettableAttribute<C,T>, ConfiguredObjectInjectedAttribute<C,T>
{
private static final Logger LOGGER = LoggerFactory.getLogger(ConfiguredSettableInjectedAttribute.class);
private final AttributeValueConverter<T> _converter;
private final Method _validValuesMethod;
private final Pattern _secureValuePattern;
private final String _defaultValue;
private final boolean _secure;
private final boolean _persisted;
private final boolean _immutable;
private final boolean _oversized;
private final String _oversizedAltText;
private final String _description;
private final String[] _validValues;
private final String _validValuePattern;
private Initialization _initialization;
public ConfiguredSettableInjectedAttribute(final String name,
final Class<T> type,
final Type genericType,
final String defaultValue,
final boolean secure,
final boolean persisted,
final boolean immutable,
final String secureValueFilter,
final boolean oversized,
final String oversizedAltText,
final String description,
final String[] validValues,
final String validValuePattern,
final TypeValidator typeValidator,
final Initialization initialization)
{
super(name, type, genericType, typeValidator);
_converter = AttributeValueConverter.getConverter(type, genericType);
_defaultValue = defaultValue;
_secure = secure;
_persisted = persisted;
_immutable = immutable;
_oversized = oversized;
_oversizedAltText = oversizedAltText;
_description = description;
_validValues = validValues;
_validValuePattern = validValuePattern;
_initialization = initialization;
Method validValuesMethod = null;
if(_validValues != null && _validValues.length == 1)
{
String validValue = _validValues[0];
validValuesMethod = getValidValuesMethod(validValue);
}
_validValuesMethod = validValuesMethod;
if (secureValueFilter == null || "".equals(secureValueFilter))
{
_secureValuePattern = null;
}
else
{
_secureValuePattern = Pattern.compile(secureValueFilter);
}
}
@Override
public final AttributeValueConverter<T> getConverter()
{
return _converter;
}
private Method getValidValuesMethod(final String validValue)
{
if(validValue.matches("([\\w][\\w\\d_]+\\.)+[\\w][\\w\\d_\\$]*#[\\w\\d_]+\\s*\\(\\s*\\)"))
{
try
{
String className = validValue.split("#")[0].trim();
String methodName = validValue.split("#")[1].split("\\(")[0].trim();
Class<?> validValueCalculatingClass = Class.forName(className);
Method method = validValueCalculatingClass.getMethod(methodName);
if (Modifier.isStatic(method.getModifiers()) && Modifier.isPublic(method.getModifiers()))
{
if (Collection.class.isAssignableFrom(method.getReturnType()))
{
if (method.getGenericReturnType() instanceof ParameterizedType)
{
Type parameterizedType =
((ParameterizedType) method.getGenericReturnType()).getActualTypeArguments()[0];
if (parameterizedType == String.class)
{
return method;
}
}
}
}
}
catch (ClassNotFoundException | NoSuchMethodException e)
{
LOGGER.warn("The validValues of the " + getName()
+ " has value '" + validValue + "' which looks like it should be a method,"
+ " but no such method could be used.", e );
}
}
return null;
}
public boolean isAutomated()
{
return false;
}
public boolean isDerived()
{
return false;
}
public String defaultValue()
{
return _defaultValue;
}
@Override
public Initialization getInitialization()
{
return _initialization;
}
public boolean isSecure()
{
return _secure;
}
public boolean isMandatory()
{
return false;
}
public boolean isImmutable()
{
return _immutable;
}
public boolean isPersisted()
{
return _persisted;
}
@Override
public boolean isOversized()
{
return _oversized;
}
@Override
public boolean updateAttributeDespiteUnchangedValue()
{
return false;
}
@Override
public String getOversizedAltText()
{
return _oversizedAltText;
}
public String getDescription()
{
return _description;
}
public Pattern getSecureValueFilter()
{
return _secureValuePattern;
}
@Override
public boolean isSecureValue(final Object value)
{
Pattern filter;
return isSecure() &&
((filter = getSecureValueFilter()) == null || filter.matcher(String.valueOf(value)).matches());
}
public Collection<String> validValues()
{
if(_validValuesMethod != null)
{
try
{
return (Collection<String>) _validValuesMethod.invoke(null);
}
catch (InvocationTargetException | IllegalAccessException e)
{
LOGGER.warn("Could not execute the validValues generation method " + _validValuesMethod.getName(), e);
return Collections.emptySet();
}
}
else if ((_validValues == null || _validValues.length == 0) && getType().isEnum())
{
final Enum<?>[] constants = (Enum<?>[]) getType().getEnumConstants();
List<String> validValues = new ArrayList<>(constants.length);
for (Enum<?> constant : constants)
{
validValues.add(constant.name());
}
return validValues;
}
else
{
return _validValues == null ? Collections.<String>emptySet() : Arrays.asList(_validValues);
}
}
/** Returns true iff this attribute has valid values defined */
public boolean hasValidValues()
{
return validValues() != null && validValues().size() > 0;
}
@Override
public final T getValue(final C configuredObject)
{
Object value = configuredObject.getActualAttributes().get(getName());
if(value == null)
{
value = defaultValue();
}
return convert(value, configuredObject);
}
public final T convert(final Object value, final C object)
{
final AttributeValueConverter<T> converter = getConverter();
try
{
return converter.convert(value, object);
}
catch (IllegalArgumentException iae)
{
Type returnType = getGenericType();
String simpleName = returnType instanceof Class ? ((Class) returnType).getSimpleName() : returnType.toString();
throw new IllegalArgumentException("Cannot convert '" + value
+ "' into a " + simpleName
+ " for attribute " + getName()
+ " (" + iae.getMessage() + ")", iae);
}
}
@Override
public String validValuePattern()
{
return _validValuePattern;
}
}