001package org.kuali.common.util.log.log4j; 002 003import java.io.ByteArrayInputStream; 004import java.io.File; 005import java.io.IOException; 006import java.io.InputStream; 007import java.io.OutputStream; 008import java.util.Properties; 009 010import javax.xml.parsers.DocumentBuilder; 011import javax.xml.parsers.DocumentBuilderFactory; 012import javax.xml.parsers.ParserConfigurationException; 013 014import org.apache.commons.io.FileUtils; 015import org.apache.commons.io.IOUtils; 016import org.apache.commons.lang3.StringUtils; 017import org.apache.log4j.LogManager; 018import org.apache.log4j.PropertyConfigurator; 019import org.apache.log4j.xml.DOMConfigurator; 020import org.kuali.common.util.Assert; 021import org.kuali.common.util.Encodings; 022import org.kuali.common.util.LocationUtils; 023import org.kuali.common.util.PropertyUtils; 024import org.kuali.common.util.log.log4j.model.Log4JConfiguration; 025import org.kuali.common.util.xml.service.XmlService; 026import org.w3c.dom.Document; 027import org.w3c.dom.Element; 028import org.xml.sax.SAXException; 029 030public final class DefaultLog4JService implements Log4JService { 031 032 // ASCII should actually be good enough, log4j config files shouldn't contain special characters 033 private static final String ENCODING = Encodings.UTF8; 034 private static final String PROPERTIES_SUFFIX = ".properties"; 035 private static final String XML_SUFFIX = ".xml"; 036 private static final String UNSUPPORTED_LOCATION_TYPE = "Only " + PROPERTIES_SUFFIX + " and " + XML_SUFFIX + " locations are supported"; 037 038 private final XmlService service; 039 040 public DefaultLog4JService(XmlService service) { 041 Assert.noNulls(service); 042 this.service = service; 043 } 044 045 @Override 046 public void configure(Log4JConfiguration config) { 047 String xml = toXml(config); 048 Document document = getDocument(xml); 049 configure(document); 050 } 051 052 @Override 053 public void reset() { 054 LogManager.resetConfiguration(); 055 } 056 057 @Override 058 public void configure(String location) { 059 060 // Make sure the location exists 061 Assert.isTrue(LocationUtils.exists(location), "[" + location + "] does not exist"); 062 063 // Make sure it is either a .properties or .xml 064 boolean properties = StringUtils.endsWithIgnoreCase(location, PROPERTIES_SUFFIX); 065 boolean xml = StringUtils.endsWithIgnoreCase(location, XML_SUFFIX); 066 Assert.isTrue(properties || xml, UNSUPPORTED_LOCATION_TYPE); 067 068 if (properties) { 069 configure(PropertyUtils.load(location, ENCODING)); 070 } else if (xml) { 071 configureFromXmlLocation(location); 072 } else { 073 // Should never get here since the earlier assertions guarantee it is either .xml or .properties 074 throw new IllegalArgumentException(UNSUPPORTED_LOCATION_TYPE); 075 } 076 } 077 078 @Override 079 public String toXml(Log4JConfiguration config) { 080 return service.toXml(config, ENCODING); 081 } 082 083 @Override 084 public void configure(Element element) { 085 DOMConfigurator.configure(element); 086 } 087 088 @Override 089 public void configure(Properties properties) { 090 PropertyConfigurator.configure(properties); 091 } 092 093 @Override 094 public void write(File file, Log4JConfiguration config) { 095 OutputStream out = null; 096 try { 097 String xml = toXml(config); 098 out = FileUtils.openOutputStream(file); 099 IOUtils.write(xml, out, ENCODING); 100 } catch (IOException e) { 101 throw new IllegalStateException("Unexpected IO error", e); 102 } finally { 103 IOUtils.closeQuietly(out); 104 } 105 } 106 107 protected void configure(Document document) { 108 DOMConfigurator.configure(document.getDocumentElement()); 109 } 110 111 protected void configureFromXmlLocation(String location) { 112 InputStream in = null; 113 try { 114 in = LocationUtils.getInputStream(location); 115 Document document = getDocument(in); 116 configure(document); 117 } catch (Exception e) { 118 throw new IllegalStateException(e); 119 } finally { 120 IOUtils.closeQuietly(in); 121 } 122 } 123 124 protected Document getDocument(InputStream in) throws IOException, SAXException, ParserConfigurationException { 125 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 126 DocumentBuilder parser = dbf.newDocumentBuilder(); 127 return parser.parse(in); 128 } 129 130 protected Document getDocument(String xml) { 131 try { 132 ByteArrayInputStream in = new ByteArrayInputStream(xml.getBytes(ENCODING)); 133 return getDocument(in); 134 } catch (Exception e) { 135 throw new IllegalStateException(e); 136 } 137 } 138 139 public XmlService getXmlService() { 140 return service; 141 } 142 143}