Skip to content

Commit 0d37770

Browse files
committed
Release XLT 9.1.2
2 parents 5b5367a + 844af53 commit 0d37770

7 files changed

Lines changed: 383 additions & 50 deletions

File tree

config/testreport/js/xlt.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@
3939

4040
// the filter function, returns true if the value is to be shown
4141
function doFilter(value, filterPhrase) {
42-
// request table cells contain the URLs as well, so cut them off
43-
value = value.trim().split('\n')[0];
42+
value = value.trim();
4443

4544
// split filter phrase into filters
4645
var filters = filterPhrase.split('|');
@@ -455,6 +454,19 @@
455454

456455
// setup the tables
457456
(function setupTables() {
457+
// patch the Table plugin to ignore cluetip text content (e.g. distinct URLs) when filtering and sorting
458+
const tableGetCellValue = Table.getCellValue;
459+
Table.getCellValue = function() {
460+
const node = arguments[0];
461+
// don't let element nodes having CSS class 'cluetip-data' contribute any text to computed table cell value
462+
if (node && node.nodeType === Node.ELEMENT_NODE && node.classList.contains("cluetip-data")) {
463+
return "";
464+
}
465+
// invoke the original function
466+
return tableGetCellValue.apply(Table, arguments);
467+
};
468+
469+
// now set up the tables
458470
Table.auto();
459471

460472
// hide loader and show content after HTML for table is build (only if present)

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.xceptance</groupId>
88
<artifactId>xlt</artifactId>
9-
<version>9.1.1</version>
9+
<version>9.1.2</version>
1010
<packaging>jar</packaging>
1111

1212
<name>XLT</name>

src/main/java/com/xceptance/xlt/engine/htmlunit/okhttp3/CookieJarImpl.java

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.List;
2020
import java.util.stream.Collectors;
2121

22-
import org.apache.commons.lang3.StringUtils;
2322
import org.htmlunit.CookieManager;
2423
import org.htmlunit.util.Cookie;
2524

@@ -32,6 +31,8 @@
3231
*/
3332
class CookieJarImpl implements CookieJar
3433
{
34+
static final String ERROR_MSG_COOKIE_INVALID = "Cookie not valid for use with OkHttp";
35+
3536
/**
3637
* HtmlUnit's cookie manager.
3738
*/
@@ -95,36 +96,55 @@ private static Cookie toHtmlUnitCookie(final okhttp3.Cookie okHttpCookie)
9596
* the source cookie
9697
* @return the converted cookie
9798
*/
98-
private static okhttp3.Cookie toOkHttpCookie(final Cookie htmlUnitCookie)
99+
static okhttp3.Cookie toOkHttpCookie(final Cookie htmlUnitCookie)
99100
{
100-
final Builder builder = new okhttp3.Cookie.Builder();
101-
102-
builder.name(htmlUnitCookie.getName()).value(htmlUnitCookie.getValue()).path(htmlUnitCookie.getPath())
103-
.expiresAt(htmlUnitCookie.getExpires().getTime());
104-
105-
final String domain = htmlUnitCookie.getDomain();
106-
if (domain.startsWith("."))
107-
{
108-
// "wildcard" domain, such as ".example.com"
109-
// the cookie builder expects the domain to be passed without the leading dot
110-
builder.domain(StringUtils.stripStart(domain, "."));
111-
}
112-
else
101+
try
113102
{
114-
// "host" domain, such as "www.example.com"
115-
builder.hostOnlyDomain(domain);
103+
final Builder builder = new okhttp3.Cookie.Builder();
104+
105+
builder.name(htmlUnitCookie.getName());
106+
builder.value(htmlUnitCookie.getValue());
107+
108+
final String domain = htmlUnitCookie.getDomain();
109+
if (domain.startsWith("."))
110+
{
111+
// "wildcard" domain, such as ".example.com"
112+
// the cookie builder expects the domain to be passed without the leading dot
113+
builder.domain(domain.substring(1));
114+
}
115+
else
116+
{
117+
// "host" domain, such as "www.example.com"
118+
builder.hostOnlyDomain(domain);
119+
}
120+
121+
final String path = htmlUnitCookie.getPath();
122+
if (path != null)
123+
{
124+
builder.path(path);
125+
}
126+
127+
final Date expires = htmlUnitCookie.getExpires();
128+
if (expires != null)
129+
{
130+
builder.expiresAt(expires.getTime());
131+
}
132+
133+
if (htmlUnitCookie.isSecure())
134+
{
135+
builder.secure();
136+
}
137+
138+
if (htmlUnitCookie.isHttpOnly())
139+
{
140+
builder.httpOnly();
141+
}
142+
143+
return builder.build();
116144
}
117-
118-
if (htmlUnitCookie.isSecure())
145+
catch (final Exception e)
119146
{
120-
builder.secure();
147+
throw new IllegalArgumentException(ERROR_MSG_COOKIE_INVALID + ": '" + htmlUnitCookie + "'", e);
121148
}
122-
123-
if (htmlUnitCookie.isHttpOnly())
124-
{
125-
builder.httpOnly();
126-
}
127-
128-
return builder.build();
129149
}
130150
}

src/main/java/org/htmlunit/HttpWebConnection.java

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
/**
119119
* Default implementation of {@link WebConnection}, using the HttpClient library to perform HTTP requests.
120120
*
121-
* @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
121+
* @author Mike Bowler
122122
* @author Noboru Sinohara
123123
* @author David D. Kilzer
124124
* @author Marc Guillemot
@@ -138,7 +138,7 @@ public class HttpWebConnection implements WebConnection {
138138
private static final String HACKED_COOKIE_POLICY = "mine";
139139

140140
// have one per thread because this is (re)configured for every call (see configureHttpProcessorBuilder)
141-
// do not use a ThreadLocal because this in only accessed form this class
141+
// do not use a ThreadLocal because this in only accessed form this class, but we still need it synchronized
142142
private final Map<Thread, HttpClientBuilder> httpClientBuilder_ = new WeakHashMap<>();
143143
private final WebClient webClient_;
144144

@@ -212,7 +212,9 @@ public WebResponse getResponse(final WebRequest webRequest) throws IOException {
212212
// Calling code may catch the StackOverflowError, but due to the leak, the httpClient_ may
213213
// come out of connections and throw a ConnectionPoolTimeoutException.
214214
// => best solution, discard the HttpClient instance.
215-
httpClientBuilder_.remove(Thread.currentThread());
215+
synchronized (httpClientBuilder_) {
216+
httpClientBuilder_.remove(Thread.currentThread());
217+
}
216218
throw e;
217219
}
218220
}
@@ -427,7 +429,8 @@ private static Charset getCharset(final Charset charset, final List<NameValuePai
427429
final KeyDataPair pairWithFile = (KeyDataPair) pair;
428430
if (pairWithFile.getData() == null && pairWithFile.getFile() != null) {
429431
final String fileName = pairWithFile.getFile().getName();
430-
for (int i = 0; i < fileName.length(); i++) {
432+
final int length = fileName.length();
433+
for (int i = 0; i < length; i++) {
431434
if (fileName.codePointAt(i) > 127) {
432435
return charset;
433436
}
@@ -532,23 +535,26 @@ protected HttpRequestBase buildHttpMethod(final HttpMethod submitMethod, final U
532535
*/
533536
protected HttpClientBuilder getHttpClientBuilder() {
534537
final Thread currentThread = Thread.currentThread();
535-
HttpClientBuilder builder = httpClientBuilder_.get(currentThread);
536-
if (builder == null) {
537-
builder = createHttpClientBuilder();
538538

539-
// this factory is required later
540-
// to be sure this is done, we do it outside the createHttpClient() call
541-
final RegistryBuilder<CookieSpecProvider> registeryBuilder
542-
= RegistryBuilder.<CookieSpecProvider>create()
543-
.register(HACKED_COOKIE_POLICY, htmlUnitCookieSpecProvider_);
544-
builder.setDefaultCookieSpecRegistry(registeryBuilder.build());
539+
synchronized (httpClientBuilder_) {
540+
HttpClientBuilder builder = httpClientBuilder_.get(currentThread);
541+
if (builder == null) {
542+
builder = createHttpClientBuilder();
543+
544+
// this factory is required later
545+
// to be sure this is done, we do it outside the createHttpClient() call
546+
final RegistryBuilder<CookieSpecProvider> registeryBuilder
547+
= RegistryBuilder.<CookieSpecProvider>create()
548+
.register(HACKED_COOKIE_POLICY, htmlUnitCookieSpecProvider_);
549+
builder.setDefaultCookieSpecRegistry(registeryBuilder.build());
550+
551+
builder.setDefaultCookieStore(new HtmlUnitCookieStore(webClient_.getCookieManager()));
552+
builder.setUserAgent(webClient_.getBrowserVersion().getUserAgent());
553+
httpClientBuilder_.put(currentThread, builder);
554+
}
545555

546-
builder.setDefaultCookieStore(new HtmlUnitCookieStore(webClient_.getCookieManager()));
547-
builder.setUserAgent(webClient_.getBrowserVersion().getUserAgent());
548-
httpClientBuilder_.put(currentThread, builder);
556+
return builder;
549557
}
550-
551-
return builder;
552558
}
553559

554560
/**
@@ -1288,7 +1294,11 @@ public synchronized String toString() {
12881294
*/
12891295
@Override
12901296
public void close() {
1291-
httpClientBuilder_.clear();
1297+
synchronized (httpClientBuilder_) {
1298+
httpClientBuilder_.clear();
1299+
}
1300+
sharedAuthCache_.clear();
1301+
httpClientContextByThread_.clear();
12921302

12931303
if (connectionManager_ != null) {
12941304
connectionManager_.shutdown();

0 commit comments

Comments
 (0)