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 |
|
|
47 |
|
|
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 |
0 |
public InputSource resolveEntity(java.lang.String class="keyword">publicId, java.lang.String systemId) throws SAXException, |
351 |
|
java.io.IOException |
352 |
|
{ |
353 |
0 |
if (systemId.equals("http://jetty.mortbay.org/configure.dtd")) |
354 |
|
{ |
355 |
0 |
return new InputSource(getClass().getResourceAsStream("jetty/configure_6_0.dtd")); |
356 |
|
} |
357 |
0 |
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 |
|
} |