1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2024, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  
15  package ch.qos.logback.core.joran.action;
16  
17  import ch.qos.logback.core.joran.spi.ActionException;
18  import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
19  import ch.qos.logback.core.model.Model;
20  import ch.qos.logback.core.model.ResourceModel;
21  import org.xml.sax.Attributes;
22  
23  /**
24   * An action which builds subclass instances of {@link ResourceModel}.
25   *
26   * @since 1.5.8
27   */
28  abstract public class ResourceAction extends Action {
29  
30      private static final String FILE_ATTR = "file";
31      private static final String URL_ATTR = "url";
32      private static final String RESOURCE_ATTR = "resource";
33      private static final String OPTIONAL_ATTR = "optional";
34  
35      Model parentModel;
36      ResourceModel resourceModel;
37      boolean inError = false;
38  
39      abstract protected ResourceModel makeNewResourceModel();
40  
41      @Override
42      public void begin(SaxEventInterpretationContext seic, String tagName, Attributes attributes) throws ActionException {
43          String optionalStr = attributes.getValue(OPTIONAL_ATTR);
44  
45          this.resourceModel = makeNewResourceModel();
46          this.resourceModel.setOptional(optionalStr);
47          fillInIncludeModelAttributes(resourceModel, tagName, attributes);
48          if (!seic.isModelStackEmpty()) {
49              parentModel = seic.peekModel();
50          }
51          final int lineNumber = getLineNumber(seic);
52          this.resourceModel.setLineNumber(lineNumber);
53          seic.pushModel(this.resourceModel);
54      }
55  
56      private void fillInIncludeModelAttributes(ResourceModel resourceModel, String tagName, Attributes attributes) {
57          this.resourceModel.setTag(tagName);
58          String fileAttribute = attributes.getValue(FILE_ATTR);
59          String urlAttribute = attributes.getValue(URL_ATTR);
60          String resourceAttribute = attributes.getValue(RESOURCE_ATTR);
61  
62          this.resourceModel.setFile(fileAttribute);
63          this.resourceModel.setUrl(urlAttribute);
64          this.resourceModel.setResource(resourceAttribute);
65      }
66  
67      @Override
68      public void end(SaxEventInterpretationContext seic, String name) throws ActionException {
69          if(inError)
70              return;
71  
72          Model m = seic.peekModel();
73  
74          if (m != resourceModel) {
75              addWarn("The object at the of the stack is not the model [" + resourceModel.idString()
76                              + "] pushed earlier.");
77              addWarn("This is wholly unexpected.");
78          }
79  
80          // do not pop nor add to parent if there is no parent
81          if (parentModel != null) {
82              parentModel.addSubModel(resourceModel);
83              seic.popModel();
84          }
85      }
86  }