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.model.processor.conditional;
015
016import ch.qos.logback.core.util.EnvUtil;
017import ch.qos.logback.core.util.OptionHelper;
018import ch.qos.logback.core.Context;
019import ch.qos.logback.core.CoreConstants;
020import ch.qos.logback.core.joran.conditional.Condition;
021import ch.qos.logback.core.model.Model;
022import ch.qos.logback.core.model.conditional.IfModel;
023import ch.qos.logback.core.model.conditional.IfModel.BranchState;
024import ch.qos.logback.core.model.processor.ModelHandlerBase;
025import ch.qos.logback.core.model.processor.ModelHandlerException;
026import ch.qos.logback.core.model.processor.ModelInterpretationContext;
027import ch.qos.logback.core.spi.ScanException;
028
029public class IfModelHandler extends ModelHandlerBase {
030
031
032    public static final String MISSING_JANINO_MSG = "Could not find Janino library on the class path. Skipping conditional processing.";
033    public static final String MISSING_JANINO_SEE = "See also " + CoreConstants.CODES_URL + "#ifJanino";
034
035    public static final String BLACKLISTED_REF_DISALLOWED_MSG = "The 'condition' attribute may not contain blacklisted references.";
036    public static final String BLACKLISTED_REF_DISALLOWED_SEE = "See also " + CoreConstants.CODES_URL + "#conditionBlacklisted";
037
038    public static final String UNICODE_DISALLOWED_MSG = "The 'condition' attribute may not contain unicode escape characters.";
039    public static final String UNICODE_DISALLOWED_SEE = "See also " + CoreConstants.CODES_URL + "#conditionUnicode";
040
041
042    public static final String CONDITION_ATTR_DEPRECATED_MSG = "The 'condition' attribute in <if> element is deprecated and slated for removal. Use <condition> element instead.";
043    public static final String CONDITION_ATTR_DEPRECATED_SEE = "See also " + CoreConstants.CODES_URL + "#conditionAttributeDeprecation";
044
045    enum Branch {IF_BRANCH, ELSE_BRANCH; }
046    
047    IfModel ifModel = null;
048    
049    public IfModelHandler(Context context) {
050        super(context);
051    }
052
053    static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext ic) {
054        return new IfModelHandler(context);
055    }
056
057    @Override
058    protected Class<IfModel> getSupportedModelClass() {
059        return IfModel.class;
060    }
061    
062    @Override
063    public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {
064        
065        ifModel = (IfModel) model;
066        mic.pushModel(ifModel);
067        Object micTopObject = mic.peekObject();
068        String conditionStr = ifModel.getCondition();
069        emitDeprecationWarningIfNecessary(conditionStr);
070
071
072        if(micTopObject instanceof BranchState) {
073            BranchState branchState = (BranchState) micTopObject;
074            ifModel.setBranchState(branchState);
075            // consume the BranchState at top of the object stack
076            mic.popObject();
077        }
078    }
079
080
081    private void emitDeprecationWarningIfNecessary(String conditionStr) {
082        if(!OptionHelper.isNullOrEmptyOrAllSpaces(conditionStr)) {
083            addWarn(CONDITION_ATTR_DEPRECATED_MSG);
084            addWarn(CONDITION_ATTR_DEPRECATED_SEE);
085        }
086    }
087
088
089
090    @Override
091    public void postHandle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {
092
093        if(mic.isModelStackEmpty()) {
094            addError("Unexpected unexpected empty model stack.");
095            return;
096        }
097
098        Object o = mic.peekModel();
099        if (o != ifModel) {
100            addWarn("The object [" + o + "] on the top the of the stack is not the expected [" + ifModel);
101        } else {
102            mic.popModel();
103        }
104    }
105
106}