1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.joran.action;
15
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.MalformedURLException;
21 import java.net.URI;
22 import java.net.URL;
23 import java.util.List;
24
25 import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
26 import org.xml.sax.Attributes;
27
28 import ch.qos.logback.core.joran.event.SaxEvent;
29 import ch.qos.logback.core.joran.event.SaxEventRecorder;
30 import ch.qos.logback.core.joran.spi.ActionException;
31 import ch.qos.logback.core.joran.spi.InterpretationContext;
32 import ch.qos.logback.core.joran.spi.JoranException;
33 import ch.qos.logback.core.util.Loader;
34 import ch.qos.logback.core.util.OptionHelper;
35
36 public class IncludeAction extends Action {
37
38 private static final String INCLUDED_TAG = "included";
39 private static final String FILE_ATTR = "file";
40 private static final String URL_ATTR = "url";
41 private static final String RESOURCE_ATTR = "resource";
42
43 private String attributeInUse;
44
45 @Override
46 public void begin(InterpretationContext ec, String name, Attributes attributes)
47 throws ActionException {
48
49 SaxEventRecorder recorder = new SaxEventRecorder();
50
51 this.attributeInUse = null;
52
53 if (!checkAttributes(attributes)) {
54 return;
55 }
56
57 InputStream in = getInputStream(ec, attributes);
58
59 try {
60 if (in != null) {
61 parseAndRecord(in, recorder);
62
63 trimHeadAndTail(recorder);
64
65
66 ec.getJoranInterpreter().getEventPlayer().addEventsDynamically(recorder.saxEventList, 2);
67 }
68 } catch (JoranException e) {
69 addError("Error while parsing " + attributeInUse, e);
70 } finally {
71 close(in);
72 }
73
74 }
75
76 void close(InputStream in) {
77 if (in != null) {
78 try {
79 in.close();
80 } catch (IOException e) {
81 }
82 }
83 }
84
85 private boolean checkAttributes(Attributes attributes) {
86 String fileAttribute = attributes.getValue(FILE_ATTR);
87 String urlAttribute = attributes.getValue(URL_ATTR);
88 String resourceAttribute = attributes.getValue(RESOURCE_ATTR);
89
90 int count = 0;
91
92 if (!OptionHelper.isEmpty(fileAttribute)) {
93 count++;
94 }
95 if (!OptionHelper.isEmpty(urlAttribute)) {
96 count++;
97 }
98 if (!OptionHelper.isEmpty(resourceAttribute)) {
99 count++;
100 }
101
102 if (count == 0) {
103 addError("One of \"path\", \"resource\" or \"url\" attributes must be set.");
104 return false;
105 } else if (count > 1) {
106 addError("Only one of \"file\", \"url\" or \"resource\" attributes should be set.");
107 return false;
108 } else if (count == 1) {
109 return true;
110 }
111 throw new IllegalStateException("Count value [" + count
112 + "] is not expected");
113 }
114
115 private InputStream getInputStreamByFilePath(String pathToFile) {
116 try {
117 return new FileInputStream(pathToFile);
118 } catch (IOException ioe) {
119 String errMsg = "File [" + pathToFile + "] does not exist.";
120 addError(errMsg, ioe);
121 return null;
122 }
123 }
124
125 URL attributeToURL(String urlAttribute) {
126 try {
127 return new URL(urlAttribute);
128 } catch (MalformedURLException mue) {
129 String errMsg = "URL [" + urlAttribute + "] is not well formed.";
130 addError(errMsg, mue);
131 return null;
132 }
133 }
134
135 private InputStream getInputStreamByUrl(URL url) {
136 return openURL(url);
137 }
138
139 InputStream openURL(URL url) {
140 try {
141 return url.openStream();
142 } catch (IOException e) {
143 String errMsg = "Failed to open [" + url.toString() + "]";
144 addError(errMsg, e);
145 return null;
146 }
147 }
148
149 URL resourceAsURL(String resourceAttribute) {
150 URL url = Loader.getResourceBySelfClassLoader(resourceAttribute);
151 if (url == null) {
152 String errMsg = "Could not find resource corresponding to ["
153 + resourceAttribute + "]";
154 addError(errMsg);
155 return null;
156 } else
157 return url;
158 }
159
160 URL filePathAsURL(String path) {
161 URI uri = new File(path).toURI();
162 try {
163 return uri.toURL();
164 } catch (MalformedURLException e) {
165
166 e.printStackTrace();
167 return null;
168 }
169 }
170
171 private InputStream getInputStreamByResource(URL url) {
172 return openURL(url);
173 }
174
175 URL getInputURL(InterpretationContext ec, Attributes attributes) {
176 String fileAttribute = attributes.getValue(FILE_ATTR);
177 String urlAttribute = attributes.getValue(URL_ATTR);
178 String resourceAttribute = attributes.getValue(RESOURCE_ATTR);
179
180 if (!OptionHelper.isEmpty(fileAttribute)) {
181 this.attributeInUse = ec.subst(fileAttribute);
182 return filePathAsURL(attributeInUse);
183 }
184
185 if (!OptionHelper.isEmpty(urlAttribute)) {
186 this.attributeInUse = ec.subst(urlAttribute);
187 return attributeToURL(attributeInUse);
188 }
189
190 if (!OptionHelper.isEmpty(resourceAttribute)) {
191 this.attributeInUse = ec.subst(resourceAttribute);
192 return resourceAsURL(attributeInUse);
193 }
194
195 throw new IllegalStateException("A URL stream should have been returned");
196
197 }
198
199 InputStream getInputStream(InterpretationContext ec, Attributes attributes) {
200 URL inputURL = getInputURL(ec, attributes);
201 if (inputURL == null)
202 return null;
203
204 ConfigurationWatchListUtil.addToWatchList(context, inputURL);
205 return openURL(inputURL);
206 }
207
208 private void trimHeadAndTail(SaxEventRecorder recorder) {
209
210
211
212 List<SaxEvent> saxEventList = recorder.saxEventList;
213
214 if (saxEventList.size() == 0) {
215 return;
216 }
217
218 SaxEvent first = saxEventList.get(0);
219 if (first != null && first.qName.equalsIgnoreCase(INCLUDED_TAG)) {
220 saxEventList.remove(0);
221 }
222
223 SaxEvent last = saxEventList.get(recorder.saxEventList.size() - 1);
224 if (last != null && last.qName.equalsIgnoreCase(INCLUDED_TAG)) {
225 saxEventList.remove(recorder.saxEventList.size() - 1);
226 }
227 }
228
229 private void parseAndRecord(InputStream inputSource, SaxEventRecorder recorder)
230 throws JoranException {
231 recorder.setContext(context);
232 recorder.recordEvents(inputSource);
233 }
234
235 @Override
236 public void end(InterpretationContext ec, String name) throws ActionException {
237
238 }
239
240 }