1 package org.apache.maven.j2ee;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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><servlet></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
276 File tempFile = File.createTempFile("maven", null);
277
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><error-code></code> or <code><
323 * exception-type></code>, the value is <code><location></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><form-login-config></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 }