View Javadoc

1   package org.apache.maven.j2ee;
2   
3   /* ====================================================================
4    *   Copyright 2001-2004 The Apache Software Foundation.
5    *
6    *   Licensed under the Apache License, Version 2.0 (the "License");
7    *   you may not use this file except in compliance with the License.
8    *   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, software
13   *   distributed under the License is distributed on an "AS IS" BASIS,
14   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *   See the License for the specific language governing permissions and
16   *   limitations under the License.
17   * ====================================================================
18   */
19  
20  import java.io.BufferedInputStream;
21  import java.io.BufferedOutputStream;
22  import java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.util.Enumeration;
27  import java.util.HashMap;
28  import java.util.HashSet;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Set;
33  import java.util.jar.JarEntry;
34  import java.util.jar.JarFile;
35  
36  import org.apache.maven.j2ee.war.FormLoginConfig;
37  
38  import org.dom4j.Document;
39  import org.dom4j.DocumentException;
40  import org.dom4j.Node;
41  import org.dom4j.io.SAXReader;
42  
43  /**
44   * Represents a J2EE War File
45   *
46   * @author <a href="mailto:dion@multitask.com.au">dIon Gillard</a>
47   * @version $Id: WarFile.java 170200 2005-05-15 06:24:19Z brett $
48   */
49  public class WarFile extends JarFile
50  {
51  
52      /** web.xml entry in the war */
53      public static final String WEB_XML = "WEB-INF/web.xml";
54      /** lib entry in the war for jar files */
55      public static final String LIB = "WEB-INF/lib/";
56      
57      /** 
58       * Creates a new instance of WarFile
59       * 
60       * @param name the {@link File file} name of a war file
61       * @throws IOException when an I/O error occurs
62       */
63      public WarFile(String name) throws IOException
64      {
65          super(name);
66      }
67      
68      /** 
69       * Creates a new instance of WarFile
70       * 
71       * @param name the {@link File file} name of a war file
72       * @param verify whether or not to verify the war file if it is signed
73       * @throws IOException when an I/O error occurs
74       */
75      public WarFile(String name, boolean verify) throws IOException
76      {
77          super(name, verify);
78      }
79      
80      /** 
81       * Creates a new instance of WarFile
82       * 
83       * @param warFile a J2EE .war {@link File file}
84       * @throws IOException when an I/O error occurs
85       */
86      public WarFile(File warFile) throws IOException
87      {
88          super(warFile);
89      }
90  
91      /** 
92       * Creates a new instance of WarFile
93       * 
94       * @param warFile a J2EE .war {@link File file}
95       * @param verify whether or not to verify the war file if it is signed
96       * @throws IOException when an I/O error occurs
97       */
98      public WarFile(File warFile, boolean verify) throws IOException
99      {
100         super(warFile, verify);
101     }
102 
103     /** 
104      * Creates a new instance of WarFile
105      * 
106      * @param warFile a J2EE .war {@link File file}
107      * @param verify whether or not to verify the war file if it is signed
108      * @param mode the mode in which the file is to be opened
109      * @throws IOException when an I/O error occurs
110      */
111     public WarFile(File warFile, boolean verify, int mode) throws IOException
112     {
113         super(warFile, verify, mode);
114     }
115 
116     /**
117      * Retrieves the WEB-INF/web.xml entry if it exists.
118      * 
119      * @return a {@link JarEntry} for web.xml
120      */
121     public JarEntry getWebXmlEntry()
122     {
123         return getJarEntry(WarFile.WEB_XML);
124     }
125     
126     /**
127      * Get a map of servlet name -> servlet class. The map has a size of zero
128      * if there are no servlets or no web.xml in the war.
129      * 
130      * @return a map of servlets held in the war.
131      * @throws IOException if there are problems reading from the war
132      */
133     public Map getServlets() throws IOException
134     {
135         Map servlets = new HashMap();
136         if (getWebXmlEntry() != null)
137         {
138             Document webXml = getWebXml();
139             List servletNodes = webXml.selectNodes("//servlet");
140             Node node = null;
141             for (Iterator nodes = servletNodes.iterator(); nodes.hasNext();)
142             {
143                 node = (Node) nodes.next();
144                 String servletName = node.selectSingleNode("./servlet-name")
145                     .getText();
146                 Node servletClass = node.selectSingleNode("./servlet-class");
147                 if (servletClass != null)
148                 {
149                     servlets.put(servletName, servletClass.getText());
150                 }
151             }
152         }
153         return servlets;
154     }
155 
156     /**
157      * Get a map of servlet name -> jsp file. The map has a size of zero
158      * if there are no jsp files defined or no web.xml in the war.
159      * 
160      * @return a map of jsps defined using the <code>&lt;servlet&gt;</code> tag
161      *      held in the war.
162      * @throws IOException if there are problems reading from the war
163      */
164     public Map getJSPs() throws IOException
165     {
166         Map jsps = new HashMap();
167         if (getWebXmlEntry() != null)
168         {
169             Document webXml = getWebXml();
170             List servletNodes = webXml.selectNodes("//servlet");
171             Node node = null;
172             for (Iterator nodes = servletNodes.iterator(); nodes.hasNext();)
173             {
174                 node = (Node) nodes.next();
175                 String servletName = node.selectSingleNode("./servlet-name")
176                     .getText();
177                 Node jspFile = node.selectSingleNode("./jsp-file");
178                 if (jspFile != null)
179                 {
180                     jsps.put(servletName, jspFile.getText());
181                 }
182             }
183         }
184 
185         return jsps;
186     }
187     
188     /** 
189      * Get a map of taglib-uri -> taglib-location. The map has zero size
190      * if there are no taglibs defined or no web.xml in the war
191      * 
192      * @return a map of uri to location
193      * @throws IOException when an I/O error occurs reading the war
194      */
195     public Map getTaglibs() throws IOException
196     {
197         Map taglibs = new HashMap();
198         if (getWebXmlEntry() != null)
199         {
200             Document webXml = getWebXml();
201             List taglibNodes = webXml.selectNodes("//taglib");
202             Node node = null;
203             for (Iterator nodes = taglibNodes.iterator(); nodes.hasNext();)
204             {
205                 node = (Node) nodes.next();
206                 String taglibUri = node.selectSingleNode("./taglib-uri")
207                     .getText();
208                 String taglibLocation = node.selectSingleNode(
209                     "./taglib-location").getText();
210                 taglibs.put(taglibUri, taglibLocation);
211             }
212         }
213         return taglibs;
214     }
215     
216     /**
217      * Get the web.xml back as a dom4j Document, for easier processing
218      * 
219      * @return a {@link Document} representing the web.xml
220      * @throws IOException if there are any issues reading the web.xml
221      * or producing the xml document
222      */
223     protected Document getWebXml() throws IOException
224     {
225         if (getWebXmlEntry() == null)
226         {
227             throw new IOException("Attempted to get non-existent web.xml");
228         }
229         try 
230         {
231             SAXReader xmlReader = new SAXReader(false);
232             xmlReader.setEntityResolver(new J2EEEntityResolver());
233             InputStream webXmlStream = getInputStream(getWebXmlEntry());
234             Document webXml = xmlReader.read(webXmlStream);
235             return webXml;
236         }
237         catch (DocumentException de)
238         {
239             de.printStackTrace();
240             throw new IOException(de.getMessage());
241         }
242     }
243     
244     /**
245      * Provide a set of jar files as found in WEB-INF/lib
246      * 
247      * @return a set of jar files as {@link JarEntry entries} from WEB-INF/lib
248      */
249     public Set getLibEntries()
250     {
251         Set libs = new HashSet();
252         Enumeration entries = entries();
253         JarEntry entry = null;
254         while (entries.hasMoreElements())
255         {
256             entry = (JarEntry) entries.nextElement();
257             if (entry.getName().startsWith("WEB-INF/lib/")
258                 && entry.getName().toLowerCase().endsWith(".jar"))
259             { 
260                 libs.add(entry);
261             }
262         }
263         return libs;
264     }
265     
266     /**
267      * Extract the given {@link JarEntry entry} to a temporary file
268      * 
269      * @param entry a previously retrieved entry from the jar file
270      * @return the {@link File} created 
271      * @throws IOException when an I/O error occurs reading the war
272      */
273     public File extract(JarEntry entry) throws IOException
274     {
275         // expand to temp dir and add to list
276         File tempFile = File.createTempFile("maven", null);
277         // read from jar and write to the tempJar file
278         BufferedInputStream inStream = new BufferedInputStream(getInputStream(
279             entry));
280         BufferedOutputStream outStream = new BufferedOutputStream(
281             new FileOutputStream(tempFile));
282         int status = -1;
283         while ((status = inStream.read()) != -1)
284         {
285             outStream.write(status);
286         }
287         outStream.close();
288         inStream.close();
289         
290         return tempFile;
291     }
292     
293     /**
294      * Tests whether a 'file' exists in the war. A file in this case is
295      * a jar entry prefixed with a '/'. e.g. the file /WEB-INF/web.xml  is
296      * the same as the jar entry WEB-INF/web.xml
297      * 
298      * @param fileName an entry in the war to be searched for
299      * @return whether the entry exists
300      */
301     public boolean hasFile(String fileName)
302     {
303         if (fileName == null)
304         {
305             throw new NullPointerException("fileName parameter can't be null");
306         }
307         
308         String entryName = null;
309         if (fileName.startsWith("/"))
310         {
311             entryName = fileName.substring(1);
312             return getJarEntry(entryName) != null;
313         }
314         else
315         {
316             return false;
317         }
318     }
319     
320     /**
321      * Get a map of error pages to error locations. The key of the map is
322      * either the <code>&lt;error-code&gt;</code> or <code>&lt;
323      * exception-type&gt;</code>, the value is <code>&lt;location&gt;</code>.
324      * 
325      * @return a map of error page to error location
326      * @throws IOException if there are problems reading from the war
327      */
328     public Map getErrorPages() throws IOException
329     {
330         Map errorPages = new HashMap();
331         if (getWebXmlEntry() != null)
332         {
333             Document webXml = getWebXml();
334             List errorNodes = webXml.selectNodes("//error-page");
335             Node node = null;
336             for (Iterator nodes = errorNodes.iterator(); nodes.hasNext();)
337             {
338                 node = (Node) nodes.next();
339                 Node errorCodeNode = node.selectSingleNode("./error-code");
340                 Node exceptionTypeNode = node.selectSingleNode(
341                     "./exception-type");
342                 String location = node.selectSingleNode("./location").getText();
343                 String key = null;
344                 if (errorCodeNode == null)
345                 {
346                     key = exceptionTypeNode.getText();
347                 }
348                 else
349                 {
350                     key = errorCodeNode.getText();
351                 }
352                 errorPages.put(key, location);
353             }
354         }
355         return errorPages;
356     }
357     
358     /**
359      * Get the <code>&lt;form-login-config&gt</code> details specified in the
360      * war file, or null if the element is not present
361      * 
362      * @return a {@link FormLoginConfig} with the login and error pages
363      * @throws IOException if there are problems reading from the war
364      */
365     public FormLoginConfig getFormLoginConfig() throws IOException 
366     {
367         FormLoginConfig config = null;
368         if (getWebXmlEntry() != null)
369         {
370             Document webXml = getWebXml();
371             Node formLoginConfigNode = webXml.selectSingleNode(
372                 "//form-login-config");
373             if (formLoginConfigNode != null) 
374             {
375                 String login = formLoginConfigNode.selectSingleNode(
376                     "./form-login-page").getText();
377                 String error = formLoginConfigNode.selectSingleNode(
378                     "./form-error-page").getText();
379                 config = new FormLoginConfig(login, error);
380             }
381         }
382         return config;
383     }
384     
385     /** 
386      * Get a map of servlet name -> url pattern for all defined servlets
387      *
388      * @return a map as specified
389      * @throws IOException if there are problems reading from the war
390      */
391     public Map getServletMappings() throws IOException
392     {
393         Map mappings = new HashMap();
394         
395         if (getWebXmlEntry() != null)
396         {
397             Document webXml = getWebXml();
398             List nodes = webXml.selectNodes("/web-app/servlet-mapping");
399             Node node = null;
400             for (int nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++)
401             {
402                 node = (Node) nodes.get(nodeIndex);
403                 String servletName = node.valueOf("./servlet-name");
404                 String urlPattern = node.valueOf("./url-pattern");
405                 mappings.put(servletName, urlPattern);
406             }
407         }
408         return mappings;
409     }
410 }