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