package org.webcat.exceptiondoctor.handlers; import java.util.ArrayList; import java.util.List; import org.webcat.exceptiondoctor.AbstractHandler; import org.webcat.exceptiondoctor.ExceptionHandlerInterface; public class ArithmeticExceptionHandler extends AbstractHandler implements ExceptionHandlerInterface { private static final Class<ArithmeticException> CLASS_TYPE = ArithmeticException.class; @Override protected Class<? extends Throwable> getExceptionType() { return CLASS_TYPE; } @Override public String getNewMessage( Throwable exToWrap ) { String oldMessage = exToWrap.getMessage(); String newMessage = "The code was trying to perform an illegal " + "arithmetic operation. "; String line = super.findLine(exToWrap); if (line != null && oldMessage != null && oldMessage.equals("/ by zero")) { List<String> denoms = new ArrayList<String>(); findDenomExpressions(line, denoms, 0); newMessage += getDivideZeroMessage(denoms); } else { newMessage += "Contact your instructor or a TA if you need more help."; } return newMessage; } private String getDivideZeroMessage(List<String> exprs) { String newMessage; if (exprs.size() == 0) { newMessage = "It appears as if a denominator on this line " + "evaluates to zero, but of course you cannot divide " + "by zero. You may want to add some code to check that " + "the expression is not zero before dividing. "; } else if (exprs.contains("0")) { newMessage = "The code has tried to divide by zero, which " + "can't be done, of course! "; } else if (exprs.size() == 1) { newMessage = "It appears as if the expression \"" + exprs.get(0) + "\" evaluates to zero, but of course you cannot divide " + "by zero. You may want to add some code to check that " + "the expression is not zero before dividing. "; } else { newMessage = "It appears as if one of the denominator expressions " + "evaluates to zero ("; boolean isFirst = true; for (String expr : exprs) { if (!isFirst) { newMessage += " or "; } newMessage += '"' + expr + '"'; isFirst = false; } newMessage += "), but of course you cannot divide " + "by zero. You may want to add some code to check that " + "the expression is not zero before dividing. "; } return newMessage; } public void findDenomExpressions( String line, List<String> denoms, int beginIndex) { line = stripComments(line); int index = getOperatorIndex(line, beginIndex); if (index < 0) { return; } // now walk through the line and try to find where the denominator // ends // first, ignore any blank space do { index++; } while (Character.isWhitespace(line.charAt(index))); // okay we found something... this is where we start int start = index; // keep track of left and right parens int paren = 0; // keep looking until you find some whitespace or a semicolon // To do: see if this can be done more efficiently // To do: test other possible expressions while (index < line.length()) { char c = line.charAt(index); if (c == ';') break; if (c == '(') paren++; if (c == ')') paren--; if (Character.isWhitespace(c) && paren == 0) break; index++; } String expr = line.substring(start, index); if (!expr.matches("([1-9][0-9\\.]*)|(0\\.[0-9]+)")) { denoms.add(expr); } if (index < line.length()) { findDenomExpressions(line, denoms, index); } } private int getOperatorIndex(String line, int beginIndex) { // Figure out what the denominator was // First start with the slash // To do: there may be more than Throwable exception = null;one division int index = line.indexOf("/", beginIndex); // also check for the mod operator if (index == -1) index = line.indexOf("%", beginIndex); return index; } }