/** * Copyright (c) 2014, the Railo Company Ltd. * Copyright (c) 2015, Lucee Assosication Switzerland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ package lucee.commons.io.log.log4j; import java.io.IOException; import java.io.PrintWriter; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import lucee.commons.io.CharsetUtil; import lucee.commons.io.log.Log; import lucee.commons.io.log.log4j.appender.ConsoleAppender; import lucee.commons.io.log.log4j.appender.DatasourceAppender; import lucee.commons.io.log.log4j.appender.RollingResourceAppender; import lucee.commons.io.log.log4j.appender.TaskAppender; import lucee.commons.io.log.log4j.layout.ClassicLayout; import lucee.commons.io.res.Resource; import lucee.commons.io.res.util.ResourceUtil; import lucee.commons.io.retirement.RetireListener; import lucee.commons.lang.ClassUtil; import lucee.commons.lang.StringUtil; import lucee.runtime.config.Config; import lucee.runtime.config.ConfigWeb; import lucee.runtime.config.ConfigWebUtil; import lucee.runtime.db.ClassDefinition; import lucee.runtime.exp.PageException; import lucee.runtime.op.Caster; import lucee.runtime.reflection.Reflector; import lucee.transformer.library.ClassDefinitionImpl; import org.apache.log4j.Appender; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.HTMLLayout; import org.apache.log4j.Layout; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.xml.XMLLayout; public class Log4jUtil { public static final long MAX_FILE_SIZE=1024*1024*10; public static final int MAX_FILES=10; private static final String DEFAULT_PATTERN = "%d{dd.MM.yyyy HH:mm:ss,SSS} %-5p [%c] %m%n"; public static Logger getResourceLog(Config config, Resource res, Charset charset, String name, Level level, int timeout,RetireListener listener, boolean async) throws IOException { Appender a = new RollingResourceAppender( new ClassicLayout() ,res ,charset ,true ,RollingResourceAppender.DEFAULT_MAX_FILE_SIZE ,RollingResourceAppender.DEFAULT_MAX_BACKUP_INDEX ,timeout,listener); // no open stream at all if(async) { a=new TaskAppender(config, a); } return getLogger(config, a, name, level); } public static Logger getConsoleLog(Config config, boolean errorStream, String name, Level level) { // Printwriter PrintWriter pw=errorStream?config.getErrWriter():config.getOutWriter(); if(pw==null)pw=new PrintWriter(errorStream?System.err:System.out); return getLogger(config, new ConsoleAppender(pw,new PatternLayout(DEFAULT_PATTERN)), name, level); } public static final Logger getLogger(Config config,Appender appender, String name, Level level){ // fullname String fullname=name; if(config instanceof ConfigWeb) { ConfigWeb cw=(ConfigWeb) config; fullname="web."+cw.getLabel()+"."+name; } else fullname="server."+name; Logger l = LogManager.exists(fullname); if(l!=null) l.removeAllAppenders(); else l = LogManager.getLogger(fullname); l.setAdditivity(false); l.addAppender(appender); l.setLevel(level); return l; } public static final Appender getAppender(Config config,Layout layout,String name,ClassDefinition cd, Map<String, String> appenderArgs){ if(appenderArgs==null)appenderArgs=new HashMap<String, String>(); // Appender Appender appender=null; if(cd!=null && cd.hasClass()) { // Console Appender if(ConsoleAppender.class.getName().equalsIgnoreCase(cd.getClassName())) { // stream-type boolean doError=false; String st = Caster.toString(appenderArgs.get("streamtype"),null); if(!StringUtil.isEmpty(st,true)) { st=st.trim().toLowerCase(); if(st.equals("err") || st.equals("error")) doError=true; } appenderArgs.put("streamtype",doError?"error":"output"); // get print writer PrintWriter pw; if(doError) { if(config.getErrWriter()==null)pw=new PrintWriter(System.err); else pw=config.getErrWriter(); } else { if(config.getOutWriter()==null)pw=new PrintWriter(System.out); else pw=config.getOutWriter(); } appender = new ConsoleAppender(pw,layout); } else if(DatasourceAppender.class.getName().equalsIgnoreCase(cd.getClassName())) { // datasource String dsn = Caster.toString(appenderArgs.get("datasource"),null); if(StringUtil.isEmpty(dsn,true)) dsn = Caster.toString(appenderArgs.get("datasourceName"),null); if(!StringUtil.isEmpty(dsn,true)) dsn=dsn.trim(); appenderArgs.put("datasource",dsn); // username String user = Caster.toString(appenderArgs.get("username"),null); if(StringUtil.isEmpty(user,true)) user = Caster.toString(appenderArgs.get("user"),null); if(!StringUtil.isEmpty(user,true)) user=user.trim(); else user=null; appenderArgs.put("username",user); // password String pass = Caster.toString(appenderArgs.get("password"),null); if(StringUtil.isEmpty(pass,true)) pass = Caster.toString(appenderArgs.get("pass"),null); if(!StringUtil.isEmpty(pass,true)) pass=pass.trim(); else pass=null; appenderArgs.put("password",pass); try { appender = new DatasourceAppender(config, layout, dsn, user, pass); } catch (PageException e) {e.printStackTrace(); appender = null; } } else if(RollingResourceAppender.class.getName().equalsIgnoreCase(cd.getClassName())) { // path Resource res=null; String path = Caster.toString(appenderArgs.get("path"),null); if(!StringUtil.isEmpty(path,true)) { path=path.trim(); path=ConfigWebUtil.translateOldPath(path); res=ConfigWebUtil.getFile(config, config.getConfigDir(),path, ResourceUtil.TYPE_FILE); if(res.isDirectory()) { res=res.getRealResource(name+".log"); } } if(res==null) { res=ConfigWebUtil.getFile(config, config.getConfigDir(),"logs/"+name+".log", ResourceUtil.TYPE_FILE); } // charset Charset charset = CharsetUtil.toCharset(Caster.toString(appenderArgs.get("charset"),null),null); if(charset==null){ charset=config.getResourceCharset(); appenderArgs.put("charset",charset.name()); } // maxfiles int maxfiles = Caster.toIntValue(appenderArgs.get("maxfiles"),10); appenderArgs.put("maxfiles",Caster.toString(maxfiles)); // maxfileSize long maxfilesize = Caster.toLongValue(appenderArgs.get("maxfilesize"),1024*1024*10); appenderArgs.put("maxfilesize",Caster.toString(maxfilesize)); // timeout int timeout = Caster.toIntValue(appenderArgs.get("timeout"),60); // timeout in seconds appenderArgs.put("timeout",Caster.toString(timeout)); try { appender=new RollingResourceAppender(layout,res,charset,true,maxfilesize,maxfiles,timeout,null); } catch (IOException e) { e.printStackTrace(); } } // class defintion else { Object obj = ClassUtil.loadInstance(cd.getClazz(null),null,null); if(obj instanceof Appender) { appender=(Appender) obj; AppenderSkeleton as=obj instanceof AppenderSkeleton?(AppenderSkeleton)obj:null; Iterator<Entry<String, String>> it = appenderArgs.entrySet().iterator(); Entry<String, String> e; String n; while(it.hasNext()){ e = it.next(); n=e.getKey(); if(as!=null) { if("threshold".equalsIgnoreCase(n)) { Level level = Level.toLevel(e.getValue(),null); if(level!=null) { as.setThreshold(level); continue; } } } try { Reflector.callSetter(obj, e.getKey(), e.getValue()); } catch (PageException e1) { e1.printStackTrace(); // TODO log } } } } } if(appender instanceof AppenderSkeleton) { ((AppenderSkeleton)appender).activateOptions(); } else if(appender==null) { PrintWriter pw; if(config.getOutWriter()==null)pw=new PrintWriter(System.out); else pw=config.getOutWriter(); appender=new ConsoleAppender(pw,layout); } return appender; } public static ClassDefinition<Appender> appenderClassDefintion(String className) { if("console".equalsIgnoreCase(className))return new ClassDefinitionImpl( ConsoleAppender.class); if("resource".equalsIgnoreCase(className))return new ClassDefinitionImpl( RollingResourceAppender.class); if("datasource".equalsIgnoreCase(className))return new ClassDefinitionImpl( DatasourceAppender.class); return new ClassDefinitionImpl( className); } public static final Layout getLayout(ClassDefinition cd, Map<String, String> layoutArgs) { if(layoutArgs==null)layoutArgs=new HashMap<String, String>(); // Layout Layout layout=null; if(cd!=null && cd.hasClass()) { // Classic Layout if(ClassicLayout.class.getName().equalsIgnoreCase(cd.getClassName())) layout=new ClassicLayout(); // HTML Layout else if(HTMLLayout.class.getName().equalsIgnoreCase(cd.getClassName())) { HTMLLayout html = new HTMLLayout(); layout=html; // Location Info Boolean locInfo = Caster.toBoolean(layoutArgs.get("locationinfo"),null); if(locInfo!=null) html.setLocationInfo(locInfo.booleanValue()); else locInfo=Boolean.FALSE; layoutArgs.put("locationinfo", locInfo.toString()); // Title String title = Caster.toString(layoutArgs.get("title"),""); if(!StringUtil.isEmpty(title,true)) html.setTitle(title); layoutArgs.put("title", title); } // XML Layout else if(XMLLayout.class.getName().equalsIgnoreCase(cd.getClassName())) { XMLLayout xml = new XMLLayout(); layout=xml; // Location Info Boolean locInfo = Caster.toBoolean(layoutArgs.get("locationinfo"),null); if(locInfo!=null) xml.setLocationInfo(locInfo.booleanValue()); else locInfo=Boolean.FALSE; layoutArgs.put("locationinfo", locInfo.toString()); // Properties Boolean props = Caster.toBoolean(layoutArgs.get("properties"),null); if(props!=null) xml.setProperties(props.booleanValue()); else props=Boolean.FALSE; layoutArgs.put("properties", props.toString()); } // Pattern Layout else if(PatternLayout.class.getName().equalsIgnoreCase(cd.getClassName())) { PatternLayout patt = new PatternLayout(); layout=patt; // pattern String pattern = Caster.toString(layoutArgs.get("pattern"),null); if(!StringUtil.isEmpty(pattern,true)) patt.setConversionPattern(pattern); else { patt.setConversionPattern(DEFAULT_PATTERN); layoutArgs.put("pattern", DEFAULT_PATTERN); } } // class defintion else { Object obj = ClassUtil.loadInstance(cd.getClazz(null),null,null); if(obj instanceof Layout) { layout=(Layout) obj; Iterator<Entry<String, String>> it = layoutArgs.entrySet().iterator(); Entry<String, String> e; while(it.hasNext()){ e = it.next(); try { Reflector.callSetter(obj, e.getKey(), e.getValue()); } catch (PageException e1) { e1.printStackTrace(); // TODO log } } } } } if(layout!=null) return layout; return new ClassicLayout(); } public static ClassDefinition<Layout> layoutClassDefintion(String className) { if("classic".equalsIgnoreCase(className))return new ClassDefinitionImpl( ClassicLayout.class); if("html".equalsIgnoreCase(className))return new ClassDefinitionImpl( HTMLLayout.class); if("xml".equalsIgnoreCase(className))return new ClassDefinitionImpl( XMLLayout.class); if("pattern".equalsIgnoreCase(className))return new ClassDefinitionImpl( PatternLayout.class); return new ClassDefinitionImpl( className); } //private static LoggerRepository repository=new Hierarchy(null); public static Level toLevel(int level) { switch(level){ case Log.LEVEL_FATAL: return Level.FATAL; case Log.LEVEL_ERROR: return Level.ERROR; case Log.LEVEL_WARN: return Level.WARN; case Log.LEVEL_DEBUG: return Level.DEBUG; case Log.LEVEL_INFO: return Level.INFO; case Log.LEVEL_TRACE: return Level.TRACE; } return Level.INFO; } public static int toLevel(Level level) { if(Level.FATAL.equals(level)) return Log.LEVEL_FATAL; if(Level.ERROR.equals(level)) return Log.LEVEL_ERROR; if(Level.WARN.equals(level)) return Log.LEVEL_WARN; if(Level.DEBUG.equals(level)) return Log.LEVEL_DEBUG; if(Level.INFO.equals(level)) return Log.LEVEL_INFO; if(Level.TRACE.equals(level)) return Log.LEVEL_TRACE; return Log.LEVEL_INFO; } public static Level toLevel(String strLevel, Level defaultValue) { if(strLevel==null) return defaultValue; strLevel=strLevel.toLowerCase().trim(); if(strLevel.startsWith("info")) return Level.INFO; if(strLevel.startsWith("debug")) return Level.DEBUG; if(strLevel.startsWith("warn")) return Level.WARN; if(strLevel.startsWith("error")) return Level.ERROR; if(strLevel.startsWith("fatal")) return Level.FATAL; if(strLevel.startsWith("trace")) return Level.TRACE; return defaultValue; } }