Author: markt
Date: Fri Jun 22 11:36:01 2018
New Revision: 1834114

URL: http://svn.apache.org/viewvc?rev=1834114&view=rev
Log:
Refactor HTTP date creation and parsing to reduce code duplication, reduce the 
use of ThreadLocals and to increase the use of caching.

Added:
    tomcat/trunk/java/org/apache/tomcat/util/http/ConcurrentDateFormat.java   
(with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
    tomcat/trunk/java/org/apache/catalina/connector/Request.java
    tomcat/trunk/java/org/apache/catalina/connector/Response.java
    tomcat/trunk/java/org/apache/catalina/filters/RemoteIpFilter.java
    tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java
    tomcat/trunk/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java
    tomcat/trunk/java/org/apache/catalina/util/ConcurrentDateFormat.java
    tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java
    tomcat/trunk/java/org/apache/tomcat/util/http/FastHttpDateFormat.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: 
tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java 
Fri Jun 22 11:36:01 2018
@@ -19,7 +19,6 @@ package org.apache.catalina.authenticato
 import java.io.IOException;
 import java.security.Principal;
 import java.security.cert.X509Certificate;
-import java.util.Date;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -55,7 +54,6 @@ import org.apache.catalina.authenticator
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
 import org.apache.catalina.realm.GenericPrincipal;
-import org.apache.catalina.util.ConcurrentDateFormat;
 import org.apache.catalina.util.SessionIdGeneratorBase;
 import org.apache.catalina.util.StandardSessionIdGenerator;
 import org.apache.catalina.valves.ValveBase;
@@ -65,6 +63,7 @@ import org.apache.juli.logging.LogFactor
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.descriptor.web.LoginConfig;
 import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.apache.tomcat.util.http.FastHttpDateFormat;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -93,7 +92,7 @@ public abstract class AuthenticatorBase
     /**
      * "Expires" header always set to Date(1), so generate once only
      */
-    private static final String DATE_ONE = 
ConcurrentDateFormat.formatRfc1123(new Date(1));
+    private static final String DATE_ONE = FastHttpDateFormat.formatDate(1);
 
     /**
      * The string manager for this package.

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=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Fri Jun 22 
11:36:01 2018
@@ -175,7 +175,10 @@ public class Request implements HttpServ
 
     // ----------------------------------------------------- Variables
 
-
+    /**
+     * @deprecated Unused. This will be removed in Tomact 10.
+     */
+    @Deprecated
     protected static final TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT");
 
 
@@ -196,9 +199,13 @@ public class Request implements HttpServ
      *
      * Notice that because SimpleDateFormat is not thread-safe, we can't
      * declare formats[] as a static variable.
+     *
+     * @deprecated Unused. This will be removed in Tomcat 10
      */
+    @Deprecated
     protected final SimpleDateFormat formats[];
 
+    @Deprecated
     private static final SimpleDateFormat formatsTemplate[] = {
         new SimpleDateFormat(FastHttpDateFormat.RFC1123_DATE, Locale.US),
         new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
@@ -2186,7 +2193,7 @@ public class Request implements HttpServ
         }
 
         // Attempt to convert the date header in a variety of formats
-        long result = FastHttpDateFormat.parseDate(value, formats);
+        long result = FastHttpDateFormat.parseDate(value);
         if (result != (-1L)) {
             return result;
         }

Modified: tomcat/trunk/java/org/apache/catalina/connector/Response.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Response.java?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Response.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Response.java Fri Jun 22 
11:36:01 2018
@@ -34,7 +34,6 @@ import java.util.Enumeration;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.TimeZone;
 import java.util.Vector;
 import java.util.function.Supplier;
 
@@ -95,7 +94,10 @@ public class Response implements HttpSer
 
     /**
      * The date format we will use for creating date headers.
+     *
+     * @deprecated Unused. This will be removed in Tomcat 10
      */
+    @Deprecated
     protected SimpleDateFormat format = null;
 
 
@@ -998,14 +1000,7 @@ public class Response implements HttpSer
             return;
         }
 
-        if (format == null) {
-            format = new SimpleDateFormat(FastHttpDateFormat.RFC1123_DATE,
-                                          Locale.US);
-            format.setTimeZone(TimeZone.getTimeZone("GMT"));
-        }
-
-        addHeader(name, FastHttpDateFormat.formatDate(value, format));
-
+        addHeader(name, FastHttpDateFormat.formatDate(value));
     }
 
 
@@ -1373,13 +1368,7 @@ public class Response implements HttpSer
             return;
         }
 
-        if (format == null) {
-            format = new SimpleDateFormat(FastHttpDateFormat.RFC1123_DATE,
-                                          Locale.US);
-            format.setTimeZone(TimeZone.getTimeZone("GMT"));
-        }
-
-        setHeader(name, FastHttpDateFormat.formatDate(value, format));
+        setHeader(name, FastHttpDateFormat.formatDate(value));
     }
 
 

Modified: tomcat/trunk/java/org/apache/catalina/filters/RemoteIpFilter.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/filters/RemoteIpFilter.java?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/filters/RemoteIpFilter.java (original)
+++ tomcat/trunk/java/org/apache/catalina/filters/RemoteIpFilter.java Fri Jun 
22 11:36:01 2018
@@ -18,17 +18,12 @@ package org.apache.catalina.filters;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.Collections;
-import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.regex.Pattern;
 
@@ -49,6 +44,7 @@ import org.apache.catalina.connector.Req
 import org.apache.catalina.util.RequestUtil;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.http.FastHttpDateFormat;
 
 /**
  * <p>
@@ -447,18 +443,6 @@ public class RemoteIpFilter extends Gene
 
     public static class XForwardedRequest extends HttpServletRequestWrapper {
 
-        static final ThreadLocal<SimpleDateFormat[]> threadLocalDateFormats = 
new ThreadLocal<SimpleDateFormat[]>() {
-            @Override
-            protected SimpleDateFormat[] initialValue() {
-                return new SimpleDateFormat[] {
-                    new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", 
Locale.US),
-                    new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", 
Locale.US),
-                    new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
-                };
-
-            }
-        };
-
         protected final Map<String, List<String>> headers;
 
         protected int localPort;
@@ -495,20 +479,11 @@ public class RemoteIpFilter extends Gene
             if (value == null) {
                 return -1;
             }
-            DateFormat[] dateFormats = threadLocalDateFormats.get();
-            Date date = null;
-            for (int i = 0; ((i < dateFormats.length) && (date == null)); i++) 
{
-                DateFormat dateFormat = dateFormats[i];
-                try {
-                    date = dateFormat.parse(value);
-                } catch (ParseException ex) {
-                    // Ignore
-                }
-            }
-            if (date == null) {
+            long date = FastHttpDateFormat.parseDate(value);
+            if (date == -1) {
                 throw new IllegalArgumentException(value);
             }
-            return date.getTime();
+            return date;
         }
 
         @Override

Modified: tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java (original)
+++ tomcat/trunk/java/org/apache/catalina/servlets/WebdavServlet.java Fri Jun 
22 11:36:01 2018
@@ -43,11 +43,11 @@ import javax.xml.parsers.ParserConfigura
 
 import org.apache.catalina.WebResource;
 import org.apache.catalina.connector.RequestFacade;
-import org.apache.catalina.util.ConcurrentDateFormat;
 import org.apache.catalina.util.DOMWriter;
 import org.apache.catalina.util.URLEncoder;
 import org.apache.catalina.util.XMLWriter;
 import org.apache.tomcat.util.buf.UDecoder;
+import org.apache.tomcat.util.http.ConcurrentDateFormat;
 import org.apache.tomcat.util.http.FastHttpDateFormat;
 import org.apache.tomcat.util.http.RequestUtil;
 import org.apache.tomcat.util.security.ConcurrentMessageDigest;
@@ -2068,7 +2068,7 @@ public class WebdavServlet extends Defau
             generatedXML.writeElement("D", "displayname", XMLWriter.CLOSING);
             if (isFile) {
                 generatedXML.writeProperty("D", "getlastmodified",
-                        FastHttpDateFormat.formatDate(lastModified, null));
+                        FastHttpDateFormat.formatDate(lastModified));
                 generatedXML.writeProperty("D", "getcontentlength", 
Long.toString(contentLength));
                 if (contentType != null) {
                     generatedXML.writeProperty("D", "getcontenttype", 
contentType);
@@ -2186,7 +2186,7 @@ public class WebdavServlet extends Defau
                 } else if (property.equals("getlastmodified")) {
                     if (isFile) {
                         generatedXML.writeProperty("D", "getlastmodified",
-                                FastHttpDateFormat.formatDate(lastModified, 
null));
+                                FastHttpDateFormat.formatDate(lastModified));
                     } else {
                         propertiesNotFound.addElement(property);
                     }
@@ -2405,7 +2405,7 @@ public class WebdavServlet extends Defau
             result.append("\nOwner:");
             result.append(owner);
             result.append("\nExpiration:");
-            result.append(FastHttpDateFormat.formatDate(expiresAt, null));
+            result.append(FastHttpDateFormat.formatDate(expiresAt));
             Enumeration<String> tokensList = tokens.elements();
             while (tokensList.hasMoreElements()) {
                 result.append("\nToken:");

Modified: tomcat/trunk/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java Fri 
Jun 22 11:36:01 2018
@@ -20,10 +20,7 @@ package org.apache.catalina.ssi;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.util.Locale;
-import java.util.TimeZone;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletOutputStream;
@@ -31,7 +28,7 @@ import javax.servlet.http.HttpServletReq
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponseWrapper;
 
-import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.http.FastHttpDateFormat;
 
 /**
  * A HttpServletResponseWrapper, used from
@@ -46,8 +43,6 @@ public class ResponseIncludeWrapper exte
      */
     private static final String CONTENT_TYPE = "content-type";
     private static final String LAST_MODIFIED = "last-modified";
-    private static final DateFormat RFC1123_FORMAT;
-    private static final String RFC1123_PATTERN = "EEE, dd MMM yyyy HH:mm:ss 
z";
 
     protected long lastModified = -1;
     private String contentType = null;
@@ -62,11 +57,6 @@ public class ResponseIncludeWrapper exte
     private final ServletContext context;
     private final HttpServletRequest request;
 
-    static {
-        RFC1123_FORMAT = new SimpleDateFormat(RFC1123_PATTERN, Locale.US);
-        RFC1123_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
-    }
-
     /**
      * Initialize our wrapper with the current HttpServletResponse and
      * ServletOutputStream.
@@ -211,12 +201,9 @@ public class ResponseIncludeWrapper exte
         super.addHeader(name, value);
         String lname = name.toLowerCase(Locale.ENGLISH);
         if (lname.equals(LAST_MODIFIED)) {
-            try {
-                synchronized(RFC1123_FORMAT) {
-                    lastModified = RFC1123_FORMAT.parse(value).getTime();
-                }
-            } catch (Throwable ignore) {
-                ExceptionUtils.handleThrowable(ignore);
+            long lastModified = FastHttpDateFormat.parseDate(value);
+            if (lastModified != -1) {
+                this.lastModified = lastModified;
             }
         } else if (lname.equals(CONTENT_TYPE)) {
             contentType = value;
@@ -237,16 +224,11 @@ public class ResponseIncludeWrapper exte
         super.setHeader(name, value);
         String lname = name.toLowerCase(Locale.ENGLISH);
         if (lname.equals(LAST_MODIFIED)) {
-            try {
-                synchronized(RFC1123_FORMAT) {
-                    lastModified = RFC1123_FORMAT.parse(value).getTime();
-                }
-            } catch (Throwable ignore) {
-                ExceptionUtils.handleThrowable(ignore);
+            long lastModified = FastHttpDateFormat.parseDate(value);
+            if (lastModified != -1) {
+                this.lastModified = lastModified;
             }
-        }
-        else if (lname.equals(CONTENT_TYPE))
-        {
+        } else if (lname.equals(CONTENT_TYPE)) {
             contentType = value;
         }
     }

Modified: tomcat/trunk/java/org/apache/catalina/util/ConcurrentDateFormat.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/ConcurrentDateFormat.java?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/util/ConcurrentDateFormat.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/util/ConcurrentDateFormat.java Fri 
Jun 22 11:36:01 2018
@@ -27,7 +27,11 @@ import java.util.concurrent.ConcurrentLi
  * A thread safe wrapper around {@link SimpleDateFormat} that does not make use
  * of ThreadLocal and - broadly - only creates enough SimpleDateFormat objects
  * to satisfy the concurrency requirements.
+ *
+ * @deprecated Unused. This will be removed in Tomcat 10.
+ *             Use {@link org.apache.tomcat.util.http.ConcurrentDateFormat}
  */
+@Deprecated
 public class ConcurrentDateFormat {
 
     private final String format;

Modified: 
tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java 
Fri Jun 22 11:36:01 2018
@@ -17,12 +17,11 @@
 package org.apache.catalina.webresources;
 
 import java.io.InputStream;
-import java.util.Date;
 
 import org.apache.catalina.WebResource;
 import org.apache.catalina.WebResourceRoot;
-import org.apache.catalina.util.ConcurrentDateFormat;
 import org.apache.juli.logging.Log;
+import org.apache.tomcat.util.http.FastHttpDateFormat;
 import org.apache.tomcat.util.res.StringManager;
 
 public abstract class AbstractResource implements WebResource {
@@ -56,9 +55,10 @@ public abstract class AbstractResource i
 
     @Override
     public final String getLastModifiedHttp() {
-        return ConcurrentDateFormat.formatRfc1123(new Date(getLastModified()));
+        return FastHttpDateFormat.formatDate(getLastModified());
     }
 
+
     @Override
     public final String getETag() {
         if (weakETag == null) {

Added: tomcat/trunk/java/org/apache/tomcat/util/http/ConcurrentDateFormat.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/ConcurrentDateFormat.java?rev=1834114&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/ConcurrentDateFormat.java 
(added)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/ConcurrentDateFormat.java Fri 
Jun 22 11:36:01 2018
@@ -0,0 +1,73 @@
+/*
+ * 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.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Queue;
+import java.util.TimeZone;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * A thread safe wrapper around {@link SimpleDateFormat} that does not make use
+ * of ThreadLocal and - broadly - only creates enough SimpleDateFormat objects
+ * to satisfy the concurrency requirements.
+ */
+public class ConcurrentDateFormat {
+
+    private final String format;
+    private final Locale locale;
+    private final TimeZone timezone;
+    private final Queue<SimpleDateFormat> queue = new 
ConcurrentLinkedQueue<>();
+
+    public ConcurrentDateFormat(String format, Locale locale,
+            TimeZone timezone) {
+        this.format = format;
+        this.locale = locale;
+        this.timezone = timezone;
+        SimpleDateFormat initial = createInstance();
+        queue.add(initial);
+    }
+
+    public String format(Date date) {
+        SimpleDateFormat sdf = queue.poll();
+        if (sdf == null) {
+            sdf = createInstance();
+        }
+        String result = sdf.format(date);
+        queue.add(sdf);
+        return result;
+    }
+
+    public Date parse(String source) throws ParseException {
+        SimpleDateFormat sdf = queue.poll();
+        if (sdf == null) {
+            sdf = createInstance();
+        }
+        Date result = sdf.parse(source);
+        queue.add(sdf);
+        return result;
+    }
+
+    private SimpleDateFormat createInstance() {
+        SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
+        sdf.setTimeZone(timezone);
+        return sdf;
+    }
+}

Propchange: 
tomcat/trunk/java/org/apache/tomcat/util/http/ConcurrentDateFormat.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/java/org/apache/tomcat/util/http/FastHttpDateFormat.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/FastHttpDateFormat.java?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/http/FastHttpDateFormat.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/http/FastHttpDateFormat.java Fri 
Jun 22 11:36:01 2018
@@ -18,7 +18,6 @@ package org.apache.tomcat.util.http;
 
 import java.text.DateFormat;
 import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Locale;
 import java.util.Map;
@@ -42,25 +41,35 @@ public final class FastHttpDateFormat {
 
     /**
      * The only date format permitted when generating HTTP headers.
+     *
+     * @deprecated Unused. This will be removed in Tomcat 10.
      */
-    public static final String RFC1123_DATE =
-            "EEE, dd MMM yyyy HH:mm:ss zzz";
+    @Deprecated
+    public static final String RFC1123_DATE = "EEE, dd MMM yyyy HH:mm:ss zzz";
 
-    private static final SimpleDateFormat format =
-            new SimpleDateFormat(RFC1123_DATE, Locale.US);
+    // HTTP date formats
+    private static final String DATE_RFC5322 = "EEE, dd MMM yyyy HH:mm:ss z";
+    private static final String DATE_OBSOLETE_RFC850 = "EEEEEE, dd-MMM-yy 
HH:mm:ss zzz";
+    private static final String DATE_OBSOLETE_ASCTIME = "EEE MMMM d HH:mm:ss 
yyyy";
+
+    private static final ConcurrentDateFormat FORMAT_RFC5322;
+    private static final ConcurrentDateFormat FORMAT_OBSOLETE_RFC850;
+    private static final ConcurrentDateFormat FORMAT_OBSOLETE_ASCTIME;
 
+    private static final ConcurrentDateFormat[] httpParseFormats;
 
-    private static final TimeZone gmtZone = TimeZone.getTimeZone("GMT");
+    static {
+        // All the formats that use a timezone use GMT
+        TimeZone tz = TimeZone.getTimeZone("GMT");
 
+        FORMAT_RFC5322 = new ConcurrentDateFormat(DATE_RFC5322, Locale.US, tz);
+        FORMAT_OBSOLETE_RFC850 = new 
ConcurrentDateFormat(DATE_OBSOLETE_RFC850, Locale.US, tz);
+        FORMAT_OBSOLETE_ASCTIME = new 
ConcurrentDateFormat(DATE_OBSOLETE_ASCTIME, Locale.US, tz);
 
-    /**
-     * GMT timezone - all HTTP dates are on GMT
-     */
-    static {
-        format.setTimeZone(gmtZone);
+        httpParseFormats = new ConcurrentDateFormat[] {
+                FORMAT_RFC5322, FORMAT_OBSOLETE_RFC850, 
FORMAT_OBSOLETE_ASCTIME };
     }
 
-
     /**
      * Instant on which the currentDate object was generated.
      */
@@ -93,47 +102,44 @@ public final class FastHttpDateFormat {
      * @return the HTTP date
      */
     public static final String getCurrentDate() {
-
         long now = System.currentTimeMillis();
         if ((now - currentDateGenerated) > 1000) {
-            synchronized (format) {
-                if ((now - currentDateGenerated) > 1000) {
-                    currentDate = format.format(new Date(now));
-                    currentDateGenerated = now;
-                }
-            }
+            currentDate = FORMAT_RFC5322.format(new Date(now));
+            currentDateGenerated = now;
         }
         return currentDate;
-
     }
 
 
     /**
      * Get the HTTP format of the specified date.
      * @param value The date
-     * @param threadLocalformat Local format to avoid synchronization
+     * @param threadLocalformat Ignored. The local ConcurrentDateFormat will
+     *                          always be used.
      * @return the HTTP date
+     *
+     * @deprecated Unused. This will be removed in Tomcat 10
      */
-    public static final String formatDate
-        (long value, DateFormat threadLocalformat) {
+    @Deprecated
+    public static final String formatDate(long value, DateFormat 
threadLocalformat) {
+        return formatDate(value);
+    }
 
+
+    /**
+     * Get the HTTP format of the specified date.
+     * @param value The date
+     * @return the HTTP date
+     */
+    public static final String formatDate(long value) {
         Long longValue = Long.valueOf(value);
         String cachedDate = formatCache.get(longValue);
         if (cachedDate != null) {
             return cachedDate;
         }
 
-        String newDate = null;
-        Date dateValue = new Date(value);
-        if (threadLocalformat != null) {
-            newDate = threadLocalformat.format(dateValue);
-            updateFormatCache(longValue, newDate);
-        } else {
-            synchronized (format) {
-                newDate = format.format(dateValue);
-            }
-            updateFormatCache(longValue, newDate);
-        }
+        String newDate = FORMAT_RFC5322.format(new Date(value));
+        updateFormatCache(longValue, newDate);
         return newDate;
     }
 
@@ -141,49 +147,43 @@ public final class FastHttpDateFormat {
     /**
      * Try to parse the given date as a HTTP date.
      * @param value The HTTP date
-     * @param threadLocalformats Local format to avoid synchronization
+     * @param threadLocalformats Ignored. The local array of
+     *                           ConcurrentDateFormat will always be used.
      * @return the date as a long
+     *
+     * @deprecated Unused. This will be removed in Tomcat 10
+     *             Use {@link #parseDate(String)}
+     */
+    @Deprecated
+    public static final long parseDate(String value, DateFormat[] 
threadLocalformats) {
+        return parseDate(value);
+    }
+
+
+    /**
+     * Try to parse the given date as a HTTP date.
+     * @param value The HTTP date
+     * @return the date as a long or <code>-1<code> if the value cannot be
+     *         parsed
      */
-    public static final long parseDate(String value,
-                                       DateFormat[] threadLocalformats) {
+    public static final long parseDate(String value) {
 
         Long cachedDate = parseCache.get(value);
         if (cachedDate != null) {
             return cachedDate.longValue();
         }
 
-        Long date = null;
-        if (threadLocalformats != null) {
-            date = internalParseDate(value, threadLocalformats);
-            updateParseCache(value, date);
-        } else {
-            throw new IllegalArgumentException();
-        }
-        if (date == null) {
-            return -1L;
-        }
-
-        return date.longValue();
-    }
-
-
-    /**
-     * Parse date with given formatters.
-     */
-    private static final Long internalParseDate
-        (String value, DateFormat[] formats) {
-        Date date = null;
-        for (int i = 0; (date == null) && (i < formats.length); i++) {
+        long date = -1;
+        for (int i = 0; (date == -1) && (i < httpParseFormats.length); i++) {
             try {
-                date = formats[i].parse(value);
+                date = httpParseFormats[i].parse(value).getTime();
+                updateParseCache(value, Long.valueOf(date));
             } catch (ParseException e) {
                 // Ignore
             }
         }
-        if (date == null) {
-            return null;
-        }
-        return Long.valueOf(date.getTime());
+
+        return date;
     }
 
 

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1834114&r1=1834113&r2=1834114&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Fri Jun 22 11:36:01 2018
@@ -45,6 +45,15 @@
   issues do not "pop up" wrt. others).
 -->
 <section name="Tomcat 9.0.11 (markt)" rtext="in development">
+  <subsection name="Coyote">
+    <changelog>
+      <scode>
+        Refactor HTTP date creation and parsing to reduce code duplication,
+        reduce the use of ThreadLocals and to increase the use of caching.
+        (markt)
+      </scode>
+    </changelog>
+  </subsection>
   <subsection name="Other">
     <changelog>
       <update>



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to