001: /*
002: * Hammurapi
003: * Automated Java code review system.
004: * Copyright (C) 2004 Hammurapi Group
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: support@hammurapi.biz
022: */
023: package org.hammurapi.inspectors;
024:
025: import org.hammurapi.InspectorBase;
026: import org.hammurapi.HammurapiException;
027:
028: import com.pavelvlasov.jsel.Method;
029: import com.pavelvlasov.jsel.expressions.MethodCall;
030: import com.pavelvlasov.util.AccumulatingVisitorExceptionSink;
031: import com.pavelvlasov.util.DispatchingVisitor;
032:
033: /**
034: * ER-090
035: * Call 'super.clone ()' in all 'clone ()' methods
036: * @author Janos Czako
037: * @version $Revision: 1.4 $
038: */
039: public class SuperCloneRule extends InspectorBase {
040:
041: /**
042: * The chained visitor class which searches after calling super.clone().
043: */
044: public static class MethodCallSnooper {
045:
046: /**
047: * The list of the calls found.
048: */
049: java.util.List returns = new java.util.ArrayList();
050:
051: /**
052: * The name of the "clone" method.
053: */
054: private static final String SUPER_CLONE_CALL = "super.clone";
055:
056: /**
057: * Reviews the calls to super.clone()
058: *
059: * @param call the calls to be reviewed.
060: */
061: public void visit(MethodCall call) {
062: String callTxt = call.getName().toString();
063: if (callTxt.indexOf(SUPER_CLONE_CALL) == 0
064: && call.getParameters().size() == 0) {
065:
066: returns.add(call);
067: }
068: }
069: }
070:
071: /**
072: * The name of the "clone" method.
073: */
074: private static final String CLONE_NAME = "clone";
075:
076: /**
077: * The error text for exceptions in the chained visitor.
078: */
079: private static final String CHAINED_ERRS = "There have been exceptions (see above)";
080:
081: /**
082: * Reviews the method definitions, if they are "clone()" and call
083: * "super.clone()".
084: *
085: * @param element the method definition to be reviewed.
086: * @throws HammurapiException In case of any exception in the chained visitor.
087: */
088: public void visit(Method element) throws HammurapiException {
089: if (element.getName().compareTo(CLONE_NAME) == 0
090: && element.getParameters().size() == 0) {
091:
092: AccumulatingVisitorExceptionSink es = new AccumulatingVisitorExceptionSink();
093: MethodCallSnooper rs = new MethodCallSnooper();
094: element.accept(new DispatchingVisitor(rs, es));
095:
096: if (rs.returns.size() != 1) {
097: context.reportViolation(element);
098: }
099: if (!es.getExceptions().isEmpty()) {
100: es.dump();
101: throw new HammurapiException(CHAINED_ERRS);
102: }
103: }
104: }
105:
106: }
|