siark.com blog

November 11, 2010

Tomcat 6, Securing the Admin Pages in web.xml

Filed under: Eclipse, Java, Web Application — Tags: , , , , , , — Mark Gould @ 7:38 am

To the right of the top menu on the siark.com website is the ‘admin’ link that accesses the administration (create, update and delete) pages. The hierarchy of the pages are such that the admin pages are in a series of admin directories (the admin pages for the galleries are in /gallery/admin, the admin pages for the keywords are in /keyword/admin and so on). Therefore it is necessary to restrict access to any pages to all of the admin subdirectories. This restriction is done by specifying security settings in the web-xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
	version="2.5">
	<display-name>igallery</display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	<servlet>
		<servlet-name>igallery</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
				/WEB-INF/igallery-servlet.xml
			</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>igallery</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>
	<security-constraint>
		<web-resource-collection>
			<web-resource-name>Admin Security</web-resource-name>
			<url-pattern>/gallery/admin/*</url-pattern>
		</web-resource-collection>
		<auth-constraint>
			<role-name>myrole</role-name>
		</auth-constraint>
	</security-constraint>
	<login-config>
		<auth-method>BASIC</auth-method>
	</login-config>
	<security-role>
		<role-name>myrole</role-name>
	</security-role>
</web-app>

As I am using Tomcat 6, I can simply specify user and role information in the tomcat-users.xml file. To do this from the server instance in Eclipse, expand the ‘Servers’ directory in the ‘Project Explorer’, then expand the appropriate server, and you’ll see the file. There are sample roles and users in the file already. Create a role to match the role used in the web.xml file (in this case myrole).

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
	<role rolename="myrole" />
	<user username="myuser" password="mypassword" roles="myrole" />
</tomcat-users>

Note: It’s possible to specify the HTTP methods in the web.xml web-resource-collection, however this will mean that *only* these methods to the url-pattern specified will be secured and other methods will be unsecured (see http://www.aspectsecurity.com/documents/Bypassing_VBAAC_with_HTTP_Verb_Tampering.pdf).

October 8, 2010

Using mod_jk to Connect Apache 2 HTTP Server and Tomcat 6 on OS X Snow Leopard

Filed under: Systems Administration — Tags: , , , — Mark Gould @ 8:52 pm

Mac OS X Snow Leopard has the Apache HTTP Server (httpd) pre-installed (I have version 2.2.14). As I mentioned in a previous blog post, I’m using the Apache Server to handle the http requests to http://www.siark.com and I want it to forward those requests to the Tomcat servlet conainer which is listening on port 8080. To do this I’m using the Apache Tomcat Connector (mod_jk).

1 Download the Tomcat Connector version 1.2.30 source files (I downloaded the gziped tar file).

2 Decompress the downloaded file.

$ cd ~/Downloads
$ tar -xvf ~/Downloads/tomcat-connectors-1.2.30-src.tar

3 As with compiling jsvc in an earlier post, the gcc compiler in the OS X developer tools is needed. As mod_jk is an Apache Server extension module, it must be configured, compiled and then installed. To configure the make file the Apache Extension tool (apxs) is used.

$ cd tomcat-connectors-1.2.30-src/native
$ ./configure --with-apxs=/usr/sbin/apxs
$ make clean
$ make
$ sudo make install

4 To configure mod_jk two configuration files are needed, both located in /etc/apache2/other. The first file is mod_jk.conf and the second is workers.properties. For both of these files I’ve used the examples in the Quick Start HowTo on the Apache Tomcat Connector website, with some minor alterations.

$ cd /etc/apache2/other
$ sudo vi mod_jk.conf
LoadModule jk_module libexec/apache2/mod_jk.so
JkWorkersFile /etc/apache2/other/workers.properties
JkShmFile /var/log/apache2/mod_jk.shm
JkLogFile /var/log/apache2/mod_jk.log
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
JkMount /examples/* ajp13
JkMount /host-manager/* ajp13
JkMount /docs/* ajp13
JkMount /manager/* ajp13

The JkMount directive assign URL’s to Tomcat and the JkUnmount directive blocks URL’s from being assigned to Tomcat. I have usewd a combination of these two directives to filter the appropriate URL’s to Tomcat.

$ sudo vi workers.properties
worker.list=worker1
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009

5 Finally stop and restart the Apache HTTP Server.

$ sudo apachectl graceful-stop
$ sudo apachectl start

If the server does not restart, there may be a problem with the configuration. To troubleshoot the configuration use the apachectl command with the configtest option.

Finally, visit the siark.com website.

September 29, 2010

Web MVC Project using Spring Framework 3 Eclipse Helios and Maven 2 on OS X Snow Leopard

I want to create the simplest of webapps using Spring Framework 3 and JSP documents. The version of JSP is 2.1 as that is the version used by Tomcat 6.

1 Update the pom.xml with the Spring Framework dependencies.

<project xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.siark.igallery</groupId>
	<artifactId>igallery</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>Siark iGallery Webapp</name>
	<url>http://www.siark.com</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>igallery</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<properties>
		<org.springframework.version>3.0.4.RELEASE</org.springframework.version>
	</properties>
</project>

2 Update the web.xml file to include the Spring Framework Dispatcher Servlet.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
	version="2.5">
	<display-name>igallery</display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	<servlet>
		<servlet-name>igallery</servlet-name>
			<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>igallery</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>
</web-app>

The Dispatcher Servlet handles requests to all resources that have the extension html. The DispatcherServlet class is in the spring-webmvc artifact.

3 I want the JSP pages to be in the WEB-INF/jsp directory. As this directory is not part of the public hierarchy, the welcome page (index.jsp) must redirect to the home page (home.html) which is then intercepted by the Spring Framework Dispatcher servlet.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" info="siark.com home page" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
		<title>siark.com home</title>
	</head>
	<body>
		<%-- Redirected because we can't set the welcome page to a virtual URL. --%>
		<c:redirect url="home.html" />
	</body>
</html>

4 The Spring Framework Web MVC uses a special file to configure it’s web application context and is based on the servlet name assigned to the dispatcher servlet (igallery). This file then is igallery-servlet.xml and by default is in the WEB-INF directory.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<context:component-scan base-package="com.siark.igallery" />
	
	<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
		<property name="prefix" value="/WEB-INF/jsp/"/>
		<property name="suffix" value=".jspx"/>
	</bean>
</beans>

This minimal web application context configuration file includes an entry to enable auto-detection of annotated controllers and an entry to configure the view resolver.

5 The controller for the home page is as simple as possible and just handles an HTTP GET request.

package com.siark.igallery.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@Controller
@RequestMapping("/home")
public class HomeController {
	
	protected final Log logger = LogFactory.getLog(getClass());
	
	/**
	 *
	 */
	@RequestMapping(method=RequestMethod.GET)
	public void get() {
		logger.info("Returning the home view.");
	}
}

The Controller annotation is in the spring-context artifact and the RequestMapping and RequestMethod annotations are in the spring-web artifact.

6 The home page itself is home.jspx and is in the WEB-INF/jsp directory. It is a JSP document.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" 
		xmlns:c="http://java.sun.com/jsp/jstl/core"
		xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
		version="2.0">
    <jsp:directive.page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" />
    <!-- According to the W3C XHTML 1.0 Recommendation, an XML declaration is not required, but authors are strongly encouraged to use XML declarations in documents. -->
    <jsp:text>
        <![CDATA[ <?xml version="1.0" encoding="ISO-8859-1" ?> ]]>
    </jsp:text>
    <!-- According to the W3C XHTML 1.0 Recommendation, there must be a DOCTYPE declaration prior to the root element. -->
    <jsp:text>
        <![CDATA[ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ]]>
    </jsp:text>
	<html xmlns="http://www.w3.org/1999/xhtml">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
		</head>
		<body>
			<p>Welcome to the siark.com website.</p>
		</body>
	</html>
</jsp:root>

September 20, 2010

Installing Hudson CI on OS X Snow Leopard and Configuring it to use Subversion, Maven 2 and Nexus

Filed under: Maven 2, Systems Administration — Tags: , , , , , — Mark Gould @ 2:59 pm

1 Download the hudson.war file.

2 Create a HUDSON_HOME directory. As I did with Nexus, I am creating this in the Tomcat home directory. Create the .m2 directory for maven and copy the settings.xml that configures Maven 2 to use Nexus.

$ cd /Library/Tomcat/Home
$ mkdir .hudson
$ cd .hudson
$ mkdir .m2
$ cp ~/.m2/settings.xml .
$ sudo chown tomcat settings.xml

3 Edit the Tomcat5.sh script used to start Tomcat and add a HUDSON_HOME environment variable.

$ cd bin
$ sudo vi Tomcat5.sh
...
CATALINA_OPTS="-DHUDSON_HOME=$CATALINA_HOME/.hudson/ -Xmx512m -Djava.awt.headless=true"
...

4 Stop and restart Tomcat.

$ sudo ./Tomcat5.sh stop
$ sudo ./Tomcat5.sh start

5 Deploy the hudson.war using the Tomcat Web Application Manager. To do this navigate to http://localhost:8080/manager, and half way down the page is the Deploy section with a WAR file to deploy subsection. Press the Choose File button to choose the hudson.war file. then press the Deploy button to deploy it.

6 Navigate to http://localhost:8080/hudson to check the installation worked.

7 On the Hudson home page click the ‘New Job’ link. Add the job name igallery and choose the ‘Build a maven 2 project’ radio button. Click the ‘OK’ button.

8 On the next page, choose the ‘Subversion’ radio button under the ‘Source Code Management’ section. Add ‘http://localhost/svn/repos&#8217; in the ‘Modules Repository URL’. You will need to enter the username and password setup for Subversion. Uncheck the ‘Use update’ checkbox and check the ‘Revert’ checkbox. In the ‘Build Triggers’ section check the ‘Poll SCM’ checkbox and choose a schedule. In the ‘Build’ section click the ‘system configuration’ link for the Maven Version. On the Hudson configuration page uncheck the tick box ‘Install automatically’ in the ‘Maven’ section and add ‘/usr/share/maven’ to ‘MAVEN_HOME’. Add a name for this maven installation. In the ‘Global properties’ section tick the ‘Environment variables’ checkbox and add the environment variable ‘HOME’ and give it the value ‘/Library/Tomcat/Home/.hudson’.

9 Back on the igallery job configuration page add ‘package’ to the ‘Goals and Options’ of the ‘Build’ section. Click the ‘Save’ button.

September 17, 2010

A Simple Web Application in Eclipse

A web application contains a structured hierarchy of directories. The root of the directory hierarchy is known as the document root. The WEB-INF diretory is special directory within the directory hierarchy that is not part of the public hierarchy of directories. The contents of the WEB-INF directory include the web.xml deployment descriptor file, a classes directory and a lib directory.

When a web application is packaged as a WAR file, a META-INF directory is included in the root of the directory hierarchy.

Tomcat 6 supports the Servlet 2.5 specification. The web.xml file for a web application deployed to Tomcat 6 must contain as a minimum a web-app element. However, to create the first page of the siark.com website I want to include an index.jsp page that will be used as a welcome file.

1 Create the web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
	version="2.5">
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

2 Create the index.jsp file in the root of the directory hierarchy (src/main/webapp).

<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" info="siark.com home page" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
		<title>siark.com home</title>
	</head>
	<body>
		<p>Welcome to the siark.com website.</p>
	</body>
</html>

To deploy and run the project, right click on the igallery project in the ‘Project Explorer’ view. Select ‘Run on Server’ from the ‘Run As’ menu item. Select the server created. Eclipse will deploy the igallery web app to the server and a browser tab will open in the Eclipse workbench displaying the landing page of the web app.

September 16, 2010

Checking out a Project using Subclipse and Creating a new Server Runtime

Filed under: Eclipse — Tags: , , , , , — Mark Gould @ 10:20 am

Checking out the igallery project using Subclipse amd Creating a new Server Runtime.

1 Go to the SVN Repositories view. The ‘repos’ repositry set up earlier should be visible (http://siark-desktop.local/svn/repos). Click on the grey triangle to the left of the repository to expand it so that the ‘igallery’ project is visible, then expand ‘igallery’ so that ‘trunk’ is visible.

2 Right click ‘trunk’ and select ‘Checkout…’ On the first dialog box, the ‘Checkout from SVN’ dialog, leave all the options as they are and just click ‘Finish’ to checkout the project using the ‘New Project Wizard’.

3 The next dialog box is the ‘New Project’ dialog. Expand the ‘Web’ option and select the ‘Dynamic Web Project’ (a dynamic projects include resources such as Servlets and JSP files, wheras static projects just contain resources such as HTML files). Click on the ‘Next >’ button.

4 The next dialog box is the first ‘New Dynamic Web Project’ wizard dialog. Give the project a name. I’m using the name ‘igallery’. In the ‘Target Runtime’ section, press the ‘New Runtime…’ button.

5 On the ‘New Server Runtime Environment’ dialog box, select ‘Apache Tomcat v6.0’ from the expanded ‘Apache’ option. Check the ‘Create a new local server’ option so that a server is added to the ‘Servers’ view. Click the ‘Next >’ button.

6 On the next ‘New Server Runtime Environment’ dialog box, click the ‘Browse…’ button and select the Tomcat installation directory (/Library/Tomcat/Home), then click the ‘Finish’ button.

7 Back on the ‘New Dynamic Web Project’ wizard dialog, the ‘Dynamic web module version’ should be set to 2.5 (Tomcat 6 implements the Servlet 2.5 spec). Select ‘Minimal Configuration’ in the ‘Configuration’ section. Click the ‘Next >’ button.

8 On the second ‘New Dynamic Web Project’ wizard dialog, delete ‘src’ from the “Source folders on build path:’ and add ‘src/main/java’ and ‘src/test/java’ then click the ‘Next >’ button.

9 On the third and last ‘New Dynamic Web Project’ wizard dialog, change the ‘Content directory:’ to ‘src/main/webapp’. Click the ‘Finish’ button.

September 13, 2010

Installing Tomcat 6 on OS X Snow Leopard with jsvc and launchd

Filed under: Systems Administration — Tags: , , , — Mark Gould @ 4:00 pm

Although Tomcat 7 is now avalible I am using Tomcat 6 on my iMac. I’m using Tomcat version 6.0.29. I want to start Tomcat when I start my iMac. To do this I’ll start Tomcat with launchd as a daemon using jsvc.

1 Download the core Tomcat 6 binary distribution (I downloaded the gziped tar file).

2 Create a new Standard user called ‘tomcat’. This user will be used to run Tomcat (so that Tomcat is not run as root). Eventually I’ll use the Tomcat Connector aka mod_jk to connect Tomcat to Apache, so Apache will be the webserver for the siark.com website, with Tomcat as the Servlet/JSP container. Apache will, of course be using port 80 (which is why it is run as root), and Tomcat port 8080, which is why it can be run as user ‘tomcat’). Hide the tomcat user (and other) from the login screen.

$ sudo defaults write /Library/Preferences/com.apple.loginwindow HiddenUsersList -array-add tomcat
$ sudo defaults write /Library/Preferences/com.apple.loginwindow SHOWOTHERUSERS_MANAGED -bool false

3 Create a directory for tomcat.

$ cd /Library
$ mkdir Tomcat

Create a directory for tomcat.
$ cd /Library$ mkdir Tomcat

4 Install Tomcat into the new Tomcat directory.

$ cd Tomcat
$ tar -xvzf ~/Downloads/apache-tomcat-6.0.29.tar

5 Create a symbolic link to the apache-tomcat-6.0.29 called Home.

$ ln -sfhv apache-tomcat-6.0.29 Home

6 jsvc is part of the Commons Daemon project and is included in the Tomcat download but isn’t built. As jsvc is a C program, the gcc compiler is needed to build it. The gcc compiler is included in the OS X developer tools.

$ cd /Library/Tomcat/Home/bin
$ tar -xvzf commons-daemon-native.tar.gz
$ cd commons-daemon-1.0.2-native-src/
$ cd unix

7 A quick read of the INSTALL.txt document indicates that to build an OS X Universal Binary a couple of environment variables need to be set prior to configuring make.

$ export CFLAGS="-arch i386 -arch x86_64"
$ export LDFLAGS="-arch i386 -arch x86_64"
$ ./configure
$ make clean
$ make

8 Configure the Tomcat5.sh script. Change the JAVA_HOME, CATALINA_HOME, DAEMON_HOME, TOMCAT_USER, CATALINA_BASE, CATALINA_OPTS, the ‘start’ and ‘stop’ cases

$ cd /Library/Tomcat/Home/bin/commons-daemon-1.0.2-native-src/unix/native
$ cp Tomcat5.sh ../../..
$ cd ../../..
$ vi Tomcat5.sh
JAVA_HOME=/Library/Java/Home
CATALINA_HOME=/Library/Tomcat/Home
DAEMON_HOME=$CATALINA_HOME/bin
TOMCAT_USER=mark
CATALINA_BASE=$CATALINA_HOME
CATALINA_OPTS=
start)
#
# Start Tomcat
#
$DAEMON_HOME/jsvc \
...
stop)
#
# Stop Tomcat
#
$DAEMON_HOME/jsvc \
...

9 Change the owner of the Tomcat directory to the user tomcat.

$ cd /Library
$ sudo chown -R tomcat Tomcat

10 Start Tomcat using jsvc at boot-up using launchd. Create a plist file for launchd and make root the owner of the file.

$ cd /Library/LaunchDaemons
$ sudo vi org.apache.commons.jsvc.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>Label</key>
<string>org.apache.commons.jsvc</string>
<key>ProgramArguments</key>
<array>
<string>bin/Tomcat5.sh</string>
<string>start</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>WorkingDirectory</key>
<string>/Library/Tomcat/Home</string>
</dict>
</plist>
$ sudo chown root org.apache.commons.jsvc.plist

11 Test the install.

$ sudo launchctl load /Library/LaunchDaemons/org.apache.commons.jsvc.plist
$ ps -ef | grep jsvc

Resources

http://tomcat.apache.org/

http://commons.apache.org/daemon/jsvc.html

Blog at WordPress.com.