44package com .azure .tools .bomgenerator ;
55
66import com .azure .tools .bomgenerator .models .BomDependency ;
7+ import com .azure .tools .bomgenerator .models .BomDependencyManagement ;
8+ import com .fasterxml .jackson .annotation .JsonInclude ;
9+ import com .fasterxml .jackson .databind .SerializationFeature ;
10+ import com .fasterxml .jackson .dataformat .xml .XmlMapper ;
711import org .apache .maven .model .Dependency ;
812import org .apache .maven .model .DependencyManagement ;
913import org .apache .maven .model .Model ;
10- import org .apache .maven .model .io .xpp3 .MavenXpp3Reader ;
11- import org .apache .maven .model .io .xpp3 .MavenXpp3Writer ;
12- import org .codehaus .plexus .util .xml .pull .XmlPullParserException ;
1314import org .slf4j .Logger ;
1415import org .slf4j .LoggerFactory ;
15-
16+ import org .w3c .dom .Document ;
17+ import org .w3c .dom .Node ;
18+ import org .xml .sax .InputSource ;
19+ import org .xml .sax .SAXException ;
20+
21+ import javax .xml .parsers .DocumentBuilder ;
22+ import javax .xml .parsers .DocumentBuilderFactory ;
23+ import javax .xml .parsers .ParserConfigurationException ;
24+ import javax .xml .transform .OutputKeys ;
25+ import javax .xml .transform .Transformer ;
26+ import javax .xml .transform .TransformerException ;
27+ import javax .xml .transform .TransformerFactory ;
28+ import javax .xml .transform .dom .DOMSource ;
29+ import javax .xml .transform .stream .StreamResult ;
30+ import java .io .File ;
1631import java .io .FileNotFoundException ;
17- import java .io .FileReader ;
1832import java .io .FileWriter ;
1933import java .io .IOException ;
34+ import java .io .StringReader ;
2035import java .nio .file .Files ;
2136import java .nio .file .Path ;
2237import java .nio .file .Paths ;
2944import java .util .stream .Collectors ;
3045
3146import static com .azure .tools .bomgenerator .Utils .ANALYZE_MODE ;
32- import static com .azure .tools .bomgenerator .Utils .BASE_AZURE_GROUPID ;
3347import static com .azure .tools .bomgenerator .Utils .AZURE_PERF_LIBRARY_IDENTIFIER ;
3448import static com .azure .tools .bomgenerator .Utils .AZURE_TEST_LIBRARY_IDENTIFIER ;
49+ import static com .azure .tools .bomgenerator .Utils .BASE_AZURE_GROUPID ;
3550import static com .azure .tools .bomgenerator .Utils .EXCLUSION_LIST ;
3651import static com .azure .tools .bomgenerator .Utils .GENERATE_MODE ;
3752import static com .azure .tools .bomgenerator .Utils .INPUT_DEPENDENCY_PATTERN ;
4055import static com .azure .tools .bomgenerator .Utils .STRING_SPLIT_BY_COLON ;
4156import static com .azure .tools .bomgenerator .Utils .isPublishedArtifact ;
4257import static com .azure .tools .bomgenerator .Utils .parsePomFileContent ;
58+ import static com .azure .tools .bomgenerator .Utils .parsePomFileModel ;
4359import static com .azure .tools .bomgenerator .Utils .toBomDependencyNoVersion ;
4460import static com .azure .tools .bomgenerator .Utils .validateNotNullOrEmpty ;
61+ import static javax .xml .transform .OutputKeys .OMIT_XML_DECLARATION ;
4562
4663public class BomGenerator {
4764 private String outputFileName ;
@@ -137,8 +154,6 @@ private boolean generate() {
137154
138155 // 4. Create the new BOM file.
139156 if (!validationFailed ) {
140- // Rewrite the existing BOM to have the dependencies in the order in which we insert them, making the diff PR easier to review.
141- rewriteExistingBomFile ();
142157 writeBom (outputDependencies );
143158 return true ;
144159 }
@@ -257,28 +272,41 @@ private BomDependency scanDependency(String line) {
257272 }
258273
259274 private Model readModel () {
260- MavenXpp3Reader reader = new MavenXpp3Reader ();
261- try {
262- Model model = reader .read (new FileReader (this .pomFileName ));
263- return model ;
264- } catch (XmlPullParserException | IOException e ) {
265- logger .error ("BOM reading failed with: {}" , e .toString ());
266- }
267-
268- return null ;
269- }
270-
271- private void writeModel (Model model ) {
272- String pomFileName = this .pomFileName ;
273- writeModel (pomFileName , model );
275+ return parsePomFileModel (this .pomFileName , Model .class );
274276 }
275277
276- private void writeModel (String fileName , Model model ) {
277- MavenXpp3Writer writer = new MavenXpp3Writer ();
278+ private void writeModel (String inputFileName , String outputFileName , Model model ) {
279+ // First read the pom file.
278280 try {
279- writer .write (new FileWriter (fileName ), model );
280- } catch (IOException exception ) {
281- logger .error ("BOM writing failed with: {}" , exception .toString ());
281+ DocumentBuilder db = DocumentBuilderFactory .newInstance ().newDocumentBuilder ();
282+ Document oldBomDoc = db .parse (new File (inputFileName ));
283+ Node oldDependencyManagementNode = oldBomDoc .getElementsByTagName ("dependencyManagement" ).item (0 );
284+ Node parentNode = oldDependencyManagementNode .getParentNode ();
285+
286+ // Now add the other node to this list.
287+ XmlMapper mapper = new XmlMapper ();
288+ mapper .setSerializationInclusion (JsonInclude .Include .NON_NULL );
289+ mapper .configure (SerializationFeature .INDENT_OUTPUT , true );
290+ BomDependencyManagement dependencyManagement = new BomDependencyManagement (model .getDependencyManagement ().getDependencies ());
291+ String dependencies = mapper .writeValueAsString (dependencyManagement );
292+ DocumentBuilder newBomDoc = DocumentBuilderFactory .newInstance ().newDocumentBuilder ();
293+ Document newDependencies = newBomDoc .parse (new InputSource (new StringReader (dependencies )));
294+ Node newDependencyManagementNode = newDependencies .getElementsByTagName ("dependencyManagement" ).item (0 );
295+ Node firstDocImportedDependencyManagementNode = oldBomDoc .importNode (newDependencyManagementNode , true );
296+ parentNode .replaceChild (firstDocImportedDependencyManagementNode , oldDependencyManagementNode );
297+
298+ // Use a Transformer for output
299+ TransformerFactory tFactory = TransformerFactory .newInstance ();
300+ Transformer transformer = tFactory .newTransformer ();
301+ transformer .setOutputProperty (OMIT_XML_DECLARATION , "yes" );
302+ transformer .setOutputProperty (OutputKeys .INDENT , "no" );
303+ DOMSource source = new DOMSource (oldBomDoc );
304+ FileWriter writer = new FileWriter (outputFileName );
305+ StreamResult result = new StreamResult (writer );
306+ transformer .transform (source , result );
307+
308+ } catch (IOException | ParserConfigurationException | SAXException | TransformerException e ) {
309+ e .printStackTrace ();
282310 }
283311 }
284312
@@ -295,15 +323,6 @@ private List<Dependency> getExternalDependencies() {
295323 return management .getDependencies ().stream ().filter (dependency -> dependency .getType ().equals (POM_TYPE )).collect (Collectors .toList ());
296324 }
297325
298- private void rewriteExistingBomFile () {
299- Model model = readModel ();
300- DependencyManagement management = model .getDependencyManagement ();
301- List <Dependency > dependencies = management .getDependencies ();
302- dependencies .sort (new DependencyComparator ());
303- management .setDependencies (dependencies );
304- writeModel (model );
305- }
306-
307326 private void writeBom (Collection <BomDependency > bomDependencies ) {
308327 Model model = readModel ();
309328 DependencyManagement management = model .getDependencyManagement ();
@@ -318,6 +337,6 @@ private void writeBom(Collection<BomDependency> bomDependencies) {
318337 dependencies .addAll (externalBomDependencies );
319338 dependencies .sort (new DependencyComparator ());
320339 management .setDependencies (dependencies );
321- writeModel (this .outputFileName , model );
340+ writeModel (this .pomFileName , this . outputFileName , model );
322341 }
323342}
0 commit comments