1   package org.slf4j.ext;
2   
3   import org.slf4j.Logger;
4   import org.slf4j.Marker;
5   import org.slf4j.MarkerFactory;
6   import org.slf4j.helpers.MessageFormatter;
7   import org.slf4j.spi.LocationAwareLogger;
8   
9   /**
10   * A utility that provides standard mechanisms for logging certain kinds of
11   * activities.
12   * 
13   * @author Ralph Goers
14   * @author Ceki Gülcü
15   */
16  public class XLogger extends LoggerWrapper implements Logger {
17  
18    private static final String FQCN = XLogger.class.getName();
19    static Marker FLOW_MARKER = MarkerFactory.getMarker("FLOW");
20    static Marker ENTRY_MARKER = MarkerFactory.getMarker("ENTRY");
21    static Marker EXIT_MARKER = MarkerFactory.getMarker("EXIT");
22  
23    static Marker EXCEPTION_MARKER = MarkerFactory.getMarker("EXCEPTION");
24    static Marker THROWING_MARKER = MarkerFactory.getMarker("THROWING");
25    static Marker CATCHING_MARKER = MarkerFactory.getMarker("CATCHING");
26  
27    static String EXIT_MESSAGE_0 = "exit";
28    static String EXIT_MESSAGE_1 = "exit with ({})";
29  
30    static String ENTRY_MESSAGE_0 = "entry";
31    static String ENTRY_MESSAGE_1 = "entry with ({})";
32    static String ENTRY_MESSAGE_2 = "entry with ({}, {})";
33    static String ENTRY_MESSAGE_3 = "entry with ({}, {}, {})";
34    static String ENTRY_MESSAGE_4 = "entry with ({}, {}, {}, {})";
35    static int ENTRY_MESSAGE_ARRAY_LEN = 5;
36    static String[] ENTRY_MESSAGE_ARRAY = new String[ENTRY_MESSAGE_ARRAY_LEN];
37    static {
38      ENTRY_MARKER.add(FLOW_MARKER);
39      EXIT_MARKER.add(FLOW_MARKER);
40      THROWING_MARKER.add(EXCEPTION_MARKER);
41      CATCHING_MARKER.add(EXCEPTION_MARKER);
42  
43      ENTRY_MESSAGE_ARRAY[0] = ENTRY_MESSAGE_0;
44      ENTRY_MESSAGE_ARRAY[1] = ENTRY_MESSAGE_1;
45      ENTRY_MESSAGE_ARRAY[2] = ENTRY_MESSAGE_2;
46      ENTRY_MESSAGE_ARRAY[3] = ENTRY_MESSAGE_3;
47      ENTRY_MESSAGE_ARRAY[4] = ENTRY_MESSAGE_4;
48    }
49  
50    /**
51     * Given an underlying logger, construct an XLogger
52     * 
53     * @param logger
54     *                underlying logger
55     */
56    public XLogger(Logger logger) {
57      // If class B extends A, assuming B does not override method x(), the caller
58      // of new B().x() is A and not B, see also
59      // http://bugzilla.slf4j.org/show_bug.cgi?id=114
60      super(logger, LoggerWrapper.class.getName());
61    }
62  
63    /**
64     * Log method entry.
65     * 
66     * @param argArray
67     *                supplied parameters
68     */
69    public void entry(Object... argArray) {
70      if (instanceofLAL && logger.isTraceEnabled(ENTRY_MARKER)) {
71        String messagePattern = null;
72        if (argArray.length <= ENTRY_MESSAGE_ARRAY_LEN) {
73          messagePattern = ENTRY_MESSAGE_ARRAY[argArray.length];
74        } else {
75          messagePattern = buildMessagePattern(argArray.length);
76        }
77        String formattedMessage = MessageFormatter.arrayFormat(messagePattern,
78            argArray);
79        ((LocationAwareLogger) logger).log(ENTRY_MARKER, FQCN,
80            LocationAwareLogger.TRACE_INT, formattedMessage, null);
81      }
82    }
83  
84    /**
85     * Log method exit
86     */
87    public void exit() {
88      if (instanceofLAL && logger.isTraceEnabled(ENTRY_MARKER)) {
89        ((LocationAwareLogger) logger).log(EXIT_MARKER, FQCN,
90            LocationAwareLogger.TRACE_INT, EXIT_MESSAGE_0, null);
91      }
92    }
93  
94    /**
95     * Log method exit
96     * 
97     * @param result
98     *                The result of the method being exited
99     */
100   public void exit(Object result) {
101     if (instanceofLAL && logger.isTraceEnabled(ENTRY_MARKER)) {
102       String formattedMessage = MessageFormatter.format(EXIT_MESSAGE_1, result);
103       ((LocationAwareLogger) logger).log(EXIT_MARKER, FQCN,
104           LocationAwareLogger.TRACE_INT, formattedMessage, null);
105     }
106   }
107 
108   /**
109    * Log an exception being thrown
110    * 
111    * @param throwable
112    *                the exception being caught.
113    */
114   public void throwing(Throwable throwable) {
115     if (instanceofLAL) {
116       ((LocationAwareLogger) logger).log(THROWING_MARKER, FQCN,
117           LocationAwareLogger.ERROR_INT, "throwing", throwable);
118     }
119   }
120 
121   /**
122    * Log an exception being caught
123    * 
124    * @param throwable
125    *                the exception being caught.
126    */
127   public void catching(Throwable throwable) {
128     if (instanceofLAL) {
129       ((LocationAwareLogger) logger).log(CATCHING_MARKER, FQCN,
130           LocationAwareLogger.ERROR_INT, "catching", throwable);
131     }
132   }
133 
134   private static String buildMessagePattern(int len) {
135     StringBuilder sb = new StringBuilder();
136     sb.append(" entry with (");
137     for (int i = 0; i < len; i++) {
138       sb.append("{}");
139       if (i != len - 1)
140         sb.append(", ");
141     }
142     sb.append(')');
143     return sb.toString();
144   }
145 }