001/** 002 * Copyright 2010-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.common.util.log.log4j; 017 018import java.io.ByteArrayInputStream; 019import java.io.File; 020import java.io.IOException; 021import java.io.InputStream; 022import java.io.OutputStream; 023import java.util.Properties; 024 025import javax.xml.parsers.DocumentBuilder; 026import javax.xml.parsers.DocumentBuilderFactory; 027import javax.xml.parsers.ParserConfigurationException; 028 029import org.apache.commons.io.FileUtils; 030import org.apache.commons.io.IOUtils; 031import org.apache.commons.lang3.StringUtils; 032import org.apache.log4j.LogManager; 033import org.apache.log4j.PropertyConfigurator; 034import org.apache.log4j.xml.DOMConfigurator; 035import org.kuali.common.util.Assert; 036import org.kuali.common.util.Encodings; 037import org.kuali.common.util.LocationUtils; 038import org.kuali.common.util.PropertyUtils; 039import org.kuali.common.util.log.log4j.model.Log4JConfiguration; 040import org.kuali.common.util.xml.service.XmlService; 041import org.w3c.dom.Document; 042import org.w3c.dom.Element; 043import org.xml.sax.SAXException; 044 045public final class DefaultLog4JService implements Log4JService { 046 047 // ASCII should actually be good enough, log4j config files shouldn't contain special characters 048 private static final String ENCODING = Encodings.UTF8; 049 private static final String PROPERTIES_SUFFIX = ".properties"; 050 private static final String XML_SUFFIX = ".xml"; 051 private static final String UNSUPPORTED_LOCATION_TYPE = "Only " + PROPERTIES_SUFFIX + " and " + XML_SUFFIX + " locations are supported"; 052 053 private final XmlService service; 054 055 public DefaultLog4JService(XmlService service) { 056 Assert.noNulls(service); 057 this.service = service; 058 } 059 060 @Override 061 public void configure(Log4JConfiguration config) { 062 String xml = toXml(config); 063 Document document = getDocument(xml); 064 configure(document); 065 } 066 067 @Override 068 public void reset() { 069 LogManager.resetConfiguration(); 070 } 071 072 @Override 073 public void configure(String location) { 074 075 // Make sure the location exists 076 Assert.isTrue(LocationUtils.exists(location), "[" + location + "] does not exist"); 077 078 // Make sure it is either a .properties or .xml 079 boolean properties = StringUtils.endsWithIgnoreCase(location, PROPERTIES_SUFFIX); 080 boolean xml = StringUtils.endsWithIgnoreCase(location, XML_SUFFIX); 081 Assert.isTrue(properties || xml, UNSUPPORTED_LOCATION_TYPE); 082 083 if (properties) { 084 configure(PropertyUtils.load(location, ENCODING)); 085 } else if (xml) { 086 configureFromXmlLocation(location); 087 } else { 088 // Should never get here since the earlier assertions guarantee it is either .xml or .properties 089 throw new IllegalArgumentException(UNSUPPORTED_LOCATION_TYPE); 090 } 091 } 092 093 @Override 094 public String toXml(Log4JConfiguration config) { 095 return service.toXml(config, ENCODING); 096 } 097 098 @Override 099 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}