1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ch.qos.logback.core.model.processor;
16
17 import ch.qos.logback.core.Context;
18 import ch.qos.logback.core.joran.GenericXMLConfigurator;
19 import ch.qos.logback.core.joran.event.SaxEvent;
20 import ch.qos.logback.core.joran.event.SaxEventRecorder;
21 import ch.qos.logback.core.joran.spi.JoranException;
22 import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
23 import ch.qos.logback.core.model.IncludeModel;
24 import ch.qos.logback.core.model.Model;
25 import ch.qos.logback.core.spi.ContextAwarePropertyContainer;
26 import ch.qos.logback.core.spi.ErrorCodes;
27 import ch.qos.logback.core.util.Loader;
28 import ch.qos.logback.core.util.OptionHelper;
29
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.net.MalformedURLException;
34 import java.net.URI;
35 import java.net.URL;
36 import java.util.List;
37 import java.util.function.Supplier;
38
39 import static ch.qos.logback.core.joran.JoranConstants.CONFIGURATION_TAG;
40 import static ch.qos.logback.core.joran.JoranConstants.INCLUDED_TAG;
41
42
43
44
45 public class IncludeModelHandler extends ResourceHandlerBase {
46 boolean inError = false;
47
48 public IncludeModelHandler(Context context) {
49 super(context);
50 }
51
52 static public IncludeModelHandler makeInstance(Context context, ModelInterpretationContext mic) {
53 return new IncludeModelHandler(context);
54 }
55
56 @Override
57 protected Class<IncludeModel> getSupportedModelClass() {
58 return IncludeModel.class;
59 }
60
61 @Override
62 public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {
63 IncludeModel includeModel = (IncludeModel) model;
64
65 URL topURL = mic.getTopURL();
66 Boolean topScan = mic.getTopScanBoolean();
67 Model modelFromIncludedFile = buildModelFromIncludedFile(mic, topURL, topScan, includeModel);
68 if (modelFromIncludedFile == null) {
69 warnIfRequired("Failed to build include model from included file");
70 return;
71 }
72 processModelFromIncludedFile(includeModel, modelFromIncludedFile);
73 }
74
75
76
77
78
79
80
81
82
83 public Model buildModelFromIncludedFile(ContextAwarePropertyContainer capc, URL topURL, Boolean topScan, IncludeModel includeModel) throws ModelHandlerException {
84
85 this.optional = OptionHelper.toBoolean(includeModel.getOptional(), false);
86
87 if (!checkAttributes(includeModel)) {
88 inError = true;
89 return null;
90 }
91
92
93 URL inputURL = getInputURL(capc, includeModel);
94 if (inputURL == null) {
95 inError = true;
96 return null;
97 }
98
99 InputStream in = openURL(inputURL);
100 if (in == null) {
101 inError = true;
102 return null;
103 }
104
105 updateConfigurationWatchList(inputURL, topURL, topScan);
106
107
108 SaxEventRecorder recorder = null;
109
110 try {
111 recorder = populateSaxEventRecorder(in);
112
113 List<SaxEvent> saxEvents = recorder.getSaxEventList();
114 if (saxEvents.isEmpty()) {
115 addWarn("Empty sax event list");
116 return null;
117 }
118
119 Supplier<? extends GenericXMLConfigurator> jcSupplier = capc.getConfiguratorSupplier();
120 if (jcSupplier == null) {
121 addError("null configurator supplier. Abandoning inclusion of [" + attributeInUse + "]");
122 inError = true;
123 return null;
124 }
125
126 GenericXMLConfigurator genericXMLConfigurator = jcSupplier.get();
127 genericXMLConfigurator.getRuleStore().addPathPathMapping(INCLUDED_TAG, CONFIGURATION_TAG);
128
129 Model modelFromIncludedFile = genericXMLConfigurator.buildModelFromSaxEventList(recorder.getSaxEventList());
130 return modelFromIncludedFile;
131 } catch (JoranException e) {
132 inError = true;
133 addError("Error processing XML data in [" + attributeInUse + "]", e);
134 return null;
135 }
136 }
137
138 private void processModelFromIncludedFile(IncludeModel includeModel, Model modelFromIncludedFile) {
139 includeModel.getSubModels().addAll(modelFromIncludedFile.getSubModels());
140 }
141
142 public SaxEventRecorder populateSaxEventRecorder(final InputStream inputStream) throws JoranException {
143 SaxEventRecorder recorder = new SaxEventRecorder(context);
144 recorder.recordEvents(inputStream);
145 return recorder;
146 }
147
148 private void updateConfigurationWatchList(URL inputURL, URL topURL, Boolean topScan) throws ModelHandlerException {
149
150 if(topScan == Boolean.TRUE) {
151 if(topURL != null) {
152 ConfigurationWatchListUtil.addToWatchList(context, inputURL);
153 } else {
154 addWarn("No top URL for XML configuration file. Will not add [" + inputURL + "] to watch list.");
155 }
156 }
157
158 }
159
160 }