3939import org .apache .maven .api .spi .ModelParser ;
4040import org .apache .maven .api .spi .ModelParserException ;
4141
42+ import static org .apache .maven .api .spi .ModelParser .STRICT ;
43+
4244/**
4345 *
4446 * Note: uses @Typed to limit the types it is available for injection to just ModelProcessor.
45- *
47+ * <p>
4648 * This is because the ModelProcessor interface extends ModelLocator and ModelReader. If we
4749 * made this component available under all its interfaces then it could end up being injected
4850 * into itself leading to a stack overflow.
49- *
51+ * <p>
5052 * A side effect of using @Typed is that it translates to explicit bindings in the container.
5153 * So instead of binding the component under a 'wildcard' key it is now bound with an explicit
5254 * key. Since this is a default component; this will be a plain binding of ModelProcessor to
5355 * this implementation type; that is, no hint/name.
54- *
56+ * <p>
5557 * This leads to a second side effect in that any @Inject request for just ModelProcessor in
5658 * the same injector is immediately matched to this explicit binding, which means extensions
5759 * cannot override this binding. This is because the lookup is always short-circuited in this
5860 * specific situation (plain @Inject request, and plain explicit binding for the same type.)
59- *
61+ * <p>
6062 * The simplest solution is to use a custom @Named here so it isn't bound under the plain key.
6163 * This is only necessary for default components using @Typed that want to support overriding.
62- *
64+ * <p>
6365 * As a non-default component this now gets a negative priority relative to other implementations
6466 * of the same interface. Since we want to allow overriding this doesn't matter in this case.
6567 * (if it did we could add @Priority of 0 to match the priority given to default components.)
@@ -77,17 +79,19 @@ public DefaultModelProcessor(ModelXmlFactory modelXmlFactory, @Nullable List<Mod
7779 this .modelParsers = modelParsers ;
7880 }
7981
82+ /**
83+ * @implNote
84+ * The ModelProcessor#locatePom never returns null while the ModelParser#locatePom needs to return an existing path!
85+ */
8086 @ Override
8187 public Path locateExistingPom (Path projectDirectory ) {
82- // Note that the ModelProcessor#locatePom never returns null
83- // while the ModelParser#locatePom needs to return an existing path!
8488 Path pom = modelParsers .stream ()
8589 .map (m -> m .locate (projectDirectory )
8690 .map (org .apache .maven .api .services .Source ::getPath )
8791 .orElse (null ))
8892 .filter (Objects ::nonNull )
8993 .findFirst ()
90- .orElseGet (() -> doLocateExistingPom (projectDirectory ));
94+ .orElseGet (() -> locateExistingPomWithUserDirDefault (projectDirectory ));
9195 if (pom != null && !pom .equals (projectDirectory ) && !pom .getParent ().equals (projectDirectory )) {
9296 throw new IllegalArgumentException ("The POM found does not belong to the given directory: " + pom );
9397 }
@@ -97,47 +101,50 @@ public Path locateExistingPom(Path projectDirectory) {
97101 @ Override
98102 public Model read (XmlReaderRequest request ) throws IOException {
99103 Objects .requireNonNull (request , "source cannot be null" );
100- Path pomFile = request .getPath ();
104+ return readOnSelfOrParent (request , request .getPath ());
105+ }
106+
107+ private Model readOnSelfOrParent (XmlReaderRequest request , Path pomFile ) throws IOException {
101108 if (pomFile != null ) {
102- Path projectDirectory = pomFile .getParent ();
103109 List <ModelParserException > exceptions = new ArrayList <>();
104110 for (ModelParser parser : modelParsers ) {
105111 try {
106- Optional <Model > model =
107- parser .locateAndParse (projectDirectory , Map .of (ModelParser .STRICT , request .isStrict ()));
108- if (model .isPresent ()) {
109- return model .get ().withPomFile (pomFile );
112+ Optional <Model > parent = readParent (request , pomFile , parser );
113+ if (parent .isPresent ()) {
114+ return parent .get ().withPomFile (pomFile );
110115 }
111116 } catch (ModelParserException e ) {
112117 exceptions .add (e );
113118 }
114119 }
115120 try {
116- return doRead (request );
121+ return readOnSelf (request );
117122 } catch (IOException e ) {
118123 exceptions .forEach (e ::addSuppressed );
119124 throw e ;
120125 }
121126 } else {
122- return doRead (request );
127+ return readOnSelf (request );
123128 }
124129 }
125130
126- private Path doLocateExistingPom (Path project ) {
127- if (project == null ) {
128- project = Paths .get (System .getProperty ("user.dir" ));
129- }
131+ private static Optional <Model > readParent (XmlReaderRequest request , Path pomFile , ModelParser parser ) {
132+ return parser .locateAndParse (pomFile .getParent (), Map .of (STRICT , request .isStrict ()));
133+ }
134+
135+ private Path locateExistingPomWithUserDirDefault (Path project ) {
136+ return locateExistingPomInDirOrFile (project != null ? project : Paths .get (System .getProperty ("user.dir" )));
137+ }
138+
139+ private static Path locateExistingPomInDirOrFile (Path project ) {
130140 if (Files .isDirectory (project )) {
131141 Path pom = project .resolve ("pom.xml" );
132142 return Files .isRegularFile (pom ) ? pom : null ;
133- } else if (Files .isRegularFile (project )) {
134- return project ;
135- } else {
136- return null ;
137143 }
144+ return project ;
138145 }
139146
140- private Model doRead (XmlReaderRequest request ) throws IOException {
147+ private Model readOnSelf (XmlReaderRequest request ) throws IOException {
141148 return modelXmlFactory .read (request );
142149 }
143150}
0 commit comments