1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.access.tomcat;
15
16 import java.io.File;
17 import java.io.IOException;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22
23 import javax.servlet.ServletContext;
24 import javax.servlet.ServletException;
25
26 import org.apache.catalina.Lifecycle;
27 import org.apache.catalina.LifecycleListener;
28 import org.apache.catalina.connector.Request;
29 import org.apache.catalina.connector.Response;
30 import org.apache.catalina.valves.ValveBase;
31
32 import ch.qos.logback.access.AccessConstants;
33 import ch.qos.logback.access.joran.JoranConfigurator;
34 import ch.qos.logback.access.spi.AccessEvent;
35 import ch.qos.logback.core.Appender;
36 import ch.qos.logback.core.BasicStatusManager;
37 import ch.qos.logback.core.Context;
38 import ch.qos.logback.core.CoreConstants;
39 import ch.qos.logback.core.filter.Filter;
40 import ch.qos.logback.core.joran.spi.JoranException;
41 import ch.qos.logback.core.spi.AppenderAttachable;
42 import ch.qos.logback.core.spi.AppenderAttachableImpl;
43 import ch.qos.logback.core.spi.FilterAttachable;
44 import ch.qos.logback.core.spi.FilterAttachableImpl;
45 import ch.qos.logback.core.spi.FilterReply;
46 import ch.qos.logback.core.status.InfoStatus;
47 import ch.qos.logback.core.status.StatusManager;
48 import ch.qos.logback.core.status.WarnStatus;
49 import ch.qos.logback.core.util.OptionHelper;
50 import ch.qos.logback.core.util.StatusPrinter;
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class LogbackValve extends ValveBase implements Lifecycle, Context,
65 AppenderAttachable<AccessEvent>, FilterAttachable<AccessEvent> {
66
67 public final static String DEFAULT_CONFIG_FILE = "conf" + File.separatorChar
68 + "logback-access.xml";
69
70 private long birthTime = System.currentTimeMillis();
71 Object configurationLock = new Object();
72
73
74 private String name;
75 StatusManager sm = new BasicStatusManager();
76
77
78
79 Map<String, String> propertyMap = new HashMap<String, String>();
80 Map<String, Object> objectMap = new HashMap<String, Object>();
81 private FilterAttachableImpl<AccessEvent> fai = new FilterAttachableImpl<AccessEvent>();
82
83 AppenderAttachableImpl<AccessEvent> aai = new AppenderAttachableImpl<AccessEvent>();
84 String filename;
85 boolean quiet;
86 boolean started;
87 boolean alreadySetLogbackStatusManager = false;
88
89 public LogbackValve() {
90 putObject(CoreConstants.EVALUATOR_MAP, new HashMap());
91 }
92
93 public void start() {
94 if (filename == null) {
95 String tomcatHomeProperty = OptionHelper
96 .getSystemProperty("catalina.home");
97
98 filename = tomcatHomeProperty + File.separatorChar + DEFAULT_CONFIG_FILE;
99 getStatusManager().add(
100 new InfoStatus("filename property not set. Assuming [" + filename
101 + "]", this));
102 }
103 File configFile = new File(filename);
104 if (configFile.exists()) {
105 try {
106 JoranConfigurator jc = new JoranConfigurator();
107 jc.setContext(this);
108 jc.doConfigure(filename);
109 } catch (JoranException e) {
110
111 e.printStackTrace();
112 }
113 } else {
114 getStatusManager().add(
115 new WarnStatus("[" + filename + "] does not exist", this));
116 }
117
118 if (!quiet) {
119 StatusPrinter.print(getStatusManager());
120 }
121
122 started = true;
123 }
124
125 public String getFilename() {
126 return filename;
127 }
128
129 public void setFilename(String filename) {
130 this.filename = filename;
131 }
132
133 public boolean isQuiet() {
134 return quiet;
135 }
136
137 public void setQuiet(boolean quiet) {
138 this.quiet = quiet;
139 }
140
141 public void invoke(Request request, Response response) throws IOException,
142 ServletException {
143
144 try {
145
146 if (!alreadySetLogbackStatusManager) {
147 alreadySetLogbackStatusManager = true;
148 org.apache.catalina.Context tomcatContext = request.getContext();
149 if (tomcatContext != null) {
150 ServletContext sc = tomcatContext.getServletContext();
151 if (sc != null) {
152 sc.setAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY,
153 getStatusManager());
154 }
155 }
156 }
157
158 getNext().invoke(request, response);
159
160 TomcatServerAdapter adapter = new TomcatServerAdapter(request, response);
161 AccessEvent accessEvent = new AccessEvent(request, response, adapter);
162
163 if (getFilterChainDecision(accessEvent) == FilterReply.DENY) {
164 return;
165 }
166
167
168 aai.appendLoopOnAppenders(accessEvent);
169 } finally {
170 request.removeAttribute(AccessConstants.LOGBACK_STATUS_MANAGER_KEY);
171 }
172 }
173
174 public void stop() {
175 started = false;
176 }
177
178 public void addAppender(Appender<AccessEvent> newAppender) {
179 aai.addAppender(newAppender);
180 }
181
182 public Iterator<Appender<AccessEvent>> iteratorForAppenders() {
183 return aai.iteratorForAppenders();
184 }
185
186 public Appender<AccessEvent> getAppender(String name) {
187 return aai.getAppender(name);
188 }
189
190 public boolean isAttached(Appender<AccessEvent> appender) {
191 return aai.isAttached(appender);
192 }
193
194 public void detachAndStopAllAppenders() {
195 aai.detachAndStopAllAppenders();
196
197 }
198
199 public boolean detachAppender(Appender<AccessEvent> appender) {
200 return aai.detachAppender(appender);
201 }
202
203 public boolean detachAppender(String name) {
204 return aai.detachAppender(name);
205 }
206
207 public String getInfo() {
208 return "Logback's implementation of ValveBase";
209 }
210
211
212 public StatusManager getStatusManager() {
213 return sm;
214 }
215
216 public Map<String, String> getPropertyMap() {
217 return propertyMap;
218 }
219
220 public void putProperty(String key, String val) {
221 this.propertyMap.put(key, val);
222 }
223
224 public String getProperty(String key) {
225 return (String) this.propertyMap.get(key);
226 }
227
228 public Map<String, String> getCopyOfPropertyMap() {
229 return new HashMap<String, String>(this.propertyMap);
230 }
231
232 public Object getObject(String key) {
233 return objectMap.get(key);
234 }
235
236 public void putObject(String key, Object value) {
237 objectMap.put(key, value);
238 }
239
240 public void addFilter(Filter<AccessEvent> newFilter) {
241 fai.addFilter(newFilter);
242 }
243
244 public void clearAllFilters() {
245 fai.clearAllFilters();
246 }
247
248 public List<Filter<AccessEvent>> getCopyOfAttachedFiltersList() {
249 return fai.getCopyOfAttachedFiltersList();
250 }
251
252 public FilterReply getFilterChainDecision(AccessEvent event) {
253 return fai.getFilterChainDecision(event);
254 }
255
256 public String getName() {
257 return name;
258 }
259
260 public void setName(String name) {
261 if (this.name != null) {
262 throw new IllegalStateException(
263 "LogbackValve has been already given a name");
264 }
265 this.name = name;
266 }
267
268 public long getBithTime() {
269 return birthTime;
270 }
271
272 public Object getConfigurationLock() {
273 return configurationLock;
274 }
275
276
277
278 public void addLifecycleListener(LifecycleListener arg0) {
279
280 }
281
282 public LifecycleListener[] findLifecycleListeners() {
283 return new LifecycleListener[0];
284 }
285
286 public void removeLifecycleListener(LifecycleListener arg0) {
287
288 }
289
290 }