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:
027: import com.pavelvlasov.jsel.JselException;
028: import com.pavelvlasov.jsel.LanguageElement;
029: import com.pavelvlasov.jsel.Method;
030: import com.pavelvlasov.jsel.Operation;
031: import com.pavelvlasov.jsel.Parameter;
032: import com.pavelvlasov.jsel.statements.SynchronizedStatement;
033: import com.pavelvlasov.util.Visitor;
034:
035: /**
036: * ER-103
037: * Minimize synchronization in Servlets
038: * @author Pavel Vlasov
039: * @version $Revision: 1.4 $
040: */
041: public class SynchronizationInServletsRule extends InspectorBase {
042:
043: private static final String JAVAX_SERVLET_SERVLETRESPONSE = "javax.servlet.ServletResponse";
044: private static final String JAVAX_SERVLET_SERVLETREQUEST = "javax.servlet.ServletRequest";
045: private static final String JAVAX_SERVLET_SERVLET = "javax.servlet.Servlet";
046:
047: public void visit(SynchronizedStatement element) {
048: if (((LanguageElement) element).getEnclosingCode() instanceof Method) {
049: checkCallers((Method) ((LanguageElement) element)
050: .getEnclosingCode());
051: }
052: }
053:
054: private boolean j2eeChecked = false;
055:
056: public void visit(Method element) {
057: if (element.getModifiers().contains("synchronized")) {
058: checkCallers(element);
059: }
060: }
061:
062: /**
063: * @param method
064: */
065: private void checkCallers(Method method) {
066: if (!j2eeChecked) {
067: j2eeChecked = true;
068: try {
069: method.getRepository().loadClass(JAVAX_SERVLET_SERVLET);
070: } catch (ClassNotFoundException e) {
071: disable(e.getMessage());
072: return;
073: }
074: }
075:
076: try {
077: /* this buffer will accumulate list of servlet
078: * methods invoking this method directly or indirectly
079: */
080: final StringBuffer sb = new StringBuffer();
081:
082: // Check whether this method is invoked from servlet
083: // methods with 2 parameters of type ServletRequest and ServletResponse.
084: method.visitCallers(new Visitor() {
085:
086: public boolean visit(Object target) {
087: Operation.Invocation inv = (Operation.Invocation) target;
088: if (inv.getCaller() instanceof Method) {
089: Method caller = (Method) inv.getCaller();
090: try {
091: if (caller.getEnclosingType().isKindOf(
092: JAVAX_SERVLET_SERVLET)
093: && caller.getParameters().size() == 2
094: && ((Parameter) caller
095: .getParameters().get(0))
096: .isTypeOf(JAVAX_SERVLET_SERVLETREQUEST)
097: && ((Parameter) caller
098: .getParameters().get(0))
099: .isTypeOf(JAVAX_SERVLET_SERVLETRESPONSE)) {
100: if (sb.length() > 0) {
101: sb.append(", ");
102: }
103: sb.append(caller.getEnclosingType()
104: .getFcn());
105: sb.append(".");
106: sb.append(caller
107: .getOperationSignature());
108: }
109: } catch (JselException e) {
110: context.warn(caller, e);
111: }
112: }
113: return true;
114: }
115:
116: });
117:
118: if (sb.length() > 0) {
119: context.reportViolation(method, context.getDescriptor()
120: .getMessage()
121: + ". Synchronized method "
122: + method.getOperationSignature()
123: + " is invoked from servlet method(s) "
124: + sb.toString());
125: }
126: } catch (JselException e) {
127: context.warn(method, e);
128: }
129: }
130: }
|