View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.internal.impl.model;
20  
21  import java.util.Collection;
22  import java.util.EnumSet;
23  import java.util.List;
24  import java.util.Set;
25  
26  import org.apache.maven.api.model.InputLocation;
27  import org.apache.maven.api.model.Model;
28  import org.apache.maven.api.services.BuilderProblem;
29  import org.apache.maven.api.services.ModelBuilderException;
30  import org.apache.maven.api.services.ModelBuilderResult;
31  import org.apache.maven.api.services.ModelProblem;
32  import org.apache.maven.api.services.ModelProblemCollector;
33  import org.apache.maven.api.spi.ModelParserException;
34  
35  /**
36   * Collects problems that are encountered during model building. The primary purpose of this component is to account for
37   * the fact that the problem reporter has/should not have information about the calling context and hence cannot provide
38   * an expressive source hint for the model problem. Instead, the source hint is configured by the model builder before
39   * it delegates to other components that potentially encounter problems. Then, the problem reporter can focus on
40   * providing a simple error message, leaving the donkey work of creating a nice model problem to this component.
41   *
42   */
43  class DefaultModelProblemCollector implements ModelProblemCollector {
44  
45      private final ModelBuilderResult result;
46  
47      private List<ModelProblem> problems;
48  
49      private String source;
50  
51      private Model sourceModel;
52  
53      private Model rootModel;
54  
55      private Set<ModelProblem.Severity> severities = EnumSet.noneOf(ModelProblem.Severity.class);
56  
57      DefaultModelProblemCollector(ModelBuilderResult result) {
58          this.result = result;
59          this.problems = result.getProblems();
60  
61          for (ModelProblem problem : this.problems) {
62              severities.add(problem.getSeverity());
63          }
64      }
65  
66      public boolean hasFatalErrors() {
67          return severities.contains(ModelProblem.Severity.FATAL);
68      }
69  
70      public boolean hasErrors() {
71          return severities.contains(ModelProblem.Severity.ERROR) || severities.contains(ModelProblem.Severity.FATAL);
72      }
73  
74      @Override
75      public List<ModelProblem> getProblems() {
76          return problems;
77      }
78  
79      public void setSource(String source) {
80          this.source = source;
81          this.sourceModel = null;
82      }
83  
84      public void setSource(Model source) {
85          this.sourceModel = source;
86          this.source = null;
87  
88          if (rootModel == null) {
89              rootModel = source;
90          }
91      }
92  
93      private String getSource() {
94          if (source == null && sourceModel != null) {
95              source = ModelProblemUtils.toPath(sourceModel);
96          }
97          return source;
98      }
99  
100     private String getModelId() {
101         return ModelProblemUtils.toId(sourceModel);
102     }
103 
104     public void setRootModel(Model rootModel) {
105         this.rootModel = rootModel;
106     }
107 
108     public Model getRootModel() {
109         return rootModel;
110     }
111 
112     public String getRootModelId() {
113         return ModelProblemUtils.toId(rootModel);
114     }
115 
116     @Override
117     public void add(ModelProblem problem) {
118         problems.add(problem);
119 
120         severities.add(problem.getSeverity());
121     }
122 
123     public void addAll(Collection<ModelProblem> problems) {
124         this.problems.addAll(problems);
125 
126         for (ModelProblem problem : problems) {
127             severities.add(problem.getSeverity());
128         }
129     }
130 
131     @Override
132     public void add(BuilderProblem.Severity severity, ModelProblem.Version version, String message) {
133         add(severity, version, message, null, null);
134     }
135 
136     @Override
137     public void add(
138             BuilderProblem.Severity severity, ModelProblem.Version version, String message, InputLocation location) {
139         add(severity, version, message, location, null);
140     }
141 
142     @Override
143     public void add(
144             BuilderProblem.Severity severity, ModelProblem.Version version, String message, Exception exception) {
145         add(severity, version, message, null, exception);
146     }
147 
148     public void add(
149             BuilderProblem.Severity severity,
150             ModelProblem.Version version,
151             String message,
152             InputLocation location,
153             Exception exception) {
154         int line = -1;
155         int column = -1;
156         String source = null;
157         String modelId = null;
158 
159         if (location != null) {
160             line = location.getLineNumber();
161             column = location.getColumnNumber();
162             if (location.getSource() != null) {
163                 modelId = location.getSource().getModelId();
164                 source = location.getSource().getLocation();
165             }
166         }
167 
168         if (modelId == null) {
169             modelId = getModelId();
170             source = getSource();
171         }
172 
173         if (line <= 0 && column <= 0 && exception instanceof ModelParserException e) {
174             line = e.getLineNumber();
175             column = e.getColumnNumber();
176         }
177 
178         ModelProblem problem =
179                 new DefaultModelProblem(message, severity, version, source, line, column, modelId, exception);
180 
181         add(problem);
182     }
183 
184     public ModelBuilderException newModelBuilderException() {
185         ModelBuilderResult result = this.result;
186         if (result.getModelIds().isEmpty()) {
187             DefaultModelBuilderResult tmp = new DefaultModelBuilderResult();
188             tmp.setEffectiveModel(result.getEffectiveModel());
189             tmp.setProblems(getProblems());
190             tmp.setActiveExternalProfiles(result.getActiveExternalProfiles());
191             String id = getRootModelId();
192             tmp.addModelId(id);
193             tmp.setRawModel(id, getRootModel());
194             result = tmp;
195         }
196         return new ModelBuilderException(result);
197     }
198 }