]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.core/src/main/java/org/argeo/security/log4j/SecureLogger.java
70945f07c31f29181be3413dc820c46f67d81958
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.core / src / main / java / org / argeo / security / log4j / SecureLogger.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.argeo.security.log4j;
18
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Properties;
22
23 import org.apache.log4j.AppenderSkeleton;
24 import org.apache.log4j.Level;
25 import org.apache.log4j.Logger;
26 import org.apache.log4j.PropertyConfigurator;
27 import org.apache.log4j.spi.LoggingEvent;
28 import org.argeo.ArgeoException;
29 import org.argeo.ArgeoLogListener;
30 import org.springframework.security.Authentication;
31 import org.springframework.security.context.SecurityContext;
32 import org.springframework.security.context.SecurityContextHolder;
33 import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken;
34
35 /** Not meant to be used directly in standard log4j config */
36 public class SecureLogger {
37 private List<ArgeoLogListener> listeners;
38
39 private Boolean disabled = false;
40
41 private String level = null;
42
43 private Level log4jLevel = null;
44 // private Layout layout;
45
46 private Properties configuration;
47
48 private AppenderImpl appender;
49
50 /** Marker to prevent stack overflow */
51 private ThreadLocal<Boolean> dispatching = new ThreadLocal<Boolean>() {
52
53 @Override
54 protected Boolean initialValue() {
55 return false;
56 }
57 };
58
59 public void init() {
60 try {
61 // if (layout != null)
62 // setLayout(layout);
63 // else
64 // setLayout(new PatternLayout(pattern));
65 appender = new AppenderImpl();
66
67 if (configuration != null)
68 PropertyConfigurator.configure(configuration);
69
70 Logger.getRootLogger().addAppender(appender);
71 } catch (Exception e) {
72 throw new ArgeoException("Cannot initialize log4j");
73 }
74 }
75
76 public void destroy() throws Exception {
77 Logger.getRootLogger().removeAppender(appender);
78 }
79
80 // public void setLayout(Layout layout) {
81 // this.layout = layout;
82 // }
83
84 /** For development purpose, since using regular logging is not easy here */
85 static void stdOut(Object obj) {
86 System.out.println(obj);
87 }
88
89 // public void setPattern(String pattern) {
90 // this.pattern = pattern;
91 // }
92
93 public void setDisabled(Boolean disabled) {
94 this.disabled = disabled;
95 }
96
97 public void setLevel(String level) {
98 this.level = level;
99 }
100
101 public void setListeners(List<ArgeoLogListener> listeners) {
102 this.listeners = listeners;
103 }
104
105 public void setConfiguration(Properties configuration) {
106 this.configuration = configuration;
107 }
108
109 private class AppenderImpl extends AppenderSkeleton {
110 public boolean requiresLayout() {
111 return false;
112 }
113
114 public void close() {
115 }
116
117 @Override
118 protected void append(LoggingEvent event) {
119 if (disabled)
120 return;
121
122 if (dispatching.get())
123 return;
124
125 if (level != null && !level.trim().equals("")) {
126 if (log4jLevel == null || !log4jLevel.toString().equals(level))
127 try {
128 log4jLevel = Level.toLevel(level);
129 } catch (Exception e) {
130 System.err
131 .println("Log4j level could not be set for level '"
132 + level + "', resetting it to null.");
133 e.printStackTrace();
134 level = null;
135 }
136
137 if (log4jLevel != null
138 && !event.getLevel().isGreaterOrEqual(log4jLevel)) {
139 return;
140 }
141 }
142
143 try {
144 Thread currentThread = Thread.currentThread();
145 String username = null;
146
147 // find username
148 SecurityContext securityContext = SecurityContextHolder
149 .getContext();
150 if (securityContext != null) {
151 Authentication authentication = securityContext
152 .getAuthentication();
153 if (authentication != null) {
154 if (authentication instanceof AnonymousAuthenticationToken) {
155 username = null;
156 } else {
157 username = authentication.getName();
158 }
159 }
160 }
161
162 // Spring OSGi safe
163 Iterator<ArgeoLogListener> it = listeners.iterator();
164 while (it.hasNext()) {
165 ArgeoLogListener logListener = it.next();
166 logListener.appendLog(username, event.getTimeStamp(), event
167 .getLevel().toString(), event.getLoggerName(),
168 currentThread.getName(), event.getMessage(), event.getThrowableStrRep());
169 }
170 } catch (Exception e) {
171 stdOut("Cannot process logging event");
172 e.printStackTrace();
173 }
174 }
175
176 }
177 }