1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.logging;
35
36 import info.magnolia.cms.core.FileSystemHelper;
37 import info.magnolia.init.MagnoliaConfigurationProperties;
38 import info.magnolia.objectfactory.Components;
39
40 import java.io.ByteArrayInputStream;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.util.Collections;
44 import java.util.Locale;
45 import java.util.Map;
46 import java.util.Properties;
47
48 import javax.xml.parsers.DocumentBuilder;
49 import javax.xml.parsers.DocumentBuilderFactory;
50 import javax.xml.parsers.ParserConfigurationException;
51
52 import org.apache.commons.io.IOUtils;
53 import org.apache.commons.lang3.StringUtils;
54 import org.apache.log4j.LogManager;
55 import org.apache.log4j.PropertyConfigurator;
56 import org.apache.log4j.xml.DOMConfigurator;
57 import org.w3c.dom.Document;
58 import org.xml.sax.EntityResolver;
59 import org.xml.sax.InputSource;
60 import org.xml.sax.SAXException;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 public class Log4jConfigurer {
86
87
88
89
90 public static final String LOG4J_CONFIG = "log4j.config";
91
92
93
94
95
96 @Deprecated
97 public static void initLogging() {
98 initLogging(Components.getComponent(MagnoliaConfigurationProperties.class), Components.getComponent(FileSystemHelper.class));
99 }
100
101
102
103
104 public static void initLogging(MagnoliaConfigurationProperties configurationProperties, FileSystemHelper fileSystemHelper) {
105
106
107 log("Initializing Log4J");
108
109 String log4jFileName = configurationProperties.getProperty(LOG4J_CONFIG);
110 if (StringUtils.isNotEmpty(log4jFileName)) {
111 boolean isXml = log4jFileName.toLowerCase(Locale.ROOT).endsWith(".xml");
112
113 log("Initializing Log4J from [" + log4jFileName + "]");
114
115 final String config;
116 try {
117 config = fileSystemHelper.getTokenizedConfigFile(log4jFileName);
118 } catch (IOException e) {
119 log("Unable to initialize Log4J from [" + log4jFileName + "], got a IOException " + e.getMessage());
120 return;
121 }
122
123
124 if (isXml) {
125 try {
126 final Map dtds = Collections.singletonMap("log4j.dtd", "/org/apache/log4j/xml/log4j.dtd");
127 final Document document = string2DOM(config, dtds);
128 DOMConfigurator.configure(document.getDocumentElement());
129 } catch (Exception e) {
130 log("Unable to initialize Log4J from [" + log4jFileName + "], got an Exception during reading the xml file : " + e.getMessage());
131 }
132 } else {
133 try {
134 final Properties properties = new Properties();
135 properties.load(IOUtils.toInputStream(config));
136 PropertyConfigurator.configure(properties);
137 } catch (IOException e) {
138 log("Unable to initialize Log4J from [" + log4jFileName + "], got an Exception during reading the properties file : " + e.getMessage());
139 }
140 }
141
142 }
143 }
144
145
146
147
148 public static void shutdownLogging() {
149 log("Shutting down Log4J");
150 LogManager.shutdown();
151 }
152
153
154
155
156
157
158 private static void log(String message) {
159 System.out.println(message);
160 }
161
162
163
164
165
166 private static Document string2DOM(String xml, final Map<String, String> dtds) throws ParserConfigurationException, SAXException, IOException {
167 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
168 dbf.setValidating(false);
169
170 if (dtds.size() == 0) {
171 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
172 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
173 dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
174 dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
175 dbf.setNamespaceAware(true);
176 }
177 DocumentBuilder builder = dbf.newDocumentBuilder();
178 builder.setEntityResolver(new MapDTDEntityResolver(dtds));
179 return builder.parse(IOUtils.toInputStream(xml));
180 }
181
182
183
184
185 private static final class MapDTDEntityResolver implements EntityResolver {
186
187 private final Map<String, String> dtds;
188
189 private MapDTDEntityResolver(Map<String, String> dtds) {
190 this.dtds = dtds;
191 }
192
193 @Override
194 public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
195 String key = StringUtils.substringAfterLast(systemId, "/");
196 if (dtds.containsKey(key)) {
197 Class<? extends MapDTDEntityResolver> clazz = getClass();
198 InputStream in = clazz.getResourceAsStream(dtds.get(key));
199 if (in == null) {
200 log("Could not find [" + systemId + "]. Used [" + clazz.getClassLoader() + "] class loader in the search, parsed without DTD.");
201 return new InputSource(new ByteArrayInputStream(new byte[]{}));
202 }
203 return new InputSource(in);
204 }
205 return new InputSource(new ByteArrayInputStream(new byte[]{}));
206 }
207 }
208
209 }