1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.deployment.impl;
18
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.FileNotFoundException;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.util.Enumeration;
26 import java.util.Iterator;
27 import java.util.jar.JarFile;
28 import java.util.zip.ZipEntry;
29
30 import org.apache.jetspeed.components.portletregistry.PortletRegistry;
31 import org.apache.jetspeed.deployment.DeploymentEvent;
32 import org.apache.jetspeed.deployment.DeploymentException;
33 import org.apache.jetspeed.tools.pamanager.PortletApplicationManagement;
34 import org.jdom.Attribute;
35 import org.jdom.Document;
36 import org.jdom.Element;
37 import org.jdom.JDOMException;
38 import org.jdom.input.SAXBuilder;
39 import org.jdom.output.Format;
40 import org.jdom.output.XMLOutputter;
41 import org.xml.sax.EntityResolver;
42 import org.xml.sax.InputSource;
43 import org.xml.sax.SAXException;
44
45 /***
46 * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
47 * @version $Id: JettyDeployPortletAppEventListener.java 549661 2007-06-22 01:24:32Z ate $
48 */
49 public class JettyDeployPortletAppEventListener extends DeployPortletAppEventListener
50 {
51 private String jettyContextsDir;
52
53 public JettyDeployPortletAppEventListener(PortletApplicationManagement pam, PortletRegistry registry, String webAppDir, String localAppDir, boolean stripLoggers, String jettyContextsDir) throws FileNotFoundException
54 {
55 super(pam, registry, webAppDir, localAppDir, stripLoggers);
56 initJettyContextsDir(jettyContextsDir);
57 }
58
59 public JettyDeployPortletAppEventListener(PortletApplicationManagement pam, PortletRegistry registry, String webAppDir, String localAppDir, String localAppStagingDir, boolean stripLoggers, String jettyContextsDir) throws FileNotFoundException
60 {
61 super(pam, registry, webAppDir, localAppDir, localAppStagingDir, stripLoggers);
62 initJettyContextsDir(jettyContextsDir);
63 }
64
65 private void initJettyContextsDir(String jettyContextsDir) throws FileNotFoundException
66 {
67 File jettyContextsDirFile = new File(jettyContextsDir);
68
69 if (jettyContextsDirFile.exists())
70 {
71 try
72 {
73 this.jettyContextsDir = jettyContextsDirFile.getCanonicalPath();
74 }
75 catch (IOException e) {}
76 }
77 else
78 {
79 throw new FileNotFoundException("The jetty contexts directory \""
80 + jettyContextsDirFile.getAbsolutePath() + "\" does not exist.");
81 }
82 }
83
84 protected void deployPortletApplication(DeploymentEvent event) throws DeploymentException
85 {
86 try
87 {
88 String fileName = event.getName();
89 String filePath = event.getPath();
90 String appName = fileName.substring(0, fileName.length() - 4);
91 Document context = getJettyContext(filePath);
92 File contextFile = getCurrentJettyContextFile(appName);
93 if (contextFile != null)
94 {
95 if (context == null)
96 {
97 context = getCurrentJettyContext(contextFile);
98 }
99 contextFile.delete();
100 }
101 if (context == null)
102 {
103 context = getJettyContextTemplate();
104 }
105 updateJettyContext(appName, new File(getWebAppDir(), fileName).getAbsolutePath(), context);
106 removeCurrentPA(appName);
107 super.deployPortletApplication(event);
108 writeJettyContext(appName,context);
109 }
110 catch (Exception e)
111 {
112 throw new DeploymentException(e);
113 }
114 }
115
116 protected void removeCurrentPA(String contextName) throws IOException
117 {
118 File warFile = new File(getWebAppDir(), contextName + ".war");
119 if (warFile.exists())
120 {
121 warFile.delete();
122 }
123 File warDir = new File(getWebAppDir(), contextName);
124 if (warDir.exists() && warDir.isDirectory())
125 {
126 removeDir(warDir);
127 }
128 }
129
130 protected boolean removeDir(File file)
131 {
132 if (file.isDirectory())
133 {
134 String[] children = file.list();
135 for (int i = 0; i < children.length; i++)
136 {
137 boolean success = removeDir(new File(file, children[i]));
138 if (!success)
139 {
140 return false;
141 }
142 }
143 }
144
145
146 return file.delete();
147 }
148
149 protected File getCurrentJettyContextFile(String contextName) throws IOException
150 {
151 File contextFile = new File(jettyContextsDir, contextName+".xml");
152 if (contextFile.exists())
153 {
154 if (contextFile.isDirectory())
155 {
156 throw new IOException("Cannot deploy application"+contextName+" as there already exists a directory in "+jettyContextsDir+" with the same name");
157 }
158 return contextFile;
159 }
160 return null;
161 }
162
163 protected Document getCurrentJettyContext(File contextFile) throws IOException
164 {
165 InputStream source = null;
166 try
167 {
168 source = new FileInputStream(contextFile);
169 return parseJettyContext(source);
170 }
171 finally
172 {
173 if (source != null)
174 {
175 try
176 {
177 source.close();
178 }
179 catch (IOException e1)
180 {
181
182 }
183 }
184 }
185 }
186
187 protected Document getJettyContextTemplate() throws IOException
188 {
189 InputStream source = null;
190 try
191 {
192 source = getClass().getResourceAsStream("jetty/context-template.xml");
193 return parseJettyContext(source);
194 }
195 finally
196 {
197 if (source != null)
198 {
199 try
200 {
201 source.close();
202 }
203 catch (IOException e1)
204 {
205
206 }
207 }
208 }
209 }
210
211 protected Document getJettyContext(String fileName) throws IOException
212 {
213 JarFile jin = null;
214 InputStream source = null;
215 try
216 {
217 jin = new JarFile(fileName);
218
219 ZipEntry src;
220 Enumeration zipEntries = jin.entries();
221 while (zipEntries.hasMoreElements())
222 {
223 src = (ZipEntry) zipEntries.nextElement();
224 String target = src.getName();
225 if ("META-INF/jetspeed-jetty-context.xml".equals(target))
226 {
227 System.out.println("Found jetspeed-jetty-context.xml");
228 source = jin.getInputStream(src);
229 return parseJettyContext(source);
230 }
231 }
232 return null;
233 }
234 finally
235 {
236 if (source != null)
237 {
238 try
239 {
240 source.close();
241 }
242 catch (IOException e1)
243 {
244
245 }
246 }
247 if (jin != null)
248 {
249 try
250 {
251 jin.close();
252 jin = null;
253 }
254 catch (IOException e1)
255 {
256
257 }
258 }
259 }
260 }
261
262 protected void updateJettyContext(String contextName, String warPath, Document context)
263 {
264 Element root = context.getRootElement();
265 Iterator iter = root.getChildren("Set").iterator();
266 boolean foundSetWar = false;
267 boolean foundSetContextPath = false;
268 boolean foundSetConfigurationClasses = false;
269
270 while (iter.hasNext())
271 {
272 Element set = (Element)iter.next();
273 String name = set.getAttribute("name").getName();
274 if (name.equals("contextPath"))
275 {
276 set.setText("/"+contextName);
277 foundSetContextPath = true;
278 }
279 else if (name.equals("resourceBase"))
280 {
281 iter.remove();
282 }
283 else if (name.equals("war"))
284 {
285 set.setText(warPath);
286 foundSetWar = true;
287 }
288 else if (name.equals("configurationClasses"))
289 {
290 foundSetConfigurationClasses = true;
291 }
292 }
293 if (!foundSetContextPath)
294 {
295 root.addContent(new Element("Set").setAttribute(new Attribute("name", "contextPath")).setText("/"+contextName));
296 }
297 if (!foundSetWar)
298 {
299 root.addContent(new Element("Set").setAttribute(new Attribute("name", "war")).setText(warPath));
300 }
301 if (!foundSetConfigurationClasses)
302 {
303 Element array = new Element("Array").setAttribute(new Attribute("type","java.lang.String"));
304 array.addContent(new Element("Item").setText("org.mortbay.jetty.webapp.WebInfConfiguration"));
305 array.addContent(new Element("Item").setText("org.mortbay.jetty.plus.webapp.EnvConfiguration"));
306 array.addContent(new Element("Item").setText("org.mortbay.jetty.plus.webapp.Configuration"));
307 array.addContent(new Element("Item").setText("org.mortbay.jetty.webapp.JettyWebXmlConfiguration"));
308 array.addContent(new Element("Item").setText("org.mortbay.jetty.webapp.TagLibConfiguration"));
309 root.addContent(new Element("Set").setAttribute(new Attribute("name", "configurationClasses")).setContent(array));
310 }
311 }
312
313 protected void writeJettyContext(String contextName, Document context) throws IOException
314 {
315 File contextFile = new File(jettyContextsDir, contextName+".xml");
316 if (contextFile.exists())
317 {
318 throw new IOException("Jetty context file "+contextFile.getAbsolutePath()+" found.");
319 }
320 FileOutputStream output = null;
321 try
322 {
323 output = new FileOutputStream(contextFile);
324 XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
325 xmlOutputter.output(context, output);
326 }
327 finally
328 {
329 if (output != null)
330 {
331 try
332 {
333 output.close();
334 }
335 catch (IOException e1)
336 {
337
338 }
339 }
340 }
341 }
342
343 protected Document parseJettyContext(InputStream source) throws IOException
344 {
345
346
347 SAXBuilder saxBuilder = new SAXBuilder();
348 saxBuilder.setEntityResolver(new EntityResolver()
349 {
350 public InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId) throws SAXException,
351 java.io.IOException
352 {
353 if (systemId.equals("http://jetty.mortbay.org/configure.dtd"))
354 {
355 return new InputSource(getClass().getResourceAsStream("jetty/configure_6_0.dtd"));
356 }
357 return null;
358 }
359 });
360 try
361 {
362 Document document = saxBuilder.build(source);
363 return document;
364 }
365 catch (JDOMException e)
366 {
367 IOException ioException = new IOException("Parse failure: "+e.getMessage());
368 ioException.fillInStackTrace();
369 throw ioException;
370 }
371 }
372 }