org.jboss.logmanager.config.AbstractPropertyConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jboss-logmanager Show documentation
Show all versions of jboss-logmanager Show documentation
An implementation of java.util.logging.LogManager
/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.logmanager.config;
import static java.util.Arrays.asList;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoader;
/**
* @author David M. Lloyd
*/
abstract class AbstractPropertyConfiguration> extends AbstractBasicConfiguration implements ObjectConfigurable, PropertyConfigurable {
private final Class actualClass;
private final String moduleName;
private final String className;
private final String[] constructorProperties;
private final Map> properties = new LinkedHashMap>(0);
private final Map postConfigurationMethods = new LinkedHashMap();
protected AbstractPropertyConfiguration(final Class baseClass, final LogContextConfigurationImpl configuration, final Map refs, final Map configs, final String name, final String moduleName, final String className, final String[] constructorProperties) {
super(name, configuration, refs, configs);
this.moduleName = moduleName;
this.className = className;
if (className == null) {
throw new IllegalArgumentException("className is null");
}
this.constructorProperties = constructorProperties;
final ClassLoader classLoader;
if (moduleName != null) try {
classLoader = ModuleFinder.getClassLoader(moduleName);
} catch (Throwable e) {
throw new IllegalArgumentException(String.format("Failed to load module \"%s\" for %s \"%s\"", moduleName, getDescription(), name), e);
}
else {
classLoader = getClass().getClassLoader();
}
final Class actualClass;
try {
actualClass = Class.forName(className, true, classLoader).asSubclass(baseClass);
} catch (Exception e) {
throw new IllegalArgumentException(String.format("Failed to load class \"%s\" for %s \"%s\"", className, getDescription(), name), e);
}
this.actualClass = actualClass;
}
ConfigAction getConstructAction() {
return new ConstructAction();
}
abstract String getDescription();
class ConstructAction implements ConfigAction {
public T validate() throws IllegalArgumentException {
final int length = constructorProperties.length;
final Class[] paramTypes = new Class[length];
for (int i = 0; i < length; i++) {
final String property = constructorProperties[i];
final Class type = getConstructorPropertyType(actualClass, property);
if (type == null) {
throw new IllegalArgumentException(String.format("No property named \"%s\" for %s \"%s\"", property, getDescription(), getName()));
}
paramTypes[i] = type;
}
final Constructor constructor;
try {
constructor = actualClass.getConstructor(paramTypes);
} catch (Exception e) {
throw new IllegalArgumentException(String.format("Failed to locate constructor in class \"%s\" for %s \"%s\"", className, getDescription(), getName()), e);
}
final Object[] params = new Object[length];
for (int i = 0; i < length; i++) {
final String property = constructorProperties[i];
if (! properties.containsKey(property)) {
throw new IllegalArgumentException(String.format("No property named \"%s\" is configured on %s \"%s\"", property, getDescription(), getName()));
}
final ValueExpression valueExpression = properties.get(property);
final Object value = getConfiguration().getValue(actualClass, property, paramTypes[i], valueExpression, true).getObject();
params[i] = value;
}
try {
return constructor.newInstance(params);
} catch (Exception e) {
throw new IllegalArgumentException(String.format("Failed to instantiate class \"%s\" for %s \"%s\"", className, getDescription(), getName()), e);
}
}
public void applyPreCreate(final T param) {
getRefs().put(getName(), param);
}
public void applyPostCreate(T param) {
}
public void rollback() {
getConfigs().remove(getName());
}
}
public String getModuleName() {
return moduleName;
}
public String getClassName() {
return className;
}
static boolean contains(Object[] array, Object val) {
for (Object o : array) {
if (o.equals(val)) return true;
}
return false;
}
public void setPropertyValueString(final String propertyName, final String value) throws IllegalArgumentException {
if (isRemoved()) {
throw new IllegalArgumentException(String.format("Cannot set property \"%s\" on %s \"%s\" (removed)", propertyName, getDescription(), getName()));
}
if (propertyName == null) {
throw new IllegalArgumentException("propertyName is null");
}
setPropertyValueExpression(propertyName, ValueExpression.STRING_RESOLVER.resolve(value));
}
public String getPropertyValueString(final String propertyName) {
return getPropertyValueExpression(propertyName).getResolvedValue();
}
@Override
public ValueExpression getPropertyValueExpression(final String propertyName) {
return properties.containsKey(propertyName) ? properties.get(propertyName) : ValueExpression.NULL_STRING_EXPRESSION;
}
@Override
public void setPropertyValueExpression(final String propertyName, final String expression) {
if (isRemoved()) {
throw new IllegalArgumentException(String.format("Cannot set property \"%s\" on %s \"%s\" (removed)", propertyName, getDescription(), getName()));
}
if (propertyName == null) {
throw new IllegalArgumentException("propertyName is null");
}
setPropertyValueExpression(propertyName, ValueExpression.STRING_RESOLVER.resolve(expression));
}
@Override
public void setPropertyValueExpression(final String propertyName, final String expression, final String value) {
if (isRemoved()) {
throw new IllegalArgumentException(String.format("Cannot set property \"%s\" on %s \"%s\" (removed)", propertyName, getDescription(), getName()));
}
if (propertyName == null) {
throw new IllegalArgumentException("propertyName is null");
}
setPropertyValueExpression(propertyName, new ValueExpressionImpl(expression, value));
}
private void setPropertyValueExpression(final String propertyName, final ValueExpression expression) {
final boolean replacement = properties.containsKey(propertyName);
final boolean constructorProp = contains(constructorProperties, propertyName);
final Method setter = getPropertySetter(actualClass, propertyName);
if (setter == null && ! constructorProp) {
throw new IllegalArgumentException(String.format("No property \"%s\" setter found for %s \"%s\"", propertyName, getDescription(), getName()));
}
final ValueExpression oldValue = properties.put(propertyName, expression);
getConfiguration().addAction(new ConfigAction() {
public ObjectProducer validate() throws IllegalArgumentException {
if (setter == null) {
return ObjectProducer.NULL_PRODUCER;
}
final Class propertyType = getPropertyType(actualClass, propertyName);
if (propertyType == null) {
throw new IllegalArgumentException(String.format("No property \"%s\" type could be determined for %s \"%s\"", propertyName, getDescription(), getName()));
}
return getConfiguration().getValue(actualClass, propertyName, propertyType, expression, false);
}
public void applyPreCreate(final ObjectProducer param) {
addPostConfigurationActions();
}
public void applyPostCreate(final ObjectProducer param) {
if (setter != null) {
final T instance = getRefs().get(getName());
try {
setter.invoke(instance, param.getObject());
} catch (Throwable e) {
// todo log it properly...
e.printStackTrace();
}
}
}
public void rollback() {
if (replacement) {
properties.put(propertyName, oldValue);
} else {
properties.remove(propertyName);
}
}
});
}
public boolean hasProperty(final String propertyName) {
return properties.containsKey(propertyName);
}
public boolean removeProperty(final String propertyName) {
if (isRemoved()) {
throw new IllegalArgumentException(String.format("Cannot remove property \"%s\" on %s \"%s\" (removed)", propertyName, getDescription(), getName()));
}
try {
return properties.containsKey(propertyName);
} finally {
properties.remove(propertyName);
}
}
public List getPropertyNames() {
return new ArrayList(properties.keySet());
}
@Override
public boolean hasConstructorProperty(final String propertyName) {
return contains(constructorProperties, propertyName);
}
Class getActualClass() {
return actualClass;
}
@Override
public List getConstructorProperties() {
return Arrays.asList(constructorProperties);
}
@Override
public boolean addPostConfigurationMethod(final String methodName) {
final LogContextConfigurationImpl configuration = getConfiguration();
if (postConfigurationMethods.containsKey(methodName)) {
return false;
}
configuration.addAction(new ConfigAction() {
public Method validate() throws IllegalArgumentException {
try {
return actualClass.getMethod(methodName);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(String.format("Method '%s' not found on '%s'", methodName, actualClass.getName()));
}
}
public void applyPreCreate(final Method param) {
}
public void applyPostCreate(final Method param) {
postConfigurationMethods.put(methodName, param);
// TODO (jrp) this isn't the best for performance
addPostConfigurationActions(true);
}
public void rollback() {
postConfigurationMethods.remove(methodName);
addPostConfigurationActions(true);
}
});
return true;
}
@Override
public List getPostConfigurationMethods() {
return new ArrayList(postConfigurationMethods.keySet());
}
@Override
public void setPostConfigurationMethods(final String... methodNames) {
setPostConfigurationMethods(asList(methodNames));
}
@Override
public void setPostConfigurationMethods(final List methodNames) {
final Map oldMethods = new LinkedHashMap(postConfigurationMethods);
postConfigurationMethods.clear();
final LinkedHashSet names = new LinkedHashSet(methodNames);
getConfiguration().addAction(new ConfigAction