openrewrite / rewrite

Automated mass refactoring of source code.
https://docs.openrewrite.org
Apache License 2.0
1.98k stars 293 forks source link

ClassCastException in MavenParser in case of malformed POM #3699

Closed api-from-the-ion closed 7 months ago

api-from-the-ion commented 7 months ago

What version of OpenRewrite are you using?

I am using

How are you running OpenRewrite?

I am using the Maven plugin, calling from the shell.

mvn -U org.openrewrite.maven:rewrite-maven-plugin:5.11.0:run \
  -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-testing-frameworks:RELEASE \
  -Drewrite.activeRecipes=org.openrewrite.java.testing.junit5.JUnit4to5Migration    ... 

What is the smallest, simplest way to reproduce the problem?

We have malformed POM with something like this:

<configuration>
  <url>jdbc:postgresql://localhost</url>&gt;
</configuration>

What did you expect to see?

I expect Rewrite to work and not to break with ClassCastException. Additionally, it would be nice to have a logging possibility here, so I wouldn't have to clone the source code and remote debug the Maven plugin here to get to know what exactly is wrong at this place.

What did you see instead?

Instead, I see an exception; see the stack trace below.

What is the full stack trace of any errors you encountered?

java.lang.ClassCastException: org.openrewrite.tree.ParseError cannot be cast to org.openrewrite.xml.tree.Xml$Document
    at org.openrewrite.maven.MavenParser.parseInputs (MavenParser.java:87)
    at org.openrewrite.Parser.parse (Parser.java:58)
    at org.openrewrite.maven.MavenMojoProjectParser.parseMaven (MavenMojoProjectParser.java:478)
    at org.openrewrite.maven.MavenMojoProjectParser.listSourceFiles (MavenMojoProjectParser.java:150)
    at org.openrewrite.maven.AbstractRewriteMojo.loadSourceSet (AbstractRewriteMojo.java:257)
    at org.openrewrite.maven.AbstractRewriteMojo.listResults (AbstractRewriteMojo.java:239)
    at org.openrewrite.maven.AbstractRewriteRunMojo.execute (AbstractRewriteRunMojo.java:53)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:906)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:206)
    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:283)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:226)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:407)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:348)

Are you interested in contributing a fix to OpenRewrite?

The solution is clear here: we can't take for granted that the call to the iterator().next() will deliver us a Xml.Document here. In our case, it is a ParseError, but it could be any other SourceFile-derivated class.

So we need to put the result of this call in some temporary variable with SourceFile as a type. Then we should check the type of this variable per instanceof. In case, it is really a Xml.Document, we can cast and do the rest of the loop and put some things into theses two maps. Otherwise, we should put the temporary variable into the parsed list.

I don't know how to log and signal that there were some troubles with POM. And I don't know how to contribute this solution here.

api-from-the-ion commented 7 months ago

Thank you for review and merge. I wrote a comment in the PR.