001/*
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2024, 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 v1.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 */
014
015package ch.qos.logback.core.joran.action;
016
017import ch.qos.logback.core.joran.spi.ActionException;
018import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
019import ch.qos.logback.core.model.Model;
020import ch.qos.logback.core.model.ResourceModel;
021import org.xml.sax.Attributes;
022
023/**
024 * An action which builds subclass instances of {@link ResourceModel}.
025 *
026 * @since 1.5.8
027 */
028abstract public class ResourceAction extends Action {
029
030    private static final String FILE_ATTR = "file";
031    private static final String URL_ATTR = "url";
032    private static final String RESOURCE_ATTR = "resource";
033    private static final String OPTIONAL_ATTR = "optional";
034
035    Model parentModel;
036    ResourceModel resourceModel;
037    boolean inError = false;
038
039    abstract protected ResourceModel makeNewResourceModel();
040
041    @Override
042    public void begin(SaxEventInterpretationContext seic, String tagName, Attributes attributes) throws ActionException {
043        String optionalStr = attributes.getValue(OPTIONAL_ATTR);
044
045        this.resourceModel = makeNewResourceModel();
046        this.resourceModel.setOptional(optionalStr);
047        fillInIncludeModelAttributes(resourceModel, tagName, attributes);
048        if (!seic.isModelStackEmpty()) {
049            parentModel = seic.peekModel();
050        }
051        final int lineNumber = getLineNumber(seic);
052        this.resourceModel.setLineNumber(lineNumber);
053        seic.pushModel(this.resourceModel);
054    }
055
056    private void fillInIncludeModelAttributes(ResourceModel resourceModel, String tagName, Attributes attributes) {
057        this.resourceModel.setTag(tagName);
058        String fileAttribute = attributes.getValue(FILE_ATTR);
059        String urlAttribute = attributes.getValue(URL_ATTR);
060        String resourceAttribute = attributes.getValue(RESOURCE_ATTR);
061
062        this.resourceModel.setFile(fileAttribute);
063        this.resourceModel.setUrl(urlAttribute);
064        this.resourceModel.setResource(resourceAttribute);
065    }
066
067    @Override
068    public void end(SaxEventInterpretationContext seic, String name) throws ActionException {
069        if(inError)
070            return;
071
072        Model m = seic.peekModel();
073
074        if (m != resourceModel) {
075            addWarn("The object at the of the stack is not the model [" + resourceModel.idString()
076                            + "] pushed earlier.");
077            addWarn("This is wholly unexpected.");
078        }
079
080        // do not pop nor add to parent if there is no parent
081        if (parentModel != null) {
082            parentModel.addSubModel(resourceModel);
083            seic.popModel();
084        }
085    }
086}