View Javadoc
1   package org.codehaus.mojo.gwt.webxml;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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   * @version $Id$
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           * <!ELEMENT web-app (icon?, display-name?, description?, distributable?, context-param*, filter*,
87           * filter-mapping*, listener*, servlet*, servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?,
88           * error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*, login-config?, security-role*,
89           * env-entry*, ejb-ref*, ejb-local-ref*)>
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                 // Allready declared in target web.xml
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 }