class JstlOutDetector implements Detector {
    private static final boolean DEBUG = false;
    private static final String JSP_JSTL_OUT = "JSP_JSTL_OUT";

    private static final InvokeMatcherBuilder OUT_TAG_ESCAPE_XML = invokeInstruction().atClass("org.apache.taglibs.standard.tag.rt.core.OutTag",
            "org.apache.taglibs.standard.tag.el.core.OutTag",
            "com.caucho.jstl.el.CoreOutTag",
            "com.caucho.jstl.rt.OutTag",
            "org.apache.taglibs.standard.tag.compat.core.OutTag",
            "org.appfuse.webapp.taglib.OutTag")
            .atMethod("setEscapeXml").withArgs("(Z)V","(Ljava/lang/String;)V");

    private final BugReporter bugReporter;



    public JstlOutDetector(BugReporter bugReporter) {
        this.bugReporter = bugReporter;
    }

    @Override
    public void visitClassContext(ClassContext classContext) {
        JavaClass javaClass = classContext.getJavaClass();

        try {
            if(!Hierarchy.isSubtype(javaClass.getClassName(), "javax.servlet.http.HttpServlet")) {
                return;
            }
        } catch (ClassNotFoundException e) {
            AnalysisContext.reportMissingClass(e);
        }
        for (Method m : javaClass.getMethods()) {
            try {
                analyzeMethod(m, classContext);
            } catch (CFGBuilderException e) {
            } catch (DataflowAnalysisException e) {
            }
        }
    }

    private void analyzeMethod(Method m, ClassContext classContext) throws CFGBuilderException, DataflowAnalysisException {<FILL_FUNCTION_BODY>}


    @Override
    public void report() {
    }

}


        //Conditions that needs to fill to identify the vulnerability
        boolean escapeXmlSetToFalse = false;
        boolean escapeXmlValueUnknown = false;
        Location locationWeakness = null;

        ConstantPoolGen cpg = classContext.getConstantPoolGen();
        CFG cfg = classContext.getCFG(m);

        LinkedList<Instruction> instructionVisited = new LinkedList<Instruction>();

        for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) {
            Location location = i.next();

            Instruction inst = location.getHandle().getInstruction();
            //ByteCode.printOpCode(inst, cpg);

            instructionVisited.add(inst);

//     JspSpringEvalDetector: [0047]  aload   4
//     JspSpringEvalDetector: [0049]  iconst_1
//     JspSpringEvalDetector: [0050]  invokevirtual   org/apache/taglibs/standard/tag/rt/core/OutTag.setEscapeXml (Z)V

            if (inst instanceof InvokeInstruction) {
                InvokeInstruction invoke = (InvokeInstruction) inst;

                if(OUT_TAG_ESCAPE_XML.matches(invoke,cpg)) {
                    Integer booleanValue = ByteCode.getConstantInt(location.getHandle().getPrev());
                    if (booleanValue != null && booleanValue == 0) {
                        escapeXmlSetToFalse = true;
                        locationWeakness = location;
                    } else {
                        //Some JSP compiler convert boolean value at runtime (WebLogic)
                        String stringValue = JspUtils.getContanstBooleanAsString(instructionVisited, cpg);
                        if (stringValue != null && stringValue.equals("false")) {
                            escapeXmlSetToFalse = true;
                            locationWeakness = location;
                        }

                        if(booleanValue == null && stringValue == null) {
                            escapeXmlValueUnknown = true;
                            locationWeakness = location;
                        }
                    }
                }
            }
        }

        //Both condition have been found in the same method
        if (escapeXmlSetToFalse) {
            JavaClass clz = classContext.getJavaClass();
            bugReporter.reportBug(new BugInstance(this, JSP_JSTL_OUT, Priorities.NORMAL_PRIORITY) //
                    .addClass(clz)
                    .addMethod(clz, m)
                    .addSourceLine(classContext, m, locationWeakness));
        } else if (escapeXmlValueUnknown) {
            JavaClass clz = classContext.getJavaClass();
            bugReporter.reportBug(new BugInstance(this, JSP_JSTL_OUT, Priorities.LOW_PRIORITY) //
                    .addClass(clz)
                    .addMethod(clz, m)
                    .addSourceLine(classContext, m, locationWeakness));
        }
    
<no_super_class>