/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, 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.as.logging;
import static org.jboss.as.logging.Logging.createOperationFailure;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.DefaultAttributeMarshaller;
import org.jboss.as.controller.ObjectTypeAttributeDefinition;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationStepHandler;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.PathElement;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.transform.description.ResourceTransformationDescriptionBuilder;
import org.jboss.as.logging.LoggingOperations.LoggingWriteAttributeHandler;
import org.jboss.as.logging.logging.LoggingLogger;
import org.jboss.as.logging.validators.RegexValidator;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.jboss.logmanager.config.FormatterConfiguration;
import org.jboss.logmanager.config.LogContextConfiguration;
import org.jboss.logmanager.formatters.PatternFormatter;
/**
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
public class PatternFormatterResourceDefinition extends TransformerResourceDefinition {
static final String COLOR_MAP_VALIDATION_PATTERN = "^((severe|fatal|error|warn|warning|info|debug|trace|config|fine|finer|finest|):(clear|black|green|red|yellow|blue|magenta|cyan|white|brightblack|brightred|brightgreen|brightblue|brightyellow|brightmagenta|brightcyan|brightwhite|)(,(?!$)|$))*$";
// Pattern formatter options
public static final PropertyAttributeDefinition COLOR_MAP = PropertyAttributeDefinition.Builder.of("color-map", ModelType.STRING)
.setAllowExpression(true)
.setAllowNull(true)
.setPropertyName("colors")
.setValidator(new RegexValidator(ModelType.STRING, true, true, COLOR_MAP_VALIDATION_PATTERN))
.build();
public static final PropertyAttributeDefinition PATTERN = PropertyAttributeDefinition.Builder.of("pattern", ModelType.STRING, true)
.setAllowExpression(true)
.setDefaultValue(new ModelNode("%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"))
.build();
public static final ObjectTypeAttributeDefinition PATTERN_FORMATTER = ObjectTypeAttributeDefinition.Builder.of("pattern-formatter", PATTERN, COLOR_MAP)
.setAllowExpression(false)
.setAllowNull(true)
.setAttributeMarshaller(new DefaultAttributeMarshaller() {
@Override
public void marshallAsElement(final AttributeDefinition attribute, final ModelNode resourceModel, final boolean marshallDefault, final XMLStreamWriter writer) throws XMLStreamException {
if (isMarshallable(attribute, resourceModel, marshallDefault)) {
writer.writeStartElement(attribute.getXmlName());
final String pattern = resourceModel.get(PATTERN.getName()).asString();
writer.writeAttribute(PATTERN.getXmlName(), pattern);
if (resourceModel.hasDefined(COLOR_MAP.getName())) {
final String colorMap = resourceModel.get(COLOR_MAP.getName()).asString();
writer.writeAttribute(COLOR_MAP.getXmlName(), colorMap);
}
writer.writeEndElement();
}
}
@Override
public boolean isMarshallable(final AttributeDefinition attribute, final ModelNode resourceModel, final boolean marshallDefault) {
return resourceModel.hasDefined(PATTERN.getName());
}
})
.build();
static final PathElement PATTERN_FORMATTER_PATH = PathElement.pathElement(PATTERN_FORMATTER.getName());
static final PropertyAttributeDefinition[] ATTRIBUTES = {
COLOR_MAP,
PATTERN,
};
/**
* A step handler to add a pattern formatter
*/
static final OperationStepHandler ADD = new LoggingOperations.LoggingAddOperationStepHandler() {
@Override
public void updateModel(final ModelNode operation, final ModelNode model) throws OperationFailedException {
for (AttributeDefinition attribute : ATTRIBUTES) {
attribute.validateAndSet(operation, model);
}
}
@Override
public void performRuntime(final OperationContext context, final ModelNode operation, final LogContextConfiguration logContextConfiguration, final String name, final ModelNode model) throws OperationFailedException {
FormatterConfiguration configuration = logContextConfiguration.getFormatterConfiguration(name);
if (configuration == null) {
LoggingLogger.ROOT_LOGGER.tracef("Adding formatter '%s' at '%s'", name, LoggingOperations.getAddress(operation));
configuration = logContextConfiguration.addFormatterConfiguration(null, PatternFormatter.class.getName(), name);
}
for (PropertyAttributeDefinition attribute : ATTRIBUTES) {
attribute.setPropertyValue(context, model, configuration);
}
}
};
static final OperationStepHandler WRITE = new LoggingWriteAttributeHandler(ATTRIBUTES) {
@Override
protected boolean applyUpdate(final OperationContext context, final String attributeName, final String addressName, final ModelNode value, final LogContextConfiguration logContextConfiguration) throws OperationFailedException {
final FormatterConfiguration configuration = logContextConfiguration.getFormatterConfiguration(addressName);
for (PropertyAttributeDefinition attribute : ATTRIBUTES) {
if (attribute.getName().equals(attributeName)) {
configuration.setPropertyValueString(attribute.getPropertyName(), value.asString());
break;
}
}
return false;
}
};
/**
* A step handler to remove
*/
static final OperationStepHandler REMOVE = new LoggingOperations.LoggingRemoveOperationStepHandler() {
@Override
protected void performRemove(final OperationContext context, final ModelNode operation, final LogContextConfiguration logContextConfiguration, final String name, final ModelNode model) throws OperationFailedException {
context.removeResource(PathAddress.EMPTY_ADDRESS);
}
@Override
public void performRuntime(final OperationContext context, final ModelNode operation, final LogContextConfiguration logContextConfiguration, final String name, final ModelNode model) throws OperationFailedException {
final FormatterConfiguration configuration = logContextConfiguration.getFormatterConfiguration(name);
if (configuration == null) {
throw createOperationFailure(LoggingLogger.ROOT_LOGGER.formatterNotFound(name));
}
logContextConfiguration.removeFormatterConfiguration(name);
}
};
static final PatternFormatterResourceDefinition INSTANCE = new PatternFormatterResourceDefinition();
public PatternFormatterResourceDefinition() {
super(PATTERN_FORMATTER_PATH,
LoggingExtension.getResourceDescriptionResolver(PATTERN_FORMATTER.getName()),
ADD, REMOVE);
}
@Override
public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
for (AttributeDefinition def : ATTRIBUTES) {
resourceRegistration.registerReadWriteAttribute(def, null, WRITE);
}
}
@Override
public void registerTransformers(final KnownModelVersion modelVersion, final ResourceTransformationDescriptionBuilder resourceBuilder, final ResourceTransformationDescriptionBuilder loggingProfileBuilder) {
switch (modelVersion) {
case VERSION_1_3_0:
resourceBuilder.rejectChildResource(PATTERN_FORMATTER_PATH);
loggingProfileBuilder.rejectChildResource(PATTERN_FORMATTER_PATH);
break;
}
}
}