You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by fs...@apache.org on 2016/11/27 13:35:46 UTC

svn commit: r1771589 - in /jmeter/trunk: ./ res/maven/ src/protocol/http/org/apache/jmeter/protocol/http/parser/ xdocs/

Author: fschumacher
Date: Sun Nov 27 13:35:45 2016
New Revision: 1771589

URL: http://svn.apache.org/viewvc?rev=1771589&view=rev
Log:
Fix race-conditions in CssParser.
Based on a patch by Jerome Loisel (loisel.jerome at gmail.com)

This closes github pr #221
Bugzilla Id: 59934

Added:
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CSSParseExceptionCallback.java
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParserCacheLoader.java
Modified:
    jmeter/trunk/LICENSE
    jmeter/trunk/build.properties
    jmeter/trunk/build.xml
    jmeter/trunk/eclipse.classpath
    jmeter/trunk/res/maven/ApacheJMeter_parent.pom
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParser.java
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/URLCollection.java
    jmeter/trunk/xdocs/changes.xml

Modified: jmeter/trunk/LICENSE
URL: http://svn.apache.org/viewvc/jmeter/trunk/LICENSE?rev=1771589&r1=1771588&r2=1771589&view=diff
==============================================================================
--- jmeter/trunk/LICENSE [utf-8] (original)
+++ jmeter/trunk/LICENSE [utf-8] Sun Nov 27 13:35:45 2016
@@ -242,6 +242,7 @@ The following software is provided under
 - Software produced outside the ASF which is available under AL 2.0:
 
 * accessors-smart-1.1.jar
+* caffeine-2.3.5.jar
 * freemarker-2.3.23.jar (AL2.0, see licenses/bin for additional info)
 * json-path-2.2.0.jar
 * json-smart-2.2.1.jar

Modified: jmeter/trunk/build.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/build.properties?rev=1771589&r1=1771588&r2=1771589&view=diff
==============================================================================
--- jmeter/trunk/build.properties (original)
+++ jmeter/trunk/build.properties Sun Nov 27 13:35:45 2016
@@ -85,6 +85,11 @@ bcpkix.jar                  = bcpkix-jdk
 bcpkix.loc                  = ${maven2.repo}/org/bouncycastle/bcpkix-jdk15on/${bcprov.version}
 bcpkix.md5                  = cb025ef84fb991e14fdf62f6bef7be53
 
+caffeine.version            = 2.3.5
+caffeine.jar                = caffeine-${caffeine.version}.jar
+caffeine.loc                = ${maven2.repo}/com/github/ben-manes/caffeine/caffeine/${caffeine.version}
+caffeine.md5                = 5ff5404cc94337fd6976a06ed6f1f023
+
 commons-codec.version       = 1.10
 commons-codec.jar           = commons-codec-${commons-codec.version}.jar
 commons-codec.loc           = ${maven2.repo}/commons-codec/commons-codec/${commons-codec.version}

Modified: jmeter/trunk/build.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/build.xml?rev=1771589&r1=1771588&r2=1771589&view=diff
==============================================================================
--- jmeter/trunk/build.xml (original)
+++ jmeter/trunk/build.xml Sun Nov 27 13:35:45 2016
@@ -393,6 +393,7 @@
     <include name="${lib.dir}/${asm.jar}"/>
     <include name="${lib.dir}/${avalon-framework.jar}"/>
     <include name="${lib.dir}/${beanshell.jar}"/>
+    <include name="${lib.dir}/${caffeine.jar}"/>
     <include name="${lib.dir}/${commons-codec.jar}"/>
     <include name="${lib.dir}/${commons-collections.jar}"/>
     <include name="${lib.dir}/${commons-dbcp2.jar}"/>
@@ -469,6 +470,7 @@
     <pathelement location="${lib.dir}/${asm.jar}"/>
     <pathelement location="${lib.dir}/${avalon-framework.jar}"/>
     <pathelement location="${lib.dir}/${beanshell.jar}"/>
+    <pathelement location="${lib.dir}/${caffeine.jar}"/>
     <pathelement location="${lib.dir}/${commons-codec.jar}"/>
     <pathelement location="${lib.dir}/${commons-collections.jar}"/>
     <pathelement location="${lib.dir}/${commons-dbcp2.jar}"/>
@@ -3024,6 +3026,7 @@ run JMeter unless all the JMeter jars ar
     <process_jarfile jarname="bcprov" dest.dir="${lib.api}"/>
     <process_jarfile jarname="bcpkix" dest.dir="${lib.api}"/>
     <process_jarfile jarname="beanshell"/>
+    <process_jarfile jarname="caffeine"/>
     <process_jarfile jarname="commons-codec"/>
     <process_jarfile jarname="commons-collections"/>
     <process_jarfile jarname="commons-dbcp2"/>

Modified: jmeter/trunk/eclipse.classpath
URL: http://svn.apache.org/viewvc/jmeter/trunk/eclipse.classpath?rev=1771589&r1=1771588&r2=1771589&view=diff
==============================================================================
--- jmeter/trunk/eclipse.classpath (original)
+++ jmeter/trunk/eclipse.classpath Sun Nov 27 13:35:45 2016
@@ -49,6 +49,7 @@
 	<classpathentry kind="lib" path="lib/avalon-framework-4.1.4.jar"/>
 	<classpathentry kind="lib" path="lib/bsf-2.4.0.jar"/>
 	<classpathentry kind="lib" path="lib/bsh-2.0b5.jar"/>
+	<classpathentry kind="lib" path="lib/caffeine-2.3.5.jar"/>
 	<classpathentry kind="lib" path="lib/commons-codec-1.10.jar"/>
 	<classpathentry kind="lib" path="lib/commons-collections-3.2.2.jar"/>
 	<classpathentry kind="lib" path="lib/commons-dbcp2-2.1.1.jar"/>

Modified: jmeter/trunk/res/maven/ApacheJMeter_parent.pom
URL: http://svn.apache.org/viewvc/jmeter/trunk/res/maven/ApacheJMeter_parent.pom?rev=1771589&r1=1771588&r2=1771589&view=diff
==============================================================================
--- jmeter/trunk/res/maven/ApacheJMeter_parent.pom (original)
+++ jmeter/trunk/res/maven/ApacheJMeter_parent.pom Sun Nov 27 13:35:45 2016
@@ -60,6 +60,7 @@ under the License.
       <bcmail.version>1.49</bcmail.version>
       <bcprov.version>1.49</bcprov.version>
       <bcpkix.version>1.49</bcpkix.version>
+      <caffeine.version>2.3.5</caffeine.version>
       <commons-codec.version>1.10</commons-codec.version>
       <commons-collections.version>3.2.2</commons-collections.version>
       <commons-dbcp2.version>2.1.1</commons-dbcp2.version>
@@ -153,6 +154,11 @@ under the License.
         <version>${bcpkix.version}</version>
       </dependency>
       <dependency>
+      <groupId>com.github.ben-manes.caffeine</groupId>
+        <artifactId>caffeine</artifactId>
+        <version>${caffeine.version}</version>
+      </dependency>
+      <dependency>
         <groupId>commons-codec</groupId>
         <artifactId>commons-codec</artifactId>
         <version>${commons-codec.version}</version>

Added: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CSSParseExceptionCallback.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CSSParseExceptionCallback.java?rev=1771589&view=auto
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CSSParseExceptionCallback.java (added)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CSSParseExceptionCallback.java Sun Nov 27 13:35:45 2016
@@ -0,0 +1,58 @@
+/*
+ * 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.jmeter.protocol.http.parser;
+
+import java.net.URL;
+
+import org.apache.commons.lang3.Validate;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+import com.helger.css.handler.ICSSParseExceptionCallback;
+import com.helger.css.parser.ParseException;
+import com.helger.css.reader.errorhandler.LoggingCSSParseErrorHandler;
+
+public class CSSParseExceptionCallback implements ICSSParseExceptionCallback {
+
+    private static final long serialVersionUID = -4277276398858139449L;
+    private static final Logger LOG = LoggingManager.getLoggerForClass();
+    private static final boolean IGNORE_UNRECOVERABLE_PARSING_ERROR = JMeterUtils
+            .getPropDefault(
+                    "httpsampler.ignore_failed_embedded_resource", false); //$NON-NLS-1$
+
+    private final URL baseUrl;
+
+    public CSSParseExceptionCallback(URL baseUrl) {
+        this.baseUrl = Validate.notNull(baseUrl);
+    }
+
+    @Override
+    public void onException(ParseException ex) {
+        final String message = "Failed to parse CSS: " + baseUrl + ", "
+                + LoggingCSSParseErrorHandler.createLoggingStringParseError(ex);
+        if (IGNORE_UNRECOVERABLE_PARSING_ERROR) {
+            LOG.warn(message);
+        } else {
+            throw new IllegalArgumentException(message);
+        }
+
+    }
+
+}

Modified: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParser.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParser.java?rev=1771589&r1=1771588&r2=1771589&view=diff
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParser.java (original)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParser.java Sun Nov 27 13:35:45 2016
@@ -20,163 +20,58 @@ package org.apache.jmeter.protocol.http.
 
 import java.net.URL;
 import java.nio.charset.Charset;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.collections.map.LRUMap;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.apache.commons.lang3.tuple.Triple;
 import org.apache.jmeter.util.JMeterUtils;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.log.Logger;
 
-import com.helger.css.ECSSVersion;
-import com.helger.css.decl.CSSDeclaration;
-import com.helger.css.decl.CSSExpressionMemberTermURI;
-import com.helger.css.decl.CSSImportRule;
-import com.helger.css.decl.CascadingStyleSheet;
-import com.helger.css.decl.ICSSTopLevelRule;
-import com.helger.css.decl.visit.CSSVisitor;
-import com.helger.css.decl.visit.DefaultCSSUrlVisitor;
-import com.helger.css.handler.LoggingCSSParseExceptionCallback;
-import com.helger.css.parser.ParseException;
-import com.helger.css.reader.CSSReader;
-import com.helger.css.reader.CSSReaderSettings;
-import com.helger.css.reader.errorhandler.DoNothingCSSInterpretErrorHandler;
-import com.helger.css.reader.errorhandler.ICSSInterpretErrorHandler;
-import com.helger.css.reader.errorhandler.LoggingCSSParseErrorHandler;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
 
 /**
  * CSS Parser used to extract from CSS files external urls
+ *
  * @since 3.0
  */
 public class CssParser implements LinkExtractorParser {
-    private static final boolean IGNORE_UNRECOVERABLE_PARSING_ERROR = JMeterUtils.getPropDefault("httpsampler.ignore_failed_embedded_resource", false); //$NON-NLS-1$
+    private static final URLCollection EMPTY_URL_COLLECTION = new URLCollection(Collections.emptyList());
     private static final Logger LOG = LoggingManager.getLoggerForClass();
 
     /**
      *
      */
-    private static final int CSS_URL_CACHE_MAX_SIZE = JMeterUtils.getPropDefault("css.parser.cache.size", 400);
-    private static final boolean IGNORE_ALL_CSS_ERRORS = JMeterUtils.getPropDefault("css.parser.ignore_all_css_errors", true);
-
-    /**
-     *
-     */
-    @SuppressWarnings("unchecked")
-    private static final Map<String, URLCollection> CSS_URL_CACHE =
-            CSS_URL_CACHE_MAX_SIZE > 0 ? Collections.synchronizedMap(new LRUMap(CSS_URL_CACHE_MAX_SIZE)) : null;
-
-
-    private static final class CustomLoggingCSSParseExceptionCallback extends LoggingCSSParseExceptionCallback {
-        /**
-         *
-         */
-        private static final long serialVersionUID = -9111232037888068394L;
-        private URL cssUrl;
-
-        /**
-         * @param cssUrl {@link URL}
-         */
-        public CustomLoggingCSSParseExceptionCallback(URL cssUrl) {
-            this.cssUrl = cssUrl;
-        }
-        /**
-         * @see com.helger.css.handler.LoggingCSSParseExceptionCallback#onException(com.helger.css.parser.ParseException)
-         */
-        @Override
-        public void onException(ParseException ex) {
-            if(IGNORE_UNRECOVERABLE_PARSING_ERROR) {
-                LOG.warn("Failed to parse CSS: " + cssUrl + ", " + LoggingCSSParseErrorHandler.createLoggingStringParseError (ex));
-            } else {
-                throw new IllegalStateException("Failed to parse CSS: " + cssUrl + ", " + LoggingCSSParseErrorHandler.createLoggingStringParseError (ex));
-            }
-        }
-    }
-
-    /**
-     *
-     */
-    public CssParser() {
+    private static final LoadingCache<Triple<String, URL, Charset>, URLCollection> CSS_URL_CACHE;
+    static {
+        final int cacheSize = JMeterUtils.getPropDefault(
+                "css.parser.cache.size", 400);
+        CSS_URL_CACHE = Caffeine.newBuilder().maximumSize(cacheSize)
+                .build(new CssParserCacheLoader());
     }
 
     /**
      *
-     * @see
-     * org.apache.jmeter.protocol.http.parser.LinkExtractorParser#getEmbeddedResourceURLs
-     * (java.lang.String, byte[], java.net.URL, java.lang.String)
+     * @see org.apache.jmeter.protocol.http.parser.LinkExtractorParser#getEmbeddedResourceURLs
+     *      (java.lang.String, byte[], java.net.URL, java.lang.String)
      */
     @Override
     public Iterator<URL> getEmbeddedResourceURLs(String userAgent, byte[] data,
-            final URL baseUrl, String encoding) throws LinkExtractorParseException {
+            final URL baseUrl, String encoding)
+            throws LinkExtractorParseException {
         try {
-            boolean cacheEnabled = CSS_URL_CACHE_MAX_SIZE > 0;
-            String md5Key = null;
-            URLCollection urlCollection = null;
-            if(cacheEnabled) {
-                md5Key = DigestUtils.md5Hex(data);
-                urlCollection = CSS_URL_CACHE.get(md5Key);
-            }
+            final String cssContent = new String(data, encoding);
+            final Charset charset = Charset.forName(encoding);
+            final Triple<String, URL, Charset> triple = ImmutableTriple.of(
+                    cssContent, baseUrl, charset);
+            final URLCollection urlCollection = orDefault(CSS_URL_CACHE.get(triple), EMPTY_URL_COLLECTION);
 
-            if(urlCollection == null) {
-                String cssContent = new String(data, encoding);
-                final CSSReaderSettings cssSettings = new CSSReaderSettings()
-                        .setBrowserCompliantMode(true)
-                        .setFallbackCharset(Charset.forName(encoding))
-                        .setCSSVersion(ECSSVersion.CSS30)
-                        .setCustomErrorHandler(
-                                new LoggingCSSParseErrorHandler())
-                        .setCustomExceptionHandler(
-                                new CustomLoggingCSSParseExceptionCallback(
-                                        baseUrl));
-                if (IGNORE_ALL_CSS_ERRORS) {
-                    cssSettings
-                            .setInterpretErrorHandler(new DoNothingCSSInterpretErrorHandler());
-                }
-                final CascadingStyleSheet aCSS = CSSReader
-                        .readFromStringStream(cssContent, cssSettings);
-                final List<URLString> list = new ArrayList<>();
-                urlCollection = new URLCollection(list);
-                final URLCollection localCollection = urlCollection;
-                if(aCSS != null) {
-                    CSSVisitor.visitCSSUrl(aCSS, new DefaultCSSUrlVisitor() {
-                        @Override
-                        public void onImport(final CSSImportRule importRule) {
-                            String location = importRule.getLocationString();
-                            if(!StringUtils.isEmpty(location)) {
-                                localCollection.addURL(location, baseUrl);
-                            }
-                        }
-                        // Call for URLs outside of URLs
-                        @Override
-                        public void onUrlDeclaration(
-                                final ICSSTopLevelRule aTopLevelRule,
-                                final CSSDeclaration aDeclaration,
-                                final CSSExpressionMemberTermURI aURITerm) {
-                            // NOOP
-                            // Browser fetch such urls only when CSS rule matches
-                            // so we disable this code
-                            //urlCollection.addURL(aURITerm.getURIString(), baseUrl);
-                        }
-                    });
-                    if(cacheEnabled) {
-                        CSS_URL_CACHE.put(md5Key, urlCollection);
-                    }
-                } else {
-                   LOG.warn("Failed parsing url:"+baseUrl+", got null CascadingStyleSheet");
-                }
-            }
-
-            if(LOG.isDebugEnabled()) {
-                StringBuilder builder = new StringBuilder();
-                for (Iterator<URL> iterator = urlCollection.iterator(); iterator.hasNext();) {
-                    URL urlString = iterator.next();
-                    builder.append(urlString).append(',');
-                }
-                LOG.debug("Parsed:"+baseUrl+", got:"+builder.toString());
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Parsed:" + baseUrl + ", got:" + StringUtils.join(urlCollection, ","));
             }
 
             return urlCollection.iterator();
@@ -185,6 +80,14 @@ public class CssParser implements LinkEx
         }
     }
 
+    private URLCollection orDefault(URLCollection urlCollection,
+            URLCollection defaultValue) {
+        if (urlCollection == null) {
+            return Validate.notNull(defaultValue);
+        }
+        return urlCollection;
+    }
+
     @Override
     public boolean isReusable() {
         return true;

Added: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParserCacheLoader.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParserCacheLoader.java?rev=1771589&view=auto
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParserCacheLoader.java (added)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/CssParserCacheLoader.java Sun Nov 27 13:35:45 2016
@@ -0,0 +1,103 @@
+/*
+ * 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.jmeter.protocol.http.parser;
+
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Triple;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+import com.github.benmanes.caffeine.cache.CacheLoader;
+import com.helger.css.ECSSVersion;
+import com.helger.css.decl.CSSDeclaration;
+import com.helger.css.decl.CSSExpressionMemberTermURI;
+import com.helger.css.decl.CSSImportRule;
+import com.helger.css.decl.CascadingStyleSheet;
+import com.helger.css.decl.ICSSTopLevelRule;
+import com.helger.css.decl.visit.CSSVisitor;
+import com.helger.css.decl.visit.DefaultCSSUrlVisitor;
+import com.helger.css.reader.CSSReader;
+import com.helger.css.reader.CSSReaderSettings;
+import com.helger.css.reader.errorhandler.DoNothingCSSInterpretErrorHandler;
+import com.helger.css.reader.errorhandler.LoggingCSSParseErrorHandler;
+
+public class CssParserCacheLoader implements
+        CacheLoader<Triple<String, URL, Charset>, URLCollection> {
+
+    private static final Logger LOG = LoggingManager.getLoggerForClass();
+    private static final boolean IGNORE_ALL_CSS_ERRORS = JMeterUtils
+            .getPropDefault("css.parser.ignore_all_css_errors", true);
+
+    @Override
+    public URLCollection load(Triple<String, URL, Charset> triple)
+            throws Exception {
+        final String cssContent = triple.getLeft();
+        final URL baseUrl = triple.getMiddle();
+        final Charset charset = triple.getRight();
+        final CSSReaderSettings readerSettings = new CSSReaderSettings()
+                .setBrowserCompliantMode(true)
+                .setFallbackCharset(charset)
+                .setCSSVersion(ECSSVersion.CSS30)
+                .setCustomErrorHandler(new LoggingCSSParseErrorHandler())
+                .setCustomExceptionHandler(
+                        new CSSParseExceptionCallback(baseUrl));
+        if (IGNORE_ALL_CSS_ERRORS) {
+            readerSettings
+                    .setInterpretErrorHandler(new DoNothingCSSInterpretErrorHandler());
+        }
+        final CascadingStyleSheet aCSS = CSSReader.readFromStringReader(
+                cssContent, readerSettings);
+
+        final URLCollection urls = new URLCollection(new ArrayList<URLString>());
+
+        if (aCSS == null) {
+            LOG.warn("Failed parsing CSS: " + baseUrl
+                    + ", got null CascadingStyleSheet");
+            return urls;
+        }
+
+        CSSVisitor.visitCSSUrl(aCSS, new DefaultCSSUrlVisitor() {
+            @Override
+            public void onImport(CSSImportRule rule) {
+                final String location = rule.getLocationString();
+                if (!StringUtils.isEmpty(location)) {
+                    urls.addURL(location, baseUrl);
+                }
+            }
+
+            // Call for URLs outside of URLs
+            @Override
+            public void onUrlDeclaration(final ICSSTopLevelRule aTopLevelRule,
+                    final CSSDeclaration aDeclaration,
+                    final CSSExpressionMemberTermURI aURITerm) {
+                // NOOP
+                // Browser fetch such urls only when CSS rule matches
+                // so we disable this code
+            }
+        });
+
+        return urls;
+    }
+
+}

Modified: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/URLCollection.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/URLCollection.java?rev=1771589&r1=1771588&r2=1771589&view=diff
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/URLCollection.java (original)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/parser/URLCollection.java Sun Nov 27 13:35:45 2016
@@ -24,6 +24,7 @@ import java.util.Collection;
 import java.util.Iterator;
 
 import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.lang3.Validate;
 import org.apache.jmeter.protocol.http.util.ConversionUtils;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.log.Logger;
@@ -38,17 +39,17 @@ import org.apache.log.Logger;
  * does not support remove()
  *
  */
-public class URLCollection {
+public class URLCollection implements Iterable<URL> {
     private static final Logger log = LoggingManager.getLoggerForClass();
     private final Collection<URLString> coll;
 
     /**
      * Creates a new URLCollection from an existing Collection
      *
-     * @param c collection to start with
+     * @param c collection to start with (Must not be {@code null})
      */
     public URLCollection(Collection<URLString> c) {
-        coll = c;
+        coll = Validate.notNull(c);
     }
 
     /**
@@ -98,6 +99,7 @@ public class URLCollection {
         return b;
     }
 
+    @Override
     public Iterator<URL> iterator() {
         return new UrlIterator(coll.iterator());
     }

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1771589&r1=1771588&r2=1771589&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Sun Nov 27 13:35:45 2016
@@ -97,7 +97,7 @@ Fill in some detail.
 
 <h3>HTTP Samplers and Test Script Recorder</h3>
 <ul>
-    <li><bug>xxx</bug>...</li>
+    <li><bug>59934</bug>Fix race-conditions in CssParser. Based on a patch by Jerome Loisel (loisel.jerome at gmail.com)</li>
 </ul>
 
 <h3>Other samplers</h3>
@@ -181,7 +181,7 @@ Fill in some detail.
 <p>We thank all contributors mentioned in bug and improvement sections above:
 </p>
 <ul>
-<li>Foo Bar (foo.bar at example.com)</li>
+<li>Jerome Loisel (loisel.jerome at gmail.com)</li>
 </ul>
 <p>We also thank bug reporters who helped us improve JMeter. <br/>
 For this release we want to give special thanks to the following reporters for the clear reports and tests made after our fixes:</p>