class XmlStreamReaderDetector extends OpcodeStackDetector {

    private static final String XXE_XMLSTREAMREADER_TYPE = "XXE_XMLSTREAMREADER";;
    private static final String PROPERTY_SUPPORT_DTD = "javax.xml.stream.supportDTD";
    private static final String PROPERTY_IS_SUPPORTING_EXTERNAL_ENTITIES = "javax.xml.stream.isSupportingExternalEntities";
    private final BugReporter bugReporter;

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

    @Override
    public void sawOpcode(int seen) {<FILL_FUNCTION_BODY>}
}

        if (seen != Const.INVOKEVIRTUAL) {
            return;
        }
        String fullClassName = getClassConstantOperand();
        String method = getNameConstantOperand();

        //The method call is doing XML parsing (see class javadoc)
        if (fullClassName.equals("javax/xml/stream/XMLInputFactory") &&
                (method.equals("createXMLStreamReader") || method.equals("createXMLEventReader") ||
                 method.equals("createFilteredReader"))) {
            ClassContext classCtx = getClassContext();
            ConstantPoolGen cpg = classCtx.getConstantPoolGen();
            CFG cfg;
            try {
                cfg = classCtx.getCFG(getMethod());
            } catch (CFGBuilderException e) {
                AnalysisContext.logError("Cannot get CFG", e);
                return;
            }
            for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
                Location location = i.next();
                Instruction inst = location.getHandle().getInstruction();

                //DTD disallow
                //XMLInputFactory.setProperty
                if (inst instanceof org.apache.bcel.generic.INVOKEVIRTUAL) {
                    InvokeInstruction invoke = (InvokeInstruction) inst;
                    if ("setProperty".equals(invoke.getMethodName(cpg))) {
                        org.apache.bcel.generic.LDC loadConst = ByteCode.getPrevInstruction(location.getHandle(), LDC.class);
                        if (loadConst != null) {
                            if (PROPERTY_SUPPORT_DTD.equals(loadConst.getValue(cpg)) || PROPERTY_IS_SUPPORTING_EXTERNAL_ENTITIES.equals(loadConst.getValue(cpg))){
                                InstructionHandle prev1 = location.getHandle().getPrev();
                                InstructionHandle prev2 = prev1.getPrev();
                                //Case where the boolean is wrapped like : Boolean.valueOf(true) : 2 instructions
                                if (invokeInstruction().atClass("java.lang.Boolean").atMethod("valueOf").matches(prev1.getInstruction(),cpg)) {
                                    if (prev2.getInstruction() instanceof ICONST) {
                                        Integer valueWrapped = ByteCode.getConstantInt(prev2);
                                        if (valueWrapped != null && valueWrapped.equals(0)) { //Value is false
                                            return; //Safe feature is disable
                                        }
                                    }
                                }
                                //Case where the boolean is declared as : Boolean.FALSE
                                else if (prev1.getInstruction() instanceof org.apache.bcel.generic.GETSTATIC) {
                                    org.apache.bcel.generic.GETSTATIC getstatic = (org.apache.bcel.generic.GETSTATIC) prev1.getInstruction();
                                    if (getstatic.getClassType(cpg).getClassName().equals("java.lang.Boolean") &&
                                            getstatic.getFieldName(cpg).equals("FALSE")) {
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //Raise a bug
            bugReporter.reportBug(new BugInstance(this, XXE_XMLSTREAMREADER_TYPE, Priorities.NORMAL_PRIORITY) //
                    .addClass(this).addMethod(this).addSourceLine(this));
        }
    
<no_super_class>