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