java.lang.ClassCastException: org.sonar.java.model.DefaultJavaFileScannerContext cannot be cast to org.sonar.java.model.DefaultJavaFileScannerContext

Sonarqube 8.2:
Hello Team,
I am using sonarquebe 8.2 for wtriting a custom java rule, below is code.

@Rule(key = "CorsEnable")
public class CorsEnableCheck2 extends IssuableSubscriptionVisitor implements EndOfAnalysisCheck {

  private static final String JAVA_CONFIG = "JAVA_CONFIG";
  private final Map<String, List<AnalyzerMessage>> messagesPerPackage = new HashMap<>();

  private static final MethodMatcherCollection ADD_ALLOWED_ORIGIN_MATCHER =
      MethodMatcherCollection.create(
          MethodMatcher.create().typeDefinition("org.springframework.web.cors.CorsConfiguration")
              .name("addAllowedOrigin").withAnyParameters(),
          MethodMatcher.create()
              .typeDefinition("org.springframework.web.servlet.config.annotation.CorsRegistration")
              .name("allowedOrigins").withAnyParameters());

  // @Override
  public List<Kind> nodesToVisit() {
    return Collections.singletonList(Tree.Kind.METHOD);
  }

  // @Override
  public void visitNode(Tree tree) {

    MethodTree methodTree = (MethodTree) tree;
    Symbol.MethodSymbol methodSymbol = methodTree.symbol();

    if (isFilter(methodSymbol)) {
      if (isInvalidFilterBasedConfiguration(methodTree, methodSymbol)) {
        addMessageToMap(JAVA_CONFIG, methodTree.simpleName());
      }
    }

  }

   private void addMessageToMap(String key, IdentifierTree classNameTree) {
    DefaultJavaFileScannerContext defaultContext = (DefaultJavaFileScannerContext) context;
    AnalyzerMessage analyzerMessage =
        defaultContext.createAnalyzerMessage(this, classNameTree, MESSAGE);
    messagesPerPackage.computeIfAbsent(key, k -> new ArrayList<>()).add(analyzerMessage);
  }

  @Override
  public void endOfAnalysis() {
    DefaultJavaFileScannerContext defaultContext = (DefaultJavaFileScannerContext) context;
    messagesPerPackage.get(JAVA_CONFIG).forEach(defaultContext::reportIssue);
    // Do something

  }

}

Here Is the exception stact trace

[ERROR] Unable to run check class org.sonar.samples.java.checks.CorsEnableCheck - CorsEnable on file 'src/main/java/com/example/demo/WebConfig.java', To help improve the SonarSource Java Analyzer, please report this problem to SonarSource: see https://community.sonarsource.com/
java.lang.ClassCastException: org.sonar.java.model.DefaultJavaFileScannerContext cannot be cast to org.sonar.java.model.DefaultJavaFileScannerContext
        at org.sonar.samples.java.checks.CorsEnableCheck.addMessageToMap(CorsEnableCheck.java:175)
        at org.sonar.samples.java.checks.CorsEnableCheck.visitNode(CorsEnableCheck.java:88)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.lambda$visit$6(VisitorsBridge.java:311)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.lambda$forEach$9(VisitorsBridge.java:326)
        at org.sonar.java.model.VisitorsBridge.runScanner(VisitorsBridge.java:189)
        at org.sonar.java.model.VisitorsBridge.access$100(VisitorsBridge.java:66)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.forEach(VisitorsBridge.java:326)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visit(VisitorsBridge.java:313)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visitChildren(VisitorsBridge.java:297)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visit(VisitorsBridge.java:317)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visitChildren(VisitorsBridge.java:297)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visit(VisitorsBridge.java:317)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visitChildren(VisitorsBridge.java:297)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visit(VisitorsBridge.java:317)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visitChildren(VisitorsBridge.java:297)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visit(VisitorsBridge.java:317)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visitChildren(VisitorsBridge.java:297)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visit(VisitorsBridge.java:317)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visitChildren(VisitorsBridge.java:297)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visit(VisitorsBridge.java:317)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visitChildren(VisitorsBridge.java:297)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.visit(VisitorsBridge.java:317)
        at org.sonar.java.model.VisitorsBridge$IssuableSubsciptionVisitorsRunner.run(VisitorsBridge.java:288)
        at org.sonar.java.model.VisitorsBridge.visitFile(VisitorsBridge.java:171)
        at org.sonar.java.ast.JavaAstScanner.simpleScan(JavaAstScanner.java:98)
        at org.sonar.java.ast.JavaAstScanner.scan(JavaAstScanner.java:64)
        at org.sonar.java.JavaSquid.scanSources(JavaSquid.java:120)
        at org.sonar.java.JavaSquid.scan(JavaSquid.java:113)
        at org.sonar.plugins.java.JavaSquidSensor.execute(JavaSquidSensor.java:103)
        at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:48)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:85)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:59)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:77)
        at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:59)
        at org.sonar.scanner.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:82)
        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:137)
        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:123)
        at org.sonar.scanner.scan.ProjectScanContainer.scan(ProjectScanContainer.java:386)
        at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:382)
        at org.sonar.scanner.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:351)
        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:137)
        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:123)
        at org.sonar.scanner.bootstrap.GlobalContainer.doAfterStart(GlobalContainer.java:141)
        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:137)
        at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:123)
        at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:72)
        at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:66)
        at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
        at com.sun.proxy.$Proxy28.execute(Unknown Source)
        at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:189)
        at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:138)
        at org.sonarsource.scanner.maven.bootstrap.ScannerBootstrapper.execute(ScannerBootstrapper.java:65)
        at org.sonarsource.scanner.maven.SonarQubeMojo.execute(SonarQubeMojo.java:104)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:956)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:192)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)

FYI: I have addded the depdency

org.sonarsource.java
java-frontend
${sonarjava.version}

to fix the MethodMatcherCollection, class not found issue.

Hello,

When working with custom rules, I highly recommend using only what is provided by the public API (org.sonar.plugins.java.api.).
What could go wrong?
In fact, the code you provide is already a perfect example: we reworked MethodMatchers in version 6.3, and removed MethodMatcherCollection. This means that if you use the new version, your custom plugin will not work anymore, and understanding why can be tricky. Of course, public API can also change, but you can expect to be notified if it happens.
The good part is that we reworked MethodMatchers exactly for the purpose of exposing it in the public API, so I would advise you to update to 6.3 (or not use it!).

Now, coming back to your original problem, I would not be surprised if you are facing the same issue as in the post you just linked:

only classes under api packages are provided during analyze time or during rules loading at the server side.

The solutions provided there can probably lead your researches, but be sure to be aware of what it implies to avoid painful hours of debugging in the future!

Best,
Quentin

1 Like

@Quentin, Thanks for the reply, I have upgraded to version 6.3, But still, I am having an issue with EndOfAnalysisCheck, For this, I need to add java-frontend.jar into my classpath otherwise I am getting Class NotFoud Exception, If I add the java-frontend.jar again the same old story I am getting java.lang.ClassCastException: Cannot cast org.sonar.java.model.DefaultJavaFileScannerContext to org.sonar.java.model.DefaultJavaFileScannerContext
Can you please let me know how to work with EndOfAnalysisCheck or is there any equivalent way. I need to check something after the scanning has done, Thank you.

The reason why EndOfAnalysisCheck is not part of the public API is that it is still an experimental feature on our side (hence annotated with @Beta), we did not reach a state where we are satisfied enough to expose it to the public.

Concerning the workaround that you are trying, as explained in my first post, this is not the way it is intended to work, I don’t think I can help here. To my knowledge, there is no official way to obtain such behavior in custom plugins, we take good notes of your request and will be happy to consider it if it happens to be a common request.

Best,
Quentin

Hello @Mahesh,

Can you give us more context in which you face this problem?
Especially, which version of SonarQube are you using? Or are you using SonarCloud?
Could you provide us a code sample reproducing the error and the full stack-trace?

Thanks,
Quentin

Edit: I misunderstood the situation and splitting this topic was not a good move, putting everything back at the same place.

Hello @Mahesh,

First, your version of SonarQube (7.5?) is not supported anymore. The current SonarQube LTS version is 7.9, available here. I would therefore strongly encourage you to migrate to this version.

Now, you apparently duplicated the rule into a dedicated java custom-rules plugin. This is not supported as well. It is shown through your stack trace that we are here not dealing with the same implementation class as the rule S4605 delivered with the original SonarSource Java Analyzer.

More precisely, the rule causing your issue is having its fully qualified name being:
my.personal.organization.not.being.sonarsource.checks.SpringBeansShouldBeAccessibleCheck

While the SonarSource rule’s fully qualified name is supposed to be:
org.sonar.java.checks.spring.SpringBeansShouldBeAccessibleCheck

Duplicating classes from the SonarSource’s implementation, exposed in our open-source repository, directly into custom plugins is not a valid use case, as our rules have access at runtime to classes a custom plugin won’t be allowed to reach, for security reasons.

More particularly, in your context, you can not access the DefaultJavaFileScannerContext. This is an implementation class not visible outside of the scope of the Java Analyzer inner rules.

Also, please note that this very particular rule is using features that are not exposed in our public API, which can not be duplicated by copy-pasting code into custom plugins. In conclusion, this behavior simply can not be used in custom plugins, because it has not been designed to do so.

I hope this helps,
Michael