<?xml version="1.0"?>

<!--
 * ========================================================================
 * 
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * ========================================================================
-->

<document id="howto_config">

  <properties>
    <title>Configuration Howto</title>
  </properties>

  <body>

    <section title="Cactus Configuration">

      <p>
        Here are the configuration files used to configure Cactus manually:
      </p>

      <figure src="images/config.jpg" alt="Configuration files"/>

      <p>
        There are 3 kinds of configuration:
      </p>
      <ul>
        <li>
          <jump anchor="clientside">Client side configuration</jump>
        </li>
        <li>
          <jump anchor="serverside">Server side configuration</jump>
        </li>
        <li>
          <jump anchor="logging">Cactus logging configuration</jump>
        </li>
      </ul>

      <p>
        Cactus configuration works by setting Java System properties. You can
        set the Cactus configuration properties:
      </p>
      <ul>
          <li>
            On the command line (using <code>-Dxxx=yyy</code>).
          </li>
          <li>
            In a configuration file (recommended). By default Cactus will look
            for a <code>cactus.properties</code> file located in your
            classpath. You can override the name and location of the
            configuration file by setting the <code>cactus.config</code> System
            property. For example you can pass the following when starting the
            JVM: <code>-Dcactus.config=c:/cactus.txt</code>.
          </li>
          <li>
            In your tests (using <code>System.setProperty()</code>). This
            option is not recommended as it is better to share a single
            configuration across all tests.
          </li>
      </ul>

      <note>
        Please note that the different options for configuring Cactus works
        both for Cactus client side (i.e. from where you start the JUnit Test
        Runner) and for the Cactus server side (i.e. from where you start your
        application server).
      </note>

      <anchor id="clientside"/>
      <section title="Client side configuration">

        <p>
          The following table lists the properties that can be defined on
          Cactus client side:
        </p>

        <table>
          <tr>
            <th>Property Name</th>
            <td>
              <code>cactus.contextURL</code>
            </td>
          </tr>
          <tr>
            <th>Required</th>
            <td>
              Yes
            </td>
          </tr>
          <tr>
            <th>Description</th>
            <td>
              Webapp Context under which the application to test runs.
            </td>
          </tr>
          <tr>
            <th>Example</th>
            <td>
              <code>cactus.contextURL = http://localhost:8080/test</code>
            </td>
          </tr>
        </table>

        <p>
          <br/>
        </p>

        <table>
          <tr>
            <th>Property Name</th>
            <td>
              <code>cactus.servletRedirectorName</code>
            </td>
          </tr>
          <tr>
            <th>Required</th>
            <td>
              No. Defaults to "<code>ServletRedirector</code>".
            </td>
          </tr>
          <tr>
            <th>Description</th>
            <td>
              Name of the Cactus Servlet Redirector as it is mapped on the
              server side in <code>web.xml</code> (see below). This property
              is needed only if your test classes are extending
              <code>ServletTestCase</code> (see the
              <link href="site:howto_testcase">TestCase Howto</link>
              tutorial).
            </td>
          </tr>
          <tr>
            <th>Example</th>
            <td>
              <code>cactus.servletRedirectorName = ServletRedirector</code>
            </td>
          </tr>
        </table>

        <p>
          <br/>
        </p>

        <table>
          <tr>
            <th>Property Name</th>
            <td>
              <code>cactus.jspRedirectorName</code>
            </td>
          </tr>
          <tr>
            <th>Required</th>
            <td>
              No. Defaults to "<code>JspRedirector</code>".
            </td>
          </tr>
          <tr>
            <th>Description</th>
            <td>
              Name of the Cactus JSP Redirector as it is mapped on the
              server side in <code>web.xml</code> (see below). This property
              is needed only if your test classes are extending
              <code>JspTestCase</code> (see the
              <link href="site:howto_testcase">TestCase Howto</link>
              tutorial).
            </td>
          </tr>
          <tr>
            <th>Example</th>
            <td>
              <code>cactus.jspRedirectorName = JspRedirector</code>
            </td>
          </tr>
        </table>

        <p>
          <br/>
        </p>

        <table>
          <tr>
            <th>Property Name</th>
            <td>
              <code>cactus.filterRedirectorName</code> (For J2EE API 1.3 only)
            </td>
          </tr>
          <tr>
            <th>Required</th>
            <td>
              No. Defaults to "<code>FilterRedirector</code>".
            </td>
          </tr>
          <tr>
            <th>Description</th>
            <td>
              Name of the Cactus Filter Redirector as it is mapped on the
              server side in <code>web.xml</code> (see below). This property
              is needed only if your test classes are extending
              <code>FilterTestCase</code> (see the
              <link href="site:howto_testcase">TestCase Howto</link>
              tutorial).
            </td>
          </tr>
          <tr>
            <th>Example</th>
            <td>
              <code>cactus.filterRedirectorName = FilterRedirector</code>
            </td>
          </tr>
        </table>

      </section>

      <anchor id="serverside"/>
      <section title="Server side configuration">

        <p>
          On Cactus server side, you only need to properly configure your
          application <code>web.xml</code> file to include definitions for
          Cactus Redirectors (see <link href="site:how_it_works">How it
          works</link> if you don't know what a Cactus Redirector is).
        </p>

        <p>
          You need to register the Cactus Redirectors that you use, and you
          need to map them to the <code>cactus.servletRedirectorName</code>,
          <code>cactus.jspRedirectorName</code> and
          <code>cactus.filterRedirectorName</code> that you have configured
          on the client side (or simply make sure that you use the default
          names, i.e. <code>ServletRedirector</code>,
          <code>JspRedirector</code> and <code>FilterRedirector</code>
          respectively).
        </p>

        <p>
          Here is a sample <code>web.xml</code> that defines the 3 Cactus
          Redirectors:
        </p>

<source><![CDATA[
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">

<web-app>

    <filter>
        <filter-name>FilterRedirector</filter-name>
        <filter-class>org.apache.cactus.server.FilterTestRedirector</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>FilterRedirector</filter-name>
        <url-pattern>/FilterRedirector</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>ServletRedirector</servlet-name>
        <servlet-class>org.apache.cactus.server.ServletTestRedirector</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>JspRedirector</servlet-name>
        <jsp-file>/jspRedirector.jsp</jsp-file>
    </servlet>

    <servlet-mapping>
        <servlet-name>ServletRedirector</servlet-name>
        <url-pattern>/ServletRedirector</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>JspRedirector</servlet-name>
        <url-pattern>/JspRedirector</url-pattern>
    </servlet-mapping>

</web-app>
]]></source>

        <note>
          If you are using the JSP Redirector (i.e. you have test classes
          that extend <code>JspTestCase</code>), you <strong>must</strong>
          copy the <code>jspRedirector.jsp</code> file (found in the
          <code>sample/web</code> directory where you unpacked your
          Cactus distribution) in a directory in your webapp and you need to
          put its relative path in the mapping defined above (here we
          have put it in the webapp root.
        </note>

        <p>
          If you want to provide some initialisation parameters that will
          be available to the <code>config</code> implicit object available
          in your test case, simply use the standard <code>
          &lt;init-param&gt;</code> tags.
        </p>
        <p>
          For example, for the Servlet Redirector (same principle applies
          to all other redirectors):
        </p>

<source><![CDATA[
[...]
    <servlet>
        <servlet-name>ServletRedirector</servlet-name>
        <servlet-class>org.apache.cactus.server.ServletTestRedirector</servlet-class>
        <init-param>
          <param-name>param1</param-name>
          <param-value>value1 used for testing</param-value>
        </init-param>
    </servlet>
[...]
]]></source>

        <note>
          Within your <code>testXXX()</code> code, you can also call the
          <code>config.setInitParameter()</code> method (<code>config</code>
          being the implicit object of type <code>ServletConfig</code>) to
          simulate initialisation parameters as if they had been defined in
          your <code>web.xml</code>.
        </note>

        <p>
          Last, if you need to unit test code that uses the Servlet
          Security API, please check the
          <link href="site:howto_security">Security Howto</link>.
        </p>

      </section>

      <anchor id="logging"/>
      <section title="Cactus logging configuration">

        <p>
          Since Cactus 1.4, we have switched to using the
          <link href="http://jakarta.apache.org/commons/logging.html">Jakarta
          Commons Logging</link> framework for Cactus internal logs (and any
          log you may wish to output as part of your test).
        </p>

        <p>
          This allow Cactus to use any underlying logging framework such as:
          <link href="http://jakarta.apache.org/log4j">Log4J</link>,
          <link href="http://jakarta.apache.org/avalon/logkit">LogKit</link>,
          JDK 1.4 Logging or even a Simple Logger provided as part of Commons
          Logging (it outputs to the console).
        </p>

        <p>
          Cactus is completely agnostic with regards to the logging framework
          configuration, so you will have to learn how to configure your
          favorite logging yourself. However here are some tips to help set up
          a Cactus logging configuration.
        </p>

        <section title="'cactus.logging.config' property">

          <p>
            Cactus provides an optional <code>cactus.logging.config</code>
            configuration property. If set, Cactus will load the properties 
            file pointed by this property and will set each property as a 
            system property. This allowsw putting all logging-related 
            properties into a single place, as demonstrated below.
          </p>

          <note>
            If you're using the Ant <code>&lt;cactus&gt;</code> task, please
            refer to the <a href="site:task_cactus">documentation for that 
            task</a> to set up Cactus logging.
          </note>          
          
        </section>   

        <section title="Sample logging configuration files">

          <p>
            As Cactus is running in 2 JVMs (client side and server side), 
            you'll need to provide 2 logging configuration if you wish to
            enable logging for both sides. Here are some sample configuration
            files.
          </p>

          <section title="Client side configuration sample">

            <note>
              Notice that for JDK 1.4 logging and for Log4J logging you have
              to specify that path to this file as these 2 logging systems also
              use a configuration file to configure themselves. Alternatively
              you can put configuration data in other files. However, it's
              convenient to group everything in a single file.
            </note>
          
<source><![CDATA[
# -----------------------------------------------------------------------------
# Logging properties
# -----------------------------------------------------------------------------

# Disable logging by default when running the tests. If you wish to use a 
# logging subsystem, uncomment the line below. That will let Commons logging
# decide automatically of a suitable logging system for you. You can also force
# commons-logging to use a specific logging system. For more info, see
# http://jakarta.apache.org/commons/logging

# Disable logging
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.NoOpLog

# Force to use JDK 1.4 logging
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.Jdk14Logger

# Force to use Log4J logging
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger

# Force to use Simple logging
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.SimpleLog

# ---- JDK 1.4 logging properties

# Following properties are useful if you're using the JDK 1.4 logging subsystem
# and wish to output logs to a file. Make sure to comment out the NoOpLog line 
# above.
java.util.logging.config.file = @target.dir@/logging_client.properties
handlers = java.util.logging.FileHandler
java.util.logging.FileHandler.pattern = @target.dir@/test_client.log
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

# If you want to provide finer grained logging, restrict the level for the 
# specific package name. 
# For example: 
# org.apache.cactus.server.level = ALL
# org.apache.commons.httpclient.level = ALL
# .level = ALL
org.apache.cactus.level = ALL

# ---- Log4J logging properties

# Following properties are useful if you're using the Log4J logging subsystem
# and wish to output logs to a file. Make sure to comment out the NoOpLog line 
# above.
log4j.configuration = file:/@target.dir@/logging_client.properties

log4j.appender.cactus = org.apache.log4j.FileAppender
log4j.appender.cactus.File = @target.dir@/test_client.log
log4j.appender.cactus.Append = false
log4j.appender.cactus.layout = org.apache.log4j.PatternLayout
log4j.appender.cactus.layout.ConversionPattern = %d{ABSOLUTE} [%t] %-5p %-30.30c{2} %x - %m %n

# Any application log which uses Log4J will be logged to the Cactus log file
log4j.rootCategory=DEBUG, cactus

# Debug logs for Cactus
log4j.category.org.apache.cactus = DEBUG, cactus
log4j.additivity.org.apache.cactus = false

# Debug logs for HttpClient
log4j.category.org.apache.commons.httpclient = DEBUG, cactus
log4j.additivity.org.apache.commons.httpclient = false
log4j.category.httpclient = WARN, cactus
log4j.additivity.httpclient = false

# ---- SimpleLog logging properties

org.apache.commons.logging.simplelog.showlogname = true
org.apache.commons.logging.simplelog.log.org.apache.cactus = trace
org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient = trace
]]></source>

          </section>
          
          <section title="Server side configuration sample">

            <note>
              Notice that for JDK 1.4 logging and for Log4J logging you have
              to specify that path to this file as these 2 logging systems also
              use a configuration file to configure themselves. Alternatively
              you can put configuration data in other files. However, it's
              convenient to group everything in a single file.
            </note>

<source><![CDATA[
# -----------------------------------------------------------------------------
# Logging properties
# -----------------------------------------------------------------------------

# Disable logging by default when running the tests. If you wish to use a 
# logging subsystem, uncomment the line below. That will let Commons logging
# decide automatically of a suitable logging system for you. You can also force
# commons-logging to use a specific logging system. For more info, see
# http://jakarta.apache.org/commons/logging

# Disable logging
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.NoOpLog

# Force to use JDK 1.4 logging
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.Jdk14Logger

# Force to use Log4J logging
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger

# Force to use Simple logging
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.SimpleLog

# ---- JDK 1.4 logging properties

# Following properties are useful if you're using the JDK 1.4 logging subsystem
# and wish to output logs to a file. Make sure to comment out the NoOpLog line 
# above.
java.util.logging.config.file = @target.dir@/logging_server.properties
handlers = java.util.logging.FileHandler
java.util.logging.FileHandler.pattern = @target.dir@/test_server.log
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

# If you want to provide finer grained logging, restrict the level for the 
# specific package name. 
# For example: org.apache.cactus.server.level = ALL
org.apache.cactus.level = ALL

# ---- Log4J logging properties

# Following properties are useful if you're using the Log4J logging subsystem
# and wish to output logs to a file. Make sure to comment out the NoOpLog line 
# above.
log4j.configuration = file:/@target.dir@/logging_server.properties

log4j.appender.cactus = org.apache.log4j.FileAppender
log4j.appender.cactus.File = @target.dir@/test_server.log
log4j.appender.cactus.Append = false
log4j.appender.cactus.layout = org.apache.log4j.PatternLayout
log4j.appender.cactus.layout.ConversionPattern = %d{ABSOLUTE} [%t] %-5p %-30.30c{2} %x - %m %n

# Any application log which uses Log4J will be logged to the Cactus log file
log4j.rootCategory=DEBUG, cactus

# Debug logs for Cactus
log4j.category.org.apache.cactus = DEBUG, cactus
log4j.additivity.org.apache.cactus = false

# Debug logs for HttpClient
log4j.category.org.apache.commons.httpclient = DEBUG, cactus
log4j.additivity.org.apache.commons.httpclient = false
log4j.category.httpclient = WARN, cactus
log4j.additivity.httpclient = false

# ---- SimpleLog logging properties

org.apache.commons.logging.simplelog.showlogname = true
org.apache.commons.logging.simplelog.log.org.apache.cactus = trace
org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient = trace
]]></source>

          </section>
          
        </section>
        
        <section title="Tips">

          <p>
            JUnit uses a different classloader to load each test of a TestCase
            class. Thus, Log4j will reinitialise for each test, which may lead
            to overwriting the <code>test_client.log</code> file each time
            (this is because we have set <code>log4j.appender.cactus.Append</code>
            to <code>false</code>. You can set it to <code>true</code> if you
            wish to keep all the logs but the file size will grow quickly. In
            addition logs are really only useful when there is a failure and
            thus not appending is usually a good choice.
          </p>

        </section>

      </section>

    </section>

  </body>
</document>
