KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > design > MutableExceptionCheck


1 ////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2005 Oliver Burn
4
//
5
// This library is free software; you can redistribute it and/or
6
// modify it under the terms of the GNU Lesser General Public
7
// License as published by the Free Software Foundation; either
8
// version 2.1 of the License, or (at your option) any later version.
9
//
10
// This library is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
// Lesser General Public License for more details.
14
//
15
// You should have received a copy of the GNU Lesser General Public
16
// License along with this library; if not, write to the Free Software
17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
////////////////////////////////////////////////////////////////////////////////
19
package com.puppycrawl.tools.checkstyle.checks.design;
20
21 import com.puppycrawl.tools.checkstyle.api.DetailAST;
22 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
23 import com.puppycrawl.tools.checkstyle.checks.AbstractFormatCheck;
24
25 import java.util.Stack JavaDoc;
26
27 /**
28  * <p> Ensures that exceptions (defined as any class name conforming
29  * to some regular expression) are immutable. That is, have only final
30  * fields.</p>
31  * <p> Rationale: Exception instances should represent an error
32  * condition. Having non final fields not only allows the state to be
33  * modified by accident and therefore mask the original condition but
34  * also allows developers to accidentally forget to initialise state
35  * thereby leading to code catching the exception to draw incorrect
36  * conclusions based on the state.</p>
37  *
38  * @author <a HREF="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
39  */

40 public final class MutableExceptionCheck extends AbstractFormatCheck
41 {
42     /** Default value for format property. */
43     private static final String JavaDoc DEFAULT_FORMAT = "^.*Exception$|^.*Error$";
44     /** Stack of checking information for classes. */
45     private final Stack JavaDoc mCheckingStack = new Stack JavaDoc();
46     /** Should we check current class or not. */
47     private boolean mChecking;
48
49     /** Creates new instance of the check. */
50     public MutableExceptionCheck()
51     {
52         super(DEFAULT_FORMAT);
53     }
54
55     /** {@inheritDoc} */
56     public int[] getDefaultTokens()
57     {
58         return new int[] {TokenTypes.CLASS_DEF, TokenTypes.VARIABLE_DEF};
59     }
60
61     /** {@inheritDoc} */
62     public int[] getRequiredTokens()
63     {
64         return getDefaultTokens();
65     }
66
67     /** {@inheritDoc} */
68     public void visitToken(DetailAST aAST)
69     {
70         switch (aAST.getType()) {
71         case TokenTypes.CLASS_DEF:
72             visitClassDef(aAST);
73             break;
74         case TokenTypes.VARIABLE_DEF:
75             visitVariableDef(aAST);
76             break;
77         default:
78             throw new IllegalStateException JavaDoc(aAST.toString());
79         }
80     }
81
82     /** {@inheritDoc} */
83     public void leaveToken(DetailAST aAST)
84     {
85         switch (aAST.getType()) {
86         case TokenTypes.CLASS_DEF:
87             leaveClassDef();
88             break;
89         default:
90             // Do nothing
91
}
92     }
93
94     /**
95      * Called when we start processing class definition.
96      * @param aAST class definition node
97      */

98     private void visitClassDef(DetailAST aAST)
99     {
100         mCheckingStack.push(mChecking ? Boolean.TRUE : Boolean.FALSE);
101         mChecking =
102             isExceptionClass(aAST.findFirstToken(TokenTypes.IDENT).getText());
103     }
104
105     /** Called when we leave class definition. */
106     private void leaveClassDef()
107     {
108         mChecking = ((Boolean JavaDoc) mCheckingStack.pop()).booleanValue();
109     }
110
111     /**
112      * Checks variable definition.
113      * @param aAST variable def node for check.
114      */

115     private void visitVariableDef(DetailAST aAST)
116     {
117         if (mChecking && (aAST.getParent().getType() == TokenTypes.OBJBLOCK)) {
118             final DetailAST modifiersAST =
119                 aAST.findFirstToken(TokenTypes.MODIFIERS);
120
121             if (!(modifiersAST.findFirstToken(TokenTypes.FINAL) != null)) {
122                 log(aAST.getLineNo(), aAST.getColumnNo(), "mutable.exception",
123                         aAST.findFirstToken(TokenTypes.IDENT).getText());
124             }
125         }
126     }
127
128     /**
129      * @param aClassName class name to check
130      * @return true if a given class name confirms specified format
131      */

132     private boolean isExceptionClass(String JavaDoc aClassName)
133     {
134         return getRegexp().matcher(aClassName).find();
135     }
136 }
137
Popular Tags