001: /*
002: * Hammurapi
003: * Automated Java code review system.
004: * Copyright (C) 2005 CraftOfObjects
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.org
021: * e-Mail: CraftOfObjects@gmail.com
022:
023: */
024:
025: package org.hammurapi.inspectors;
026:
027: import java.util.Vector;
028:
029: import org.hammurapi.HammurapiException;
030: import org.hammurapi.InspectorBase;
031:
032: import com.pavelvlasov.jsel.CompilationUnit;
033: import com.pavelvlasov.jsel.JselException;
034: import com.pavelvlasov.jsel.LanguageElement;
035: import com.pavelvlasov.jsel.Method;
036: import com.pavelvlasov.jsel.Operation;
037: import com.pavelvlasov.jsel.TypeDefinition;
038: import com.pavelvlasov.jsel.VariableDefinition;
039:
040: /**
041: * @author CraftOfObjects
042: *
043: * This inspector identify singleton pattern by checking for,
044: * those class variable type equal to the implementing class.
045: * ER-213 is reported.
046: *
047: * If the Singleton keeps not final variables > 1, the class is statefull.
048: * ER-212 is reported.
049: *
050: */
051: public class StatelessSingleton extends InspectorBase {
052:
053: private com.pavelvlasov.jsel.Class currentType = null;
054: private boolean currentIsSingleton = false;
055: private Vector listOfNotFinalFields = null;
056:
057: public void init() {
058: ;
059: currentIsSingleton = false;
060: listOfNotFinalFields = new Vector();
061: }
062:
063: public void visit(com.pavelvlasov.jsel.Class type) {
064: init();
065: currentType = type;
066: }
067:
068: public boolean isSingleton(VariableDefinition element)
069: throws JselException {
070: LanguageElement parent = element.getParent();
071: if (parent instanceof TypeDefinition) {
072: // System.out.println( " parent instanceof TypeDefinition TRUE " );
073: boolean ret = currentType.getFcn().equals(
074: element.getTypeSpecification().getType().getName());
075: // System.out.println( " currentType.getFcn().equals( element.getTypeSpecification().getType().getName() --> " + ret );
076: return ret;
077: } else {
078: // System.out.println( " parent instanceof TypeDefinition FALSE " );
079: return false;
080: }
081: }
082:
083: public void visit(VariableDefinition element) {
084: // // System.out.println( "++ " + element.getSignature() );
085:
086: // is this a instance or class variable?
087: LanguageElement el = element.getParent();
088: // // System.out.println( "** " + el.getClass() );
089: if (el.getClass().equals(
090: com.pavelvlasov.jsel.impl.ClassImpl.class)) {
091: try {
092: if (el != null && isSingleton(element)
093: && element.getModifiers().contains("static")
094: // || element.getModifiers().contains("final"))
095: ) {
096: context.info(currentType, "Singleton detected");
097: context.getSession().getContext("ER-213")
098: .reportViolation(element,
099: "Singleton detected");
100: this .currentIsSingleton = true;
101: }
102: if (!element.getModifiers().contains("final")) {
103: // System.out.println( " added !! " );
104: listOfNotFinalFields.add(element);
105: }
106: } catch (JselException e) {
107: context.warn(element.getEnclosingType(), e);
108: }
109: } // fi
110: }
111:
112: public void leave(TypeDefinition cu) throws HammurapiException {
113: // System.out.println( "leave: " + this.currentType.getName() );
114: this .checkStatelessSingleton();
115: }
116:
117: public void checkStatelessSingleton() {
118:
119: //-- the singleton can be NOT final
120: if (currentIsSingleton && listOfNotFinalFields.size() > 1) {
121: context.info(currentType, "Singleton has "
122: + listOfNotFinalFields.size()
123: + " non final fields.");
124: context
125: .getSession()
126: .getContext("ER-212")
127: .reportViolation(
128: currentType,
129: "Singleton contains "
130: + listOfNotFinalFields.size()
131: + " not final fields (together with the Singleton field)");
132: }
133: }
134: }
|