1 package org.apache.maven.archetype.common.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.archetype.exception.InvalidPackaging;
23 import org.apache.maven.archetype.old.ArchetypeTemplateProcessingException;
24 import org.w3c.dom.Document;
25 import org.w3c.dom.Element;
26 import org.w3c.dom.Node;
27 import org.w3c.dom.NodeList;
28 import org.xml.sax.InputSource;
29 import org.xml.sax.SAXException;
30
31 import javax.xml.XMLConstants;
32 import javax.xml.parsers.DocumentBuilder;
33 import javax.xml.parsers.DocumentBuilderFactory;
34 import javax.xml.parsers.ParserConfigurationException;
35 import javax.xml.transform.OutputKeys;
36 import javax.xml.transform.Transformer;
37 import javax.xml.transform.TransformerException;
38 import javax.xml.transform.TransformerFactory;
39 import javax.xml.transform.dom.DOMSource;
40 import javax.xml.transform.stream.StreamResult;
41 import java.io.IOException;
42 import java.io.Reader;
43 import java.io.Writer;
44
45
46
47
48 public final class PomUtils
49 {
50 private PomUtils()
51 {
52 throw new IllegalStateException( "no instantiable constructor" );
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public static boolean addNewModule( String artifactId, Reader fileReader, Writer fileWriter )
71 throws ArchetypeTemplateProcessingException, InvalidPackaging, IOException,
72 ParserConfigurationException, SAXException, TransformerException
73 {
74 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
75 dbf.setFeature( "http://apache.org/xml/features/disallow-doctype-decl", true );
76 dbf.setFeature( "http://xml.org/sax/features/external-general-entities", false );
77 dbf.setFeature( "http://xml.org/sax/features/external-parameter-entities", false );
78 dbf.setFeature( "http://apache.org/xml/features/nonvalidating/load-external-dtd", false );
79 dbf.setXIncludeAware( false );
80 dbf.setExpandEntityReferences( false );
81
82 DocumentBuilder db = dbf.newDocumentBuilder();
83 InputSource inputSource = new InputSource();
84 inputSource.setCharacterStream( fileReader );
85 Document document = db.parse( inputSource );
86
87 Element project = document.getDocumentElement();
88 if ( !"project".equals( project.getNodeName() ) )
89 {
90 throw new ArchetypeTemplateProcessingException( "Unable to find root element 'project'." );
91 }
92
93 String packaging = null;
94 NodeList packagingElement = project.getElementsByTagName( "packaging" );
95 if ( packagingElement != null && packagingElement.getLength() == 1 )
96 {
97 packaging = packagingElement.item( 0 ).getTextContent();
98 }
99 if ( !"pom".equals( packaging ) )
100 {
101 throw new InvalidPackaging(
102 "Unable to add module to the current project as it is not of packaging type 'pom'" );
103 }
104
105 Node modules = getModulesNode( project );
106
107 if ( !hasArtifactIdInModules( artifactId, modules ) )
108 {
109 Element module = document.createElement( "module" );
110 module.setTextContent( artifactId );
111 if ( modules == null )
112 {
113 modules = document.createElement( "modules" );
114 project.appendChild( modules );
115 }
116
117
118 modules.appendChild( document.createTextNode( " " ) );
119
120 modules.appendChild( module );
121
122
123 modules.appendChild( document.createTextNode( "\n " ) );
124
125 TransformerFactory tf = TransformerFactory.newInstance();
126 tf.setAttribute( XMLConstants.ACCESS_EXTERNAL_DTD, "" );
127 tf.setAttribute( XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "" );
128
129 tf.setAttribute( "indent-number", 2 );
130 Transformer tr = tf.newTransformer();
131 tr.setOutputProperty( OutputKeys.INDENT, "yes" );
132 tr.setOutputProperty( OutputKeys.METHOD, "xml" );
133 tr.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
134 tr.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "2" );
135 document.getDomConfig().setParameter( "infoset", Boolean.TRUE );
136 document.getDocumentElement().normalize();
137 tr.transform( new DOMSource( document ), new StreamResult( fileWriter ) );
138 return true;
139 }
140 else
141 {
142 return false;
143 }
144 }
145
146 private static Node getModulesNode( Element project )
147 {
148 Node modules = null;
149 NodeList nodes = project.getChildNodes();
150 for ( int len = nodes.getLength(), i = 0; i < len; i++ )
151 {
152 Node node = nodes.item( i );
153 if ( node.getNodeType() == Node.ELEMENT_NODE && "modules".equals( node.getNodeName() ) )
154 {
155 modules = node;
156 break;
157 }
158 }
159 return modules;
160 }
161
162 private static boolean hasArtifactIdInModules( String artifactId, Node modules )
163 {
164 if ( modules != null )
165 {
166 Node module = modules.getFirstChild();
167 while ( module != null )
168 {
169 if ( module.getNodeType() == Node.ELEMENT_NODE && artifactId.equals( module.getTextContent() ) )
170 {
171 return true;
172 }
173 module = module.getNextSibling();
174 }
175 }
176 return false;
177 }
178 }