-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Pull #2292: Modernize codebase with Java improvements - SOC DefaultModelProcessor#read
#2292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -29,37 +29,39 @@ | |||||
| import java.util.Optional; | ||||||
|
|
||||||
| import org.apache.maven.api.annotations.Nullable; | ||||||
| import org.apache.maven.api.di.Inject; | ||||||
| import org.apache.maven.api.di.Named; | ||||||
| import org.apache.maven.api.di.Singleton; | ||||||
| import org.apache.maven.api.model.Model; | ||||||
| import org.apache.maven.api.services.Source; | ||||||
| import org.apache.maven.api.services.model.ModelProcessor; | ||||||
| import org.apache.maven.api.services.xml.ModelXmlFactory; | ||||||
| import org.apache.maven.api.services.xml.XmlReaderRequest; | ||||||
| import org.apache.maven.api.spi.ModelParser; | ||||||
| import org.apache.maven.api.spi.ModelParserException; | ||||||
|
|
||||||
| import static org.apache.maven.api.spi.ModelParser.STRICT; | ||||||
|
|
||||||
| /** | ||||||
| * | ||||||
| * Note: uses @Typed to limit the types it is available for injection to just ModelProcessor. | ||||||
| * | ||||||
| * <p> | ||||||
| * This is because the ModelProcessor interface extends ModelLocator and ModelReader. If we | ||||||
| * made this component available under all its interfaces then it could end up being injected | ||||||
| * into itself leading to a stack overflow. | ||||||
| * | ||||||
| * <p> | ||||||
| * A side effect of using @Typed is that it translates to explicit bindings in the container. | ||||||
| * So instead of binding the component under a 'wildcard' key it is now bound with an explicit | ||||||
| * key. Since this is a default component; this will be a plain binding of ModelProcessor to | ||||||
| * this implementation type; that is, no hint/name. | ||||||
| * | ||||||
| * <p> | ||||||
| * This leads to a second side effect in that any @Inject request for just ModelProcessor in | ||||||
| * the same injector is immediately matched to this explicit binding, which means extensions | ||||||
| * cannot override this binding. This is because the lookup is always short-circuited in this | ||||||
| * specific situation (plain @Inject request, and plain explicit binding for the same type.) | ||||||
| * | ||||||
| * <p> | ||||||
| * The simplest solution is to use a custom @Named here so it isn't bound under the plain key. | ||||||
| * This is only necessary for default components using @Typed that want to support overriding. | ||||||
| * | ||||||
| * <p> | ||||||
| * As a non-default component this now gets a negative priority relative to other implementations | ||||||
| * of the same interface. Since we want to allow overriding this doesn't matter in this case. | ||||||
| * (if it did we could add @Priority of 0 to match the priority given to default components.) | ||||||
|
|
@@ -69,75 +71,74 @@ | |||||
| public class DefaultModelProcessor implements ModelProcessor { | ||||||
|
|
||||||
| private final ModelXmlFactory modelXmlFactory; | ||||||
| private final List<ModelParser> modelParsers; | ||||||
| private final @Nullable List<ModelParser> modelParsers; | ||||||
|
|
||||||
| @Inject | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you aware that Maven has its own DI framework ? If you remove the required annotations, it will probably break ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
always run root
i delete/challenge everything and see if it breaks. All worked out locally thats why i want to lern and clarify, thx. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| public DefaultModelProcessor(ModelXmlFactory modelXmlFactory, @Nullable List<ModelParser> modelParsers) { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. everything can be null, why this required?
Suggested change
|
||||||
| this.modelXmlFactory = modelXmlFactory; | ||||||
| this.modelParsers = modelParsers; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * @implNote The ModelProcessor#locatePom never returns null while the ModelParser#locatePom needs to return an existing path! | ||||||
| */ | ||||||
| @Override | ||||||
| public Path locateExistingPom(Path projectDirectory) { | ||||||
| // Note that the ModelProcessor#locatePom never returns null | ||||||
| // while the ModelParser#locatePom needs to return an existing path! | ||||||
| Path pom = modelParsers.stream() | ||||||
| .map(m -> m.locate(projectDirectory) | ||||||
| .map(org.apache.maven.api.services.Source::getPath) | ||||||
| .orElse(null)) | ||||||
| .filter(Objects::nonNull) | ||||||
| return modelParsers.stream() | ||||||
| .map(parser -> parser.locate(projectDirectory)) | ||||||
| .filter(Optional::isPresent) | ||||||
| .map(Optional::get) | ||||||
| .map(Source::getPath) | ||||||
| .peek(path -> throwIfWrongProjectDirLocation(path, projectDirectory)) | ||||||
| .findFirst() | ||||||
| .orElseGet(() -> doLocateExistingPom(projectDirectory)); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is already very nice functional clean code style. good codebase - There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You changed the semantics, it's wrong. |
||||||
| .orElseGet(() -> locateExistingPomWithUserDirDefault(projectDirectory)); | ||||||
| } | ||||||
|
|
||||||
| private static void throwIfWrongProjectDirLocation(Path pom, Path projectDirectory) { | ||||||
| if (pom != null && !pom.equals(projectDirectory) && !pom.getParent().equals(projectDirectory)) { | ||||||
| throw new IllegalArgumentException("The POM found does not belong to the given directory: " + pom); | ||||||
| } | ||||||
| return pom; | ||||||
| } | ||||||
|
|
||||||
| private Path locateExistingPomWithUserDirDefault(Path project) { | ||||||
| return locateExistingPomInDirOrFile(project != null ? project : Paths.get(System.getProperty("user.dir"))); | ||||||
| } | ||||||
|
|
||||||
| private static Path locateExistingPomInDirOrFile(Path project) { | ||||||
| return Files.isDirectory(project) ? isRegularFileOrNull(project.resolve("pom.xml")) : project; | ||||||
| } | ||||||
|
|
||||||
| private static Path isRegularFileOrNull(Path pom) { | ||||||
| return Files.isRegularFile(pom) ? pom : null; | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
| public Model read(XmlReaderRequest request) throws IOException { | ||||||
| Objects.requireNonNull(request, "source cannot be null"); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. source --> request |
||||||
| Path pomFile = request.getPath(); | ||||||
| return readPomWithParentInheritance(request, request.getPath()); | ||||||
| } | ||||||
|
|
||||||
| private Model readPomWithParentInheritance(XmlReaderRequest request, Path pomFile) { | ||||||
| List<ModelParserException> exceptions = new ArrayList<>(); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. high coupling -1 |
||||||
| if (pomFile != null) { | ||||||
| Path projectDirectory = pomFile.getParent(); | ||||||
| List<ModelParserException> exceptions = new ArrayList<>(); | ||||||
| for (ModelParser parser : modelParsers) { | ||||||
| try { | ||||||
| Optional<Model> model = | ||||||
| parser.locateAndParse(projectDirectory, Map.of(ModelParser.STRICT, request.isStrict())); | ||||||
| if (model.isPresent()) { | ||||||
| return model.get().withPomFile(pomFile); | ||||||
| } | ||||||
| } catch (ModelParserException e) { | ||||||
| exceptions.add(e); | ||||||
| return parser.locateAndParse(pomFile, Map.of(STRICT, request.isStrict())) | ||||||
| .orElseThrow() | ||||||
| .withPomFile(pomFile); | ||||||
| } catch (RuntimeException ex) { | ||||||
| exceptions.add(new ModelParserException(ex)); | ||||||
| } | ||||||
| } | ||||||
| try { | ||||||
| return doRead(request); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dry |
||||||
| } catch (IOException e) { | ||||||
| exceptions.forEach(e::addSuppressed); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then this is the last branch not covered. |
||||||
| throw e; | ||||||
| } | ||||||
| } else { | ||||||
| return doRead(request); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dry |
||||||
| } | ||||||
| return readPomWithSuppressedErrorRethrow(request, exceptions); | ||||||
| } | ||||||
|
|
||||||
| private Path doLocateExistingPom(Path project) { | ||||||
| if (project == null) { | ||||||
| project = Paths.get(System.getProperty("user.dir")); | ||||||
| } | ||||||
| if (Files.isDirectory(project)) { | ||||||
| Path pom = project.resolve("pom.xml"); | ||||||
| return Files.isRegularFile(pom) ? pom : null; | ||||||
| } else if (Files.isRegularFile(project)) { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| return project; | ||||||
| } else { | ||||||
| return null; | ||||||
| private Model readPomWithSuppressedErrorRethrow(XmlReaderRequest request, List<ModelParserException> exceptions) { | ||||||
| try { | ||||||
| return modelXmlFactory.read(request); | ||||||
| } catch (RuntimeException ex) { | ||||||
| exceptions.forEach(ex::addSuppressed); | ||||||
| throw ex; | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| private Model doRead(XmlReaderRequest request) throws IOException { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| return modelXmlFactory.read(request); | ||||||
| } | ||||||
| } | ||||||




Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider migration to https://checkstyle.org/checks/javadoc/javadocparagraph.html.
JavadocParagraph#2302