Project Report: fawkez

Packagesummary org.jcoderz.phoenix.checkstyle

org.jcoderz.phoenix.checkstyle.LoggingLevel

LineHitsNoteSource
1  /*
2   * $Id: LoggingLevel.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.phoenix.checkstyle;
34  
35  import java.util.HashSet;
36  import java.util.Set;
37  import java.util.StringTokenizer;
38  import java.util.logging.Level;
39  
40  import com.puppycrawl.tools.checkstyle.api.Check;
41  import com.puppycrawl.tools.checkstyle.api.DetailAST;
42  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
43  
44  /**
45   * This check makes sure that a class' source code does not
46   * contain illegal logging levels in calls to the Java Logging
47   * API. Such a check is interesting when you have a logging
48   * message framework that uses generated classes for messages up to
49   * a certain level in order to guarantee certain information
50   * in these messages when written to the log file.
51   * One example scenario is when log file entries should be sent
52   * to a management console where an operator is looking at the
53   * messages and needs to take actions depending on the severity
54   * of the information he receives. In such cases it is important
55   * that these logging messages need a special format to contain
56   * all the necessary information. In our special case an XML
57   * was used from which exception or warning message classes
58   * had been created. Those classes had to be used for all log
59   * levels INFO and above as these logging records were
60   * automatically forwarded to the operators sitting in from of
61   * a management console, monitoring the application behaviour.
62   * For debugging purposes the developer was allowed to use
63   * only the logging levels below INFO so that no debugging
64   * message accidentally was sent to the management console.
65   *
66   * The default configuration of this check is:
67   * <ul>
68   *    <li>LoggerName = logger</li>
69   *    <li>AllowedLoggerMethods
70   *        = fine,finer,entering,exiting,throwing,finest</li>
71   *    <li>LogCallMaxLevel = FINE</li>
72   * </ul>
73   * The class' logger instance variable must have the name 'logger'.
74   * Only calls to the methods 'fine', 'finer', 'entering', 'exiting',
75   * 'throwing', and 'finest' are allowed. For the methods 'log',
76   * 'logp', and 'logrb' only the logging level FINE and below is
77   * allowed. You can override these settings by specifying
78   * the properties in the checkstyle configuration file.
79   *
80   */
810(1)public class LoggingLevel
82        extends Check
83  {
840    private static final int [] TOKEN_LIST = new int[] {TokenTypes.METHOD_CALL};
85  
86     /** The required name of the logger. Default is 'logger'. */
87     private static final String DEFAULT_LOGGER_NAME = "logger";
88  
89     /** This is the maximum allowed level for logXYZ() calls */
900    private static final Level LOG_CALL_MAX_ALLOWED_LEVEL = Level.FINE;
91     /** This prefix covers the methods: log, logp, logrb */
92     private static final String LOG_CALL_PREFIX = "log";
93  
94     /** A set of all logger method names besides logXYZ(). */
950    private static final Set LOGGER_METHODS = new HashSet();
96  
97     /** A set of allowed logger method names besides logXYZ(). */
980    private static final Set ALLOWED_LOGGER_METHODS = new HashSet();
99  
1000    private String mLoggerName = DEFAULT_LOGGER_NAME;
1010    private Level mLogCallMaxLevel = LOG_CALL_MAX_ALLOWED_LEVEL;
102  
103     static
104     {
105        // All logger methods
1060       LOGGER_METHODS.add("severe");
1070       LOGGER_METHODS.add("warning");
1080       LOGGER_METHODS.add("info");
1090       LOGGER_METHODS.add("config");
1100       LOGGER_METHODS.add("fine");
1110       LOGGER_METHODS.add("finer");
1120       LOGGER_METHODS.add("entering");
1130       LOGGER_METHODS.add("exiting");
1140       LOGGER_METHODS.add("throwing");
1150       LOGGER_METHODS.add("finest");
116  
117        // The allowed logger methods
1180       ALLOWED_LOGGER_METHODS.add("fine");
1190       ALLOWED_LOGGER_METHODS.add("finer");
1200       ALLOWED_LOGGER_METHODS.add("entering");
1210       ALLOWED_LOGGER_METHODS.add("exiting");
1220       ALLOWED_LOGGER_METHODS.add("throwing");
1230       ALLOWED_LOGGER_METHODS.add("finest");
1240    }
125  
126     /**
127      * Sets the name of the logger instance.
128      * The default name is 'logger'.
129      *
130      * @param loggerName The name of the logger.
131      */
132     public void setLoggerName (final String loggerName)
133     {
1340       mLoggerName = loggerName;
1350    }
136  
137     /**
138      * Sets the names of allowed logger methods.
139      * The default names are: 'entering', 'exiting', 'throwing', 'fine',
140      * 'finer', and 'finest'.
141      *
142      * @param allowedLoggerMethods The names of allowed logger methods,
143      *       separated by colons.
144      */
145     public void setAllowedLoggerMethods (final String allowedLoggerMethods)
146     {
1470       final StringTokenizer st = new StringTokenizer(
148              allowedLoggerMethods, ",");
149  
1500       ALLOWED_LOGGER_METHODS.clear();
1510       while (st.hasMoreTokens())
152        {
1530          final String tok = st.nextToken();
1540          if (tok != null)
155           {
1560             ALLOWED_LOGGER_METHODS.add(tok.trim());
157           }
1580       }
1590    }
160  
161     /**
162      * Sets the maximum allowed level for logger methods
163      * starting with 'log' (log, logp, logrb).
164      * The default level is 'FINE'.
165      *
166      * @param logCallMaxLevel The maximum allowed logger level for
167      * the methods log, logp, and logrb.
168      */
169     public void setLogCallMaxLevel (final String logCallMaxLevel)
170     {
1710       mLogCallMaxLevel = Level.parse(logCallMaxLevel);
1720    }
173  
174     /** {@inheritDoc} */
175     public int[] getDefaultTokens ()
176     {
1770       final int [] rc = new int[TOKEN_LIST.length];
1780       System.arraycopy(TOKEN_LIST, 0, rc, 0, rc.length);
1790       return rc;
180     }
181  
182     /** {@inheritDoc} */
183     public void visitToken (final DetailAST ast)
184     {
1850       switch (ast.getType())
186        {
187           case TokenTypes.METHOD_CALL:
1880(2)            visitMethodCall(ast);
189  
190 (3)         default:
191              break;
192        }
1930    }
194  
195     /**
196      * Visits a method call token. Since we are interested in logger.method calls
197      * only, the first child must be a DOT type, otherwise no interest.
198      *
199      * @param methCall The visited token
200      */
201     private void visitMethodCall (final DetailAST methCall)
202     {
2030       final DetailAST dot = methCall.findFirstToken(TokenTypes.DOT);
204  
2050       if (dot != null)
206        {
207           // the first child of the dot-Token is the variable name, which is
208           // 'logger' in our case, otherwise not interested.
2090          final DetailAST varName = dot.findFirstToken(TokenTypes.IDENT);
2100          if (varName.getText().equals(mLoggerName))
211           {
2120             visitLoggerCall(methCall, varName);
213           }
214        }
2150    }
216  
217     /**
218      * Visits a logger call. The supplied node is the logger variable, the next
219      * sibling the called logger method.
220      *
221      * @param methCall The method call node.
222      * @param logger The Logger variable used in the logger call.
223      */
224     private void visitLoggerCall (
225           final DetailAST methCall,
226           final DetailAST logger)
227     {
2280       final DetailAST method = (DetailAST) logger.getNextSibling();
2290       if (method != null)
230        {
2310          final String methodName = method.getText();
232     
2330          if (methodName.startsWith(LOG_CALL_PREFIX))
234           {
2350             visitExpressionList(methCall, method);
236           }
237           else
238           {
239              // ignore all other methods than those defined above
2400             if (LOGGER_METHODS.contains(methodName)
241                    && !ALLOWED_LOGGER_METHODS.contains(methodName))
242              {
2430                logDisallowedLoggerMethod(method);
244              }
245           }
246        }
2470    }
248  
249     /**
250      * Checks the first parameter given to the supplied method call
251      *
252      * @param methCall The method call node.
253      * @param method The called logger method.
254      */
255     private void visitExpressionList (
256           final DetailAST methCall,
257           final DetailAST method)
258     {
2590       final DetailAST expressionList = methCall.
260              findFirstToken(TokenTypes.ELIST);
2610       if (expressionList != null)
262        {
2630          final DetailAST level = expressionList.findFirstToken(TokenTypes.EXPR);
2640          if (level != null)
265           {
2660             final DetailAST dot = level.findFirstToken(TokenTypes.DOT);
2670             visitLoggerLevel(methCall, dot);
268           }
269        }
2700    }
271  
272     private void visitLoggerLevel (
273           final DetailAST methCall,
274           final DetailAST dot)
275     {
276        /* in this case we are interested in the last child, which gives the
277           log level. */
2780       final DetailAST logLevel = dot.findFirstToken(TokenTypes.IDENT);
2790       if (logLevel != null)
280        {
2810          final DetailAST levelName = (DetailAST) logLevel.getNextSibling();
2820          if (levelName != null)
283           {
2840             final Level level = Level.parse(levelName.getText());
2850             if (level.intValue() > mLogCallMaxLevel.intValue())
286              {
2870                logDisallowedLogLevel(levelName);
288              }
289           }
290        }
2910    }
292  
293     /**
294      * Logs the disallowed logger level.
295      *
296      * @param level The disallowed log level.
297      */
298     private void logDisallowedLogLevel (final DetailAST level)
299     {
300        // trace.loglevel=Maximum allowed log level for trace log is
301        // ''{0}'' but was ''{1}''.
3020       log(level.getLineNo(), "trace.loglevel",
303              new Object[] {mLogCallMaxLevel, level.getText()});
3040    }
305  
306     /**
307      * Logs the disallowed logger method call.
308      *
309      * @param method The disallowed logger method.
310      */
311     private void logDisallowedLoggerMethod (final DetailAST method)
312     {
313        // trace.logmethod=Logger method ''{0}'' is not allowed.
3140       log(method.getLineNo(), "trace.logmethod",
315              new Object[] {method.getText()});
3160    }
317  }

Findings in this File

c (1) 81 : 0 Type Javadoc comment is missing an @author tag.
i (2) 188 : 0 Switch statement found in org.jcoderz.phoenix.checkstyle.LoggingLevel.visitToken(DetailAST) where default case is missing
d (3) 190 : 10 [fallthrough] possible fall-through into case