Author: remy.maucherat(a)jboss.com
Date: 2007-09-14 15:01:03 -0400 (Fri, 14 Sep 2007)
New Revision: 277
Modified:
trunk/java/org/apache/catalina/connector/OutputBuffer.java
trunk/java/org/apache/catalina/connector/Response.java
trunk/java/org/apache/catalina/session/ManagerBase.java
trunk/java/org/apache/catalina/session/mbeans-descriptors.xml
trunk/java/org/apache/catalina/valves/AccessLogValve.java
trunk/java/org/apache/catalina/valves/ExtendedAccessLogValve.java
trunk/java/org/apache/catalina/valves/JDBCAccessLogValve.java
trunk/java/org/apache/juli/ClassLoaderLogManager.java
trunk/webapps/docs/changelog.xml
trunk/webapps/docs/config/valve.xml
Log:
- Port from Tomcat 6.0.
- Better large file support in access log valves.
- Access to session creation time.
- Improved property replacement in logging configuration.
Modified: trunk/java/org/apache/catalina/connector/OutputBuffer.java
===================================================================
--- trunk/java/org/apache/catalina/connector/OutputBuffer.java 2007-09-12 10:18:02 UTC
(rev 276)
+++ trunk/java/org/apache/catalina/connector/OutputBuffer.java 2007-09-14 19:01:03 UTC
(rev 277)
@@ -70,13 +70,13 @@
/**
* Number of bytes written.
*/
- private int bytesWritten = 0;
+ private long bytesWritten = 0;
/**
* Number of chars written.
*/
- private int charsWritten = 0;
+ private long charsWritten = 0;
/**
@@ -169,7 +169,7 @@
* @param coyoteResponse Associated Coyote response
*/
public void setResponse(Response coyoteResponse) {
- this.coyoteResponse = coyoteResponse;
+ this.coyoteResponse = coyoteResponse;
}
@@ -351,7 +351,7 @@
* @throws IOException An underlying IOException occurred
*/
public void realWriteBytes(byte buf[], int off, int cnt)
- throws IOException {
+ throws IOException {
if (closed)
return;
@@ -552,22 +552,32 @@
}
-
public int getBytesWritten() {
- return bytesWritten;
+ if (bytesWritten < Integer.MAX_VALUE) {
+ return (int) bytesWritten;
+ }
+ return -1;
}
-
public int getCharsWritten() {
- return charsWritten;
+ if (charsWritten < Integer.MAX_VALUE) {
+ return (int) charsWritten;
+ }
+ return -1;
}
+ public int getContentWritten() {
+ long size = bytesWritten + charsWritten ;
+ if (size < Integer.MAX_VALUE) {
+ return (int) size;
+ }
+ return -1;
+ }
- public int getContentWritten() {
+ public long getContentWrittenLong() {
return bytesWritten + charsWritten;
}
-
-
+
/**
* True if this buffer hasn't been used ( since recycle() ) -
* i.e. no chars or bytes have been added to the buffer.
Modified: trunk/java/org/apache/catalina/connector/Response.java
===================================================================
--- trunk/java/org/apache/catalina/connector/Response.java 2007-09-12 10:18:02 UTC (rev
276)
+++ trunk/java/org/apache/catalina/connector/Response.java 2007-09-14 19:01:03 UTC (rev
277)
@@ -58,7 +58,7 @@
*
* @author Remy Maucherat
* @author Craig R. McClanahan
- * @version $Revision: 542491 $ $Date: 2007-05-29 13:24:13 +0200 (mar., 29 mai 2007) $
+ * @version $Revision: 575478 $ $Date: 2007-09-13 23:56:30 +0200 (Thu, 13 Sep 2007) $
*/
public class Response
@@ -305,8 +305,14 @@
public int getContentCount() {
return outputBuffer.getContentWritten();
}
+
+ /**
+ * Return the number of bytes actually written to the output stream.
+ */
+ public long getContentCountLong() {
+ return outputBuffer.getContentWrittenLong();
+ }
-
/**
* Set the application commit flag.
*
Modified: trunk/java/org/apache/catalina/session/ManagerBase.java
===================================================================
--- trunk/java/org/apache/catalina/session/ManagerBase.java 2007-09-12 10:18:02 UTC (rev
276)
+++ trunk/java/org/apache/catalina/session/ManagerBase.java 2007-09-14 19:01:03 UTC (rev
277)
@@ -61,7 +61,7 @@
* be subclassed to create more sophisticated Manager implementations.
*
* @author Craig R. McClanahan
- * @version $Revision: 542185 $ $Date: 2007-05-28 12:06:31 +0200 (lun., 28 mai 2007) $
+ * @version $Revision: 573964 $ $Date: 2007-09-09 11:04:27 +0200 (Sun, 09 Sep 2007) $
*/
public abstract class ManagerBase implements Manager, MBeanRegistration {
@@ -1207,12 +1207,22 @@
public String getLastAccessedTime( String sessionId ) {
Session s=(Session)sessions.get(sessionId);
if( s==null ) {
- log.info("Session not found " + sessionId);
+ if(log.isInfoEnabled())
+ log.info("Session not found " + sessionId);
return "";
}
return new Date(s.getLastAccessedTime()).toString();
}
+ public String getCreationTime( String sessionId ) {
+ Session s=(Session)sessions.get(sessionId);
+ if( s==null ) {
+ if(log.isInfoEnabled())
+ log.info("Session not found " + sessionId);
+ return "";
+ }
+ return new Date(s.getCreationTime()).toString();
+ }
// -------------------- JMX and Registration --------------------
protected String domain;
Modified: trunk/java/org/apache/catalina/session/mbeans-descriptors.xml
===================================================================
--- trunk/java/org/apache/catalina/session/mbeans-descriptors.xml 2007-09-12 10:18:02 UTC
(rev 276)
+++ trunk/java/org/apache/catalina/session/mbeans-descriptors.xml 2007-09-14 19:01:03 UTC
(rev 277)
@@ -135,6 +135,15 @@
type="java.lang.String"/>
</operation>
+ <operation name="getCreationTime"
+ description="Get the creation time"
+ impact="ACTION"
+ returnType="java.lang.String">
+ <parameter name="sessionId"
+ description="Id of the session"
+ type="java.lang.String"/>
+ </operation>
+
</mbean>
<mbean name="PersistentManager"
@@ -287,6 +296,15 @@
type="java.lang.String"/>
</operation>
+ <operation name="getCreationTime"
+ description="Get the creation time"
+ impact="ACTION"
+ returnType="java.lang.String">
+ <parameter name="sessionId"
+ description="Id of the session"
+ type="java.lang.String"/>
+ </operation>
+
</mbean>
</mbeans-descriptors>
Modified: trunk/java/org/apache/catalina/valves/AccessLogValve.java
===================================================================
--- trunk/java/org/apache/catalina/valves/AccessLogValve.java 2007-09-12 10:18:02 UTC (rev
276)
+++ trunk/java/org/apache/catalina/valves/AccessLogValve.java 2007-09-14 19:01:03 UTC (rev
277)
@@ -43,8 +43,8 @@
import org.apache.catalina.connector.Response;
import org.apache.catalina.util.LifecycleSupport;
import org.apache.catalina.util.StringManager;
+import org.apache.coyote.RequestInfo;
import org.jboss.logging.Logger;
-import org.jboss.logging.Logger;
/**
@@ -79,6 +79,7 @@
* <li><b>%v</b> - Local server name
* <li><b>%D</b> - Time taken to process the request, in millis
* <li><b>%T</b> - Time taken to process the request, in seconds
+ * <li><b>%I</b> - current Request thread name (can compare later with
stacktraces)
* </ul>
* <p>In addition, the caller can specify one of the following aliases for
* commonly utilized patterns:</p>
@@ -94,6 +95,7 @@
* It is modeled after the apache syntax:
* <ul>
* <li><code>%{xxx}i</code> for incoming headers
+ * <li><code>%{xxx}o</code> for outgoing response headers
* <li><code>%{xxx}c</code> for a specific cookie
* <li><code>%{xxx}r</code> xxx is an attribute in the ServletRequest
* <li><code>%{xxx}s</code> xxx is an attribute in the HttpSession
@@ -111,7 +113,9 @@
* @author Jason Brittain
* @author Remy Maucherat
* @author Takayuki Kaneko
- * @version $Revision: 539787 $ $Date: 2007-01-04 12:17:11 +0900
+ * @author Peter Rossbach
+ *
+ * @version $Revision: 575475 $ $Date: 2007-09-13 23:43:22 +0200 (Thu, 13 Sep 2007) $
*/
public class AccessLogValve
@@ -140,7 +144,7 @@
* The descriptive information about this implementation.
*/
protected static final String info =
- "org.apache.catalina.valves.AccessLogValve/2.0";
+ "org.apache.catalina.valves.AccessLogValve/2.1";
/**
@@ -890,6 +894,7 @@
.getString("accessLogValve.notStarted"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
+
close();
}
@@ -903,6 +908,21 @@
}
/**
+ * write thread name - %I
+ */
+ protected class ThreadNameElement implements AccessLogElement {
+ public void addElement(StringBuffer buf, Date date, Request request,
+ Response response, long time) {
+ RequestInfo info = request.getCoyoteRequest().getRequestProcessor();
+ if(info != null) {
+ buf.append(info.getWorkerThreadName());
+ } else {
+ buf.append("-");
+ }
+ }
+ }
+
+ /**
* write local IP address - %A
*/
protected class LocalAddrElement implements AccessLogElement {
@@ -1078,7 +1098,7 @@
public void addElement(StringBuffer buf, Date date, Request request,
Response response, long time) {
- int length = response.getContentCount();
+ long length = response.getContentCountLong() ;
if (length <= 0 && conversion) {
buf.append('-');
} else {
@@ -1248,6 +1268,34 @@
}
/**
+ * write a specific response header - %{xxx}o
+ */
+ protected class ResponseHeaderElement implements AccessLogElement {
+ private String header;
+
+ public ResponseHeaderElement(String header) {
+ this.header = header;
+ }
+
+ public void addElement(StringBuffer buf, Date date, Request request,
+ Response response, long time) {
+ if (null != response) {
+ String[] values = response.getHeaderValues(header);
+ if(values.length > 0) {
+ for (int i = 0; i < values.length; i++) {
+ String string = values[i];
+ buf.append(string) ;
+ if(i+1<values.length)
+ buf.append(",");
+ }
+ return ;
+ }
+ }
+ buf.append("-");
+ }
+ }
+
+ /**
* write an attribute in the ServletRequest - %{xxx}r
*/
protected class RequestAttributeElement implements AccessLogElement {
@@ -1370,10 +1418,12 @@
return new HeaderElement(header);
case 'c':
return new CookieElement(header);
+ case 'o':
+ return new ResponseHeaderElement(header);
case 'r':
return new RequestAttributeElement(header);
case 's':
- return new SessionAttributeElement(header);
+ return new SessionAttributeElement(header);
default:
return new StringElement("???");
}
@@ -1422,6 +1472,8 @@
return new RequestURIElement();
case 'v':
return new LocalServerNameElement();
+ case 'I':
+ return new ThreadNameElement();
default:
return new StringElement("???" + pattern + "???");
}
Modified: trunk/java/org/apache/catalina/valves/ExtendedAccessLogValve.java
===================================================================
--- trunk/java/org/apache/catalina/valves/ExtendedAccessLogValve.java 2007-09-12 10:18:02
UTC (rev 276)
+++ trunk/java/org/apache/catalina/valves/ExtendedAccessLogValve.java 2007-09-14 19:01:03
UTC (rev 277)
@@ -64,6 +64,7 @@
* <li><code>time-taken</code>: Time (in seconds) taken to serve the
request</li>
* <li><code>x-A(XXX)</code>: Pull XXX attribute from the servlet
context </li>
* <li><code>x-C(XXX)</code>: Pull the first cookie of the name XXX
</li>
+ * <li><code>x-O(XXX)</code>: Pull the all response header values XXX
</li>
* <li><code>x-R(XXX)</code>: Pull XXX attribute from the servlet
request </li>
* <li><code>x-S(XXX)</code>: Pull XXX attribute from the session
</li>
* <li><code>x-P(...)</code>: Call request.getParameter(...)
@@ -122,7 +123,9 @@
*
*
* @author Tim Funk
- * @version $Revision: 522854 $ $Date: 2007-03-27 12:10:45 +0200 (mar., 27 mars 2007) $
+ * @author Peter Rossbach
+ *
+ * @version $Revision: 575411 $ $Date: 2007-09-13 21:31:16 +0200 (Thu, 13 Sep 2007) $
*/
public class ExtendedAccessLogValve
@@ -138,7 +141,7 @@
* The descriptive information about this implementation.
*/
protected static final String extendedAccessLogInfo =
- "org.apache.catalina.valves.ExtendedAccessLogValve/1.0";
+ "org.apache.catalina.valves.ExtendedAccessLogValve/2.1";
// ------------------------------------------------------------- Properties
@@ -209,7 +212,7 @@
super.open();
if (currentLogFile.length()==0) {
writer.println("#Fields: " + pattern);
- writer.println("#Version: 1.0");
+ writer.println("#Version: 2.0");
writer.println("#Software: " + ServerInfo.getServerInfo());
}
}
@@ -331,6 +334,36 @@
}
}
+ /**
+ * write a specific response header - x-O(xxx)
+ */
+ protected class ResponseAllHeaderElement implements AccessLogElement {
+ private String header;
+
+ public ResponseAllHeaderElement(String header) {
+ this.header = header;
+ }
+
+ public void addElement(StringBuffer buf, Date date, Request request,
+ Response response, long time) {
+ if (null != response) {
+ String[] values = response.getHeaderValues(header);
+ if(values.length > 0) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < values.length; i++) {
+ String string = values[i];
+ buffer.append(string) ;
+ if(i+1<values.length)
+ buffer.append(",");
+ }
+ buf.append(wrap(buffer.toString()));
+ return ;
+ }
+ }
+ buf.append("-");
+ }
+ }
+
protected class RequestAttributeElement implements AccessLogElement {
private String attribute;
@@ -718,6 +751,8 @@
return getServletRequestElement(parameter);
} else if ("P".equals(token)) {
return new RequestParameterElement(parameter);
+ } else if ("O".equals(token)) {
+ return new ResponseAllHeaderElement(parameter);
}
log.error("x param for servlet request, couldn't decode value: "
+ token);
Modified: trunk/java/org/apache/catalina/valves/JDBCAccessLogValve.java
===================================================================
--- trunk/java/org/apache/catalina/valves/JDBCAccessLogValve.java 2007-09-12 10:18:02 UTC
(rev 276)
+++ trunk/java/org/apache/catalina/valves/JDBCAccessLogValve.java 2007-09-14 19:01:03 UTC
(rev 277)
@@ -45,11 +45,11 @@
* To use, copy into the server/classes directory of the Tomcat installation
* and configure in server.xml as:
* <pre>
- * <Valve className="org.apache.catalina.valves.JDBCAccessLogValve"
- * driverName="<i>your_jdbc_driver</i>"
- * connectionURL="<i>your_jdbc_url</i>"
- * pattern="combined" resolveHosts="false"
- * />
+ * <Valve
className="org.apache.catalina.valves.JDBCAccessLogValve"
+ * driverName="<i>your_jdbc_driver</i>"
+ * connectionURL="<i>your_jdbc_url</i>"
+ * pattern="combined" resolveHosts="false"
+ * />
* </pre>
* </p>
* <p>
@@ -93,6 +93,11 @@
* INDEX (userAgent)
* );
* </pre>
+ * <p>Set JDBCAccessLogValve attribute useLongContentLength="true" as you
have more then 4GB outputs.
+ * Please, use long SQL datatype at access.bytes attribute.
+ * The datatype of bytes at oracle is <i>number</i> and other databases use
<i>bytes BIGINT NOT NULL</i>.
+ * </p>
+ *
* <p>
* If the table is created as above, its name and the field names don't need
* to be defined.
@@ -120,21 +125,21 @@
* Class constructor. Initializes the fields with the default values.
* The defaults are:
* <pre>
- * driverName = null;
- * connectionURL = null;
- * tableName = "access";
- * remoteHostField = "remoteHost";
- * userField = "userName";
- * timestampField = "timestamp";
- * virtualHostField = "virtualHost";
- * methodField = "method";
- * queryField = "query";
- * statusField = "status";
- * bytesField = "bytes";
- * refererField = "referer";
- * userAgentField = "userAgent";
- * pattern = "common";
- * resolveHosts = false;
+ * driverName = null;
+ * connectionURL = null;
+ * tableName = "access";
+ * remoteHostField = "remoteHost";
+ * userField = "userName";
+ * timestampField = "timestamp";
+ * virtualHostField = "virtualHost";
+ * methodField = "method";
+ * queryField = "query";
+ * statusField = "status";
+ * bytesField = "bytes";
+ * refererField = "referer";
+ * userAgentField = "userAgent";
+ * pattern = "common";
+ * resolveHosts = false;
* </pre>
*/
public JDBCAccessLogValve() {
@@ -162,8 +167,13 @@
// ----------------------------------------------------- Instance Variables
-
/**
+ * Use long contentLength as you have more 4 GB output.
+ * @since 6.0.15
+ */
+ protected boolean useLongContentLength = false ;
+
+ /**
* The connection username to use when trying to connect to the database.
*/
protected String connectionName = null;
@@ -419,6 +429,19 @@
this.resolveHosts = new Boolean(resolveHosts).booleanValue();
}
+ /**
+ * get useLongContentLength
+ */
+ public boolean getUseLongContentLength() {
+ return this.useLongContentLength ;
+ }
+
+ /**
+ * @param useLongContentLength the useLongContentLength to set
+ */
+ public void setUseLongContentLength(boolean useLongContentLength) {
+ this.useLongContentLength = useLongContentLength;
+ }
// --------------------------------------------------------- Public Methods
@@ -435,37 +458,35 @@
*/
public void invoke(Request request, Response response)
throws IOException, ServletException {
-
+ final String EMPTY = "" ;
+
getNext().invoke(request, response);
- String remoteHost = "";
+ String remoteHost = EMPTY;
if(resolveHosts)
remoteHost = request.getRemoteHost();
else
remoteHost = request.getRemoteAddr();
- String user = "";
+ String user = EMPTY;
if(request != null)
user = request.getRemoteUser();
String query="";
if(request != null)
query = request.getRequestURI();
- int bytes = response.getContentCount();
+
+ long bytes = response.getContentCountLong() ;
if(bytes < 0)
bytes = 0;
int status = response.getStatus();
- if (pattern.equals("combined")) {
- String virtualHost = "";
- if(request != null)
- virtualHost = request.getServerName();
- String method = "";
- if(request != null)
- method = request.getMethod();
- String referer = "";
- if(request != null)
- referer = request.getHeader("referer");
- String userAgent = "";
- if(request != null)
- userAgent = request.getHeader("user-agent");
+ String virtualHost = EMPTY;
+ String method = EMPTY;
+ String referer = EMPTY;
+ String userAgent = EMPTY;
+ if (pattern.equals("combined") && request != null) {
+ virtualHost = request.getServerName();
+ method = request.getMethod();
+ referer = request.getHeader("referer");
+ userAgent = request.getHeader("user-agent");
}
synchronized (this) {
int numberOfTries = 2;
@@ -478,21 +499,15 @@
ps.setTimestamp(3, new Timestamp(getCurrentTimeMillis()));
ps.setString(4, query);
ps.setInt(5, status);
- ps.setInt(6, bytes);
+
+ if(useLongContentLength) {
+ ps.setLong(6, bytes);
+ } else {
+ if (bytes > Integer.MAX_VALUE)
+ bytes = -1 ;
+ ps.setInt(6, (int) bytes);
+ }
if (pattern.equals("combined")) {
-
- String virtualHost = "";
- if(request != null)
- virtualHost = request.getServerName();
- String method = "";
- if(request != null)
- method = request.getMethod();
- String referer = "";
- if(request != null)
- referer = request.getHeader("referer");
- String userAgent = "";
- if(request != null)
- userAgent = request.getHeader("user-agent");
ps.setString(7, virtualHost);
ps.setString(8, method);
ps.setString(9, referer);
@@ -508,11 +523,11 @@
if (conn != null)
close();
}
- numberOfTries--;
+ numberOfTries--;
}
}
- }
+ }
/**
@@ -666,7 +681,7 @@
started = false;
close() ;
-
+
}
Modified: trunk/java/org/apache/juli/ClassLoaderLogManager.java
===================================================================
--- trunk/java/org/apache/juli/ClassLoaderLogManager.java 2007-09-12 10:18:02 UTC (rev
276)
+++ trunk/java/org/apache/juli/ClassLoaderLogManager.java 2007-09-14 19:01:03 UTC (rev
277)
@@ -442,13 +442,19 @@
*/
protected String replace(String str) {
String result = str;
- if (result.startsWith("${")) {
- int pos = result.indexOf('}');
- if (pos != -1) {
- String propName = result.substring(2, pos);
+ int pos_start = result.indexOf("${");
+ if (pos_start != -1) {
+ int pos_end = result.indexOf('}');
+ if (pos_end != -1) {
+ String propName = result.substring(pos_start + 2, pos_end);
String replacement = System.getProperty(propName);
if (replacement != null) {
- result = replacement + result.substring(pos + 1);
+ if(pos_start >0) {
+ result = result.substring(0,pos_start) +
+ replacement + replace(result.substring(pos_end + 1));
+ } else {
+ result = replacement + replace(result.substring(pos_end + 1));
+ }
}
}
}
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2007-09-12 10:18:02 UTC (rev 276)
+++ trunk/webapps/docs/changelog.xml 2007-09-14 19:01:03 UTC (rev 277)
@@ -68,6 +68,11 @@
<subsection name="Catalina">
<changelog>
<fix>
+ <bug>30949</bug>: Improve previous fix. Ensure requests are
re-cycled
+ on cross-context includes and forwards when an exception occurs in the
+ target page. (markt)
+ </fix>
+ <fix>
<bug>42944</bug>: Correctly handle servlet mappings that use a
'+'
character as part of the url pattern. (markt)
</fix>
@@ -87,14 +92,31 @@
Takayuki Kaneko. (markt)
</fix>
<fix>
- <bug>43216</bug>: Set correct StandardSession#accessCount as
StandardSession.ACTIVITY_CHECK is true.
- Patch provided by Takayuki Kaneko (pero)
+ <bug>43216</bug>: Set correct StandardSession#accessCount as
StandardSession.ACTIVITY_CHECK is true.
+ Patch provided by Takayuki Kaneko (pero)
</fix>
+ <add>
+ Made session createTime accessible for all SessionManager via JMX (pero)
+ </add>
+ <update>
+ <bug>43129</bug>: Support logging of all response header values at
AccessLogValve (ex. add %{Set-Cookie}o to your pattern). (pero)
+ </update>
+ <add>
+ Support logging of all response header values at ExtendedAccessLogValve (ex. add
x-O(Set-Cookie) to your pattern). (pero)
+ </add>
+ <add>
+ Support logging of current thread name at AccessLogValve (ex. add %I to your
pattern).
+ Usefull to compare access logging entry later with a stacktraces. (pero)
+ </add>
<fix>
- <bug>30949</bug>: Improve previous fix. Ensure requests are
re-cycled
- on cross-context includes and forwards when an exception occurs in the
- target page. (markt)
- </fix>
+ Improve large-file support (more then 4 Gb) at all AccessLogValves, backport from
5.5.25. (pero)
+ </fix>
+ <update>
+ Optimized JDBCAccessLogValve combined pattern request attribute access. (pero)
+ </update>
+ <fix>
+ o.a.juli.ClassLoaderLogManager handle more then one system property replacement
at file logging.properties. (pero)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
@@ -127,7 +149,9 @@
</fix>
</changelog>
</subsection>
+
</section>
+
<section name="Tomcat 6.0.14 (remm)">
<subsection name="General">
<changelog>
Modified: trunk/webapps/docs/config/valve.xml
===================================================================
--- trunk/webapps/docs/config/valve.xml 2007-09-12 10:18:02 UTC (rev 276)
+++ trunk/webapps/docs/config/valve.xml 2007-09-14 19:01:03 UTC (rev 277)
@@ -163,6 +163,7 @@
<li><b>%v</b> - Local server name</li>
<li><b>%D</b> - Time taken to process the request, in
millis</li>
<li><b>%T</b> - Time taken to process the request, in
seconds</li>
+ <li><b>%I</b> - current request thread name (can compare later with
stacktraces)</li>
</ul>
<p>
@@ -171,6 +172,7 @@
It is modeled after the apache syntax:
<ul>
<li><b><code>%{xxx}i</code></b> for incoming
headers</li>
+ <li><b><code>%{xxx}o</code></b> for outgoing response
headers</li>
<li><b><code>%{xxx}c</code></b> for a specific
cookie</li>
<li><b><code>%{xxx}r</code></b> xxx is an attribute in
the ServletRequest</li>
<li><b><code>%{xxx}s</code></b> xxx is an attribute in
the HttpSession</li>
@@ -381,7 +383,10 @@
rechecking with the <strong>Realm</strong>.</p>
</attribute>
-
+ <attribute name="cookieDomain" required="false">
+ <p>Sets the host domain to be used for sso cookies.</p>
+ </attribute>
+
</attributes>
</subsection>