Author: markt
Date: Thu Sep 25 19:38:15 2014
New Revision: 1627619
URL: http://svn.apache.org/r1627619
Log:
Refactor cookie parsing to make it more pluggable
Added:
tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessor.java (with
props)
tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java
(with props)
Modified:
tomcat/trunk/java/org/apache/catalina/Context.java
tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
tomcat/trunk/java/org/apache/catalina/connector/Request.java
tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml
tomcat/trunk/java/org/apache/catalina/startup/ContextRuleSet.java
tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
tomcat/trunk/java/org/apache/coyote/Request.java
tomcat/trunk/java/org/apache/tomcat/util/http/Cookies.java
tomcat/trunk/test/org/apache/catalina/core/TesterContext.java
tomcat/trunk/test/org/apache/tomcat/util/http/TestCookies.java
tomcat/trunk/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java
tomcat/trunk/webapps/docs/config/context.xml
Modified: tomcat/trunk/java/org/apache/catalina/Context.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Context.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Context.java Thu Sep 25 19:38:15 2014
@@ -17,7 +17,6 @@
package org.apache.catalina;
import java.net.URL;
-import java.nio.charset.Charset;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -38,6 +37,7 @@ import org.apache.tomcat.util.descriptor
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.apache.tomcat.util.http.CookieProcessor;
/**
* A <b>Context</b> is a Container that represents a servlet context, and
@@ -1640,38 +1640,16 @@ public interface Context extends Contain
public Object getNamingToken();
/**
- * Should this context use the new RFC6265 based cookie parser for
- * processing HTTP cookies? The default value is currently false but that
- * may change in a future point release.
- */
- public void setUseRfc6265(boolean useRfc6265);
-
- /**
- * Does this context use the new RFC6265 based cookie parser for
- * processing HTTP cookies? The default value is currently false but that
- * may change in a future point release.
- */
- public boolean getUseRfc6265();
-
- /**
- * Specifies the name of the character encoding to use to convert bytes
into
- * characters when processing cookies using the RFC6265 based cookie
parser.
- * It has no effect if the RFC6265 parser is not used.
- * If an unrecognised character encoding is specified, a warning will be
- * logged and the default value of UTF-8 will be used.
- */
- public void setCookieEncoding(String encoding);
-
- /**
- * Returns the name of the character encoding used to convert bytes into
- * characters when processing cookies using the RFC6265 based cookie
parser.
- * The default value is UTF-8.
+ * Sets the {@link CookieProcessor} that will be used to process cookies
+ * for this Context.
+ *
+ * @param cookieProcessor The new cookie processor
*/
- public String getCookieEncoding();
+ public void setCookieProcessor(CookieProcessor cookieProcessor);
/**
- * Returns the character set used to convert bytes into characters when
- * processing cookies using the RFC6265 based cookie parser.
+ * Obtains the {@link CookieProcessor} that will be used to process cookies
+ * for this Context.
*/
- public Charset getCookieEncodingCharset();
+ public CookieProcessor getCookieProcessor();
}
Modified: tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Thu Sep
25 19:38:15 2014
@@ -46,8 +46,8 @@ import org.apache.tomcat.util.buf.B2CCon
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.http.Cookies;
import org.apache.tomcat.util.http.ServerCookie;
+import org.apache.tomcat.util.http.ServerCookies;
import org.apache.tomcat.util.net.SSLSupport;
import org.apache.tomcat.util.net.SocketStatus;
import org.apache.tomcat.util.res.StringManager;
@@ -903,15 +903,8 @@ public class CoyoteAdapter implements Ad
}
}
- if (request.getContext().getUseRfc6265()) {
- req.getCookies().setUseRfc6265(true);
- } else {
- req.getCookies().setUseRfc6265(false);
- }
-
-
// Look for session ID in cookies and SSL session
- parseSessionCookiesId(req, request);
+ parseSessionCookiesId(request);
parseSessionSslId(request);
sessionID = request.getRequestedSessionId();
@@ -1145,7 +1138,7 @@ public class CoyoteAdapter implements Ad
/**
* Parse session id in URL.
*/
- protected void parseSessionCookiesId(org.apache.coyote.Request req,
Request request) {
+ protected void parseSessionCookiesId(Request request) {
// If session tracking via cookies has been disabled for the current
// context, don't go looking for a session ID in a cookie as a cookie
@@ -1159,7 +1152,7 @@ public class CoyoteAdapter implements Ad
}
// Parse session id from cookies
- Cookies serverCookies = req.getCookies();
+ ServerCookies serverCookies = request.getServerCookies();
int count = serverCookies.getCookieCount();
if (count <= 0) {
return;
Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Request.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Thu Sep 25
19:38:15 2014
@@ -84,10 +84,11 @@ import org.apache.tomcat.util.ExceptionU
import org.apache.tomcat.util.buf.B2CConverter;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.http.Cookies;
+import org.apache.tomcat.util.http.CookieProcessor;
import org.apache.tomcat.util.http.FastHttpDateFormat;
import org.apache.tomcat.util.http.Parameters;
import org.apache.tomcat.util.http.ServerCookie;
+import org.apache.tomcat.util.http.ServerCookies;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.FileUploadBase;
import
org.apache.tomcat.util.http.fileupload.FileUploadBase.InvalidContentTypeException;
@@ -283,12 +284,20 @@ public class Request
/**
- * Cookies parsed flag.
+ * Cookie headers parsed flag. Indicates that the cookie headers have been
+ * parsed into ServerCookies.
*/
protected boolean cookiesParsed = false;
/**
+ * Cookie parsed flag. Indicates that the ServerCookies have been converted
+ * into user facing Cookie objects.
+ */
+ protected boolean cookiesConverted = false;
+
+
+ /**
* Secure flag.
*/
protected boolean secure = false;
@@ -462,6 +471,7 @@ public class Request
}
partsParseException = null;
cookiesParsed = false;
+ cookiesConverted = false;
locales.clear();
localesParsed = false;
secure = false;
@@ -1668,7 +1678,7 @@ public class Request
public void addCookie(Cookie cookie) {
if (!cookiesParsed) {
- parseCookies();
+ convertCookies();
}
int size = 0;
@@ -1703,6 +1713,7 @@ public class Request
*/
public void clearCookies() {
cookiesParsed = true;
+ cookiesConverted = true;
cookies = null;
}
@@ -1899,17 +1910,27 @@ public class Request
/**
- * Return the set of Cookies received with this Request.
+ * Return the set of Cookies received with this Request. Triggers parsing
of
+ * the Cookie HTTP headers followed by conversion to Cookie objects if this
+ * has not already been performed.
*/
@Override
public Cookie[] getCookies() {
-
- if (!cookiesParsed) {
- parseCookies();
+ if (!cookiesConverted) {
+ convertCookies();
}
-
return cookies;
+ }
+
+ /**
+ * Return the server representation of the cookies associated with this
+ * request. Triggers parsing of the Cookie HTTP headers (but not conversion
+ * to Cookie objects) if the headers have not yet been parsed.
+ */
+ public ServerCookies getServerCookies() {
+ parseCookies();
+ return coyoteRequest.getCookies();
}
@@ -2841,13 +2862,37 @@ public class Request
}
/**
- * Parse cookies.
+ * Parse cookies. This only parses the cookies into the memory efficient
+ * ServerCookies structure. It does not populate the Cookie objects.
*/
protected void parseCookies() {
+ if (cookiesParsed) {
+ return;
+ }
cookiesParsed = true;
- Cookies serverCookies = coyoteRequest.getCookies();
+ ServerCookies serverCookies = coyoteRequest.getCookies();
+ CookieProcessor cookieProcessor = getContext().getCookieProcessor();
+ cookieProcessor.parseCookieHeader(coyoteRequest.getMimeHeaders(),
serverCookies);
+ }
+
+ /**
+ * Converts the parsed cookies (parsing the Cookie headers first if they
+ * have not been parsed) into Cookie objects.
+ */
+ protected void convertCookies() {
+ if (cookiesConverted) {
+ return;
+ }
+
+ cookiesConverted = true;
+
+ parseCookies();
+
+ ServerCookies serverCookies = coyoteRequest.getCookies();
+ CookieProcessor cookieProcessor = getContext().getCookieProcessor();
+
int count = serverCookies.getCookieCount();
if (count <= 0) {
return;
@@ -2865,10 +2910,7 @@ public class Request
Cookie cookie = new Cookie(scookie.getName().toString(),null);
int version = scookie.getVersion();
cookie.setVersion(version);
- if (getContext().getUseRfc6265()) {
- scookie.getValue().getByteChunk().setCharset(
- getContext().getCookieEncodingCharset());
- }
+
scookie.getValue().getByteChunk().setCharset(cookieProcessor.getCharset());
cookie.setValue(unescape(scookie.getValue().toString()));
cookie.setPath(unescape(scookie.getPath().toString()));
String domain = scookie.getDomain().toString();
@@ -2888,9 +2930,9 @@ public class Request
System.arraycopy(cookies, 0, ncookies, 0, idx);
cookies = ncookies;
}
-
}
+
/**
* Parse request parameters.
*/
Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Thu Sep 25
19:38:15 2014
@@ -21,11 +21,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
@@ -118,7 +115,6 @@ import org.apache.tomcat.InstanceManager
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.IntrospectionUtils;
-import org.apache.tomcat.util.buf.B2CConverter;
import org.apache.tomcat.util.buf.UDecoder;
import org.apache.tomcat.util.descriptor.XmlIdentifiers;
import org.apache.tomcat.util.descriptor.web.ApplicationParameter;
@@ -132,6 +128,8 @@ import org.apache.tomcat.util.descriptor
import org.apache.tomcat.util.descriptor.web.MessageDestinationRef;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.apache.tomcat.util.http.CookieProcessor;
+import org.apache.tomcat.util.http.Cookies;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.apache.tomcat.util.security.PrivilegedGetTccl;
import org.apache.tomcat.util.security.PrivilegedSetTccl;
@@ -825,46 +823,23 @@ public class StandardContext extends Con
private final Object namingToken = new Object();
- private boolean useRfc6265 = false;
- private Charset cookieEncoding = StandardCharsets.UTF_8;
+ private CookieProcessor cookieProcessor;
// ----------------------------------------------------- Context Properties
-
@Override
- public void setUseRfc6265(boolean useRfc6265) {
- this.useRfc6265 = useRfc6265;
+ public void setCookieProcessor(CookieProcessor cookieProcessor) {
+ this.cookieProcessor = cookieProcessor;
}
@Override
- public boolean getUseRfc6265() {
- return useRfc6265;
- }
-
-
- @Override
- public void setCookieEncoding(String encoding) {
- try {
- Charset charset = B2CConverter.getCharset(encoding);
- cookieEncoding = charset;
- } catch (UnsupportedEncodingException uee) {
- cookieEncoding = StandardCharsets.UTF_8;
- log.warn(sm.getString("standardContext.unknownCookieEncoding"),
uee);
+ public CookieProcessor getCookieProcessor() {
+ if (cookieProcessor == null) {
+ cookieProcessor = new Cookies();
}
- }
-
-
- @Override
- public String getCookieEncoding() {
- return cookieEncoding.name();
- }
-
-
- @Override
- public Charset getCookieEncodingCharset() {
- return cookieEncoding;
+ return cookieProcessor;
}
Modified: tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml (original)
+++ tomcat/trunk/java/org/apache/catalina/core/mbeans-descriptors.xml Thu Sep
25 19:38:15 2014
@@ -103,10 +103,6 @@
type="boolean"
writeable="false" />
- <attribute name="cookieEncoding"
- description="If the new cookie parser is used, which encoding
should be used to decode the cookie values?"
- type="java.lang.String"/>
-
<attribute name="cookies"
description="Should we attempt to use cookies for session id
communication?"
type="boolean"/>
@@ -335,11 +331,6 @@
is="true"
type="boolean"/>
- <attribute name="useNewCookieParser"
- description="Use the new RFC6265 based cookie parser"
- is="false"
- type="boolean"/>
-
<attribute name="webappVersion"
description="The version of this web application - used in
parallel deployment to differentiate different versions of the same web
application"
type="java.lang.String"
Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextRuleSet.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextRuleSet.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/ContextRuleSet.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/ContextRuleSet.java Thu Sep
25 19:38:15 2014
@@ -242,6 +242,13 @@ public class ContextRuleSet extends Rule
"setJarScanFilter",
"org.apache.tomcat.JarScanFilter");
+ digester.addObjectCreate(prefix + "Context/CookieProcessor",
+ "org.apache.tomcat.util.http.Cookies",
+ "className");
+ digester.addSetProperties(prefix + "Context/CookieProcessor");
+ digester.addSetNext(prefix + "Context/CookieProcessor",
+ "setCookieProcessor",
+ "org.apache.tomcat.util.http.CookieProcessor");
}
}
Modified: tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/FailedContext.java Thu Sep 25
19:38:15 2014
@@ -19,8 +19,6 @@ package org.apache.catalina.startup;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -63,6 +61,7 @@ import org.apache.tomcat.util.descriptor
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.apache.tomcat.util.http.CookieProcessor;
import org.apache.tomcat.util.res.StringManager;
/**
@@ -758,17 +757,8 @@ public class FailedContext extends Lifec
public Object getNamingToken() { return null; }
@Override
- public void setUseRfc6265(boolean useRfc6265) { /* NO-OP */ }
+ public void setCookieProcessor(CookieProcessor cookieProcessor) { /* NO-OP
*/ }
@Override
- public boolean getUseRfc6265() {return false; }
-
- @Override
- public void setCookieEncoding(String encoding) { /* NO-OP */ }
-
- @Override
- public String getCookieEncoding() { return "UTF-8"; }
-
- @Override
- public Charset getCookieEncodingCharset() { return StandardCharsets.UTF_8;
}
+ public CookieProcessor getCookieProcessor() { return null; }
}
\ No newline at end of file
Modified: tomcat/trunk/java/org/apache/coyote/Request.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Request.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/Request.java (original)
+++ tomcat/trunk/java/org/apache/coyote/Request.java Thu Sep 25 19:38:15 2014
@@ -25,9 +25,9 @@ import javax.servlet.ReadListener;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.buf.UDecoder;
-import org.apache.tomcat.util.http.Cookies;
import org.apache.tomcat.util.http.MimeHeaders;
import org.apache.tomcat.util.http.Parameters;
+import org.apache.tomcat.util.http.ServerCookies;
import org.apache.tomcat.util.res.StringManager;
/**
@@ -62,6 +62,8 @@ public final class Request {
private static final StringManager sm =
StringManager.getManager(Constants.Package);
+ // Expected maximum typica number of cookies per request.
+ private static final int INITIAL_COOKIE_SIZE = 4;
// ----------------------------------------------------------- Constructors
@@ -121,7 +123,8 @@ public final class Request {
private long contentLength = -1;
private MessageBytes contentTypeMB = null;
private String charEncoding = null;
- private final Cookies cookies = new Cookies(headers);
+
+ private final ServerCookies serverCookies = new
ServerCookies(INITIAL_COOKIE_SIZE);
private final Parameters parameters = new Parameters();
private final MessageBytes remoteUser=MessageBytes.newInstance();
@@ -381,15 +384,13 @@ public final class Request {
// -------------------- Cookies --------------------
-
- public Cookies getCookies() {
- return cookies;
+ public ServerCookies getCookies() {
+ return serverCookies;
}
// -------------------- Parameters --------------------
-
public Parameters getParameters() {
return parameters;
}
@@ -528,7 +529,7 @@ public final class Request {
remotePort = -1;
available = 0;
- cookies.recycle();
+ serverCookies.recycle();
parameters.recycle();
uriMB.recycle();
Added: tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessor.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessor.java?rev=1627619&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessor.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessor.java Thu Sep
25 19:38:15 2014
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.tomcat.util.http;
+
+import java.nio.charset.Charset;
+
+public interface CookieProcessor {
+
+ /**
+ * Parse the provided headers into server cookie objects.
+ */
+ void parseCookieHeader(MimeHeaders headers, ServerCookies serverCookies);
+
+ /**
+ * The character set that is to be used to turn the bytes provided in the
+ * cookie header into characters for the cookie value.
+ */
+ Charset getCharset();
+}
Propchange: tomcat/trunk/java/org/apache/tomcat/util/http/CookieProcessor.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tomcat/trunk/java/org/apache/tomcat/util/http/Cookies.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/Cookies.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/Cookies.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/Cookies.java Thu Sep 25
19:38:15 2014
@@ -16,14 +16,13 @@
*/
package org.apache.tomcat.util.http;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.http.parser.Cookie;
import org.apache.tomcat.util.log.UserDataHelper;
import org.apache.tomcat.util.res.StringManager;
@@ -36,7 +35,7 @@ import org.apache.tomcat.util.res.String
* @author Costin Manolache
* @author kevin seguin
*/
-public final class Cookies {
+public final class Cookies implements CookieProcessor {
private static final Log log = LogFactory.getLog(Cookies.class);
@@ -45,72 +44,16 @@ public final class Cookies {
private static final StringManager sm =
StringManager.getManager("org.apache.tomcat.util.http");
- // expected average number of cookies per request
- public static final int INITIAL_SIZE = 4;
- private ServerCookies scookies = new ServerCookies(INITIAL_SIZE);
- private boolean unprocessed = true;
- private boolean useRfc6265 = false;
- private final MimeHeaders headers;
-
-
- /**
- * Construct a new cookie collection, that will extract
- * the information from headers.
- *
- * @param headers Cookies are lazy-evaluated and will extract the
- * information from the provided headers.
- */
- public Cookies(MimeHeaders headers) {
- this.headers = headers;
- }
-
-
- public void recycle() {
- scookies.recycle();
- unprocessed = true;
- useRfc6265 = false;
- }
-
-
- /**
- * EXPENSIVE!!! only for debugging.
- */
@Override
- public String toString() {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- pw.println("=== Cookies ===");
- int count = getCookieCount();
- for (int i = 0; i < count; ++i) {
- pw.println(getCookie(i).toString());
- }
- return sw.toString();
+ public Charset getCharset() {
+ return StandardCharsets.ISO_8859_1;
}
- /**
- * Indexed access.
- */
- public ServerCookie getCookie(int idx) {
- if (unprocessed) {
- // This will trigger cookie processing
- getCookieCount();
- }
- return scookies.getCookie(idx);
- }
-
-
- public int getCookieCount() {
- if (unprocessed) {
- unprocessed = false;
- processCookies(headers);
- }
- return scookies.getCookieCount();
- }
-
+ @Override
+ public void parseCookieHeader(MimeHeaders headers, ServerCookies
serverCookies) {
- private void processCookies(MimeHeaders headers) {
if (headers == null) {
// nothing to process
return;
@@ -135,10 +78,11 @@ public final class Cookies {
if (len > 0) {
byte[] buf = new byte[len];
System.arraycopy(bc.getBytes(), bc.getOffset(), buf,
0, len);
- processCookieHeader(buf, 0, len);
+ processCookieHeader(buf, 0, len, serverCookies);
}
} else {
- processCookieHeader(bc.getBytes(), bc.getOffset(),
bc.getLength());
+ processCookieHeader(bc.getBytes(), bc.getOffset(),
bc.getLength(),
+ serverCookies);
}
}
@@ -148,100 +92,15 @@ public final class Cookies {
}
- public void setUseRfc6265(boolean useRfc6265) {
- this.useRfc6265 = useRfc6265;
- }
-
-
- // XXX will be refactored soon!
- private static boolean equals(String s, byte b[], int start, int end) {
- int blen = end-start;
- if (b == null || blen != s.length()) {
- return false;
- }
- int boff = start;
- for (int i = 0; i < blen; i++) {
- if (b[boff++] != s.charAt(i)) {
- return false;
- }
- }
- return true;
- }
-
-
- /**
- * Returns true if the byte is a whitespace character as
- * defined in RFC2619
- * JVK
- */
- private static final boolean isWhiteSpace(final byte c) {
- // This switch statement is slightly slower
- // for my vm than the if statement.
- // Java(TM) 2 Runtime Environment, Standard Edition (build
1.5.0_07-164)
- /*
- switch (c) {
- case ' ':;
- case '\t':;
- case '\n':;
- case '\r':;
- case '\f':;
- return true;
- default:;
- return false;
- }
- */
- if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f') {
- return true;
- } else {
- return false;
- }
- }
-
-
- /**
- * Unescapes any double quotes in the given cookie value.
- *
- * @param bc The cookie value to modify
- */
- private static void unescapeDoubleQuotes(ByteChunk bc) {
-
- if (bc == null || bc.getLength() == 0 || bc.indexOf('"', 0) == -1) {
- return;
- }
-
- int src = bc.getStart();
- int end = bc.getEnd();
- int dest = src;
- byte[] buffer = bc.getBuffer();
-
- while (src < end) {
- if (buffer[src] == '\\' && src < end && buffer[src+1] == '"') {
- src++;
- }
- buffer[dest] = buffer[src];
- dest ++;
- src ++;
- }
- bc.setEnd(dest);
- }
-
-
- final void processCookieHeader(byte bytes[], int off, int len) {
- if (useRfc6265) {
- Cookie.parseCookie(bytes, off, len, scookies);
- } else {
- doProcessCookieHeaderOriginal(bytes, off, len);
- }
- }
-
-
/**
* Parses a cookie header after the initial "Cookie:"
* [WS][$]token[WS]=[WS](token|QV)[;|,]
* RFC 2965 / RFC 2109
* JVK
*/
- private void doProcessCookieHeaderOriginal(byte bytes[], int off, int len){
+ private static final void processCookieHeader(byte bytes[], int off, int
len,
+ ServerCookies serverCookies) {
+
if (len <= 0 || bytes == null) {
return;
}
@@ -460,7 +319,7 @@ public final class Cookies {
continue;
}
- sc = scookies.addCookie();
+ sc = serverCookies.addCookie();
sc.setVersion( version );
sc.getName().setBytes( bytes, nameStart,
nameEnd-nameStart);
@@ -527,4 +386,76 @@ public final class Cookies {
// Error, we have reached the end of the header w/o a end quote
return end;
}
+
+
+ private static final boolean equals(String s, byte b[], int start, int
end) {
+ int blen = end-start;
+ if (b == null || blen != s.length()) {
+ return false;
+ }
+ int boff = start;
+ for (int i = 0; i < blen; i++) {
+ if (b[boff++] != s.charAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Returns true if the byte is a whitespace character as
+ * defined in RFC2619
+ * JVK
+ */
+ private static final boolean isWhiteSpace(final byte c) {
+ // This switch statement is slightly slower
+ // for my vm than the if statement.
+ // Java(TM) 2 Runtime Environment, Standard Edition (build
1.5.0_07-164)
+ /*
+ switch (c) {
+ case ' ':;
+ case '\t':;
+ case '\n':;
+ case '\r':;
+ case '\f':;
+ return true;
+ default:;
+ return false;
+ }
+ */
+ if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Unescapes any double quotes in the given cookie value.
+ *
+ * @param bc The cookie value to modify
+ */
+ private static final void unescapeDoubleQuotes(ByteChunk bc) {
+
+ if (bc == null || bc.getLength() == 0 || bc.indexOf('"', 0) == -1) {
+ return;
+ }
+
+ int src = bc.getStart();
+ int end = bc.getEnd();
+ int dest = src;
+ byte[] buffer = bc.getBuffer();
+
+ while (src < end) {
+ if (buffer[src] == '\\' && src < end && buffer[src+1] == '"') {
+ src++;
+ }
+ buffer[dest] = buffer[src];
+ dest ++;
+ src ++;
+ }
+ bc.setEnd(dest);
+ }
}
Added: tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java?rev=1627619&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java
(added)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java
Thu Sep 25 19:38:15 2014
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.tomcat.util.http;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.http.parser.Cookie;
+
+public class Rfc6265CookieProcessor implements CookieProcessor {
+
+ private static final Log log =
LogFactory.getLog(Rfc6265CookieProcessor.class);
+
+ @Override
+ public Charset getCharset() {
+ return StandardCharsets.UTF_8;
+ }
+
+
+ @Override
+ public void parseCookieHeader(MimeHeaders headers,
+ ServerCookies serverCookies) {
+
+ if (headers == null) {
+ // nothing to process
+ return;
+ }
+
+ // process each "cookie" header
+ int pos = headers.findHeader("Cookie", 0);
+ while (pos >= 0) {
+ MessageBytes cookieValue = headers.getValue(pos);
+
+ if (cookieValue != null && !cookieValue.isNull() ) {
+ if (cookieValue.getType() != MessageBytes.T_BYTES ) {
+ Exception e = new Exception();
+ log.warn("Cookies: Parsing cookie as String. Expected
bytes.", e);
+ cookieValue.toBytes();
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Cookies: Parsing b[]: " +
cookieValue.toString());
+ }
+ ByteChunk bc = cookieValue.getByteChunk();
+
+ Cookie.parseCookie(bc.getBytes(), bc.getOffset(),
bc.getLength(),
+ serverCookies);
+ }
+
+ // search from the next position
+ pos = headers.findHeader("Cookie", ++pos);
+ }
+ }
+}
Propchange:
tomcat/trunk/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tomcat/trunk/test/org/apache/catalina/core/TesterContext.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TesterContext.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/core/TesterContext.java (original)
+++ tomcat/trunk/test/org/apache/catalina/core/TesterContext.java Thu Sep 25
19:38:15 2014
@@ -19,8 +19,6 @@ package org.apache.catalina.core;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -64,6 +62,7 @@ import org.apache.tomcat.util.descriptor
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.apache.tomcat.util.http.CookieProcessor;
/**
* Minimal implementation for use in unit tests.
@@ -1220,22 +1219,11 @@ public class TesterContext implements Co
}
@Override
- public Object getNamingToken() {
- return null;
- }
-
- @Override
- public void setUseRfc6265(boolean useRfc6265) { /* NO-OP */ }
-
- @Override
- public boolean getUseRfc6265() {return false; }
-
- @Override
- public void setCookieEncoding(String encoding) { /* NO-OP */ }
+ public Object getNamingToken() { return null; }
@Override
- public String getCookieEncoding() { return "UTF-8"; }
+ public void setCookieProcessor(CookieProcessor cookieProcessor) { /* NO-OP
*/ }
@Override
- public Charset getCookieEncodingCharset() { return StandardCharsets.UTF_8;
}
+ public CookieProcessor getCookieProcessor() { return null; }
}
Modified: tomcat/trunk/test/org/apache/tomcat/util/http/TestCookies.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/http/TestCookies.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/http/TestCookies.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/http/TestCookies.java Thu Sep 25
19:38:15 2014
@@ -472,16 +472,22 @@ public class TestCookies {
private void test(boolean useRfc6265, String header, Cookie... expected) {
MimeHeaders mimeHeaders = new MimeHeaders();
- Cookies cookies = new Cookies(mimeHeaders);
- cookies.setUseRfc6265(useRfc6265);
+ ServerCookies serverCookies = new ServerCookies(4);
+ CookieProcessor cookieProcessor;
+
+ if (useRfc6265) {
+ cookieProcessor = new Rfc6265CookieProcessor();
+ } else {
+ cookieProcessor = new Cookies();
+ }
MessageBytes cookieHeaderValue = mimeHeaders.addValue("Cookie");
byte[] bytes = header.getBytes(StandardCharsets.UTF_8);
cookieHeaderValue.setBytes(bytes, 0, bytes.length);
- // Calling getCookieCount() triggers parsing
- Assert.assertEquals(expected.length, cookies.getCookieCount());
+ cookieProcessor.parseCookieHeader(mimeHeaders, serverCookies);
+ Assert.assertEquals(expected.length, serverCookies.getCookieCount());
for (int i = 0; i < expected.length; i++) {
Cookie cookie = expected[i];
- ServerCookie actual = cookies.getCookie(i);
+ ServerCookie actual = serverCookies.getCookie(i);
Assert.assertEquals(cookie.getVersion(), actual.getVersion());
Assert.assertEquals(cookie.getName(), actual.getName().toString());
actual.getValue().getByteChunk().setCharset(StandardCharsets.UTF_8);
Modified:
tomcat/trunk/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java
(original)
+++ tomcat/trunk/test/org/apache/tomcat/util/http/TesterCookiesPerformance.java
Thu Sep 25 19:38:15 2014
@@ -45,31 +45,35 @@ public class TesterCookiesPerformance {
MessageBytes headerValue = mimeHeaders.addValue("Cookie");
headerValue.setBytes(cookieHeaderBytes, 0, cookieHeaderBytes.length);
+ ServerCookies serverCookies = new ServerCookies(4);
+
+ Cookies originalCookieProcessor = new Cookies();
+ Rfc6265CookieProcessor rfc6265CookieProcessor = new
Rfc6265CookieProcessor();
- Cookies cookies = new Cookies(mimeHeaders);
// warm up
for (int i = 0; i < parsingLoops; i++) {
- Assert.assertEquals(cookieCount, cookies.getCookieCount());
- cookies.recycle();
+ originalCookieProcessor.parseCookieHeader(mimeHeaders,
serverCookies);
+ Assert.assertEquals(cookieCount, serverCookies.getCookieCount());
+ serverCookies.recycle();
}
long oldStart = System.nanoTime();
for (int i = 0; i < parsingLoops; i++) {
- cookies.setUseRfc6265(false);
- Assert.assertEquals(cookieCount, cookies.getCookieCount());
- cookies.recycle();
+ originalCookieProcessor.parseCookieHeader(mimeHeaders,
serverCookies);
+ Assert.assertEquals(cookieCount, serverCookies.getCookieCount());
+ serverCookies.recycle();
}
long oldDuration = System.nanoTime() - oldStart;
long newStart = System.nanoTime();
for (int i = 0; i < parsingLoops; i++) {
- cookies.setUseRfc6265(true);
- Assert.assertEquals(cookieCount, cookies.getCookieCount());
- cookies.recycle();
+ rfc6265CookieProcessor.parseCookieHeader(mimeHeaders,
serverCookies);
+ Assert.assertEquals(cookieCount, serverCookies.getCookieCount());
+ serverCookies.recycle();
}
long newDuration = System.nanoTime() - newStart;
- System.out.println("Old duration: " + oldDuration);
- System.out.println("New duration: " + newDuration);
+ System.out.println("Original duration: " + oldDuration);
+ System.out.println("RFC6265 duration: " + newDuration);
}
}
Modified: tomcat/trunk/webapps/docs/config/context.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1627619&r1=1627618&r2=1627619&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/context.xml (original)
+++ tomcat/trunk/webapps/docs/config/context.xml Thu Sep 25 19:38:15 2014
@@ -300,13 +300,6 @@
no filtering will be applied.</p>
</attribute>
- <attribute name="cookieEncoding" required="false">
- <p>If the RFC6265 based cookie parser is used this attribute determines
- the encoding to be used to convert the byte values in the HTTP header
to
- strings. If not specified, the default of <code>UTF-8</code> will be
- used.</p>
- </attribute>
-
<attribute name="cookies" required="false">
<p>Set to <code>true</code> if you want cookies to be used for
session identifier communication if supported by the client (this
@@ -536,12 +529,6 @@
penalty.</p>
</attribute>
- <attribute name="useRfc6265" required="false">
- <p>Determines if the RFC6265 based cookie parser is used. The default
- value is <code>false</code> in which case the original parser based on
- RFC2109 and the Netscape cookie specification will be used.</p>
- </attribute>
-
<attribute name="useHttpOnly" required="false">
<p>Should the HttpOnly flag be set on session cookies to prevent client
side script from accessing the session ID? Defaults to
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]