001/* 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2026, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v2.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.joran.action; 015 016import ch.qos.logback.core.CoreConstants; 017import ch.qos.logback.core.joran.JoranConstants; 018import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext; 019import ch.qos.logback.core.model.ConversionRuleModel; 020import ch.qos.logback.core.model.Model; 021import ch.qos.logback.core.util.OptionHelper; 022import org.xml.sax.Attributes; 023 024import java.util.HashMap; 025import java.util.Map; 026 027import static ch.qos.logback.core.joran.JoranConstants.CONVERSION_WORD_ATTRIBUTE; 028 029public class ConversionRuleAction extends BaseModelAction { 030 031 static public String CONVERTER_CLASS_ATTRIBUTE = "converterClass"; 032 033 034 @Override 035 protected boolean validPreconditions(SaxEventInterpretationContext seic, String name, Attributes attributes) { 036 PreconditionValidator pv = new PreconditionValidator(this, seic, name, attributes); 037 038 pv.validateGivenAttribute(CONVERSION_WORD_ATTRIBUTE); 039 040 if(!pv.isValid()) { 041 // no point in going further if the conversion word is not specified 042 return false; 043 } 044 045 boolean validConverterClassAttribute = pv.isValidAttribute(CONVERTER_CLASS_ATTRIBUTE); 046 boolean validClassAttribute = pv.isValidAttribute(CLASS_ATTRIBUTE); 047 048 boolean multipleClassAttributes = (validClassAttribute) && (validConverterClassAttribute); 049 050 // If both attributes are specified, silently use 'class' (for backward compatibility) 051 // Do not warn about deprecation when 'class' is present 052 if(validConverterClassAttribute && !multipleClassAttributes) { 053 pv.addWarn("["+CONVERTER_CLASS_ATTRIBUTE +"] attribute is deprecated and replaced by ["+CLASS_ATTRIBUTE+ 054 "]. "+pv.getLocationSuffix()); 055 } 056 057 boolean missingClass = !validClassAttribute && !validConverterClassAttribute; 058 if(missingClass) { 059 pv.addMissingAttributeError(CLASS_ATTRIBUTE); 060 return false; 061 } 062 063 if(multipleClassAttributes) { 064 String converterClass = attributes.getValue(CONVERTER_CLASS_ATTRIBUTE); 065 String classAttr = attributes.getValue(CLASS_ATTRIBUTE); 066 if (!converterClass.equals(classAttr)) { 067 pv.addWarn("Both ["+CONVERTER_CLASS_ATTRIBUTE+"] and ["+CLASS_ATTRIBUTE+"] attributes are specified but have different values."); 068 } else { 069 pv.addInfo("Both [" + CONVERTER_CLASS_ATTRIBUTE + "] attribute and [" + CLASS_ATTRIBUTE + "] attribute specified. "); 070 } 071 pv.addInfo( "["+CLASS_ATTRIBUTE+"] attribute will be used. "); 072 } 073 pv.validateGivenAttribute(CONVERSION_WORD_ATTRIBUTE); 074 return pv.isValid(); 075 } 076 077 078 079 @Override 080 protected Model buildCurrentModel(SaxEventInterpretationContext interpretationContext, String name, 081 Attributes attributes) { 082 ConversionRuleModel conversionRuleModel = new ConversionRuleModel(); 083 conversionRuleModel.setConversionWord(attributes.getValue(CONVERSION_WORD_ATTRIBUTE)); 084 085 String converterClassStr = attributes.getValue(CONVERTER_CLASS_ATTRIBUTE); 086 if(!OptionHelper.isNullOrEmpty(converterClassStr)) { 087 conversionRuleModel.setClassName(converterClassStr); 088 } 089 // if both converterClass and class are specified the latter overrides. 090 String classStr = attributes.getValue(CLASS_ATTRIBUTE); 091 if(!OptionHelper.isNullOrEmpty(classStr)) { 092 conversionRuleModel.setClassName(classStr); 093 } 094 return conversionRuleModel; 095 } 096 097// /** 098// * Instantiates a layout of the given class and sets its name. 099// * 100// */ 101// @SuppressWarnings("unchecked") 102// public void begin(SaxEventInterpretationContext ec, String localName, Attributes attributes) { 103// // Let us forget about previous errors (in this object) 104// inError = false; 105// 106// String errorMsg; 107// String conversionWord = attributes.getValue(CONVERSION_WORD_ATTRIBUTE); 108// String converterClass = attributes.getValue(JoranConstants.CONVERTER_CLASS_ATTRIBUTE); 109// 110// if (OptionHelper.isNullOrEmptyOrAllSpaces(conversionWord)) { 111// inError = true; 112// errorMsg = "No 'conversionWord' attribute in <conversionRule>"; 113// addError(errorMsg); 114// 115// return; 116// } 117// 118// if (OptionHelper.isNullOrEmptyOrAllSpaces(converterClass)) { 119// inError = true; 120// errorMsg = "No 'converterClass' attribute in <conversionRule>"; 121// ec.addError(errorMsg); 122// 123// return; 124// } 125// 126// try { 127// Map<String, String> ruleRegistry = (Map<String, String>) context 128// .getObject(CoreConstants.PATTERN_RULE_REGISTRY); 129// if (ruleRegistry == null) { 130// ruleRegistry = new HashMap<String, String>(); 131// context.putObject(CoreConstants.PATTERN_RULE_REGISTRY, ruleRegistry); 132// } 133// // put the new rule into the rule registry 134// addInfo("registering conversion word " + conversionWord + " with class [" + converterClass + "]"); 135// ruleRegistry.put(conversionWord, converterClass); 136// } catch (Exception oops) { 137// inError = true; 138// errorMsg = "Could not add conversion rule to PatternLayout."; 139// addError(errorMsg); 140// } 141// } 142// 143// 144// /** 145// * Once the children elements are also parsed, now is the time to activate the 146// * appender options. 147// */ 148// public void end(SaxEventInterpretationContext ec, String n) { 149// } 150// 151// public void finish(SaxEventInterpretationContext ec) { 152// } 153}