1 package org.codehaus.mojo.gwt.webxml;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.Writer;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.Iterator;
28 import java.util.List;
29
30 import org.codehaus.plexus.util.WriterFactory;
31 import org.jdom.Comment;
32 import org.jdom.Content;
33 import org.jdom.Document;
34 import org.jdom.Element;
35 import org.jdom.JDOMException;
36 import org.jdom.Namespace;
37 import org.jdom.input.SAXBuilder;
38 import org.jdom.output.Format;
39 import org.jdom.output.XMLOutputter;
40 import org.jdom.xpath.XPath;
41
42
43
44
45 public class GwtWebInfProcessor
46 {
47 private static final String[] BEFORE_SERVLETS =
48 { "icon", "display-name", "description", "distributable", "context-param", "filter", "filter-mapping",
49 "listener", "servlet" };
50
51 private static final String[] AFTER_SERVLETS =
52 { "servlet-mapping", "session-config", "mime-mapping", "welcome-file-list", "error-page", "taglib",
53 "resource-env-ref", "resource-ref", "security-constraint", "login-config", "security-role", "env-entry",
54 "ejb-ref", "ejb-local-ref" };
55
56 private static final String[] BEFORE_MAPPINGS =
57 { "icon", "display-name", "description", "distributable", "context-param", "filter", "filter-mapping",
58 "listener", "servlet", "servlet-mapping" };
59
60 private static final String[] AFTER_MAPPINGS =
61 { "session-config", "mime-mapping", "welcome-file-list", "error-page", "taglib", "resource-env-ref",
62 "resource-ref", "security-constraint", "login-config", "security-role", "env-entry", "ejb-ref",
63 "ejb-local-ref" };
64
65 public void process( File webXml, Collection<ServletDescriptor> servletDescriptors )
66 throws Exception
67 {
68 process( webXml, webXml, servletDescriptors );
69 }
70
71 public void process( File sourceWebXml, File mergeWebXml, Collection<ServletDescriptor> servletDescriptors )
72 throws Exception
73 {
74 Document dom = insertServlets( sourceWebXml, servletDescriptors );
75 XMLOutputter xmlOut = new XMLOutputter( Format.getPrettyFormat() );
76 Writer writer = WriterFactory.newXmlWriter( mergeWebXml );
77 xmlOut.output( dom, writer );
78 writer.flush();
79 writer.close();
80 }
81
82 private Document insertServlets( File webXml, Collection<ServletDescriptor> servletDescriptors )
83 throws JDOMException, IOException
84 {
85
86
87
88
89
90
91 Document dom = getWebXmlAsDocument( webXml );
92 Element webapp = dom.getRootElement();
93 Namespace ns = webapp.getNamespace();
94
95 int insertAfter = getInsertPosition( webapp, BEFORE_SERVLETS, AFTER_SERVLETS );
96 for ( Iterator<ServletDescriptor> it = servletDescriptors.iterator(); it.hasNext(); )
97 {
98 ServletDescriptor d = it.next();
99 XPath path = XPath.newInstance( "/web-app/servlet/servlet-name[text() = '" + d.getName() + "']" );
100 if ( path.selectNodes( dom ).size() > 0 )
101 {
102
103 it.remove();
104 continue;
105 }
106
107 insertAfter++;
108 Element servlet = new Element( "servlet", ns );
109 Element servletName = new Element( "servlet-name", ns );
110 servletName.setText( d.getName() );
111 servlet.addContent( servletName );
112 Element servletClass = new Element( "servlet-class", ns );
113 servletClass.setText( d.getClassName() );
114 servlet.addContent( servletClass );
115 webapp.addContent( insertAfter, servlet );
116 }
117 insertAfter = getInsertPosition( webapp, BEFORE_MAPPINGS, AFTER_MAPPINGS );
118 for ( ServletDescriptor d : servletDescriptors )
119 {
120 insertAfter++;
121 Element servletMapping = new Element( "servlet-mapping", ns );
122 Element servletName = new Element( "servlet-name", ns );
123 servletName.setText( d.getName() );
124 servletMapping.addContent( servletName );
125 Element urlPattern = new Element( "url-pattern", ns );
126 String path = d.getPath();
127 if ( path.charAt( 0 ) != '/' )
128 {
129 path = '/' + path;
130 }
131 urlPattern.setText( path );
132 servletMapping.addContent( urlPattern );
133 webapp.addContent( insertAfter, servletMapping );
134 }
135 return dom;
136 }
137
138 private int getInsertPosition( Element webapp, String[] startAfter, String[] stopBefore )
139 throws JDOMException, IOException
140 {
141 List children = webapp.getContent();
142 Content insertAfter = new Comment( "inserted by gwt-maven-plugin" );
143
144 ArrayList<String> namesBefore = new ArrayList<String>();
145 ArrayList<String> namesAfter = new ArrayList<String>();
146
147 for ( int i = 0; i < startAfter.length; i++ )
148 {
149 namesBefore.add( startAfter[i] );
150 }
151
152 for ( int i = 0; i < stopBefore.length; i++ )
153 {
154 namesAfter.add( stopBefore[i] );
155 }
156
157 if ( ( children == null ) || ( children.size() == 0 ) )
158 {
159 webapp.addContent( insertAfter );
160 }
161 else
162 {
163 boolean foundPoint = false;
164 for ( int i = 0; !foundPoint && i < children.size(); i++ )
165 {
166 Object o = children.get( i );
167 if ( !( o instanceof Element ) )
168 {
169 continue;
170 }
171
172 Element child = (Element) o;
173
174 if ( namesAfter.contains( child.getName() ) )
175 {
176 webapp.addContent( i, insertAfter );
177 foundPoint = true;
178 break;
179 }
180
181 if ( !namesBefore.contains( child.getName() ) )
182 {
183 webapp.addContent( i + 1, insertAfter );
184 foundPoint = true;
185 break;
186 }
187 }
188 if ( !foundPoint )
189 {
190 webapp.addContent( insertAfter );
191 }
192 }
193
194 return webapp.indexOf( insertAfter );
195 }
196
197 private Document getWebXmlAsDocument( File webXml )
198 throws JDOMException, IOException
199 {
200 SAXBuilder builder = new SAXBuilder( false );
201 builder.setFeature( "http://apache.org/xml/features/nonvalidating/load-external-dtd", false );
202 return builder.build( webXml.toURI().toURL() );
203 }
204 }