old-www/LDP/LG/issue69/peda.html

659 lines
24 KiB
HTML

<!--startcut ==============================================-->
<!-- *** BEGIN HTML header *** -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML><HEAD>
<title>Installing Tomcat on Linux LG #69</title>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
ALINK="#FF0000">
<!-- *** END HTML header *** -->
<CENTER>
<A HREF="http://www.linuxgazette.com/">
<IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.png"
WIDTH="600" HEIGHT="124" border="0"></A>
<BR>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="orr.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue69/peda.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="qubism.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
<P>
</CENTER>
<!--endcut ============================================================-->
<H4 ALIGN="center">
"Linux Gazette...<I>making Linux just a little more fun!</I>"
</H4>
<P> <HR> <P>
<!--===================================================================-->
<center>
<H1><font color="maroon">Installing Tomcat on Linux</font></H1>
<H4>By <a href="mailto:tl082@yahoo.com">Allan Peda</a></H4>
</center>
<P> <HR> <P>
<!-- END header -->
<img src="misc/peda/tomcat.png"
alt="Screencap of the Tomcat Demo Webserver Running"
WIDTH="130" HEIGHT="92" ALIGN="left">
By now I'm sure many of you my have the impression that unless you know
Java, your r&eacute;sum&eacute; is severely handicapped, and even if
you are fluent in Java, increasingly employers will ask if you know Java
Server Pages (JSPs), and/or servlets. Fortunately, there is a free
application server for Java Server Pages, and the related Java
Servlets, it is called called Jakarta-Tomcat (hereafter referred to
simply as Tomcat). I decided to download and install it, documenting
my experiences for reference. I set up Tomcat on a vintage Pentium
2/200 running SuSE 7.2, however it appears that the steps described
here should work with any recent distribution, as long as Java can
compile the source.
<p>
Installation of the applet server involves the downloading and
compilation of several packages in addition to the obvious need for
Java and Tomcat. The following packages are necessary:
<p>
<table CLASS="listing">
<caption>Required Packages to Set Up Jakarta-Tomcat</caption>
<tr><th>Package</th><th>Source &nbsp;</th></tr>
<tr><td>Java SDK 1.3.1 &nbsp;</td>
<td><a href="#java_download">Sun</a> &nbsp;</td></tr>
<tr><td>XML Parser Library 1.1 &nbsp;</td>
<td><a href="#java_xml">Sun</a> &nbsp;</td></tr>
<tr><td>Secure Sockets for Java 1.0.2 &nbsp;</td>
<td><a href="#java_sse">Sun</a> &nbsp;</td></tr>
<tr><td>Java Servlet API 3.2.3 &nbsp;</td>
<td><a href="#jakarta_download">Apache Foundation</a> &nbsp;</td> </tr>
<tr><td>Jakarta Ant 1.3 &nbsp;</td>
<td><a href="#jakarta_download">Apache Foundation</a> &nbsp;</td> </tr>
<tr><td>Jakarta Tomcat 3.2.3 &nbsp;</td>
<td><a href="#jakarta_download">Apache Foundation</a> &nbsp;</td> </tr>
</table><p>
<p>
<h2>Getting Java Installed</h2><p>
Installation of Java has been written up so frequently it's almost
not worth repeating here, however for completeness I'll quickly run through the
steps using RPM. I downloaded version 1.3 of the SDK (also known as
the JDK) from the <a href="#java_download">Java web site</a>,
but 1.4 is in Beta, and may be out by the time you read this. The
notes for the Secure Sockets library indicate that 1.4 will include
them, so the installation will be simplified somewhat.
<p>
For Linux, Sun's Java comes as a script wrapped around an RPM package,
so that you must execute it and agree to the licensing before you get
to actually install the RPM.&nbsp; After unpacking the shell script to
yield an RPM, follow the standard installation as root.
<p>
<table CLASS="sourcecode">
<caption>RPM install for Java (after unpacking)</caption>
<tr><td>
<pre>
moby:~ &gt; sudo rpm -Uv jdk-1.3.1.i386.rpm
</pre>
</td></tr>
</table>
<p>
I modified my path to include the location of the JDK, on SuSE you are
advised to edit /etc/profile.local to accomplish this, although on
other distributions one might edit /etc/profile directly. Note also the
environmental variable for $JAKARTA_HOME, and $TOMCAT_HOME, we can
ignore them for now, but you will need them soon enough as part of the
installation procedure, so it's easier to set them now. Note that I
did not initially set CLASSPATH, although you may want or need to.
You'll see below the steps I took to make sure that Java could find
the libraries.
<p>
<table CLASS="sourcecode" WIDTH="100%">
<caption>Environmental Variables Needed</caption>
<tr><td>
<pre>
#!/bin/bash
JAVA_HOME=/usr/java/jdk1.3.1
JAKARTA_HOME=/opt/jakarta
ANT_HOME=$JAKARTA_HOME/jakarta-ant
TOMCAT_HOME=$JAKARTA_HOME/build/tomcat
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME JAKARTA_HOME ANT_HOME PATH TOMCAT_HOME
</pre>
</td></tr>
</table>
<p>
<h2>Installing the Java XML Parser Library</h2>
I installed the libraries for XML parsing by unzipping and copying the
required libs to the library extensions directory (as root). I
originally unzipped this file into my home directory. Where the files
are initially unzipped doesn't matter, as long as java can find the
installed libraries.<p>
<table CLASS="sourcecode" WIDTH="100%">
<caption>Copying the XML Parser Library jar files</caption>
<tr><td>
<pre>
unzip jaxp-1_1.zip; cd jaxp-1.1
moby:~/jaxp-1.1 > sudo cp *.jar $JAVA_HOME/jre/lib/ext
</pre>
</td></tr>
</table>
<p>
Now, I like to do things step by step, so to check that your setup is
able to find these new libraries, I suggest running an example
program, which is included in the XML parser library.
<br>
If your Java Virtual Machine (JVM) cannot find the libraries, you will
get an error like this:
<p>
<table CLASS="errormsg">
<caption>Error Message</caption>
<tr><td>
<pre>
moby:~/jaxp-1.1/examples/trax &gt; java Examples
Exception in thread "main" java.lang.NoClassDefFoundError:
javax/xml/transform/TransformerException
</pre>
</td></tr>
</table>
<p>
If you see something like this, check the library locations (.jar
files). I constantly ran into this problem, and I solved it by
copying symlinking them to the correct location, or modifying
$CLASSPATH.
<h2>Installing the Secure Sockets Library</h2>
<p>You follow a similar procedure to install the Secure
Sockets library copying the .jar libraries into the extensions directory.
<p>
<table CLASS="sourcecode">
<caption>Secure Sockets Library</caption>
<tr><td>
<pre>
moby:~/jsse1.0.2/lib &gt; sudo cp *.jar $JAVA_HOME/jre/lib/ext
</pre>
</td></tr>
</table>
<p>
I then edited the file
/usr/java/jdk1.3.1/jre/lib/security/java.security to contain an entry
for "com.sun.net.ssl.internal.www.protocol" which was not in the
default file.
<p>
<table CLASS="sourcecode">
<caption>Java Security Entry for SSL</caption>
<tr><td>
<pre>
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
</pre>
</td></tr>
</table>
<p>
Now, to test that javac could find these libs, I quickly typed up
compiled the following piece of code, saved it as TestSSL.java and
compiled it:
<p>
<table CLASS="sourcecode">
<caption>Testing Secure Sockets</caption>
<tr><td>
<pre>
import javax.net.ssl.*;
public class TestSSL {
public static
void main(String [] arstring) {
try {
new java.net.URL("https://" + arstring[0] + "/").getContent();
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
</pre>
</td></tr>
</table>
<p>
We compile to bytecode Using the standard javac invocation:
<pre>
moby:~/jsse1.0.2 &gt; javac TestSSL.java
</pre>
Once again, if java could not find the libray, then I would get a
java.lang.NoClassDefFoundError error, and the code would not compile
to yield the TestSSL.class bytecode file.<p>
After compiling with javac to bytecode, I wanted to test the ssl library by
connecting to an SSL site (sourceforge). Here it is necessary to
specify the use of SSL on the command line, or as Sun's install docs say,
"add the handler's implementation package name to the list of packages
which are searched by the Java URL class". I think of this as
analogous to linking the math library using -lm as a linker option
to gcc, except it's done at runtime.
<table CLASS="sourcecode">
<caption>Explicitly Specifying the Handler</caption>
<tr><td>
<pre>
moby:~/jsse1.0.2 &gt; java \
-Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol \
TestSSL sourceforge.net
moby:~/jsse1.0.2 &gt; echo $?
moby:~/jsse1.0.2 &gt; 0
</pre>
</td></tr>
</table>
<p>
<br>
As an aside, if I did not include this argument to the JVM, I would
get the following error:<p>
<table CLASS="errormsg">
<caption>Unknown Protocol Error Message</caption>
<tr><td>
<pre>
moby:~/jsse1.0.2 &gt; java TestSSL sourceforge.net
java.net.MalformedURLException: unknown protocol: https
at java.net.URL.&lt;init&gt;(URL.java:480)
at java.net.URL.&lt;init&gt;(URL.java:376)
at java.net.URL.&lt;init&gt;(URL.java:330)
at TestSSL.main(TestSSL.java:8)
</pre>
</td></tr>
</table>
<p>
So now we have Apache, Java, Java libraries for XML and Secure
Sockets, and we can install Jakarta-Tomcat. Not quite yet, we
still need Ant, a Java "make" replacement, and the Servlet API.
<h2>Installing Ant</h2>
Despite the fact that we not quite ready to install the Jakarta-Tomcat
distribution, the next step does involve installing some essential
components of Jakarta, so we need to modify our environment to
accommodate the package. We do this by creating the environmental variable
$JAKARTA_HOME which was briefly introduced with the $JAVA_HOME
variable. I decided to put Jakarta under /opt, simply because
there was space there, and also I try to put anything I build under
/opt, leaving /usr and /usr/local for the distribution RPM to
decide. Now we are getting to First, think of a place where you want
to install Ant.<p>
First download and unpack it. In my example I downloaded the
compressed source into my home directory, then changed to the
$JAKARTA_HOME directory. I then unpacked it into the $JAKARTA_HOME
directory, letting tar choose the directory name.<p>
In order to comply with the requirement that jakarta-ant be in a
directory called $JAKARTA_HOME/jakarta-ant I symlinked the build
directory to the correct directory name. Then I cd'd into the
jakarta-ant/ directory and ran the bootstrap.sh script as root.
After you run this script, there should be a new build/lib/
subdirectory containing the libraries just built:
<p>
<table CLASS="sourcecode">
<caption>Building Jakarta - Ant</caption>
<tr><td>
<pre>
moby:~ &gt; cd $JAKARTA_HOME
moby:~/opt/jakarta&gt; tar xzf ~/jakarta-ant-1.3-src.tar.gz
moby:/opt/jakarta &gt; sudo ln -s jakarta-ant-1.3/ jakarta-ant
moby:~/opt/jakarta &gt; cd jakarta-ant
moby:/opt/jakarta/jakarta-ant &gt; sudo sh bootstrap.sh
moby:/opt/jakarta/jakarta-ant > ls -1 build/lib/
ant.jar
optional.jar
</pre>
</td></tr>
</table>
<p>
<a href="misc/peda/bootstrap_ant.txt">Output of the Ant bootstrap
script</a><p>
<h2>Installing the Servlet API</h2>
Next we install the servlet API, once again symlinking the real
extract directory to the required directory name:
<p>
<table CLASS="sourcecode">
<caption>Building the Servlet API</caption>
<tr><td>
<pre>
moby:/opt/jakarta &gt; sudo tar xvzf \
&gt; ~/jakarta-servletapi-3.2.3-src.tar.gz
moby:/opt/jakarta &gt; sudo ln -s jakarta-servletapi \
&gt; jakarta-servletapi-3.2.3-src
moby:/opt/jakarta &gt; cd jakarta-servletapi
moby:/opt/jakarta/jakarta-servletapi &gt;
</pre>
</td></tr>
</table>
<p>
I was ready to build the jakarta servlet libraries, using the
build.sh script supplied. But it was at this point I had to "cheat"
in order to resolve two library related errors:
<p>
<table CLASS="errormsg">
<caption>Error messages due to libraries not being found</caption>
<tr><td>
<pre>
moby:/opt/jakarta/jakarta-servletapi &gt; sudo sh build.sh dist
Exception in thread "main" java.lang.NoClassDefFoundError:
org/apache/tools/ant/Main
/opt/jakarta/jakarta-servletapi-3.2.3-src/build.xml:31: Cannot use
classic compiler, as it is not available A common solution is to set
the environment variable JAVA_HOME to your jdk directory.
</pre>
</td></tr>
</table>
<p>
The error messages <i>look</i> different, but are really both related
to libraries not being found. The first is related to ant.jar, the
second is due to a "lost" tools.jar library. To solve these problems I
created two symlinks under $JAVA_HOME/jre/lib/ext to allow Java to
find the newly created ant.jar and tools.jar libraries.<br>
<p>
<table CLASS="sourcecode">
<caption>Symlinks set to allow Java to find "lost" Libraries</caption>
<tr><td>
<pre>
$JAVA_HOME/jre/lib/ext/ant.jar -&gt; /opt/jakarta/jakarta-ant/build/lib/ant.jar
$JAVA_HOME/jre/lib/ext/tools.jar -> /usr/java/jdk1.3.1/lib/tools.jar
</pre>
</td></tr>
</table>
<p>
Alternately I know of two other options that <i>should</i> work (but
did not for me):<p>
<ol>
<li>modify the $CLASSPATH environmental variable to include tools.jar
and ant.jar explicitly.<br>
<TT>export
CLASSPATH=$JAVA_HOME/lib/tools.jar:$ANT_HOME/lib/ant.jar</TT>
<br><em>or</em>
<li>
Explicitly specify the "-classpath" option when calling
java. This is probably impractical for any large run script.
</ol>
<br>
After creating these symlinks, the following command ran perfectly:
<p>
<table CLASS="sourcecode">
<caption>Building Tomcat</caption>
<tr><td>
<pre>
moby:/opt/jakarta/jakarta-servletapi > sudo sh build.sh dist
</pre>
</td></tr>
</table>
<p>
<a href="misc/peda/build_servlet_api.txt">Here is the output of servlet build
script</a><p>
<h2>Building Tomcat</h2>
Finally, the moment of truth, building the Jakarta-Tomcat package. I
still had one error,
<p>
<table CLASS="errormsg">
<caption>Error messages due to bin directory not being found</caption>
<tr><td>
<pre>
moby:/opt/jakarta/jakarta-tomcat > sudo sh ./build.sh dist
Buildfile: build.xml
prepare:
BUILD FAILED
/opt/jakarta/jakarta-tomcat-3.2.3-src/build.xml:32: /opt/jakarta/jakarta-ant-1.3/bin not found.
Total time: 2 seconds
</pre>
</td></tr>
</table>
<p>
The error message, unlike most, is obvious. After symlinking the bin
directory in jakarta-ant, it ran perfectly.
<p>
<table CLASS="sourcecode">
<caption>Symlink so the binaries could be found</caption>
<tr><td>
<pre>
moby:~ > cd /opt/jakarta/jakarta-ant
moby:/opt/jakarta/jakarta-ant &gt; sudo ln -s bootstrap/bin .
</pre>
</td></tr>
</table>
<p>
Here is the <a href="misc/peda/build_tomcat.txt">output of the
Tomcat build script</a><p>
At this point you can cd to $JAKARTA_HOME/dist/tomcat/bin and run
startup.sh .
<p>
<table CLASS="sourcecode">
<caption>Starting Jakarta-Tomcat</caption>
<tr><td>
<pre>
moby:/opt/jakarta/dist/tomcat/bin &gt; sudo ./startup.sh
Using classpath: /opt/jakarta/build/tomcat/classes:/opt/jakarta/build/tomcat/lib
/servlet.jar:/opt/jakarta/build/tomcat/lib/test:/usr/java/jdk1.3.1/lib/tools.jar
allan@moby:/opt/jakarta/build/tomcat/bin &gt; 2001-07-20 03:13:50 - ContextManager:
Adding context Ctx( /examples )
2001-07-20 03:13:50 - ContextManager: Adding context Ctx( /admin )
Starting tomcat. Check logs/tomcat.log for error messages
2001-07-20 03:13:50 - ContextManager: Adding context Ctx( )
2001-07-20 03:13:50 - ContextManager: Adding context Ctx( /test )
allan@moby:/opt/jakarta/build/tomcat/bin &gt; 2001-07-20 03:13:53 - \
PoolTcpConnector: Starting HttpConnectionHandler on 8080
2001-07-20 03:13:53 - PoolTcpConnector: Starting Ajp12ConnectionHandler on 8007
</pre>
</td></tr>
</table>
<p>
Similarly with shutdown:
<p>
<table CLASS="sourcecode">
<caption>Stopping Jakarta-Tomcat</caption>
<tr><td>
<pre>
moby:/opt/jakarta/dist/tomcat/bin > sudo ./shutdown.sh
Using classpath:
/opt/jakarta/build/tomcat/classes:/opt/jakarta/build \
/tomcat/lib/servlet.jar:/opt/jakarta/build/tomcat/lib/test:/usr/java \
/jdk1.3.1/lib/tools.jar
Stop tomcat
2001-07-20 03:15:47 - ContextManager: Removing context Ctx( /examples )
2001-07-20 03:15:47 - ContextManager: Removing context Ctx( /admin )
2001-07-20 03:15:47 - ContextManager: Removing context Ctx( )
2001-07-20 03:15:47 - ContextManager: Removing context Ctx( /test )
</pre>
</td></tr>
</table>
<p>
Congratulations! After running the startup script, you can view the
greeting screen by pointing your browser at the web server's machine,
port 8080, unless modified.<p>
<img src="misc/peda/tomcat_works.png"
alt="Screencap of the Tomcat Demo Webserver Running" WIDTH="600" HEIGHT="587">
<p>
Jumping to the various pages supplied you can then check out the
screen shots of the example <a href="misc/peda/servlet_examples.html">Servlets</a>
and <a href="misc/peda/jsp_samples.html">Java Server Pages</a>. This
is a bit of a tease, because you are tempted to try to run the demos
from the screencaps, but still it's nice to see what you can expect
when you actually get Jakarta Tomcat Running.
<p>
<h2>It works!</h2>
At this point you have two servers running: a simple web server
listening on port 8080, and a servlet container application server
listening on port 8007. The first thing I am concerned with is the
fact that everything was set up as root. Supporting documentation
suggests running the server as "nobody", but I felt that a special
jakarta user analogous to a database user would be a good idea because of
the special environmental variables that are set. Having a dedicated
jakarta user just for servlets would then allow configuration to be kept in
the ~jakarta home directory. This would be even more useful if there
were other versions of java installed on the system.
<p>
Anyhow this is all fairly simple. After the jakarta user is set up as
shown, you can run jakarta as that user, and since it runs from a
nonpriviliged port there should be no problem there. Still I thought
that the permissions could be tightened up more so that only the jakarta
user can run the servlet container, so I shutdown the server, and
changed the permissions as follows:<p>
<p>
<table CLASS="sourcecode" >
<caption>Tightening Up Permissions</caption>
<tr><td>
<pre>
moby:/opt/jakarta &gt; sudo $TOMCAT_HOME/bin/shutdown.sh
moby:/opt/jakarta &gt; sudo /usr/sbin/groupadd jakarta
moby:/opt/jakarta &gt; sudo /usr/sbin/useradd -g jakarta -c \
&gt; "Java Server Pages" jakarta
moby:/opt/jakarta &gt; sudo mkdir /home/jakarta
moby:/opt/jakarta &gt; sudo chown jakarta.jakarta /home/jakarta
moby:/opt/jakarta &gt; sudo chown -R jakarta.jakarta $JAKARTA_HOME
moby:/opt/jakarta &gt; sudo su - jakarta
moby:~ &gt; cd $JAKARTA_HOME
</pre>
</td></tr>
</table>
<p>
Naturally you could set the password too, but since root can get in
anyhow, I didn't bother. I decided to tighten some permissions by using
<a href="misc/peda/tighten_perms.sh.txt">this</a> script.
Now only user jakarta can start and stop the servlets, and Java server
pages. The environmental variables set in /etc/profile or
/etc/profile.local can now be set instead in ~jakarta/.profile or
~jakarta/.bash_profile leaving other users free to choose other java
versions and reducing the count of environmental variables.
<p>
Now that Tomcat is running, you can experiment with altering the stock
configuration. There are many options here, and of course since
Jakarta is a project by the Apache foundation, it is designed to
integrate easily with Apache. Take a look at the users guide
included with the source, it provides some good examples, and
you can also consult the project <a href="#tomcat_ug">web site</a>.
XML is the native format of it's configuration file, and you'll be
getting a crash course in XML, it you haven't learned about it yet.
To get you started, see the main configuration files, "server.xml" and
"web.xml".
<p>
So welcome to the wild world of Java Server Pages and Servlets.
You'll find that it's a very mature in interesting technology. Good
luck.
<p>
<hr>
References:
<ol>
<li>Linux as an Application Server -- The Tomcat Way<br>
by Chris Bush
<a href="http://www.sysadminmag.com/linux/articles/v10/i01/a4.htm">http://www.sysadminmag.com/linux/articles/v10/i01/a4.htm</a>
<li><a name="java_download">Sun's Java Software Development Kit 1.3.1</a><br>
<a href="http://java.sun.com/products/">http://java.sun.com/products/</a>
<li><a name="java_sse">Java Secure Sockets Extension (JSSE) version 1.0.2 or later</a><br>
<a href="http://java.sun.com/products/jsse/">http://java.sun.com/products/jsse/</a>
<li><a name = "java_xml">Java API for XML Parsing implementation 1.1</a><br>
<a href="http://java.sun.com/xml">http://java.sun.com/xml</a>
<li><a name="jakarta_download">Jakarta Tomcat download (includes
Jakarta Tomcat, ANT, Servlet API)</a><br>
<a href="http://jakarta.apache.org/site/sourceindex.html">http://jakarta.apache.org/site/sourceindex.html</a><br>
Note that Ant is a separate project, but the servlet API source is in the
same download directory as the Jakarta-Tomcat source.
<li>Build secure network applications with SSL and the JSSE API<br>
by Todd Sundsted
<a href="http://www.javaworld.com/javaworld/jw-05-2001/jw-0511-howto.html">http://www.javaworld.com/javaworld/jw-05-2001/jw-0511-howto.html</a>
<li>The Ant FAQ:
<a href="http://jakarta.apache.org/ant/faq.html">http://jakarta.apache.org/ant/faq.html</a>
<li><a name="tomcat_ug">The Tomcat Users Guide</a><br>
<a href="http://jakarta.apache.org/tomcat/tomcat-3.3-doc/tomcat-ug.html">http://jakarta.apache.org/tomcat/tomcat-3.3-doc/tomcat-ug.html</a>
</ol>
<!-- *** BEGIN bio *** -->
<SPACER TYPE="vertical" SIZE="30">
<P>
<H4><IMG ALIGN=BOTTOM ALT="" SRC="../gx/note.gif">Allan Peda</H4>
<EM>Allan has been enjoying Linux since about 1995, discovering Perl shortly
thereafter. Currently he is doing Linux consulting work in the NYC area.
He enjoys surfing, sailing, and dreams of owning a charter boat in
</EM>tranquilo<EM> Costa Rica.</EM>
<!-- *** END bio *** -->
<!-- *** BEGIN copyright *** -->
<P> <hr> <!-- P -->
<H5 ALIGN=center>
Copyright &copy; 2001, Allan Peda.<BR>
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
Published in Issue 69 of <i>Linux Gazette</i>, August 2001</H5>
<!-- *** END copyright *** -->
<!--startcut ==========================================================-->
<HR><P>
<CENTER>
<!-- *** BEGIN navbar *** -->
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="orr.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue69/peda.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="qubism.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
<!-- *** END navbar *** -->
</CENTER>
</BODY></HTML>
<!--endcut ============================================================-->