/* * Copyright (c) 2005-2011 Grameen Foundation USA * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * See also http://www.apache.org/licenses/LICENSE-2.0.html for an * explanation of the license and how it is applied. */ package org.mifos.framework.components.logger; import org.apache.log4j.helpers.FormattingInfo; import org.apache.log4j.helpers.PatternConverter; import org.apache.log4j.helpers.PatternParser; import org.apache.log4j.spi.LocationInfo; import org.apache.log4j.spi.LoggingEvent; /** * This class extends from the pattern parser. This class overrides the * finalizeConverter method to enable the logging of the class name, method name * and line number from where the log statement was issued with respect to the * mifos logger */ public class MifosPatternParser extends PatternParser { static final int FULL_LOCATION_CONVERTER = 1000; static final int METHOD_LOCATION_CONVERTER = 1001; static final int CLASS_LOCATION_CONVERTER = 1002; static final int LINE_LOCATION_CONVERTER = 1003; /** * Constructor: Passes the pattern string to the superclass PatternParser * * @param pattern */ public MifosPatternParser(String pattern) { super(pattern); } /** * Overridden method. If the specifier is 'L' it indicates the line number * from where the log statement was issued If 'M' indicates the method name, * 'C' indicates the class name. The MifosLocationPatternConverter will call * the required method based on whether the line number, method name or * class name is needed * * @param c * The specifier */ @Override protected void finalizeConverter(char c) { PatternConverter pc = null; switch (c) { // indicated line number specifier case 'L': pc = new MifosLocationPatternConverter(formattingInfo, LINE_LOCATION_CONVERTER); currentLiteral.setLength(0); break; // indicated method name specifier case 'M': pc = new MifosLocationPatternConverter(formattingInfo, METHOD_LOCATION_CONVERTER); currentLiteral.setLength(0); break; // indicates class name specifier case 'C': pc = new MifosLocationPatternConverter(formattingInfo, CLASS_LOCATION_CONVERTER, extractPrecisionOption()); currentLiteral.setLength(0); break; // any oter specifier the superclas method is called default: super.finalizeConverter(c); return; } // adds the convertor addConverter(pc); } /** * This class extends from the pattern convertor. This calls the convert * method. The convert method makes the decision as to whether it should * return the line number or method name or the class name */ private class MifosLocationPatternConverter extends PatternConverter { /* * Denotes whether the line number , method name or class name has to be * returned */ int type; /* Denotes the precision for displaying the class name */ int precision; public MifosLocationPatternConverter(FormattingInfo formattingInfo, int type) { super(formattingInfo); this.type = type; } public MifosLocationPatternConverter(FormattingInfo formattingInfo, int type, int precision) { super(formattingInfo); this.type = type; this.precision = precision; } @Override protected String convert(LoggingEvent event) { // The MifosLogger is passed as the FQN. LocationInfo locationInfo = new LocationInfo(new Throwable(), "org.mifos.framework.components.logger.MifosLogger"); switch (type) { // calls the method to return method name case METHOD_LOCATION_CONVERTER: return locationInfo.getMethodName(); // calls the method to return line number case LINE_LOCATION_CONVERTER: return locationInfo.getLineNumber(); // calls the method to return class name case CLASS_LOCATION_CONVERTER: String n = locationInfo.getClassName(); // depending on the precision, the rightmost token is retrieved. // If %C{1} and the class name is // org.mifos.framework.components.logger.MifosPattern, then the // display would show MifosPattern as class name // if it is %C{2} then logger.MifosPattern is shown. if (precision <= 0) { return n; } int len = n.length(); // We substract 1 from 'len' when assigning to 'end' to // avoid out of // bounds exception in return r.substring(end+1, len). This // can happen if // precision is 1 and the category name ends with a dot. int end = len - 1; for (int i = precision; i > 0; i--) { end = n.lastIndexOf('.', end - 1); if (end == -1) { return n; } } return n.substring(end + 1, len); default: return null; } } } }