KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cactus > integration > ant > container > jboss > JBoss3xContainer


1 /*
2  * ========================================================================
3  *
4  * Copyright 2003-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 package org.apache.cactus.integration.ant.container.jboss;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.StringReader JavaDoc;
25 import java.util.jar.Attributes JavaDoc;
26 import java.util.jar.JarFile JavaDoc;
27 import java.util.jar.Manifest JavaDoc;
28 import java.util.zip.ZipEntry JavaDoc;
29
30 import javax.xml.parsers.DocumentBuilder JavaDoc;
31 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
32 import javax.xml.parsers.ParserConfigurationException JavaDoc;
33
34 import org.apache.cactus.integration.ant.container.AbstractJavaContainer;
35 import org.apache.tools.ant.BuildException;
36 import org.apache.tools.ant.taskdefs.Copy;
37 import org.apache.tools.ant.taskdefs.Java;
38 import org.apache.tools.ant.types.FileSet;
39 import org.apache.tools.ant.types.Path;
40 import org.apache.tools.ant.util.FileUtils;
41 import org.w3c.dom.Document JavaDoc;
42 import org.w3c.dom.Element JavaDoc;
43 import org.w3c.dom.Node JavaDoc;
44 import org.xml.sax.EntityResolver JavaDoc;
45 import org.xml.sax.InputSource JavaDoc;
46 import org.xml.sax.SAXException JavaDoc;
47
48 /**
49  * Special container support for the JBoss application server.
50  *
51  * @version $Id: JBoss3xContainer.java,v 1.18 2004/06/20 14:04:12 vmassol Exp $
52  */

53 public class JBoss3xContainer extends AbstractJavaContainer
54 {
55     // Instance Variables ------------------------------------------------------
56

57     /**
58      * The JBoss 3.x installation directory.
59      */

60     private File JavaDoc dir;
61
62     /**
63      * The name of the server configuration to use for running the tests.
64      */

65     private String JavaDoc config = "default";
66
67     /**
68      * The location of a directory where to find the JBoss server
69      * configurations.
70      */

71     private File JavaDoc configDir;
72     
73     /**
74      * The port to which the container should be bound.
75      */

76     private int port = 8080;
77
78     /**
79      * The server JNDI Port (used during shutdown)
80      */

81     private int jndiPort = 1099;
82     
83     /**
84      * The JBoss version detected by reading the Manifest file in the
85      * installation directory.
86      */

87     private String JavaDoc version;
88
89     /**
90      * The context root of the tested application.
91      */

92     private String JavaDoc testContextRoot;
93
94     /**
95      * The temporary directory from which the container will be started.
96      */

97     private File JavaDoc tmpDir;
98     
99     // Public Methods ----------------------------------------------------------
100

101     /**
102      * Sets the JBoss installation directory.
103      *
104      * @param theDir The directory to set
105      * @throws BuildException If the specified directory doesn't contain a valid
106      * JBoss 3.x installation
107      */

108     public final void setDir(File JavaDoc theDir) throws BuildException
109     {
110         this.dir = theDir;
111     }
112
113     /**
114      * Sets the name of the server configuration to use for running the tests.
115      *
116      * @param theConfig The configuration name
117      */

118     public final void setConfig(String JavaDoc theConfig)
119     {
120         this.config = theConfig;
121     }
122
123     /**
124      * Sets the location of the server configuration directory.
125      *
126      * @param theConfigDir The configuration directory
127      */

128     public final void setConfigDir(File JavaDoc theConfigDir)
129     {
130         this.configDir = theConfigDir;
131     }
132     
133     /**
134      * Sets the port that will be used to poll the server to verify if
135      * it is started. This is needed for the use case where the user
136      * has defined his own JBoss configuration by using the
137      * {@link #setConfig(String)} call and has defined a port other
138      * than the default one.
139      *
140      * Note: This value is not yet used to set the port
141      * to which the container will listen to. The reason is that this is
142      * hard to implement with JBoss and nobody had the courage to implement
143      * it yet...
144      *
145      * @param thePort The port to set
146      */

147     public final void setPort(int thePort)
148     {
149         this.port = thePort;
150     }
151
152     /**
153      * Specify the JNDI port to use.
154      *
155      * @param theJndiPort The JNDI port
156      */

157     public final void setJndiPort(int theJndiPort)
158     {
159         this.jndiPort = theJndiPort;
160     }
161
162     /**
163      * Sets the temporary directory from which the container is run.
164      *
165      * @param theTmpDir The temporary directory to set
166      */

167     public final void setTmpDir(File JavaDoc theTmpDir)
168     {
169         this.tmpDir = theTmpDir;
170     }
171     
172     // Container Implementation ------------------------------------------------
173

174     /**
175      * @see AbstractJavaContainer#getTestContext()
176      */

177     public String JavaDoc getTestContext()
178     {
179         return this.testContextRoot;
180     }
181     
182     /**
183      * @see AbstractJavaContainer#getName()
184      */

185     public final String JavaDoc getName()
186     {
187         return "JBoss " + this.version;
188     }
189
190     /**
191      * @see AbstractJavaContainer#getPort()
192      */

193     public final int getPort()
194     {
195         return this.port;
196     }
197
198     /**
199      * Returns the server JNDI port.
200      *
201      * @return The JNDI port
202      */

203     public final int getJndiPort()
204     {
205         return this.jndiPort;
206     }
207
208     /**
209      * @return The temporary directory from which the container will be
210      * started.
211      */

212     protected final File JavaDoc getTmpDir()
213     {
214         return this.tmpDir;
215     }
216
217     /**
218      * @see AbstractJavaContainer#init()
219      */

220     public final void init()
221     {
222         // Verify the installation directory
223
this.version = getVersion(this.dir);
224         if (this.version == null)
225         {
226             throw new BuildException(this.dir
227                 + " not recognized as a JBoss 3.x installation");
228         }
229         if (!this.version.startsWith("3"))
230         {
231             throw new BuildException(
232                 "This element doesn't support version " + this.version
233                 + " of JBoss");
234         }
235
236         // Try to infer the test root context from the JBoss specific
237
// <code>jboss-web.xml</code> file.
238
this.testContextRoot = getTestContextFromJBossWebXml();
239         
240         // TODO: as long as we don't have a way to set the port on the JBoss
241
// instance, we'll at least need to extract the port from a config file
242
// in the installation directory
243
}
244
245     /**
246      * @see AbstractJavaContainer#startUp()
247      */

248     public final void startUp()
249     {
250         try
251         {
252             // TODO: It seems JBoss 3.2.x does not support server
253
// configurations located in directories with spaces in their name.
254
// Thus we define the default tmp dir to default to where default
255
// JBoss server configurations are located. This should be removed
256
// once we find out how to make JBoss work when using the default
257
// tmp dir of System.getProperty("java.io.tmpdir")
258
if (getTmpDir() == null)
259             {
260                 setTmpDir(new File JavaDoc(this.dir, "server/cactus"));
261             }
262             
263             File JavaDoc customServerDir = setupTempDirectory(getTmpDir(),
264                 "cactus/jboss3x");
265             cleanTempDirectory(customServerDir);
266             
267             prepare("cactus/jboss3x", customServerDir);
268             
269             File JavaDoc binDir = new File JavaDoc(this.dir, "bin");
270             
271             Java java = createJavaForStartUp();
272             java.setDir(binDir);
273             
274             java.addSysproperty(
275                 createSysProperty("program.name",
276                     new File JavaDoc(binDir, "run.bat")));
277             java.addSysproperty(
278                 createSysProperty("jboss.server.home.dir", customServerDir));
279             java.addSysproperty(
280                 createSysProperty("jboss.server.home.url",
281                     customServerDir.toURL().toString()));
282
283             Path classpath = java.createClasspath();
284             classpath.createPathElement().setLocation(
285                 new File JavaDoc(binDir, "run.jar"));
286             addToolsJarToClasspath(classpath);
287             java.setClassname("org.jboss.Main");
288             java.createArg().setValue("-c");
289             java.createArg().setValue(this.config);
290             java.execute();
291         }
292         catch (IOException JavaDoc ioe)
293         {
294             getLog().error("Failed to startup the container", ioe);
295             throw new BuildException(ioe);
296         }
297     }
298
299     /**
300      * @see AbstractJavaContainer#shutDown()
301      */

302     public final void shutDown()
303     {
304         File JavaDoc binDir = new File JavaDoc(this.dir, "bin");
305             
306         Java java = createJavaForShutDown();
307         java.setFork(true);
308
309         Path classPath = java.createClasspath();
310         classPath.createPathElement().setLocation(
311             new File JavaDoc(binDir, "shutdown.jar"));
312
313         java.setClassname("org.jboss.Shutdown");
314         
315         if (this.version.startsWith("3.2"))
316         {
317             java.createArg().setValue("--server=localhost:"
318                 + this.getJndiPort());
319             java.createArg().setValue("--shutdown");
320         }
321         else
322         {
323             java.createArg().setValue("localhost");
324             java.createArg().setValue(String.valueOf(getPort()));
325         }
326         java.execute();
327     }
328
329     // Private Methods ---------------------------------------------------------
330

331     /**
332      * @return the test context from JBoss's <code>jboss-web.xml</code> or null
333      * if none has been defined or if the file doesn't exist
334      */

335     private String JavaDoc getTestContextFromJBossWebXml()
336     {
337         String JavaDoc testContext = null;
338         
339         try
340         {
341             Document JavaDoc doc = getJBossWebXML();
342             Element JavaDoc root = doc.getDocumentElement();
343             Node JavaDoc context = root.getElementsByTagName("context-root").item(0);
344             testContext = context.getFirstChild().getNodeValue();
345         }
346         catch (Exception JavaDoc e)
347         {
348             // no worries if we can't find what we are looking for (for now).
349
}
350
351         return testContext;
352     }
353     
354     /**
355      * Prepares a temporary installation of the container and deploys the
356      * web-application.
357      *
358      * @param theDirName The name of the temporary container installation
359      * directory
360      * @param theCustomServerDir the directory where the JBoss server
361      * configuration is to be deployed
362      * @throws IOException If an I/O error occurs
363      */

364     private void prepare(String JavaDoc theDirName, File JavaDoc theCustomServerDir)
365         throws IOException JavaDoc
366     {
367         FileUtils fileUtils = FileUtils.newFileUtils();
368
369         // If the configDir property has not been set, let's default it to
370
// the default JBoss server configuration directory.
371
File JavaDoc computedConfigDir;
372         if (this.configDir == null)
373         {
374             computedConfigDir = new File JavaDoc(this.dir, "server");
375         }
376         else
377         {
378             computedConfigDir = this.configDir;
379         }
380         
381         // Copy the default JBoss server config directory into our custom
382
// server directory.
383
Copy copy = new Copy();
384         copy.setTaskName("cactus");
385         copy.setProject(getProject());
386         copy.setTodir(theCustomServerDir);
387         FileSet srcFiles = new FileSet();
388         srcFiles.setDir(new File JavaDoc(computedConfigDir, this.config));
389         copy.addFileset(srcFiles);
390         copy.execute();
391             
392         // Deploy the web-app by copying the WAR file into the webapps
393
// directory
394
File JavaDoc deployDir = new File JavaDoc(theCustomServerDir, "/deploy");
395         fileUtils.copyFile(getDeployableFile().getFile(),
396             new File JavaDoc(deployDir, getDeployableFile().getFile().getName()),
397             null, true);
398     }
399
400     /**
401      * Returns the version of the JBoss installation.
402      *
403      * @param theDir The JBoss installation directory
404      * @return The JBoss version, or <code>null</code> if the verion number
405      * could not be retrieved
406      */

407     private String JavaDoc getVersion(File JavaDoc theDir)
408     {
409         // Extract version information from the manifest in run.jar
410
String JavaDoc retVal = null;
411         try
412         {
413             JarFile JavaDoc runJar = new JarFile JavaDoc(new File JavaDoc(theDir, "bin/run.jar"));
414             Manifest JavaDoc mf = runJar.getManifest();
415             if (mf != null)
416             {
417                 Attributes JavaDoc attrs = mf.getMainAttributes();
418                 retVal = attrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
419             }
420             else
421             {
422                 getLog().warn("Couldn't find MANIFEST.MF in " + runJar);
423             }
424         }
425         catch (IOException JavaDoc ioe)
426         {
427             getLog().warn("Couldn't retrieve JBoss version information", ioe);
428         }
429         return retVal;
430     }
431
432     /**
433      * Get a Document object for the <code>jboss-web.xml</code> file.
434      *
435      * @return The parsed XML Document object or null if not found
436      * @throws IOException If there is a problem reading files
437      * @throws ParserConfigurationException If there is a problem w/ parser
438      * @throws SAXException If there is a problem with parsing
439      */

440     private Document JavaDoc getJBossWebXML() throws
441         IOException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc
442     {
443         Document JavaDoc doc = null;
444         File JavaDoc configDir = new File JavaDoc(this.dir, "server");
445         File JavaDoc deployDir = new File JavaDoc(configDir, this.config + "/deploy");
446         File JavaDoc warFile = new File JavaDoc(deployDir,
447             getDeployableFile().getFile().getName());
448  
449         JarFile JavaDoc war = new JarFile JavaDoc(warFile);
450         ZipEntry JavaDoc entry = war.getEntry("WEB-INF/jboss-web.xml");
451         if (entry != null)
452         {
453             DocumentBuilderFactory JavaDoc factory =
454                 DocumentBuilderFactory.newInstance();
455             factory.setValidating(false);
456             factory.setNamespaceAware(false);
457             
458             DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
459             builder.setEntityResolver(new EntityResolver JavaDoc()
460             {
461                 public InputSource JavaDoc resolveEntity(String JavaDoc thePublicId,
462                     String JavaDoc theSystemId) throws SAXException JavaDoc
463                 {
464                     return new InputSource JavaDoc(new StringReader JavaDoc(""));
465                 }
466             });
467             doc = builder.parse(war.getInputStream(entry));
468         }
469         war.close();
470         return doc;
471     }
472     
473 }
474
Popular Tags