
org.eclipse.jetty.http.CookieCache Maven / Gradle / Ivy
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.http;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Cookie parser
* Optimized stateful cookie parser.
* If the added fields are identical to those last added (as strings), then the
* cookies are not re-parsed.
*
*/
public class CookieCache implements CookieParser.Handler
{
protected static final Logger LOG = LoggerFactory.getLogger(CookieCache.class);
protected final List _rawFields = new ArrayList<>();
protected List _cookieList;
private final CookieParser _parser;
public CookieCache()
{
this(CookieCompliance.RFC6265, null);
}
public CookieCache(CookieCompliance compliance, ComplianceViolation.Listener complianceListener)
{
_parser = CookieParser.newParser(this, compliance, complianceListener);
}
@Override
public void addCookie(String cookieName, String cookieValue, int cookieVersion, String cookieDomain, String cookiePath, String cookieComment)
{
if (StringUtil.isEmpty(cookieDomain) && StringUtil.isEmpty(cookiePath) && cookieVersion <= 0 && StringUtil.isEmpty(cookieComment))
_cookieList.add(HttpCookie.from(cookieName, cookieValue));
else
{
Map attributes = new HashMap<>();
attributes.put(HttpCookie.DOMAIN_ATTRIBUTE, cookieDomain);
attributes.put(HttpCookie.PATH_ATTRIBUTE, cookiePath);
attributes.put(HttpCookie.COMMENT_ATTRIBUTE, cookieComment);
_cookieList.add(HttpCookie.from(cookieName, cookieValue, cookieVersion, attributes));
}
}
public List getCookies(HttpFields headers)
{
boolean building = false;
ListIterator raw = _rawFields.listIterator();
// For each of the headers
for (HttpField field : headers)
{
// skip non cookie headers
if (!HttpHeader.COOKIE.equals(field.getHeader()))
continue;
// skip blank cookie headers
String value = field.getValue();
if (StringUtil.isBlank(value))
continue;
// If we are building a new cookie list
if (building)
{
// just add the raw string to the list to be parsed later
_rawFields.add(value);
continue;
}
// otherwise we are checking against previous cookies.
// Is there a previous raw cookie to compare with?
if (!raw.hasNext())
{
// No, so we will flip to building state and add to the raw fields we already have.
building = true;
_rawFields.add(value);
continue;
}
// If there is a previous raw cookie and it is the same, then continue checking
if (value.equals(raw.next()))
continue;
// otherwise there is a difference in the previous raw cookie field
// so switch to building mode and remove all subsequent raw fields
// then add the current raw field to be built later.
building = true;
raw.remove();
while (raw.hasNext())
{
raw.next();
raw.remove();
}
_rawFields.add(value);
}
// If we are not building, but there are still more unmatched raw fields, then a field was deleted
if (!building && raw.hasNext())
{
// switch to building mode and delete the unmatched raw fields
building = true;
while (raw.hasNext())
{
raw.next();
raw.remove();
}
}
// If we ended up in building mode, reparse the cookie list from the raw fields.
if (building)
{
_cookieList = new ArrayList<>();
try
{
_parser.parseFields(_rawFields);
}
catch (CookieParser.InvalidCookieException invalidCookieException)
{
throw new BadMessageException(invalidCookieException.getMessage(), invalidCookieException);
}
}
return _cookieList == null ? Collections.emptyList() : _cookieList;
}
/**
* Replace the cookie list with
* @param cookies The replacement cookie list, which must be equal to the existing list
*/
public void replaceCookieList(List cookies)
{
assert _cookieList.equals(cookies);
_cookieList = cookies;
}
}