View Javadoc
1   /**
2    * Copyright 2010-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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  package org.kuali.common.util.log.log4j;
17  
18  import java.io.ByteArrayInputStream;
19  import java.io.File;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.util.Properties;
24  
25  import javax.xml.parsers.DocumentBuilder;
26  import javax.xml.parsers.DocumentBuilderFactory;
27  import javax.xml.parsers.ParserConfigurationException;
28  
29  import org.apache.commons.io.FileUtils;
30  import org.apache.commons.io.IOUtils;
31  import org.apache.commons.lang3.StringUtils;
32  import org.apache.log4j.LogManager;
33  import org.apache.log4j.PropertyConfigurator;
34  import org.apache.log4j.xml.DOMConfigurator;
35  import org.kuali.common.util.Assert;
36  import org.kuali.common.util.Encodings;
37  import org.kuali.common.util.LocationUtils;
38  import org.kuali.common.util.PropertyUtils;
39  import org.kuali.common.util.log.log4j.model.Log4JConfiguration;
40  import org.kuali.common.util.xml.service.XmlService;
41  import org.w3c.dom.Document;
42  import org.w3c.dom.Element;
43  import org.xml.sax.SAXException;
44  
45  public final class DefaultLog4JService implements Log4JService {
46  
47  	// ASCII should actually be good enough, log4j config files shouldn't contain special characters
48  	private static final String ENCODING = Encodings.UTF8;
49  	private static final String PROPERTIES_SUFFIX = ".properties";
50  	private static final String XML_SUFFIX = ".xml";
51  	private static final String UNSUPPORTED_LOCATION_TYPE = "Only " + PROPERTIES_SUFFIX + " and " + XML_SUFFIX + " locations are supported";
52  
53  	private final XmlService service;
54  
55  	public DefaultLog4JService(XmlService service) {
56  		Assert.noNulls(service);
57  		this.service = service;
58  	}
59  
60  	@Override
61  	public void configure(Log4JConfiguration config) {
62  		String xml = toXml(config);
63  		Document document = getDocument(xml);
64  		configure(document);
65  	}
66  
67  	@Override
68  	public void reset() {
69  		LogManager.resetConfiguration();
70  	}
71  
72  	@Override
73  	public void configure(String location) {
74  
75  		// Make sure the location exists
76  		Assert.isTrue(LocationUtils.exists(location), "[" + location + "] does not exist");
77  
78  		// Make sure it is either a .properties or .xml
79  		boolean properties = StringUtils.endsWithIgnoreCase(location, PROPERTIES_SUFFIX);
80  		boolean xml = StringUtils.endsWithIgnoreCase(location, XML_SUFFIX);
81  		Assert.isTrue(properties || xml, UNSUPPORTED_LOCATION_TYPE);
82  
83  		if (properties) {
84  			configure(PropertyUtils.load(location, ENCODING));
85  		} else if (xml) {
86  			configureFromXmlLocation(location);
87  		} else {
88  			// Should never get here since the earlier assertions guarantee it is either .xml or .properties
89  			throw new IllegalArgumentException(UNSUPPORTED_LOCATION_TYPE);
90  		}
91  	}
92  
93  	@Override
94  	public String toXml(Log4JConfiguration config) {
95  		return service.toXml(config, ENCODING);
96  	}
97  
98  	@Override
99  	public void configure(Element element) {
100 		DOMConfigurator.configure(element);
101 	}
102 
103 	@Override
104 	public void configure(Properties properties) {
105 		PropertyConfigurator.configure(properties);
106 	}
107 
108 	@Override
109 	public void write(File file, Log4JConfiguration config) {
110 		OutputStream out = null;
111 		try {
112 			String xml = toXml(config);
113 			out = FileUtils.openOutputStream(file);
114 			IOUtils.write(xml, out, ENCODING);
115 		} catch (IOException e) {
116 			throw new IllegalStateException("Unexpected IO error", e);
117 		} finally {
118 			IOUtils.closeQuietly(out);
119 		}
120 	}
121 
122 	protected void configure(Document document) {
123 		DOMConfigurator.configure(document.getDocumentElement());
124 	}
125 
126 	protected void configureFromXmlLocation(String location) {
127 		InputStream in = null;
128 		try {
129 			in = LocationUtils.getInputStream(location);
130 			Document document = getDocument(in);
131 			configure(document);
132 		} catch (Exception e) {
133 			throw new IllegalStateException(e);
134 		} finally {
135 			IOUtils.closeQuietly(in);
136 		}
137 	}
138 
139 	protected Document getDocument(InputStream in) throws IOException, SAXException, ParserConfigurationException {
140 		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
141 		DocumentBuilder parser = dbf.newDocumentBuilder();
142 		return parser.parse(in);
143 	}
144 
145 	protected Document getDocument(String xml) {
146 		try {
147 			ByteArrayInputStream in = new ByteArrayInputStream(xml.getBytes(ENCODING));
148 			return getDocument(in);
149 		} catch (Exception e) {
150 			throw new IllegalStateException(e);
151 		}
152 	}
153 
154 	public XmlService getXmlService() {
155 		return service;
156 	}
157 
158 }