/*
(non-Javadoc)

@see
edu.umd.cs.findbugs.classfile.IAnalysisEngine#analyze(edu.umd.cs.findbugs
.classfile.IAnalysisCache, java.lang.Object)
508500
@Override
    public NonImplicitExceptionPostDominatorsAnalysis analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
            throws CheckedAnalysisException {
        CFG cfg = getCFG(analysisCache, descriptor);
        NonImplicitExceptionPostDominatorsAnalysis analysis = new NonImplicitExceptionPostDominatorsAnalysis(cfg,
                getReverseDepthFirstSearch(analysisCache, descriptor), getDepthFirstSearch(analysisCache, descriptor));
        Dataflow<BitSet, PostDominatorsAnalysis> dataflow = new Dataflow<>(cfg, analysis);
        dataflow.execute();

        return analysis;
    }
507810
protected CFG getCFG(IAnalysisCache analysisCache, MethodDescriptor methodDescriptor) throws CheckedAnalysisException {
        return analysisCache.getMethodAnalysis(CFG.class, methodDescriptor);
    }
983041
void analyze(final MethodResult methodResult) {
        lock.lock();
        try {
            buildPackagePrefix(methodResult.getParentResource().getOriginalClass());

            final List<Instruction> visitedInstructions = interpretRelevantInstructions(methodResult.getInstructions());

            // find project defined methods in invoke occurrences
            final Set<ProjectMethod> projectMethods = findProjectMethods(visitedInstructions);

            // add project methods to global method pool
            projectMethods.forEach(MethodPool.getInstance()::addProjectMethod);

            Element returnedElement = new MethodSimulator().simulate(visitedInstructions);
            final String returnType = methodResult.getOriginalMethodSignature().getReturnType();

            // void resource methods are interpreted later; stop analyzing on error
            if (Types.PRIMITIVE_VOID.equals(returnType)) {
                return;
            }

            if (returnedElement == null) {
                // happens for abstract methods or if there is no return
                return;
            }

            final Set<Object> possibleObjects = returnedElement.getPossibleValues().stream().filter(o -> !(o instanceof HttpResponse))
                    .collect(Collectors.toSet());

            // for non-Response methods add a default if there are non-Response objects or none objects at all
            if (!Types.RESPONSE.equals(returnType)) {
                final HttpResponse defaultResponse = new HttpResponse();

                if (Types.OBJECT.equals(returnType))
                    defaultResponse.getEntityTypes().addAll(returnedElement.getTypes());
                else
                    defaultResponse.getEntityTypes().add(returnType);

                possibleObjects.stream().filter(o -> o instanceof JsonValue).map(o -> (JsonValue) o).forEach(defaultResponse.getInlineEntities()::add);

                defaultResponse.getContentTypes().addAll(methodResult.getResponseMediaTypes());

                methodResult.getResponses().add(defaultResponse);
            }

            // add Response results as well
            returnedElement.getPossibleValues().stream().filter(o -> o instanceof HttpResponse).map(o -> (HttpResponse) o).forEach(methodResult.getResponses()::add);
        } finally {
            lock.unlock();
        }
    }
423835
@Override
    public Void call() {
        if (shouldAnalyze()) {
            LOGGER.debug("Begin Analysis of '{}' ({})", dependency.getActualFilePath(), analyzer.getName());
            try {
                analyzer.analyze(dependency, engine);
            } catch (AnalysisException ex) {
                LOGGER.warn("An error occurred while analyzing '{}' ({}).", dependency.getActualFilePath(), analyzer.getName());
                LOGGER.debug("", ex);
                exceptions.add(ex);
            } catch (Throwable ex) {
                LOGGER.warn("An unexpected error occurred during analysis of '{}' ({}): {}",
                        dependency.getActualFilePath(), analyzer.getName(), ex.getMessage());
                LOGGER.error("", ex);
                exceptions.add(ex);
            }
        }
        return null;
    }
885151
public FetchedValueAnalysis analyzeFetchedValue(ExecutionContext executionContext, FetchedValue fetchedValue, ExecutionStepInfo executionInfo) throws NonNullableFieldWasNullException {
        return analyzeFetchedValueImpl(executionContext, fetchedValue, fetchedValue.getFetchedValue(), executionInfo);
    }
1093759
public void analyze(Analyzer analyzer, boolean allowFlow)
    throws Exception
  {
    _pendingTargets = new IntArray();
    _completedTargets = new IntArray();
    
    analyzeImpl(analyzer, allowFlow, _pendingTargets, _completedTargets);
  }
1206000
@Override
    public BlockTypeDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
        CFG cfg = getCFG(analysisCache, descriptor);
        DepthFirstSearch dfs = getDepthFirstSearch(analysisCache, descriptor);
        BlockTypeAnalysis analysis = new BlockTypeAnalysis(dfs);
        BlockTypeDataflow dataflow = new BlockTypeDataflow(cfg, analysis);
        dataflow.execute();
        return dataflow;
    }
870685
@Override
    public void prepareFileTypeAnalyzer(Engine engine) throws InitializationException {
        LOGGER.debug("Initializing Nexus Analyzer");
        LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled());
        if (isEnabled()) {
            final boolean useProxy = useProxy();
            LOGGER.debug("Using proxy: {}", useProxy);
            try {
                searcher = new NexusSearch(getSettings(), useProxy);
                if (!searcher.preflightRequest()) {
                    setEnabled(false);
                    throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer.");
                }
            } catch (MalformedURLException mue) {
                setEnabled(false);
                throw new InitializationException("Malformed URL to Nexus", mue);
            }
        }
    }
1074384
@Override
    public String[] analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
        SignatureParser parser = new SignatureParser(descriptor.getSignature());
        ArrayList<String> resultList = new ArrayList<>();
        for (Iterator<String> i = parser.parameterSignatureIterator(); i.hasNext();) {
            resultList.add(i.next());
        }
        return resultList.toArray(new String[resultList.size()]);
    }
112379
@Override
    public LiveLocalStoreDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor)
            throws CheckedAnalysisException {
        MethodGen methodGen = getMethodGen(analysisCache, descriptor);
        if (methodGen == null) {
            return null;
        }
        CFG cfg = getCFG(analysisCache, descriptor);

        ReverseDepthFirstSearch rdfs = getReverseDepthFirstSearch(analysisCache, descriptor);

        LiveLocalStoreAnalysis analysis = new LiveLocalStoreAnalysis(methodGen, rdfs, getDepthFirstSearch(analysisCache,
                descriptor));
        LiveLocalStoreDataflow dataflow = new LiveLocalStoreDataflow(cfg, analysis);

        dataflow.execute();
        if (ClassContext.DUMP_DATAFLOW_ANALYSIS) {
            ClassContext.dumpLiveLocalStoreDataflow(descriptor, cfg, dataflow);

        }
        return dataflow;
    }
1283949
@Override
    public TypeDataflow analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
        MethodGen methodGen = getMethodGen(analysisCache, descriptor);
        if (methodGen == null) {
            throw new MethodUnprofitableException(descriptor);
        }
        CFG cfg = getCFG(analysisCache, descriptor);
        DepthFirstSearch dfs = getDepthFirstSearch(analysisCache, descriptor);
        ExceptionSetFactory exceptionSetFactory = getExceptionSetFactory(analysisCache, descriptor);
        Method method = getMethod(analysisCache, descriptor);

        TypeAnalysis typeAnalysis = new TypeAnalysis(method, methodGen, cfg, dfs, AnalysisContext.currentAnalysisContext()
                .getLookupFailureCallback(), exceptionSetFactory);

        if (AnalysisContext.currentAnalysisContext().getBoolProperty(AnalysisFeatures.MODEL_INSTANCEOF)) {
            typeAnalysis.setValueNumberDataflow(getValueNumberDataflow(analysisCache, descriptor));
        }

        // Field store type database.
        // If present, this can give us more accurate type information
        // for values loaded from fields.
        typeAnalysis.setFieldStoreTypeDatabase(AnalysisContext.currentAnalysisContext().getFieldStoreTypeDatabase());

        TypeDataflow typeDataflow = new TypeDataflow(cfg, typeAnalysis);
        try {
            typeDataflow.execute();
        } catch (CheckedAnalysisException e) {
            AnalysisContext.logError("Error performing type dataflow analysis of " + descriptor, e);
            throw e;
        }
        if (TypeAnalysis.DEBUG || ClassContext.DUMP_DATAFLOW_ANALYSIS) {
            ClassContext.dumpTypeDataflow(method, cfg, typeDataflow);
        }

        return typeDataflow;
    }
456252
@Override
    public MethodGen analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
        Method method = getMethod(analysisCache, descriptor);

        if (method.getCode() == null) {
            return null;
        }
        XMethod xmethod =  XFactory.createXMethod(descriptor);
        if (xmethod.usesInvokeDynamic() && false) {
            AnalysisContext.currentAnalysisContext().analysisSkippedDueToInvokeDynamic(xmethod);
            return null;
        }

        try {
            AnalysisContext analysisContext = AnalysisContext.currentAnalysisContext();
            JavaClass jclass = getJavaClass(analysisCache, descriptor.getClassDescriptor());
            ConstantPoolGen cpg = getConstantPoolGen(analysisCache, descriptor.getClassDescriptor());

            String methodName = method.getName();
            int codeLength = method.getCode().getCode().length;
            String superclassName = jclass.getSuperclassName();
            if (codeLength > 6000 && Const.STATIC_INITIALIZER_NAME.equals(methodName) && "java.lang.Enum".equals(superclassName)) {
                analysisContext.getLookupFailureCallback().reportSkippedAnalysis(
                        new JavaClassAndMethod(jclass, method).toMethodDescriptor());
                return null;
            }
            if (analysisContext.getBoolProperty(AnalysisFeatures.SKIP_HUGE_METHODS)) {
                if (codeLength > 6000 || (Const.STATIC_INITIALIZER_NAME.equals(methodName) || "getContents".equals(methodName)) && codeLength > 2000) {
                    analysisContext.getLookupFailureCallback().reportSkippedAnalysis(
                            new JavaClassAndMethod(jclass, method).toMethodDescriptor());
                    return null;
                }
            }

            return new MethodGen(method, jclass.getClassName(), cpg);
        } catch (Exception e) {
            AnalysisContext.logError("Error constructing methodGen", e);
            return null;
        }
    }
273778
public <L extends JqlBaseListener> void analyze(final JQLContext jqlContext, final JQL jql, L listener) {
		analyzeInternal(jqlContext, jql.value, listener);
	}
1258950
protected <L extends JqlBaseListener> void analyzeInternal(JQLContext jqlContext, final String jql, L listener) {
		walker.walk(listener, prepareParser(jqlContext, jql).value0);
	}
771128
@Override
    public void registerAnalysisEngines(IAnalysisCache analysisCache) {
        for (IClassAnalysisEngine<?> engine : classAnalysisEngineList) {
            engine.registerWith(analysisCache);
        }

        for (IMethodAnalysisEngine<?> engine : methodAnalysisEngineList) {
            engine.registerWith(analysisCache);
        }

        for (IDatabaseFactory<?> databaseFactory : databaseFactoryList) {
            databaseFactory.registerWith(analysisCache);
        }

        // if (!Subtypes.DO_NOT_USE) {
        // new
        // ReflectionDatabaseFactory<Subtypes>(Subtypes.class).registerWith(analysisCache);
        // }
    }
4833
@Override
    public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
        try {
            final byte[] fileContent = IOUtils.toByteArray(new FileInputStream(dependency.getActualFile()));
            final ScannerFacade scanner = new ScannerFacade(jsRepository);
            final List<JsLibraryResult> results = scanner.scanScript(dependency.getActualFile().getAbsolutePath(), fileContent, 0);

            if (results.size() > 0) {
                for (JsLibraryResult libraryResult : results) {

                    final JsLibrary lib = libraryResult.getLibrary();
                    dependency.setName(lib.getName());
                    dependency.setVersion(libraryResult.getDetectedVersion());
                    try {
                        final PackageURL purl = PackageURLBuilder.aPackageURL().withType("javascript")
                                .withName(lib.getName()).withVersion(libraryResult.getDetectedVersion()).build();
                        dependency.addSoftwareIdentifier(new PurlIdentifier(purl, Confidence.HIGHEST));
                    } catch (MalformedPackageURLException ex) {
                        LOGGER.debug("Unable to build package url for retireJS", ex);
                        final GenericIdentifier id = new GenericIdentifier("javascript:" + lib.getName() + "@"
                                + libraryResult.getDetectedVersion(), Confidence.HIGHEST);
                        dependency.addSoftwareIdentifier(id);
                    }

                    dependency.addEvidence(EvidenceType.VERSION, "file", "version", libraryResult.getDetectedVersion(), Confidence.HIGH);
                    dependency.addEvidence(EvidenceType.PRODUCT, "file", "name", libraryResult.getLibrary().getName(), Confidence.HIGH);

                    final List<Vulnerability> vulns = new ArrayList<>();
                    final JsVulnerability jsVuln = libraryResult.getVuln();

                    if (jsVuln.getIdentifiers().containsKey("CVE") || jsVuln.getIdentifiers().containsKey("osvdb")) {
                        /* CVEs and OSVDB are an array of Strings - each one a unique vulnerability.
                         * So the JsVulnerability we are operating on may actually be representing
                         * multiple vulnerabilities. */

                        //TODO - can we refactor this to avoid russian doll syndrome (i.e. nesting)?
                        //CSOFF: NestedForDepth
                        for (Map.Entry<String, List<String>> entry : jsVuln.getIdentifiers().entrySet()) {
                            final String key = entry.getKey();
                            final List<String> value = entry.getValue();
                            if ("CVE".equals(key)) {
                                for (String cve : value) {
                                    Vulnerability vuln = engine.getDatabase().getVulnerability(StringUtils.trim(cve));
                                    if (vuln == null) {
                                        /* The CVE does not exist in the database and is likely in a
                                         * reserved state. Create a new one without adding it to the
                                         * database and populate it as best as possible. */
                                        vuln = new Vulnerability();
                                        vuln.setName(cve);
                                        vuln.setUnscoredSeverity(jsVuln.getSeverity());
                                        vuln.setSource(Vulnerability.Source.RETIREJS);
                                    }
                                    for (String info : jsVuln.getInfo()) {
                                        vuln.addReference("info", "info", info);
                                    }
                                    vulns.add(vuln);
                                }
                            } else if ("osvdb".equals(key)) {
                                //todo - convert to map/collect
                                value.stream().forEach((osvdb) -> {
                                    final Vulnerability vuln = new Vulnerability();
                                    vuln.setName(osvdb);
                                    vuln.setSource(Vulnerability.Source.RETIREJS);
                                    vuln.setUnscoredSeverity(jsVuln.getSeverity());
                                    jsVuln.getInfo().forEach((info) -> {
                                        vuln.addReference("info", "info", info);
                                    });
                                    vulns.add(vuln);
                                });
                            }
                            dependency.addVulnerabilities(vulns);
                        }
                        //CSON: NestedForDepth
                    } else {
                        final Vulnerability individualVuln = new Vulnerability();
                        /* ISSUE, BUG, etc are all individual vulnerabilities. The result of this
                         * iteration will be one vulnerability. */
                        for (Map.Entry<String, List<String>> entry : jsVuln.getIdentifiers().entrySet()) {
                            final String key = entry.getKey();
                            final List<String> value = entry.getValue();
                            // CSOFF: NeedBraces
                            if (null != key) {
                                switch (key) {
                                    case "issue":
                                        individualVuln.setName(libraryResult.getLibrary().getName() + " issue: " + value.get(0));
                                        individualVuln.addReference(key, key, value.get(0));
                                        break;
                                    case "bug":
                                        individualVuln.setName(libraryResult.getLibrary().getName() + " bug: " + value.get(0));
                                        individualVuln.addReference(key, key, value.get(0));
                                        break;
                                    case "summary":
                                        if (null == individualVuln.getName()) {
                                            individualVuln.setName(value.get(0));
                                        }
                                        individualVuln.setDescription(value.get(0));
                                        break;
                                    case "release":
                                        individualVuln.addReference(key, key, value.get(0));
                                        break;
                                    default:
                                        break;
                                }
                            }
                            // CSON: NeedBraces
                            individualVuln.setSource(Vulnerability.Source.RETIREJS);
                            individualVuln.setUnscoredSeverity(jsVuln.getSeverity());
                            for (String info : jsVuln.getInfo()) {
                                individualVuln.addReference("info", "info", info);
                            }
                        }
                        dependency.addVulnerability(individualVuln);
                    }
                }
            } else if (getSettings().getBoolean(Settings.KEYS.ANALYZER_RETIREJS_FILTER_NON_VULNERABLE, false)) {
                engine.removeDependency(dependency);
            }
        } catch (IOException | DatabaseException e) {
            throw new AnalysisException(e);
        }
    }
680196
@Override
    public CFG analyze(IAnalysisCache analysisCache, MethodDescriptor descriptor) throws CheckedAnalysisException {
        // Construct the CFG in its raw form
        MethodGen methodGen = analysisCache.getMethodAnalysis(MethodGen.class, descriptor);
        if (methodGen == null) {
            JavaClass jclass = analysisCache.getClassAnalysis(JavaClass.class, descriptor.getClassDescriptor());
            Method method = analysisCache.getMethodAnalysis(Method.class, descriptor);
            JavaClassAndMethod javaClassAndMethod = new JavaClassAndMethod(jclass, method);
            AnalysisContext.currentAnalysisContext().getLookupFailureCallback().reportSkippedAnalysis(descriptor);
            throw new MethodUnprofitableException(javaClassAndMethod);
        }
        CFGBuilder cfgBuilder = CFGBuilderFactory.create(descriptor, methodGen);
        cfgBuilder.build();
        CFG cfg = cfgBuilder.getCFG();

        // Mark as busy while we're pruning the CFG.
        cfg.setFlag(CFG.BUSY);

        // Important: eagerly put the CFG in the analysis cache.
        // Recursively performed analyses required to prune the CFG,
        // such as TypeAnalysis, will operate on the raw CFG.
        analysisCache.eagerlyPutMethodAnalysis(CFG.class, descriptor, cfg);

        // Record method name and signature for informational purposes
        cfg.setMethodName(SignatureConverter.convertMethodSignature(methodGen));
        cfg.setMethodGen(methodGen);

        // System.out.println("CC: getting refined CFG for " + methodId);
        if (CFGFactory.DEBUG_CFG) {
            String methodId = methodGen.getClassName() + "." + methodGen.getName() + ":" + methodGen.getSignature();
            System.out.println("CC: getting refined CFG for " + methodId);
        }
        if (ClassContext.DEBUG) {
            String methodId = methodGen.getClassName() + "." + methodGen.getName() + ":" + methodGen.getSignature();
            System.out.println("ClassContext: request to prune " + methodId);
        }

        // Remove CFG edges corresponding to failed assertions.
        boolean changed = false;
        boolean ASSUME_ASSERTIONS_ENABLED = true;
        if (ASSUME_ASSERTIONS_ENABLED) {
            LinkedList<Edge> edgesToRemove = new LinkedList<>();
            for (Iterator<Edge> i = cfg.edgeIterator(); i.hasNext();) {
                Edge e = i.next();
                if (e.getType() == EdgeTypes.IFCMP_EDGE) {
                    try {
                        BasicBlock source = e.getSource();
                        InstructionHandle last = source.getLastInstruction();
                        Instruction lastInstruction = last.getInstruction();
                        InstructionHandle prev = last.getPrev();
                        Instruction prevInstruction = prev.getInstruction();
                        if (prevInstruction instanceof GETSTATIC && lastInstruction instanceof IFNE) {
                            GETSTATIC getStatic = (GETSTATIC) prevInstruction;

                            if ("$assertionsDisabled".equals(getStatic.getFieldName(methodGen.getConstantPool()))
                                    && "Z".equals(getStatic.getSignature(methodGen.getConstantPool()))) {
                                edgesToRemove.add(e);
                            }
                        }
                    } catch (RuntimeException exception) {
                        assert true; // ignore it
                    }
                }
            }
            if (edgesToRemove.size() > 0) {
                changed = true;
                for (Edge e : edgesToRemove) {
                    cfg.removeEdge(e);
                }
            }
        }
        cfg.setFlag(CFG.PRUNED_FAILED_ASSERTION_EDGES);

        final boolean PRUNE_INFEASIBLE_EXCEPTION_EDGES = AnalysisContext.currentAnalysisContext().getBoolProperty(
                AnalysisFeatures.ACCURATE_EXCEPTIONS);

        if (PRUNE_INFEASIBLE_EXCEPTION_EDGES && !cfg.isFlagSet(CFG.PRUNED_INFEASIBLE_EXCEPTIONS)) {
            try {
                TypeDataflow typeDataflow = analysisCache.getMethodAnalysis(TypeDataflow.class, descriptor);
                // Exception edge pruning based on ExceptionSets.
                // Note: this is quite slow.
                PruneInfeasibleExceptionEdges pruner = new PruneInfeasibleExceptionEdges(cfg, methodGen, typeDataflow);
                pruner.execute();
                changed = changed || pruner.wasCFGModified();
            } catch (MissingClassException e) {
                AnalysisContext.currentAnalysisContext().getLookupFailureCallback()
                .reportMissingClass(e.getClassNotFoundException());
            } catch (DataflowAnalysisException e) {
                AnalysisContext.currentAnalysisContext().getLookupFailureCallback()
                .logError("unable to extract type analysis", e);
            } catch (ClassNotFoundException e) {
                AnalysisContext.currentAnalysisContext().getLookupFailureCallback().reportMissingClass(e);
            }
        }
        cfg.setFlag(CFG.PRUNED_INFEASIBLE_EXCEPTIONS);

        final boolean PRUNE_UNCONDITIONAL_EXCEPTION_THROWER_EDGES = !AnalysisContext.currentAnalysisContext().getBoolProperty(
                AnalysisFeatures.CONSERVE_SPACE);

        if (PRUNE_UNCONDITIONAL_EXCEPTION_THROWER_EDGES && !cfg.isFlagSet(CFG.PRUNED_UNCONDITIONAL_THROWERS)) {
            try {
                JavaClass jclass = analysisCache.getClassAnalysis(JavaClass.class, descriptor.getClassDescriptor());
                Method method = analysisCache.getMethodAnalysis(Method.class, descriptor);
                ConstantPoolGen cpg = analysisCache.getClassAnalysis(ConstantPoolGen.class, descriptor.getClassDescriptor());
                TypeDataflow typeDataflow = analysisCache.getMethodAnalysis(TypeDataflow.class, descriptor);

                PruneUnconditionalExceptionThrowerEdges pruner = new PruneUnconditionalExceptionThrowerEdges(jclass, method,
                        methodGen, cfg, cpg, typeDataflow, AnalysisContext.currentAnalysisContext());
                pruner.execute();
                if (pruner.wasCFGModified()) {
                    changed = true;

                }
            } catch (DataflowAnalysisException e) {
                AnalysisContext.logError("Error pruning normal return edges for unconditionally throwing methods for "
                        + descriptor, e);
            }
        }
        cfg.setFlag(CFG.PRUNED_UNCONDITIONAL_THROWERS);

        // Now we are done with the CFG refining process
        cfg.setFlag(CFG.REFINED);
        cfg.clearFlag(CFG.BUSY);

        // If the CFG changed as a result of pruning, purge all analysis results
        // for the method.
        if (changed) {

            DepthFirstSearch dfs = new DepthFirstSearch(cfg);
            dfs.search();
            Collection<BasicBlock> unreachable = dfs.unvisitedVertices();
            if (!unreachable.isEmpty()) {
                if (DEBUG_CFG) {
                    System.out.println("Unreachable blocks");
                }
                for (BasicBlock b : unreachable) {
                    if (DEBUG_CFG) {
                        System.out.println(" removing " + b);
                    }
                    cfg.removeVertex(b);
                }
            }
            Global.getAnalysisCache().purgeMethodAnalyses(descriptor);
        }

        return cfg;
    }