Model doReadFileModel()

in impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java [1225:1429]


        Model doReadFileModel() throws ModelBuilderException {
            ModelSource modelSource = request.getSource();
            Model model;
            Path rootDirectory;
            setSource(modelSource.getLocation());
            logger.debug("Reading file model from " + modelSource.getLocation());
            try {
                boolean strict = isBuildRequest();
                try {
                    rootDirectory = request.getSession().getRootDirectory();
                } catch (IllegalStateException ignore) {
                    rootDirectory = modelSource.getPath();
                    while (rootDirectory != null && !Files.isDirectory(rootDirectory)) {
                        rootDirectory = rootDirectory.getParent();
                    }
                }
                try (InputStream is = modelSource.openStream()) {
                    model = modelProcessor.read(XmlReaderRequest.builder()
                            .strict(strict)
                            .location(modelSource.getLocation())
                            .path(modelSource.getPath())
                            .rootDirectory(rootDirectory)
                            .inputStream(is)
                            .transformer(new InliningTransformer())
                            .build());
                } catch (XmlReaderException e) {
                    if (!strict) {
                        throw e;
                    }
                    try (InputStream is = modelSource.openStream()) {
                        model = modelProcessor.read(XmlReaderRequest.builder()
                                .strict(false)
                                .location(modelSource.getLocation())
                                .path(modelSource.getPath())
                                .rootDirectory(rootDirectory)
                                .inputStream(is)
                                .transformer(new InliningTransformer())
                                .build());
                    } catch (XmlReaderException ne) {
                        // still unreadable even in non-strict mode, rethrow original error
                        throw e;
                    }

                    add(
                            Severity.ERROR,
                            Version.V20,
                            "Malformed POM " + modelSource.getLocation() + ": " + e.getMessage(),
                            e);
                }

                InputLocation loc = model.getLocation("");
                InputSource v4src = loc != null ? loc.getSource() : null;
                if (v4src != null) {
                    try {
                        Field field = InputSource.class.getDeclaredField("modelId");
                        field.setAccessible(true);
                        field.set(v4src, ModelProblemUtils.toId(model));
                    } catch (Throwable t) {
                        // TODO: use a lazy source ?
                        throw new IllegalStateException("Unable to set modelId on InputSource", t);
                    }
                }
            } catch (XmlReaderException e) {
                add(
                        Severity.FATAL,
                        Version.BASE,
                        "Non-parseable POM " + modelSource.getLocation() + ": " + e.getMessage(),
                        e);
                throw newModelBuilderException();
            } catch (IOException e) {
                String msg = e.getMessage();
                if (msg == null || msg.isEmpty()) {
                    // NOTE: There's java.nio.charset.MalformedInputException and sun.io.MalformedInputException
                    if (e.getClass().getName().endsWith("MalformedInputException")) {
                        msg = "Some input bytes do not match the file encoding.";
                    } else {
                        msg = e.getClass().getSimpleName();
                    }
                }
                add(Severity.FATAL, Version.BASE, "Non-readable POM " + modelSource.getLocation() + ": " + msg, e);
                throw newModelBuilderException();
            }

            if (model.getModelVersion() == null) {
                String namespace = model.getNamespaceUri();
                if (namespace != null && namespace.startsWith(NAMESPACE_PREFIX)) {
                    model = model.withModelVersion(namespace.substring(NAMESPACE_PREFIX.length()));
                }
            }

            if (isBuildRequest()) {
                model = model.withPomFile(modelSource.getPath());

                Parent parent = model.getParent();
                if (parent != null) {
                    String groupId = parent.getGroupId();
                    String artifactId = parent.getArtifactId();
                    String version = parent.getVersion();
                    String path = parent.getRelativePath();
                    if ((groupId == null || artifactId == null || version == null)
                            && (path == null || !path.isEmpty())) {
                        Path pomFile = model.getPomFile();
                        Path relativePath = Paths.get(path != null ? path : "..");
                        Path pomPath = pomFile.resolveSibling(relativePath).normalize();
                        if (Files.isDirectory(pomPath)) {
                            pomPath = modelProcessor.locateExistingPom(pomPath);
                        }
                        if (pomPath != null && Files.isRegularFile(pomPath)) {
                            Model parentModel =
                                    derive(Sources.buildSource(pomPath)).readFileModel();
                            String parentGroupId = getGroupId(parentModel);
                            String parentArtifactId = parentModel.getArtifactId();
                            String parentVersion = getVersion(parentModel);
                            if ((groupId == null || groupId.equals(parentGroupId))
                                    && (artifactId == null || artifactId.equals(parentArtifactId))
                                    && (version == null || version.equals(parentVersion))) {
                                model = model.withParent(parent.with()
                                        .groupId(parentGroupId)
                                        .artifactId(parentArtifactId)
                                        .version(parentVersion)
                                        .build());
                            } else {
                                mismatchRelativePathAndGA(model, parentGroupId, parentArtifactId);
                            }
                        } else {
                            if (!MODEL_VERSION_4_0_0.equals(model.getModelVersion()) && path != null) {
                                wrongParentRelativePath(model);
                            }
                        }
                    }
                }

                // subprojects discovery
                if (getSubprojects(model).isEmpty()
                        // only discover subprojects if POM > 4.0.0
                        && !MODEL_VERSION_4_0_0.equals(model.getModelVersion())
                        // and if packaging is POM (we check type, but the session is not yet available,
                        // we would require the project realm if we want to support extensions
                        && Type.POM.equals(model.getPackaging())) {
                    List<String> subprojects = new ArrayList<>();
                    try (Stream<Path> files = Files.list(model.getProjectDirectory())) {
                        for (Path f : files.toList()) {
                            if (Files.isDirectory(f)) {
                                Path subproject = modelProcessor.locateExistingPom(f);
                                if (subproject != null) {
                                    subprojects.add(f.getFileName().toString());
                                }
                            }
                        }
                        if (!subprojects.isEmpty()) {
                            model = model.withSubprojects(subprojects);
                        }
                    } catch (IOException e) {
                        add(Severity.FATAL, Version.V41, "Error discovering subprojects", e);
                    }
                }

                // CI friendly version
                // All expressions are interpolated using user properties and properties
                // defined on the root project.
                Map<String, String> properties = new HashMap<>();
                if (!Objects.equals(rootDirectory, model.getProjectDirectory())) {
                    Path rootModelPath = modelProcessor.locateExistingPom(rootDirectory);
                    if (rootModelPath != null) {
                        Model rootModel =
                                derive(Sources.buildSource(rootModelPath)).readFileModel();
                        properties.putAll(rootModel.getProperties());
                    }
                } else {
                    properties.putAll(model.getProperties());
                }
                properties.putAll(session.getUserProperties());
                model = model.with()
                        .version(replaceCiFriendlyVersion(properties, model.getVersion()))
                        .parent(
                                model.getParent() != null
                                        ? model.getParent()
                                                .withVersion(replaceCiFriendlyVersion(
                                                        properties,
                                                        model.getParent().getVersion()))
                                        : null)
                        .build();
                // Override model properties with user properties
                Map<String, String> newProps = merge(model.getProperties(), session.getUserProperties());
                if (newProps != null) {
                    model = model.withProperties(newProps);
                }
                model = model.withProfiles(merge(model.getProfiles(), session.getUserProperties()));
            }

            for (var transformer : transformers) {
                model = transformer.transformFileModel(model);
            }

            setSource(model);
            modelValidator.validateFileModel(
                    model,
                    isBuildRequest() ? ModelValidator.VALIDATION_LEVEL_STRICT : ModelValidator.VALIDATION_LEVEL_MINIMAL,
                    this);
            if (hasFatalErrors()) {
                throw newModelBuilderException();
            }

            return model;
        }