From: Kai Moritz Date: Mon, 15 Feb 2021 20:31:47 +0000 (+0100) Subject: TMP:site (Nach Korrektur an thymeskin neu generiert??) X-Git-Url: http://juplo.de/gitweb/?a=commitdiff_plain;h=96ec104e2974d001e9bc82c3af8b21029b2042d4;p=website TMP:site (Nach Korrektur an thymeskin neu generiert??) --- diff --git a/dist/http-resources/2.0.0/apidocs/allclasses-index.html b/dist/http-resources/2.0.0/apidocs/allclasses-index.html new file mode 100644 index 00000000..ebc60d40 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/allclasses-index.html @@ -0,0 +1,189 @@ + + + + + +All Classes (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

All Classes

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/allclasses.html b/dist/http-resources/2.0.0/apidocs/allclasses.html new file mode 100644 index 00000000..6c273ccd --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/allclasses.html @@ -0,0 +1,34 @@ + + + + + +All Classes (HttpResources 2.0.0 API) + + + + + + + + + + + + +

All Classes

+
+ +
+ + diff --git a/dist/http-resources/2.0.0/apidocs/allpackages-index.html b/dist/http-resources/2.0.0/apidocs/allpackages-index.html new file mode 100644 index 00000000..9ab5b930 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/allpackages-index.html @@ -0,0 +1,165 @@ + + + + + +All Packages (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

All Packages

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/constant-values.html b/dist/http-resources/2.0.0/apidocs/constant-values.html new file mode 100644 index 00000000..2ce29a33 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/constant-values.html @@ -0,0 +1,199 @@ + + + + + +Constant Field Values (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Constant Field Values

+
+

Contents

+ +
+
+
+ + +
+

de.juplo.*

+ +
+
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResource.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResource.html new file mode 100644 index 00000000..5483ff7c --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResource.html @@ -0,0 +1,705 @@ + + + + + +HttpResource (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Class HttpResource

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    org.springframework.core.io.InputStreamSource, org.springframework.core.io.Resource, org.springframework.web.servlet.resource.HttpResource
    +
    +
    +
    public class HttpResource
    +extends Object
    +implements org.springframework.web.servlet.resource.HttpResource
    +
  • +
+
+
+ +
+
+
    +
  • + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        expires

        +
        public long expires()
        +
      • +
      + + + +
        +
      • +

        isExpired

        +
        public boolean isExpired()
        +
      • +
      + + + +
        +
      • +

        exists

        +
        public boolean exists()
        +
        +
        Specified by:
        +
        exists in interface org.springframework.core.io.Resource
        +
        +
      • +
      + + + +
        +
      • +

        isReadable

        +
        public boolean isReadable()
        +
        +
        Specified by:
        +
        isReadable in interface org.springframework.core.io.Resource
        +
        +
      • +
      + + + +
        +
      • +

        isOpen

        +
        public boolean isOpen()
        +
        +
        Specified by:
        +
        isOpen in interface org.springframework.core.io.Resource
        +
        +
      • +
      + + + +
        +
      • +

        getURL

        +
        public URL getURL()
        +           throws IOException
        +
        +
        Specified by:
        +
        getURL in interface org.springframework.core.io.Resource
        +
        Throws:
        +
        IOException
        +
        +
      • +
      + + + +
        +
      • +

        getURI

        +
        public URI getURI()
        +
        +
        Specified by:
        +
        getURI in interface org.springframework.core.io.Resource
        +
        +
      • +
      + + + +
        +
      • +

        getFile

        +
        public File getFile()
        +             throws IOException
        +
        +
        Specified by:
        +
        getFile in interface org.springframework.core.io.Resource
        +
        Throws:
        +
        IOException
        +
        +
      • +
      + + + +
        +
      • +

        contentLength

        +
        public long contentLength()
        +                   throws IOException
        +
        +
        Specified by:
        +
        contentLength in interface org.springframework.core.io.Resource
        +
        Throws:
        +
        IOException
        +
        +
      • +
      + + + +
        +
      • +

        contentType

        +
        public org.springframework.util.MimeType contentType()
        +
      • +
      + + + +
        +
      • +

        lastModified

        +
        public long lastModified()
        +                  throws IOException
        +
        +
        Specified by:
        +
        lastModified in interface org.springframework.core.io.Resource
        +
        Throws:
        +
        IOException
        +
        +
      • +
      + + + +
        +
      • +

        eTag

        +
        public String eTag()
        +
      • +
      + + + +
        +
      • +

        createRelative

        +
        public HttpResource createRelative​(String relativePath)
        +                            throws IOException
        +
        +
        Specified by:
        +
        createRelative in interface org.springframework.core.io.Resource
        +
        Throws:
        +
        IOException
        +
        +
      • +
      + + + + + + + +
        +
      • +

        getFilename

        +
        public String getFilename()
        +
        +
        Specified by:
        +
        getFilename in interface org.springframework.core.io.Resource
        +
        +
      • +
      + + + +
        +
      • +

        getDescription

        +
        public String getDescription()
        +
        +
        Specified by:
        +
        getDescription in interface org.springframework.core.io.Resource
        +
        +
      • +
      + + + +
        +
      • +

        getInputStream

        +
        public InputStream getInputStream()
        +                           throws IOException
        +
        +
        Specified by:
        +
        getInputStream in interface org.springframework.core.io.InputStreamSource
        +
        Throws:
        +
        IOException
        +
        +
      • +
      + + + +
        +
      • +

        isModified

        +
        public boolean isModified()
        +
      • +
      + + + +
        +
      • +

        fetched

        +
        public boolean fetched()
        +
        Checks, if the remote resource was already fetched.
        +
        +
        Returns:
        +
        true, if the resource was already fetched, otherwise + false
        +
        +
      • +
      + + + +
        +
      • +

        fetch

        +
        public boolean fetch()
        +
        Fetches the remote resource and reports, if it was modified. +

        + This method fetches the remote resource, if was not already fetched. + If the resource was already fetched, it revalidates it, if necessary.

        +
        +
        Returns:
        +
        true, if the resource has changed or was fetched for + the first time, otherwise false
        +
        +
      • +
      + + + +
        +
      • +

        getResponseHeaders

        +
        public org.springframework.http.HttpHeaders getResponseHeaders()
        +
        +
        Specified by:
        +
        getResponseHeaders in interface org.springframework.web.servlet.resource.HttpResource
        +
        +
      • +
      + + + +
        +
      • +

        hashCode

        +
        public int hashCode()
        +
        +
        Overrides:
        +
        hashCode in class Object
        +
        +
      • +
      + + + +
        +
      • +

        equals

        +
        public boolean equals​(Object o)
        +
        +
        Overrides:
        +
        equals in class Object
        +
        +
      • +
      + + + + +
    • +
    +
    +
  • +
+
+
+
+ + + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoader.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoader.html new file mode 100644 index 00000000..e7f29ac5 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoader.html @@ -0,0 +1,363 @@ + + + + + +HttpResourceChainAwareResourceLoader (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Class HttpResourceChainAwareResourceLoader

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • de.juplo.httpresources.HttpResourceChainAwareResourceLoader
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    org.springframework.core.io.ResourceLoader
    +
    +
    +
    public class HttpResourceChainAwareResourceLoader
    +extends Object
    +implements org.springframework.core.io.ResourceLoader
    +
  • +
+
+
+ +
+
+
    +
  • + +
    +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        HttpResourceChainAwareResourceLoader

        +
        public HttpResourceChainAwareResourceLoader​(org.springframework.core.io.ResourceLoader loader,
        +                                            String... sources)
        +
      • +
      +
    • +
    +
    + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        getResource

        +
        public org.springframework.core.io.Resource getResource​(String location)
        +
        Returns the first existing resource, or the first, if non of the + resources exists. + + This mimics the behavior of the original resolver as closeley as possible, + asuming, that the first source is a / the local one.
        +
        +
        Specified by:
        +
        getResource in interface org.springframework.core.io.ResourceLoader
        +
        Parameters:
        +
        location - The name of the requested resource
        +
        Returns:
        +
        The first existing resource, or the first resource - never null.
        +
        +
      • +
      + + + +
        +
      • +

        getClassLoader

        +
        public ClassLoader getClassLoader()
        +
        +
        Specified by:
        +
        getClassLoader in interface org.springframework.core.io.ResourceLoader
        +
        +
      • +
      +
    • +
    +
    +
  • +
+
+
+
+ + + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceFetcher.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceFetcher.html new file mode 100644 index 00000000..07cd480a --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceFetcher.html @@ -0,0 +1,406 @@ + + + + + +HttpResourceFetcher (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Class HttpResourceFetcher

+
+
+ +
+
    +
  • +
    +
    public class HttpResourceFetcher
    +extends Object
    +
  • +
+
+
+
    +
  • + +
    +
      +
    • + + +

      Field Summary

      + + + + + + + + + + + + +
      Fields 
      Modifier and TypeFieldDescription
      static intDEFAULT_TTL 
      +
    • +
    +
    + +
    +
      +
    • + + +

      Constructor Summary

      + + + + + + + + + + + + + + +
      Constructors 
      ConstructorDescription
      HttpResourceFetcher​(org.springframework.http.client.ClientHttpRequestFactory factory, + org.springframework.cache.Cache cache, + Clock clock) 
      HttpResourceFetcher​(org.springframework.http.client.ClientHttpRequestFactory factory, + org.springframework.cache.Cache cache, + Clock clock, + int defaultTTL, + int minTTL, + boolean serveStale) 
      +
    • +
    +
    + +
    + +
    +
  • +
+
+
+
    +
  • + +
    + +
    + +
    +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        HttpResourceFetcher

        +
        public HttpResourceFetcher​(org.springframework.http.client.ClientHttpRequestFactory factory,
        +                           org.springframework.cache.Cache cache,
        +                           Clock clock)
        +
      • +
      + + + +
        +
      • +

        HttpResourceFetcher

        +
        public HttpResourceFetcher​(org.springframework.http.client.ClientHttpRequestFactory factory,
        +                           org.springframework.cache.Cache cache,
        +                           Clock clock,
        +                           int defaultTTL,
        +                           int minTTL,
        +                           boolean serveStale)
        +
        +
        Parameters:
        +
        factory -
        +
        clock -
        +
        defaultTTL - default time to live in milliseconds + Default TTL, if no according information is present in the HTTP-headers. + If set to 0, caching will be disabled, if no according + HTTP-headers are present.
        +
        minTTL - the minimum time to live, if caching is enabled + A minimum TTL, that will overwrite the time to live, that was extracted + from the HTTP-headers. + The minimum TTL is only applied, if the default TTL is set to a value + greater than zero, hence enabling caching by default.
        +
        serveStale -
        +
        +
      • +
      +
    • +
    +
    + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        fetch

        +
        public de.juplo.httpresources.HttpData fetch​(URI uri,
        +                                             de.juplo.httpresources.HttpData data)
        +
        Fetches the remote resource and reports, if it was modified. + + This method fetches the remote resource, if was not already fetched. + If the resource was already fetched, it revalidates it, if necessary.
        +
        +
        Returns:
        +
        true, if the resource has changed or was fetched for + the first time, otherwise false
        +
        +
      • +
      +
    • +
    +
    +
  • +
+
+
+
+ + + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceProtocolResolver.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceProtocolResolver.html new file mode 100644 index 00000000..c9b7b55a --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourceProtocolResolver.html @@ -0,0 +1,316 @@ + + + + + +HttpResourceProtocolResolver (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Class HttpResourceProtocolResolver

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • de.juplo.httpresources.HttpResourceProtocolResolver
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    org.springframework.core.io.ProtocolResolver
    +
    +
    +
    public class HttpResourceProtocolResolver
    +extends Object
    +implements org.springframework.core.io.ProtocolResolver
    +
  • +
+
+
+ +
+
+
    +
  • + +
    +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        HttpResourceProtocolResolver

        +
        public HttpResourceProtocolResolver​(HttpResources resources)
        +
      • +
      +
    • +
    +
    + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        resolve

        +
        public HttpResource resolve​(String location,
        +                            org.springframework.core.io.ResourceLoader resourceLoader)
        +
        +
        Specified by:
        +
        resolve in interface org.springframework.core.io.ProtocolResolver
        +
        +
      • +
      +
    • +
    +
    +
  • +
+
+
+
+ + + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResources.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResources.html new file mode 100644 index 00000000..ea3af1aa --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResources.html @@ -0,0 +1,405 @@ + + + + + +HttpResources (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Class HttpResources

+
+
+ +
+
    +
  • +
    +
    public class HttpResources
    +extends Object
    +
    +
    Author:
    +
    Kai Moritz
    +
    +
  • +
+
+
+ +
+
+
    +
  • + +
    + +
    + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        getResource

        +
        public HttpResource getResource​(String uri)
        +
        +
        Parameters:
        +
        uri - the resource location (must be a valid URI)
        +
        Returns:
        +
        the corresponding Resource handle (never null)
        +
        +
      • +
      + + + +
        +
      • +

        getResource

        +
        public HttpResource getResource​(URI uri)
        +
        Returns the HttpResource, that represents the given URI. +

        Note that a Resource handle does not imply an existing resource; + you need to invoke Resource.exists() to check for existence.

        +
        +
        Parameters:
        +
        uri - the resource location, represented as an URI
        +
        Returns:
        +
        the corresponding Resource handle (never null)
        +
        +
      • +
      + + + +
        +
      • +

        convert

        +
        public static URI convert​(String url)
        +
      • +
      + + + +
        +
      • +

        normalize

        +
        public static URI normalize​(URI uri)
        +
      • +
      + + + + + + + +
        +
      • +

        isHttpResource

        +
        public static boolean isHttpResource​(String resourcePath)
        +
      • +
      +
    • +
    +
    +
  • +
+
+
+
+ + + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesAutoConfiguration.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesAutoConfiguration.html new file mode 100644 index 00000000..f1f73f8e --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesAutoConfiguration.html @@ -0,0 +1,455 @@ + + + + + +HttpResourcesAutoConfiguration (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Class HttpResourcesAutoConfiguration

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • de.juplo.httpresources.HttpResourcesAutoConfiguration
    • +
    +
  • +
+
+
    +
  • +
    +
    @Configuration
    +@EnableConfigurationProperties(HttpResourcesProperties.class)
    +@AutoConfigureBefore(org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.class)
    +public class HttpResourcesAutoConfiguration
    +extends Object
    +
    Automatic configuration
    +
    +
    Author:
    +
    Kai Moritz
    +
    +
  • +
+
+
+ +
+
+ +
+
+
+ + + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesProperties.Resolver.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesProperties.Resolver.html new file mode 100644 index 00000000..6243f9a2 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesProperties.Resolver.html @@ -0,0 +1,351 @@ + + + + + +HttpResourcesProperties.Resolver (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Class HttpResourcesProperties.Resolver

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • de.juplo.httpresources.HttpResourcesProperties.Resolver
    • +
    +
  • +
+
+ +
+
+ +
+
+
    +
  • + +
    +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        Resolver

        +
        public Resolver()
        +
      • +
      +
    • +
    +
    + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        isEnabled

        +
        public boolean isEnabled()
        +
      • +
      + + + +
        +
      • +

        setEnabled

        +
        public void setEnabled​(boolean enabled)
        +
      • +
      + + + +
        +
      • +

        getExclusionPatterns

        +
        public String[] getExclusionPatterns()
        +
      • +
      + + + +
        +
      • +

        setExclusionPatterns

        +
        public void setExclusionPatterns​(String[] exclusionPatterns)
        +
      • +
      +
    • +
    +
    +
  • +
+
+
+
+ + + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesProperties.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesProperties.html new file mode 100644 index 00000000..6a220f3d --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/HttpResourcesProperties.html @@ -0,0 +1,408 @@ + + + + + +HttpResourcesProperties (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Class HttpResourcesProperties

+
+
+ +
+
    +
  • +
    +
    @ConfigurationProperties("juplo.http-resources")
    +public class HttpResourcesProperties
    +extends Object
    +
    +
    Author:
    +
    Kai Moritz
    +
    +
  • +
+
+
+ +
+
+
    +
  • + +
    +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        HttpResourcesProperties

        +
        public HttpResourcesProperties()
        +
      • +
      +
    • +
    +
    + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        getDefaultTTL

        +
        public int getDefaultTTL()
        +
      • +
      + + + +
        +
      • +

        setDefaultTTL

        +
        public void setDefaultTTL​(int defaultTTL)
        +
      • +
      + + + +
        +
      • +

        getMinTTL

        +
        public int getMinTTL()
        +
      • +
      + + + +
        +
      • +

        setMinTTL

        +
        public void setMinTTL​(int minTTL)
        +
      • +
      + + + +
        +
      • +

        isServeStale

        +
        public boolean isServeStale()
        +
      • +
      + + + +
        +
      • +

        setServeStale

        +
        public void setServeStale​(boolean serveStale)
        +
      • +
      + + + +
        +
      • +

        isCache

        +
        public boolean isCache()
        +
      • +
      + + + +
        +
      • +

        setCache

        +
        public void setCache​(boolean cache)
        +
      • +
      +
    • +
    +
    +
  • +
+
+
+
+ + + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResource.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResource.html new file mode 100644 index 00000000..add50c36 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResource.html @@ -0,0 +1,199 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResource (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
de.juplo.httpresources.HttpResource

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoader.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoader.html new file mode 100644 index 00000000..9154edf2 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoader.html @@ -0,0 +1,177 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceChainAwareResourceLoader (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
de.juplo.httpresources.HttpResourceChainAwareResourceLoader

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceFetcher.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceFetcher.html new file mode 100644 index 00000000..cbbe94c9 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceFetcher.html @@ -0,0 +1,209 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceFetcher (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
de.juplo.httpresources.HttpResourceFetcher

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolver.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolver.html new file mode 100644 index 00000000..293f5b86 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolver.html @@ -0,0 +1,178 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceProtocolResolver (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
de.juplo.httpresources.HttpResourceProtocolResolver

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResources.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResources.html new file mode 100644 index 00000000..7e33a9fe --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResources.html @@ -0,0 +1,208 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResources (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
de.juplo.httpresources.HttpResources

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesAutoConfiguration.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesAutoConfiguration.html new file mode 100644 index 00000000..7df8c06e --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesAutoConfiguration.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourcesAutoConfiguration (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
de.juplo.httpresources.HttpResourcesAutoConfiguration

+
+
No usage of de.juplo.httpresources.HttpResourcesAutoConfiguration
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesProperties.Resolver.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesProperties.Resolver.html new file mode 100644 index 00000000..2d2620f7 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesProperties.Resolver.html @@ -0,0 +1,191 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourcesProperties.Resolver (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
de.juplo.httpresources.HttpResourcesProperties.Resolver

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesProperties.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesProperties.html new file mode 100644 index 00000000..426de8d3 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/class-use/HttpResourcesProperties.html @@ -0,0 +1,192 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourcesProperties (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Class
de.juplo.httpresources.HttpResourcesProperties

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-summary.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-summary.html new file mode 100644 index 00000000..81cd95b1 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-summary.html @@ -0,0 +1,191 @@ + + + + + +de.juplo.httpresources (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Package de.juplo.httpresources

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-tree.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-tree.html new file mode 100644 index 00000000..993d0f7e --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-tree.html @@ -0,0 +1,164 @@ + + + + + +de.juplo.httpresources Class Hierarchy (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Hierarchy For Package de.juplo.httpresources

+
+
+
+

Class Hierarchy

+ +
+
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-use.html b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-use.html new file mode 100644 index 00000000..3fb1f479 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/de/juplo/httpresources/package-use.html @@ -0,0 +1,187 @@ + + + + + +Uses of Package de.juplo.httpresources (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Uses of Package
de.juplo.httpresources

+
+
+ +
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/deprecated-list.html b/dist/http-resources/2.0.0/apidocs/deprecated-list.html new file mode 100644 index 00000000..5031cefa --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/deprecated-list.html @@ -0,0 +1,147 @@ + + + + + +Deprecated List (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

Deprecated API

+

Contents

+
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/element-list b/dist/http-resources/2.0.0/apidocs/element-list new file mode 100644 index 00000000..aee14e26 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/element-list @@ -0,0 +1 @@ +de.juplo.httpresources diff --git a/dist/http-resources/2.0.0/apidocs/help-doc.html b/dist/http-resources/2.0.0/apidocs/help-doc.html new file mode 100644 index 00000000..b6cf9532 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/help-doc.html @@ -0,0 +1,273 @@ + + + + + +API Help (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
+

How This API Document Is Organized

+
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
+
+
+
    +
  • +
    +

    Package

    +

    Each package has a page that contains a list of its classes and interfaces, with a summary for each. These pages may contain six categories:

    +
      +
    • Interfaces
    • +
    • Classes
    • +
    • Enums
    • +
    • Exceptions
    • +
    • Errors
    • +
    • Annotation Types
    • +
    +
    +
  • +
  • +
    +

    Class or Interface

    +

    Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

    +
      +
    • Class Inheritance Diagram
    • +
    • Direct Subclasses
    • +
    • All Known Subinterfaces
    • +
    • All Known Implementing Classes
    • +
    • Class or Interface Declaration
    • +
    • Class or Interface Description
    • +
    +
    +
      +
    • Nested Class Summary
    • +
    • Field Summary
    • +
    • Property Summary
    • +
    • Constructor Summary
    • +
    • Method Summary
    • +
    +
    +
      +
    • Field Detail
    • +
    • Property Detail
    • +
    • Constructor Detail
    • +
    • Method Detail
    • +
    +

    Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.

    +
    +
  • +
  • +
    +

    Annotation Type

    +

    Each annotation type has its own separate page with the following sections:

    +
      +
    • Annotation Type Declaration
    • +
    • Annotation Type Description
    • +
    • Required Element Summary
    • +
    • Optional Element Summary
    • +
    • Element Detail
    • +
    +
    +
  • +
  • +
    +

    Enum

    +

    Each enum has its own separate page with the following sections:

    +
      +
    • Enum Declaration
    • +
    • Enum Description
    • +
    • Enum Constant Summary
    • +
    • Enum Constant Detail
    • +
    +
    +
  • +
  • +
    +

    Use

    +

    Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its "Use" page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.

    +
    +
  • +
  • +
    +

    Tree (Class Hierarchy)

    +

    There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. Classes are organized by inheritance structure starting with java.lang.Object. Interfaces do not inherit from java.lang.Object.

    +
      +
    • When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
    • +
    • When viewing a particular package, class or interface page, clicking on "Tree" displays the hierarchy for only that package.
    • +
    +
    +
  • +
  • +
    +

    Deprecated API

    +

    The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.

    +
    +
  • +
  • +
    +

    Index

    +

    The Index contains an alphabetic index of all classes, interfaces, constructors, methods, and fields, as well as lists of all packages and all classes.

    +
    +
  • +
  • +
    +

    All Classes

    +

    The All Classes link shows all classes and interfaces except non-static nested types.

    +
    +
  • +
  • +
    +

    Serialized Form

    +

    Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.

    +
    +
  • +
  • +
    +

    Constant Field Values

    +

    The Constant Field Values page lists the static final fields and their values.

    +
    +
  • +
  • +
    +

    Search

    +

    You can search for definitions of modules, packages, types, fields, methods and other terms defined in the API, using some or all of the name. "Camel-case" abbreviations are supported: for example, "InpStr" will find "InputStream" and "InputStreamReader".

    +
    +
  • +
+
+This help file applies to API documentation generated by the standard doclet.
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/index-all.html b/dist/http-resources/2.0.0/apidocs/index-all.html new file mode 100644 index 00000000..cbfdb69d --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/index-all.html @@ -0,0 +1,359 @@ + + + + + +Index (HttpResources 2.0.0 API) + + + + + + + + + + + + + + +
+ +
+
+
C D E F G H I L N R S T 
All Classes All Packages + + +

C

+
+
CACHE_NAME - Static variable in class de.juplo.httpresources.HttpResourcesAutoConfiguration
+
 
+
clock() - Method in class de.juplo.httpresources.HttpResourcesAutoConfiguration
+
 
+
contentLength() - Method in class de.juplo.httpresources.HttpResource
+
 
+
contentType() - Method in class de.juplo.httpresources.HttpResource
+
 
+
convert(String) - Static method in class de.juplo.httpresources.HttpResources
+
 
+
createRelative(String) - Method in class de.juplo.httpresources.HttpResource
+
 
+
createRelative(URI) - Method in class de.juplo.httpresources.HttpResource
+
 
+
+ + + +

D

+
+
de.juplo.httpresources - package de.juplo.httpresources
+
 
+
DEFAULT_TTL - Static variable in class de.juplo.httpresources.HttpResourceFetcher
+
 
+
+ + + +

E

+
+
equals(Object) - Method in class de.juplo.httpresources.HttpResource
+
 
+
eTag() - Method in class de.juplo.httpresources.HttpResource
+
 
+
exists() - Method in class de.juplo.httpresources.HttpResource
+
 
+
expires() - Method in class de.juplo.httpresources.HttpResource
+
 
+
+ + + +

F

+
+
fetch() - Method in class de.juplo.httpresources.HttpResource
+
+
Fetches the remote resource and reports, if it was modified.
+
+
fetch(URI, HttpData) - Method in class de.juplo.httpresources.HttpResourceFetcher
+
+
Fetches the remote resource and reports, if it was modified.
+
+
fetched() - Method in class de.juplo.httpresources.HttpResource
+
+
Checks, if the remote resource was already fetched.
+
+
fetcher(ClientHttpRequestFactory, Clock, HttpResourcesProperties) - Method in class de.juplo.httpresources.HttpResourcesAutoConfiguration
+
 
+
+ + + +

G

+
+
getClassLoader() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoader
+
 
+
getDefaultTTL() - Method in class de.juplo.httpresources.HttpResourcesProperties
+
 
+
getDescription() - Method in class de.juplo.httpresources.HttpResource
+
 
+
getFile() - Method in class de.juplo.httpresources.HttpResource
+
 
+
getFilename() - Method in class de.juplo.httpresources.HttpResource
+
 
+
getInputStream() - Method in class de.juplo.httpresources.HttpResource
+
 
+
getMinTTL() - Method in class de.juplo.httpresources.HttpResourcesProperties
+
 
+
getResource(String) - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoader
+
+
Returns the first existing resource, or the first, if non of the + resources exists.
+
+
getResource(String) - Method in class de.juplo.httpresources.HttpResources
+
 
+
getResource(URI) - Method in class de.juplo.httpresources.HttpResources
+
+
Returns the HttpResource, that represents the given URI.
+
+
getResponseHeaders() - Method in class de.juplo.httpresources.HttpResource
+
 
+
getURI() - Method in class de.juplo.httpresources.HttpResource
+
 
+
getURL() - Method in class de.juplo.httpresources.HttpResource
+
 
+
+ + + +

H

+
+
hashCode() - Method in class de.juplo.httpresources.HttpResource
+
 
+
HttpResource - Class in de.juplo.httpresources
+
 
+
httpResourceChainAwareResourceLoader(ApplicationContext, String[]) - Method in class de.juplo.httpresources.HttpResourcesAutoConfiguration
+
 
+
HttpResourceChainAwareResourceLoader - Class in de.juplo.httpresources
+
 
+
HttpResourceChainAwareResourceLoader(ResourceLoader, String...) - Constructor for class de.juplo.httpresources.HttpResourceChainAwareResourceLoader
+
 
+
HttpResourceFetcher - Class in de.juplo.httpresources
+
 
+
HttpResourceFetcher(ClientHttpRequestFactory, Cache, Clock) - Constructor for class de.juplo.httpresources.HttpResourceFetcher
+
 
+
HttpResourceFetcher(ClientHttpRequestFactory, Cache, Clock, int, int, boolean) - Constructor for class de.juplo.httpresources.HttpResourceFetcher
+
 
+
httpResourceProtocolResolver(HttpResources, HttpResourcesProperties, DefaultResourceLoader) - Method in class de.juplo.httpresources.HttpResourcesAutoConfiguration
+
 
+
HttpResourceProtocolResolver - Class in de.juplo.httpresources
+
 
+
HttpResourceProtocolResolver(HttpResources) - Constructor for class de.juplo.httpresources.HttpResourceProtocolResolver
+
 
+
httpResources(HttpResourceFetcher, Clock, HttpResourcesProperties) - Method in class de.juplo.httpresources.HttpResourcesAutoConfiguration
+
 
+
HttpResources - Class in de.juplo.httpresources
+
 
+
HttpResources(HttpResourceFetcher, Clock) - Constructor for class de.juplo.httpresources.HttpResources
+
 
+
HttpResourcesAutoConfiguration - Class in de.juplo.httpresources
+
+
Automatic configuration
+
+
HttpResourcesAutoConfiguration() - Constructor for class de.juplo.httpresources.HttpResourcesAutoConfiguration
+
 
+
HttpResourcesProperties - Class in de.juplo.httpresources
+
 
+
HttpResourcesProperties() - Constructor for class de.juplo.httpresources.HttpResourcesProperties
+
 
+
+ + + +

I

+
+
isCache() - Method in class de.juplo.httpresources.HttpResourcesProperties
+
 
+
isExpired() - Method in class de.juplo.httpresources.HttpResource
+
 
+
isHttpResource(String) - Static method in class de.juplo.httpresources.HttpResources
+
 
+
isModified() - Method in class de.juplo.httpresources.HttpResource
+
 
+
isOpen() - Method in class de.juplo.httpresources.HttpResource
+
 
+
isReadable() - Method in class de.juplo.httpresources.HttpResource
+
 
+
isServeStale() - Method in class de.juplo.httpresources.HttpResourcesProperties
+
 
+
+ + + +

L

+
+
lastModified() - Method in class de.juplo.httpresources.HttpResource
+
 
+
+ + + +

N

+
+
normalize(URI) - Static method in class de.juplo.httpresources.HttpResources
+
 
+
+ + + +

R

+
+
resolve(String, ResourceLoader) - Method in class de.juplo.httpresources.HttpResourceProtocolResolver
+
 
+
resolve(URI, URI) - Static method in class de.juplo.httpresources.HttpResources
+
 
+
+ + + +

S

+
+
setCache(boolean) - Method in class de.juplo.httpresources.HttpResourcesProperties
+
 
+
setDefaultTTL(int) - Method in class de.juplo.httpresources.HttpResourcesProperties
+
 
+
setMinTTL(int) - Method in class de.juplo.httpresources.HttpResourcesProperties
+
 
+
setServeStale(boolean) - Method in class de.juplo.httpresources.HttpResourcesProperties
+
 
+
sources(ResourceProperties) - Method in class de.juplo.httpresources.HttpResourcesAutoConfiguration
+
 
+
+ + + +

T

+
+
toString() - Method in class de.juplo.httpresources.HttpResource
+
 
+
+C D E F G H I L N R S T 
All Classes All Packages
+
+ + + diff --git a/dist/http-resources/2.0.0/apidocs/index.html b/dist/http-resources/2.0.0/apidocs/index.html new file mode 100644 index 00000000..9c1b987c --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/index.html @@ -0,0 +1,23 @@ + + + + + +HttpResources 2.0.0 API + + + + + + + +
+ +

de/juplo/httpresources/package-summary.html

+
+ + diff --git a/dist/http-resources/2.0.0/apidocs/jquery/external/jquery/jquery.js b/dist/http-resources/2.0.0/apidocs/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..50937333 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/jquery/external/jquery/jquery.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/dist/http-resources/2.0.0/apidocs/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/dist/http-resources/2.0.0/apidocs/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/dist/http-resources/2.0.0/apidocs/jquery/jszip-utils/dist/jszip-utils.js b/dist/http-resources/2.0.0/apidocs/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":37}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":38}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.2.0"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + if (Buffer.from && Buffer.from !== Uint8Array.from) { + return Buffer.from(data, encoding); + } else { + if (typeof data === "number") { + // Safeguard for old Node.js versions. On newer versions, + // Buffer.from(number) / Buffer(number, encoding) already throw. + throw new Error("The \"data\" argument must not be a number"); + } + return new Buffer(data, encoding); + } + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + var buf = new Buffer(size); + buf.fill(0); + return buf; + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('set-immediate-shim'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"set-immediate-shim":54}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + + + + + + + + +
+ +
+
+
+

Hierarchy For All Packages

+Package Hierarchies: + +
+
+
+

Class Hierarchy

+ +
+
+
+
+ +

Copyright © 2020–2021 juplo. All rights reserved.

+
+ + diff --git a/dist/http-resources/2.0.0/apidocs/package-search-index.js b/dist/http-resources/2.0.0/apidocs/package-search-index.js new file mode 100644 index 00000000..b3220c85 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"de.juplo.httpresources"}] \ No newline at end of file diff --git a/dist/http-resources/2.0.0/apidocs/package-search-index.zip b/dist/http-resources/2.0.0/apidocs/package-search-index.zip new file mode 100644 index 00000000..88fa6fa2 Binary files /dev/null and b/dist/http-resources/2.0.0/apidocs/package-search-index.zip differ diff --git a/dist/http-resources/2.0.0/apidocs/resources/glass.png b/dist/http-resources/2.0.0/apidocs/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/dist/http-resources/2.0.0/apidocs/resources/glass.png differ diff --git a/dist/http-resources/2.0.0/apidocs/resources/x.png b/dist/http-resources/2.0.0/apidocs/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/dist/http-resources/2.0.0/apidocs/resources/x.png differ diff --git a/dist/http-resources/2.0.0/apidocs/script.js b/dist/http-resources/2.0.0/apidocs/script.js new file mode 100644 index 00000000..7dc93c48 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/script.js @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("module-search-index.json").async("text").then(function(content){ + moduleSearchIndex = JSON.parse(content); + }); + }); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("package-search-index.json").async("text").then(function(content){ + packageSearchIndex = JSON.parse(content); + }); + }); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("type-search-index.json").async("text").then(function(content){ + typeSearchIndex = JSON.parse(content); + }); + }); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("member-search-index.json").async("text").then(function(content){ + memberSearchIndex = JSON.parse(content); + }); + }); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("tag-search-index.json").async("text").then(function(content){ + tagSearchIndex = JSON.parse(content); + }); + }); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { + count = 0; + for (var key in data) { + var row = document.getElementById(key); + if ((data[key] & type) !== 0) { + row.style.display = ''; + row.className = (count++ % 2) ? rowColor : altColor; + } + else + row.style.display = 'none'; + } + updateTabs(type); +} + +function updateTabs(type) { + for (var value in tabs) { + var sNode = document.getElementById(tabs[value][0]); + var spanNode = sNode.firstChild; + if (value == type) { + sNode.className = activeTableTab; + spanNode.innerHTML = tabs[value][1]; + } + else { + sNode.className = tableTab; + spanNode.innerHTML = "" + tabs[value][1] + ""; + } + } +} + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/dist/http-resources/2.0.0/apidocs/search.js b/dist/http-resources/2.0.0/apidocs/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
  • " + item.category + "
  • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
  • ").appendTo(ul); + var div = $("
    ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
    " + + item.d + "
    "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/dist/http-resources/2.0.0/apidocs/stylesheet.css b/dist/http-resources/2.0.0/apidocs/stylesheet.css new file mode 100644 index 00000000..fa246765 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/stylesheet.css @@ -0,0 +1,906 @@ +/* + * Javadoc style sheet + */ + +@import url('resources/fonts/dejavu.css'); + +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + +body { + background-color:#ffffff; + color:#353833; + font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; + font-size:14px; + margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; +} +a:link, a:visited { + text-decoration:none; + color:#4A6782; +} +a[href]:hover, a[href]:focus { + text-decoration:none; + color:#bb7a2a; +} +a[name] { + color:#353833; +} +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; +} +pre { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; +} +h1 { + font-size:20px; +} +h2 { + font-size:18px; +} +h3 { + font-size:16px; + font-style:italic; +} +h4 { + font-size:13px; +} +h5 { + font-size:12px; +} +h6 { + font-size:11px; +} +ul { + list-style-type:disc; +} +code, tt { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; + margin-top:8px; + line-height:1.4em; +} +dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; +} +table tr td dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + vertical-align:top; + padding-top:4px; +} +sup { + font-size:8px; +} + +/* + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ +.clear { + clear:both; + height:0px; + overflow:hidden; +} +.aboutLanguage { + float:right; + padding:0px 21px; + font-size:11px; + z-index:200; + margin-top:-9px; +} +.legalCopy { + margin-left:.5em; +} +.bar a, .bar a:link, .bar a:visited, .bar a:active { + color:#FFFFFF; + text-decoration:none; +} +.bar a:hover, .bar a:focus { + color:#bb7a2a; +} +.tab { + background-color:#0066FF; + color:#ffffff; + padding:8px; + width:5em; + font-weight:bold; +} +/* + * Styles for navigation bar. + */ +.bar { + background-color:#4D7A97; + color:#FFFFFF; + padding:.8em .5em .4em .8em; + height:auto;/*height:1.8em;*/ + font-size:11px; + margin:0; +} +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} +.topNav { + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.bottomNav { + margin-top:10px; + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.subNav { + background-color:#dee3e9; + float:left; + width:100%; + overflow:hidden; + font-size:12px; +} +.subNav div { + clear:left; + float:left; + padding:0 0 5px 6px; + text-transform:uppercase; +} +ul.navList, ul.subNavList { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.navList li{ + list-style:none; + float:left; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { + list-style:none; + float:left; +} +.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { + color:#FFFFFF; + text-decoration:none; + text-transform:uppercase; +} +.topNav a:hover, .bottomNav a:hover { + text-decoration:none; + color:#bb7a2a; + text-transform:uppercase; +} +.navBarCell1Rev { + background-color:#F8981D; + color:#253441; + margin: auto 5px; +} +.skipNav { + position:absolute; + top:auto; + left:-9999px; + overflow:hidden; +} +/* + * Styles for page header and footer. + */ +.header, .footer { + clear:both; + margin:0 20px; + padding:5px 0 0 0; +} +.indexNav { + position:relative; + font-size:12px; + background-color:#dee3e9; +} +.indexNav ul { + margin-top:0; + padding:5px; +} +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { + font-size:13px; +} +.title { + color:#2c4557; + margin:10px 0; +} +.subTitle { + margin:5px 0 0 0; +} +.header ul { + margin:0 0 15px 0; + padding:0; +} +.footer ul { + margin:20px 0 5px 0; +} +.header ul li, .footer ul li { + list-style:none; + font-size:13px; +} +/* + * Styles for headings. + */ +div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList li.blockList h3 { + padding:0; + margin:15px 0; +} +ul.blockList li.blockList h2 { + padding:0px 0 20px 0; +} +/* + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { + clear:both; + padding:10px 20px; + position:relative; +} +.indexContainer { + margin:10px; + position:relative; + font-size:12px; +} +.indexContainer h2 { + font-size:13px; + padding:0 0 3px 0; +} +.indexContainer ul { + margin:0; + padding:0; +} +.indexContainer ul li { + list-style:none; + padding-top:2px; +} +.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { + font-size:12px; + font-weight:bold; + margin:10px 0 0 0; + color:#4E4E4E; +} +.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { + margin:5px 0 10px 0px; + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; +} +.serializedFormContainer dl.nameValue dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +.serializedFormContainer dl.nameValue dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* + * Styles for lists. + */ +li.circle { + list-style:circle; +} +ul.horizontal li { + display:inline; + font-size:0.9em; +} +ul.inheritance { + margin:0; + padding:0; +} +ul.inheritance li { + display:inline; + list-style:none; +} +ul.inheritance li ul.inheritance { + margin-left:15px; + padding-left:15px; + padding-top:1px; +} +ul.blockList, ul.blockListLast { + margin:10px 0 10px 0; + padding:0; +} +ul.blockList li.blockList, ul.blockListLast li.blockList { + list-style:none; + margin-bottom:15px; + line-height:1.4; +} +ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { + padding:0px 20px 5px 10px; + border:1px solid #ededed; + background-color:#f8f8f8; +} +ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { + padding:0 0 5px 8px; + background-color:#ffffff; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { + margin-left:0; + padding-left:0; + padding-bottom:15px; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { + list-style:none; + border-bottom:none; + padding-bottom:0; +} +table tr td dl, table tr td dl dt, table tr td dl dd { + margin-top:0; + margin-bottom:1px; +} +/* + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { + width:100%; + border-spacing:0; + border-left:1px solid #EEE; + border-right:1px solid #EEE; + border-bottom:1px solid #EEE; +} +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { + padding:0px; +} +.overviewSummary caption, .memberSummary caption, .typeSummary caption, +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:#253441; + font-weight:bold; + clear:none; + overflow:hidden; + padding:0px; + padding-top:10px; + padding-left:1px; + margin:0px; + white-space:pre; +} +.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, +.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, +.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, +.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { + color:#FFFFFF; +} +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} +.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + padding-bottom:7px; + display:inline-block; + float:left; + background-color:#F8981D; + border: none; + height:16px; +} +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#F8981D; + height:16px; +} +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#4D7A97; + height:16px; +} +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { + padding-top:0px; + padding-left:0px; + padding-right:0px; + background-image:none; + float:none; + display:inline; +} +.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { + display:none; + width:5px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + background-color:#4D7A97; + float:left; +} +.rowColor th, .altColor th { + font-weight:normal; +} +.overviewSummary td, .memberSummary td, .typeSummary td, +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { + text-align:left; + padding:0px 0px 12px 10px; +} +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { + vertical-align:top; + padding-right:0px; + padding-top:8px; + padding-bottom:3px; +} +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { + background:#dee3e9; + text-align:left; + padding:8px 3px 3px 7px; +} +td.colFirst, th.colFirst { + font-size:13px; +} +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { + font-size:13px; +} +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; + font-size:13px; +} +.overviewSummary td.colFirst, .overviewSummary th.colFirst, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, +.memberSummary td.colFirst, .memberSummary th.colFirst, +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { + vertical-align:top; +} +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { + font-weight:bold; +} +.tableSubHeadingColor { + background-color:#EEEEFF; +} +.altColor, .altColor th { + background-color:#FFFFFF; +} +.rowColor, .rowColor th { + background-color:#EEEEEF; +} +/* + * Styles for contents. + */ +.description pre { + margin-top:0; +} +.deprecatedContent { + margin:0; + padding:10px 0; +} +.docSummary { + padding:0; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + font-style:normal; +} +div.block { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; +} +td.colLast div { + padding-top:0px; +} +td.colLast a { + padding-bottom:3px; +} +/* + * Styles for formatting effect. + */ +.sourceLineNo { + color:green; + padding:0 30px 0 0; +} +h1.hidden { + visibility:hidden; + overflow:hidden; + font-size:10px; +} +.block { + display:block; + margin:3px 10px 2px 0px; + color:#474747; +} +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { + font-weight:bold; +} +.deprecationComment, .emphasizedPhrase, .interfaceName { + font-style:italic; +} +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, +div.block div.block span.interfaceName { + font-style:normal; +} +div.contentContainer ul.blockList li.blockList h2 { + padding-bottom:0px; +} +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/dist/http-resources/2.0.0/apidocs/type-search-index.js b/dist/http-resources/2.0.0/apidocs/type-search-index.js new file mode 100644 index 00000000..4c3c1899 --- /dev/null +++ b/dist/http-resources/2.0.0/apidocs/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"l":"All Classes","url":"allclasses-index.html"},{"p":"de.juplo.httpresources","l":"HttpResource"},{"p":"de.juplo.httpresources","l":"HttpResourceChainAwareResourceLoader"},{"p":"de.juplo.httpresources","l":"HttpResourceFetcher"},{"p":"de.juplo.httpresources","l":"HttpResourceProtocolResolver"},{"p":"de.juplo.httpresources","l":"HttpResources"},{"p":"de.juplo.httpresources","l":"HttpResourcesAutoConfiguration"},{"p":"de.juplo.httpresources","l":"HttpResourcesProperties"}] \ No newline at end of file diff --git a/dist/http-resources/2.0.0/apidocs/type-search-index.zip b/dist/http-resources/2.0.0/apidocs/type-search-index.zip new file mode 100644 index 00000000..bbe2dfb0 Binary files /dev/null and b/dist/http-resources/2.0.0/apidocs/type-search-index.zip differ diff --git a/dist/http-resources/2.0.0/auto-configuration.html b/dist/http-resources/2.0.0/auto-configuration.html new file mode 100644 index 00000000..c4da89ae --- /dev/null +++ b/dist/http-resources/2.0.0/auto-configuration.html @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HttpResources — Auto-Configuration + + + + +

    Path

    +

    +

      +
    1. HttpResources
    2. Auto-Configuration
    +

    +
    +
    + + + + +

    Getting Started

    +
    +

    Maven Dependency

    + +
    +
    
    +    <dependency>
    +      <groupId>de.juplo</groupId>
    +      <artifactId>http-resources</artifactId>
    +      <version>2.0.0</version>
    +    </dependency>
    +  
    +
    +

    Configuration Properties

    +
    +

    juplo.http-resources.default-ttl

    + +

    Default-value: 6400

    + +

    +

    +
    +

    juplo.http-resources.min-ttl

    + +

    Default-value: 0

    + +

    +

    +
    +

    juplo.http-resources.serve-stale

    + +

    Default-value: true

    + +

    +

    +
    +

    juplo.http-resources.cache

    + +

    Default-value: true

    + +

    +

    +
    +

    Autoconfiguration

    +
    +

    HttpResources

    + +

    +

    +
    +

    HttpResourceProtocolResolver

    + +

    +

    +
    +

    HttpResourceChainAwareResourceLoader

    + +

    +

    +
    +

    HttpResourceFetcher

    + +

    +

    +
    +

    Clock

    + +

    +

    +
    +

    Examples

    + + +
    + +
    +
    +

    Pages

    +

    +

    +

    + + diff --git a/dist/http-resources/2.0.0/configuration-properties.html b/dist/http-resources/2.0.0/configuration-properties.html new file mode 100644 index 00000000..c8749bfc --- /dev/null +++ b/dist/http-resources/2.0.0/configuration-properties.html @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HttpResources — Configuration-Properties + + + + +

    Path

    +

    +

      +
    1. HttpResources
    2. Configuration-Properties
    +

    +
    +
    + + + + +

    Getting Started

    +
    +

    Maven Dependency

    + +
    +
    
    +    <dependency>
    +      <groupId>de.juplo</groupId>
    +      <artifactId>http-resources</artifactId>
    +      <version>2.0.0</version>
    +    </dependency>
    +  
    +
    +

    Configuration Properties

    +
    +

    juplo.http-resources.default-ttl

    + +

    Default-value: 6400

    + +

    +

    +
    +

    juplo.http-resources.min-ttl

    + +

    Default-value: 0

    + +

    +

    +
    +

    juplo.http-resources.serve-stale

    + +

    Default-value: true

    + +

    +

    +
    +

    juplo.http-resources.cache

    + +

    Default-value: true

    + +

    +

    +
    +

    Autoconfiguration

    +
    +

    HttpResources

    + +

    +

    +
    +

    HttpResourceProtocolResolver

    + +

    +

    +
    +

    HttpResourceChainAwareResourceLoader

    + +

    +

    +
    +

    HttpResourceFetcher

    + +

    +

    +
    +

    Clock

    + +

    +

    +
    +

    Examples

    + + +
    + +
    +
    +

    Pages

    +

    +

    +

    + + diff --git a/dist/http-resources/2.0.0/cpd.html b/dist/http-resources/2.0.0/cpd.html new file mode 100644 index 00000000..ec617f5a --- /dev/null +++ b/dist/http-resources/2.0.0/cpd.html @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HttpResources – CPD Results + + + + +

    Path

    +

    +

      +
    +

    +
    +
    +
    +

    CPD Results

    +

    The following document contains the results of PMD's CPD 6.29.0.

    +

    Duplications

    +

    CPD found no problems in your source code.

    +
    +
    +

    Pages

    +

    +

    +

    + + diff --git a/dist/http-resources/2.0.0/css/maven-base.css b/dist/http-resources/2.0.0/css/maven-base.css new file mode 100644 index 00000000..322efae7 --- /dev/null +++ b/dist/http-resources/2.0.0/css/maven-base.css @@ -0,0 +1,168 @@ +/* + * 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. + */ + +body { + margin: 0px; + padding: 0px; +} +table { + padding:0px; + width: 100%; + margin-left: -2px; + margin-right: -2px; +} +acronym { + cursor: help; + border-bottom: 1px dotted #feb; +} +table.bodyTable th, table.bodyTable td { + padding: 2px 4px 2px 4px; + vertical-align: top; +} +div.clear{ + clear:both; + visibility: hidden; +} +div.clear hr{ + display: none; +} +#bannerLeft, #bannerRight { + font-size: xx-large; + font-weight: bold; +} +#bannerLeft img, #bannerRight img { + margin: 0px; +} +.xleft, #bannerLeft img { + float:left; +} +.xright, #bannerRight { + float:right; +} +#banner { + padding: 0px; +} +#breadcrumbs { + padding: 3px 10px 3px 10px; +} +#leftColumn { + width: 170px; + float:left; + overflow: auto; +} +#bodyColumn { + margin-right: 1.5em; + margin-left: 197px; +} +#legend { + padding: 8px 0 8px 0; +} +#navcolumn { + padding: 8px 4px 0 8px; +} +#navcolumn h5 { + margin: 0; + padding: 0; + font-size: small; +} +#navcolumn ul { + margin: 0; + padding: 0; + font-size: small; +} +#navcolumn li { + list-style-type: none; + background-image: none; + background-repeat: no-repeat; + background-position: 0 0.4em; + padding-left: 16px; + list-style-position: outside; + line-height: 1.2em; + font-size: smaller; +} +#navcolumn li.expanded { + background-image: url(../images/expanded.gif); +} +#navcolumn li.collapsed { + background-image: url(../images/collapsed.gif); +} +#navcolumn li.none { + text-indent: -1em; + margin-left: 1em; +} +#poweredBy { + text-align: center; +} +#navcolumn img { + margin-top: 10px; + margin-bottom: 3px; +} +#poweredBy img { + display:block; + margin: 20px 0 20px 17px; +} +#search img { + margin: 0px; + display: block; +} +#search #q, #search #btnG { + border: 1px solid #999; + margin-bottom:10px; +} +#search form { + margin: 0px; +} +#lastPublished { + font-size: x-small; +} +.navSection { + margin-bottom: 2px; + padding: 8px; +} +.navSectionHead { + font-weight: bold; + font-size: x-small; +} +.section { + padding: 4px; +} +#footer { + padding: 3px 10px 3px 10px; + font-size: x-small; +} +#breadcrumbs { + font-size: x-small; + margin: 0pt; +} +.source { + padding: 12px; + margin: 1em 7px 1em 7px; +} +.source pre { + margin: 0px; + padding: 0px; +} +#navcolumn img.imageLink, .imageLink { + padding-left: 0px; + padding-bottom: 0px; + padding-top: 0px; + padding-right: 2px; + border: 0px; + margin: 0px; +} diff --git a/dist/http-resources/2.0.0/css/maven-theme.css b/dist/http-resources/2.0.0/css/maven-theme.css new file mode 100644 index 00000000..4e2bdfbe --- /dev/null +++ b/dist/http-resources/2.0.0/css/maven-theme.css @@ -0,0 +1,161 @@ +/* + * 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. + */ + +body { + padding: 0px 0px 10px 0px; +} +body, td, select, input, li{ + font-family: Verdana, Helvetica, Arial, sans-serif; + font-size: 13px; +} +code{ + font-family: Courier, monospace; + font-size: 13px; +} +a { + text-decoration: none; +} +a:link { + color:#36a; +} +a:visited { + color:#47a; +} +a:active, a:hover { + color:#69c; +} +#legend li.externalLink { + background: url(../images/external.png) left top no-repeat; + padding-left: 18px; +} +a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover { + background: url(../images/external.png) right center no-repeat; + padding-right: 18px; +} +#legend li.newWindow { + background: url(../images/newwindow.png) left top no-repeat; + padding-left: 18px; +} +a.newWindow, a.newWindow:link, a.newWindow:visited, a.newWindow:active, a.newWindow:hover { + background: url(../images/newwindow.png) right center no-repeat; + padding-right: 18px; +} +h2 { + padding: 4px 4px 4px 6px; + border: 1px solid #999; + color: #900; + background-color: #ddd; + font-weight:900; + font-size: x-large; +} +h3 { + padding: 4px 4px 4px 6px; + border: 1px solid #aaa; + color: #900; + background-color: #eee; + font-weight: normal; + font-size: large; +} +h4 { + padding: 4px 4px 4px 6px; + border: 1px solid #bbb; + color: #900; + background-color: #fff; + font-weight: normal; + font-size: large; +} +h5 { + padding: 4px 4px 4px 6px; + color: #900; + font-size: medium; +} +p { + line-height: 1.3em; + font-size: small; +} +#breadcrumbs { + border-top: 1px solid #aaa; + border-bottom: 1px solid #aaa; + background-color: #ccc; +} +#leftColumn { + margin: 10px 0 0 5px; + border: 1px solid #999; + background-color: #eee; + padding-bottom: 3px; /* IE-9 scrollbar-fix */ +} +#navcolumn h5 { + font-size: smaller; + border-bottom: 1px solid #aaaaaa; + padding-top: 2px; + color: #000; +} + +table.bodyTable th { + color: white; + background-color: #bbb; + text-align: left; + font-weight: bold; +} + +table.bodyTable th, table.bodyTable td { + font-size: 1em; +} + +table.bodyTable tr.a { + background-color: #ddd; +} + +table.bodyTable tr.b { + background-color: #eee; +} + +.source { + border: 1px solid #999; +} +dl { + padding: 4px 4px 4px 6px; + border: 1px solid #aaa; + background-color: #ffc; +} +dt { + color: #900; +} +#organizationLogo img, #projectLogo img, #projectLogo span{ + margin: 8px; +} +#banner { + border-bottom: 1px solid #fff; +} +.errormark, .warningmark, .donemark, .infomark { + background: url(../images/icon_error_sml.gif) no-repeat; +} + +.warningmark { + background-image: url(../images/icon_warning_sml.gif); +} + +.donemark { + background-image: url(../images/icon_success_sml.gif); +} + +.infomark { + background-image: url(../images/icon_info_sml.gif); +} + diff --git a/dist/http-resources/2.0.0/css/print.css b/dist/http-resources/2.0.0/css/print.css new file mode 100644 index 00000000..18fcbad7 --- /dev/null +++ b/dist/http-resources/2.0.0/css/print.css @@ -0,0 +1,26 @@ +/* + * 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. + */ + +#banner, #footer, #leftcol, #breadcrumbs, .docs #toc, .docs .courtesylinks, #leftColumn, #navColumn { + display: none !important; +} +#bodyColumn, body.docs div.docs { + margin: 0 !important; + border: none !important +} diff --git a/dist/http-resources/2.0.0/dependencies.html b/dist/http-resources/2.0.0/dependencies.html index 45544cd5..8161f4e6 100644 --- a/dist/http-resources/2.0.0/dependencies.html +++ b/dist/http-resources/2.0.0/dependencies.html @@ -1,6 +1,6 @@ - + @@ -15,62 +15,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -82,33 +29,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -118,9 +41,9 @@ - + - + @@ -130,9 +53,9 @@ - + - + @@ -142,27 +65,12 @@ - - - - - - - - - - + - - - - - - - + @@ -171,7 +79,7 @@ - + @@ -183,7 +91,7 @@ - + @@ -202,15 +110,15 @@ - + - + - + @@ -218,178 +126,71 @@ xmlns="http://www.w3.org/1999/xhtml" th:replace="~{/templates/layout.html :: layout( uri='/http-resources/2.0.0/dependencies.html', + title=~{:: title}, + maincontent=~{:: .maincontent}, json='MERGE: { - "_names": { + "_titles": { - "/http-resources/2.0.0/dependencies.html": "Dependencies" - , - "/http-resources/2.0.0/dependency-info.html": "Dependency Information" - , - "/http-resources/2.0.0/dependency-management.html": "Dependency Management" - , - "/http-resources/2.0.0/distribution-management.html": "Distribution Management" - , - "/http-resources/2.0.0/index.html": "HttpResources" + "/http-resources/2.0.0/index.html": "Franz" , - "/http-resources/2.0.0/licenses.html": "Licenses" + "/http-resources/2.0.0/getting-started.html": "Getting Started" , - "/http-resources/2.0.0/plugin-management.html": "Plugin Management" + "/http-resources/2.0.0/configuration-properties.html": "Configuration-Properties" , - "/http-resources/2.0.0/plugins.html": "Plugins" - , - "/http-resources/2.0.0/scm.html": "Source Code Management" - , - "/http-resources/2.0.0/summary.html": "Summary" - , - "/http-resources/2.0.0/team.html": "Team" + "/http-resources/2.0.0/auto-configuration.html": "Auto-Configuration" , "/http-resources/2.0.0/project-info.html": "Project Information" , "/http-resources/2.0.0/project-reports.html": "Project Reports" }, "_childs": { - + "/http-resources/2.0.0/index.html": [ "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/project-reports.html" - ] - , - "/http-resources/2.0.0/project-info.html": [ - - "/http-resources/2.0.0/dependencies.html" - , - "/http-resources/2.0.0/dependency-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - , - "/http-resources/2.0.0/distribution-management.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/licenses.html" - , - "/http-resources/2.0.0/plugin-management.html" + "/http-resources/2.0.0/getting-started.html" , - "/http-resources/2.0.0/plugins.html" + "/http-resources/2.0.0/configuration-properties.html" , - "/http-resources/2.0.0/scm.html" + "/http-resources/2.0.0/auto-configuration.html" , - "/http-resources/2.0.0/summary.html" + "/http-resources/2.0.0/project-info.html" , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/project-reports.html" ] - }, + }, "_crumbs": { - "/http-resources/2.0.0/dependencies.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependencies.html" - ] - , - "/http-resources/2.0.0/dependency-info.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-info.html" - ] - , - "/http-resources/2.0.0/dependency-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - ] - , - "/http-resources/2.0.0/distribution-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/distribution-management.html" - ] - , "/http-resources/2.0.0/index.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" ] , - "/http-resources/2.0.0/licenses.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/licenses.html" - ] - , - "/http-resources/2.0.0/plugin-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugin-management.html" - ] - , - "/http-resources/2.0.0/plugins.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugins.html" - ] - , - "/http-resources/2.0.0/scm.html": [ + "/http-resources/2.0.0/getting-started.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/scm.html" + "/http-resources/2.0.0/getting-started.html" ] , - "/http-resources/2.0.0/summary.html": [ + "/http-resources/2.0.0/configuration-properties.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/summary.html" + "/http-resources/2.0.0/configuration-properties.html" ] , - "/http-resources/2.0.0/team.html": [ + "/http-resources/2.0.0/auto-configuration.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/auto-configuration.html" ] , "/http-resources/2.0.0/project-info.html": [ @@ -420,7 +221,7 @@

    Path

      -
    1. HttpResources
    2. Project Information
    3. Dependencies
    +


    @@ -492,24 +293,30 @@ jar The Apache Software License, Version 2.0 +org.mockito +mockito-core +3.3.3 +jar +The MIT License + org.springframework.boot spring-boot-starter-logging 2.3.5.RELEASE jar Apache License, Version 2.0 - + org.springframework.boot spring-boot-starter-test 2.3.5.RELEASE jar Apache License, Version 2.0 - + org.springframework.boot spring-boot-starter-thymeleaf 2.3.5.RELEASE jar Apache License, Version 2.0 - + org.testcontainers nginx 1.14.3 @@ -1143,149 +950,143 @@ The Apache Software License, Version 2.0 org.mockito -mockito-core -3.3.3 -jar -The MIT License - -org.mockito mockito-junit-jupiter 3.3.3 jar The MIT License - + org.mozilla rhino 1.7.7.2 jar Mozilla Public License, Version 2.0 - + org.objenesis objenesis 2.6 jar Apache 2 - + org.opentest4j opentest4j 1.2.0 jar The Apache License, Version 2.0 - + org.ow2.asm asm 5.0.4 jar BSD - + org.rnorth tcp-unix-socket-proxy 1.0.2 jar MIT - + org.rnorth.duct-tape duct-tape 1.0.8 jar MIT - + org.rnorth.visible-assertions visible-assertions 2.1.2 jar MIT - + org.scijava native-lib-loader 2.0.2 jar CC0 1.0 Universal License - + org.skyscreamer jsonassert 1.5.0 jar The Apache Software License, Version 2.0 - + org.slf4j jul-to-slf4j 1.7.30 jar MIT License - + org.slf4j slf4j-ext 1.7.30 jar MIT License - + org.springframework spring-test 5.2.10.RELEASE jar Apache License, Version 2.0 - + org.springframework.boot spring-boot-starter 2.3.5.RELEASE jar Apache License, Version 2.0 - + org.springframework.boot spring-boot-test 2.3.5.RELEASE jar Apache License, Version 2.0 - + org.springframework.boot spring-boot-test-autoconfigure 2.3.5.RELEASE jar Apache License, Version 2.0 - + org.testcontainers testcontainers 1.14.3 jar MIT - + org.thymeleaf thymeleaf 3.0.11.RELEASE jar The Apache Software License, Version 2.0 - + org.thymeleaf thymeleaf-spring5 3.0.11.RELEASE jar The Apache Software License, Version 2.0 - + org.thymeleaf.extras thymeleaf-extras-java8time 3.0.4.RELEASE jar The Apache Software License, Version 2.0 - + org.unbescape unbescape 1.1.6.RELEASE jar The Apache Software License, Version 2.0 - + org.xmlunit xmlunit-core 2.7.0 jar The Apache Software License, Version 2.0 - + org.xmlunit xmlunit-placeholders 2.7.0 jar The Apache Software License, Version 2.0 - + org.yaml snakeyaml 1.26 @@ -1320,9 +1121,9 @@ HttpResources -

    Description: A library to serve remote content as Spring Resource

    -

    URL: https://spring.io/projects/spring-boot/http-resources

    -

    Project Licenses: Apache License, Version 2.0

    +

    Description: A library to serve remote content as Spring Resources

    +

    URL: https://juplo.de/http-resources/

    +

    Project Licenses: The Apache Software License, Version 2.0

    • org.springframework:spring-webmvc:jar:5.2.10.RELEASE (compile) [Information]
  • -
  • org.mockito:mockito-core:jar:3.3.3 (test) [Information] -
      -
    • net.bytebuddy:byte-buddy:jar:1.10.17 (test) [Information]
    • -
    • net.bytebuddy:byte-buddy-agent:jar:1.10.17 (test) [Information]
    • -
    • org.objenesis:objenesis:jar:2.6 (test) [Information]
  • -
  • org.mockito:mockito-junit-jupiter:jar:3.3.3 (test) [Information]
  • org.mockito:mockito-junit-jupiter:jar:3.3.3 (test) [Information]
  • -
  • org.skyscreamer:jsonassert:jar:1.5.0 (test) [Information]
  • org.skyscreamer:jsonassert:jar:1.5.0 (test) [Information]
      -
    • com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1 (test) [Information]
    • com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1 (test) [Information]
  • -
  • org.springframework:spring-test:jar:5.2.10.RELEASE (test) [Information]
  • org.springframework:spring-test:jar:5.2.10.RELEASE (test) [Information]
  • -
  • org.xmlunit:xmlunit-core:jar:2.7.0 (test) [Information]
  • org.xmlunit:xmlunit-core:jar:2.7.0 (test) [Information]
  • -
  • org.jmockit:jmockit:jar:1.49 (test) [Information]
  • org.jmockit:jmockit:jar:1.49 (test) [Information]
  • +
  • org.mockito:mockito-core:jar:3.3.3 (test) [Information] +
      +
    • net.bytebuddy:byte-buddy:jar:1.10.17 (test) [Information]
    • +
    • net.bytebuddy:byte-buddy-agent:jar:1.10.17 (test) [Information]
    • +
    • org.objenesis:objenesis:jar:2.6 (test) [Information]
  • org.apache.httpcomponents:httpclient:jar:4.5.13 (test) [Information]
  • Franz
  • Getting Started
  • Configuration-Properties
  • Auto-Configuration
  • Project Information
  • Project Reports
  • diff --git a/dist/http-resources/2.0.0/pmd.html b/dist/http-resources/2.0.0/pmd.html new file mode 100644 index 00000000..95d3b577 --- /dev/null +++ b/dist/http-resources/2.0.0/pmd.html @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HttpResources – PMD Results + + + + +

    Path

    +

    +

      +
    +

    +
    +
    +
    +

    PMD Results

    +

    The following document contains the results of PMD 6.29.0.

    +

    Violations By Priority

    +

    Priority 3

    +

    de/juplo/httpresources/HttpResourceFetcher.java

    + + + + + + + + + + + + + + + + + + + + +
    RuleViolationLine
    UnusedLocalVariableAvoid unused local variables such as 'must_revalidate'.104
    EmptyIfStmtAvoid empty if statements173179
    EmptyCatchBlockAvoid empty catch blocks226
    EmptyCatchBlockAvoid empty catch blocks265
    +

    Priority 4

    +

    de/juplo/httpresources/HttpResourceFetcher.java

    + + + + + + + + + + + + +
    RuleViolationLine
    UselessParenthesesUseless parentheses.168
    UselessParenthesesUseless parentheses.168
    +

    Files

    +

    de/juplo/httpresources/HttpResourceFetcher.java

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    RuleViolationPriorityLine
    UnusedLocalVariableAvoid unused local variables such as 'must_revalidate'.3104
    UselessParenthesesUseless parentheses.4168
    UselessParenthesesUseless parentheses.4168
    EmptyIfStmtAvoid empty if statements3173179
    EmptyCatchBlockAvoid empty catch blocks3226
    EmptyCatchBlockAvoid empty catch blocks3265
    +
    +
    +

    Pages

    +

    +

    +

    + + diff --git a/dist/http-resources/2.0.0/project-info.html b/dist/http-resources/2.0.0/project-info.html index caf1ca99..64725c79 100644 --- a/dist/http-resources/2.0.0/project-info.html +++ b/dist/http-resources/2.0.0/project-info.html @@ -1,6 +1,6 @@ - + @@ -15,62 +15,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -82,33 +29,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -118,9 +41,9 @@ - + - + @@ -130,9 +53,9 @@ - + - + @@ -142,27 +65,12 @@ - - - - - - - - - - - - - - + - - - + @@ -171,7 +79,7 @@ - + @@ -183,7 +91,7 @@ - + @@ -202,7 +110,7 @@ - + @@ -210,7 +118,7 @@ - + @@ -218,178 +126,71 @@ xmlns="http://www.w3.org/1999/xhtml" th:replace="~{/templates/layout.html :: layout( uri='/http-resources/2.0.0/project-info.html', + title=~{:: title}, + maincontent=~{:: .maincontent}, json='MERGE: { - "_names": { + "_titles": { - "/http-resources/2.0.0/dependencies.html": "Dependencies" - , - "/http-resources/2.0.0/dependency-info.html": "Dependency Information" - , - "/http-resources/2.0.0/dependency-management.html": "Dependency Management" - , - "/http-resources/2.0.0/distribution-management.html": "Distribution Management" + "/http-resources/2.0.0/index.html": "Franz" , - "/http-resources/2.0.0/index.html": "HttpResources" + "/http-resources/2.0.0/getting-started.html": "Getting Started" , - "/http-resources/2.0.0/licenses.html": "Licenses" + "/http-resources/2.0.0/configuration-properties.html": "Configuration-Properties" , - "/http-resources/2.0.0/plugin-management.html": "Plugin Management" - , - "/http-resources/2.0.0/plugins.html": "Plugins" - , - "/http-resources/2.0.0/scm.html": "Source Code Management" - , - "/http-resources/2.0.0/summary.html": "Summary" - , - "/http-resources/2.0.0/team.html": "Team" + "/http-resources/2.0.0/auto-configuration.html": "Auto-Configuration" , "/http-resources/2.0.0/project-info.html": "Project Information" , "/http-resources/2.0.0/project-reports.html": "Project Reports" }, "_childs": { - + "/http-resources/2.0.0/index.html": [ "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/project-reports.html" - ] - , - "/http-resources/2.0.0/project-info.html": [ - - "/http-resources/2.0.0/dependencies.html" - , - "/http-resources/2.0.0/dependency-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - , - "/http-resources/2.0.0/distribution-management.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/licenses.html" - , - "/http-resources/2.0.0/plugin-management.html" + "/http-resources/2.0.0/getting-started.html" , - "/http-resources/2.0.0/plugins.html" + "/http-resources/2.0.0/configuration-properties.html" , - "/http-resources/2.0.0/scm.html" + "/http-resources/2.0.0/auto-configuration.html" , - "/http-resources/2.0.0/summary.html" + "/http-resources/2.0.0/project-info.html" , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/project-reports.html" ] - }, + }, "_crumbs": { - "/http-resources/2.0.0/dependencies.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependencies.html" - ] - , - "/http-resources/2.0.0/dependency-info.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-info.html" - ] - , - "/http-resources/2.0.0/dependency-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - ] - , - "/http-resources/2.0.0/distribution-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/distribution-management.html" - ] - , "/http-resources/2.0.0/index.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" ] , - "/http-resources/2.0.0/licenses.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/licenses.html" - ] - , - "/http-resources/2.0.0/plugin-management.html": [ + "/http-resources/2.0.0/getting-started.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugin-management.html" + "/http-resources/2.0.0/getting-started.html" ] , - "/http-resources/2.0.0/plugins.html": [ + "/http-resources/2.0.0/configuration-properties.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugins.html" + "/http-resources/2.0.0/configuration-properties.html" ] , - "/http-resources/2.0.0/scm.html": [ + "/http-resources/2.0.0/auto-configuration.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/scm.html" - ] - , - "/http-resources/2.0.0/summary.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/summary.html" - ] - , - "/http-resources/2.0.0/team.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/auto-configuration.html" ] , "/http-resources/2.0.0/project-info.html": [ @@ -446,7 +247,7 @@ This document provides informations on the distribution management of this project. About -A library to serve remote content as Spring Resource +A library to serve remote content as Spring Resources Licenses This document lists the project license(s). @@ -470,7 +271,7 @@

    Pages

    +
  • Franz
  • Getting Started
  • Configuration-Properties
  • Auto-Configuration
  • Project Information
  • Project Reports
  • diff --git a/dist/http-resources/2.0.0/project-reports.html b/dist/http-resources/2.0.0/project-reports.html new file mode 100644 index 00000000..f5cb6c1e --- /dev/null +++ b/dist/http-resources/2.0.0/project-reports.html @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HttpResources – Generated Reports + + + + +

    Path

    +

    +

      +
    1. HttpResources
    2. Project Reports
    +

    +
    +
    +
    +

    Generated Reports

    +

    This document provides an overview of the various reports that are automatically generated by Maven . Each report is briefly described below.

    +

    Overview

    + + + + + + + + + + + + + + + + + + + + + +
    DocumentDescription
    JavadocJavadoc API documentation.
    Test JavadocTest Javadoc API documentation.
    Source XrefHTML based, cross-reference version of Java source code.
    Test Source XrefHTML based, cross-reference version of Java test source code.
    CPDDuplicate code detection.
    PMDVerification of coding rules.
    +
    +
    +

    Pages

    +

    +

    +

    + + diff --git a/dist/http-resources/2.0.0/scm.html b/dist/http-resources/2.0.0/scm.html index 6a9c9147..fd459277 100644 --- a/dist/http-resources/2.0.0/scm.html +++ b/dist/http-resources/2.0.0/scm.html @@ -1,6 +1,6 @@ - + @@ -15,62 +15,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -82,33 +29,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -118,9 +41,9 @@ - + - + @@ -130,9 +53,9 @@ - + - + @@ -142,27 +65,12 @@ - - - - - - - - - - - - - - + - - - + @@ -171,7 +79,7 @@ - + @@ -183,7 +91,7 @@ - + @@ -202,15 +110,15 @@ - + - + - + @@ -218,178 +126,71 @@ xmlns="http://www.w3.org/1999/xhtml" th:replace="~{/templates/layout.html :: layout( uri='/http-resources/2.0.0/scm.html', + title=~{:: title}, + maincontent=~{:: .maincontent}, json='MERGE: { - "_names": { + "_titles": { - "/http-resources/2.0.0/dependencies.html": "Dependencies" - , - "/http-resources/2.0.0/dependency-info.html": "Dependency Information" - , - "/http-resources/2.0.0/dependency-management.html": "Dependency Management" - , - "/http-resources/2.0.0/distribution-management.html": "Distribution Management" - , - "/http-resources/2.0.0/index.html": "HttpResources" + "/http-resources/2.0.0/index.html": "Franz" , - "/http-resources/2.0.0/licenses.html": "Licenses" + "/http-resources/2.0.0/getting-started.html": "Getting Started" , - "/http-resources/2.0.0/plugin-management.html": "Plugin Management" + "/http-resources/2.0.0/configuration-properties.html": "Configuration-Properties" , - "/http-resources/2.0.0/plugins.html": "Plugins" - , - "/http-resources/2.0.0/scm.html": "Source Code Management" - , - "/http-resources/2.0.0/summary.html": "Summary" - , - "/http-resources/2.0.0/team.html": "Team" + "/http-resources/2.0.0/auto-configuration.html": "Auto-Configuration" , "/http-resources/2.0.0/project-info.html": "Project Information" , "/http-resources/2.0.0/project-reports.html": "Project Reports" }, "_childs": { - + "/http-resources/2.0.0/index.html": [ "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/project-reports.html" - ] - , - "/http-resources/2.0.0/project-info.html": [ - - "/http-resources/2.0.0/dependencies.html" - , - "/http-resources/2.0.0/dependency-info.html" + "/http-resources/2.0.0/getting-started.html" , - "/http-resources/2.0.0/dependency-management.html" - , - "/http-resources/2.0.0/distribution-management.html" - , - "/http-resources/2.0.0/index.html" + "/http-resources/2.0.0/configuration-properties.html" , - "/http-resources/2.0.0/licenses.html" + "/http-resources/2.0.0/auto-configuration.html" , - "/http-resources/2.0.0/plugin-management.html" - , - "/http-resources/2.0.0/plugins.html" - , - "/http-resources/2.0.0/scm.html" - , - "/http-resources/2.0.0/summary.html" + "/http-resources/2.0.0/project-info.html" , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/project-reports.html" ] - }, + }, "_crumbs": { - "/http-resources/2.0.0/dependencies.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependencies.html" - ] - , - "/http-resources/2.0.0/dependency-info.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-info.html" - ] - , - "/http-resources/2.0.0/dependency-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - ] - , - "/http-resources/2.0.0/distribution-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/distribution-management.html" - ] - , "/http-resources/2.0.0/index.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" ] , - "/http-resources/2.0.0/licenses.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/licenses.html" - ] - , - "/http-resources/2.0.0/plugin-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugin-management.html" - ] - , - "/http-resources/2.0.0/plugins.html": [ + "/http-resources/2.0.0/getting-started.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugins.html" + "/http-resources/2.0.0/getting-started.html" ] , - "/http-resources/2.0.0/scm.html": [ + "/http-resources/2.0.0/configuration-properties.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/scm.html" + "/http-resources/2.0.0/configuration-properties.html" ] , - "/http-resources/2.0.0/summary.html": [ + "/http-resources/2.0.0/auto-configuration.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/summary.html" - ] - , - "/http-resources/2.0.0/team.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/auto-configuration.html" ] , "/http-resources/2.0.0/project-info.html": [ @@ -420,17 +221,25 @@

    Path

      -
    1. HttpResources
    2. Project Information
    3. Source Code Management
    +


    Overview

    -

    This project uses a source code management system to manage its source code.

    +

    This project uses Git to manage its source code. Instructions on Git use can be found at https://git-scm.com/documentation.

    Web Browser Access

    The following is a link to a browsable version of the source repository:

    +
    http://juplo.de/gitweb/?p=http-resources;a=summary
    +

    Anonymous Access

    +

    The source can be checked out anonymously from Git with this command (See https://git-scm.com/docs/git-clone):

    +
    +
    $ git clone http://juplo.de/git/http-resources
    +

    Developer Access

    +

    Only project developers can access the Git tree via this method (See https://git-scm.com/docs/git-clone).

    +
    +
    $ git clone ssh://juplo.de/var/lib/git/juplo/http-resources

    Access from Behind a Firewall

    Refer to the documentation of the SCM used for more information about access behind a firewall.

    @@ -438,7 +247,7 @@

    Pages

    +
  • Franz
  • Getting Started
  • Configuration-Properties
  • Auto-Configuration
  • Project Information
  • Project Reports
  • diff --git a/dist/http-resources/2.0.0/site/css/maven-base.css b/dist/http-resources/2.0.0/site/css/maven-base.css deleted file mode 100644 index 322efae7..00000000 --- a/dist/http-resources/2.0.0/site/css/maven-base.css +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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. - */ - -body { - margin: 0px; - padding: 0px; -} -table { - padding:0px; - width: 100%; - margin-left: -2px; - margin-right: -2px; -} -acronym { - cursor: help; - border-bottom: 1px dotted #feb; -} -table.bodyTable th, table.bodyTable td { - padding: 2px 4px 2px 4px; - vertical-align: top; -} -div.clear{ - clear:both; - visibility: hidden; -} -div.clear hr{ - display: none; -} -#bannerLeft, #bannerRight { - font-size: xx-large; - font-weight: bold; -} -#bannerLeft img, #bannerRight img { - margin: 0px; -} -.xleft, #bannerLeft img { - float:left; -} -.xright, #bannerRight { - float:right; -} -#banner { - padding: 0px; -} -#breadcrumbs { - padding: 3px 10px 3px 10px; -} -#leftColumn { - width: 170px; - float:left; - overflow: auto; -} -#bodyColumn { - margin-right: 1.5em; - margin-left: 197px; -} -#legend { - padding: 8px 0 8px 0; -} -#navcolumn { - padding: 8px 4px 0 8px; -} -#navcolumn h5 { - margin: 0; - padding: 0; - font-size: small; -} -#navcolumn ul { - margin: 0; - padding: 0; - font-size: small; -} -#navcolumn li { - list-style-type: none; - background-image: none; - background-repeat: no-repeat; - background-position: 0 0.4em; - padding-left: 16px; - list-style-position: outside; - line-height: 1.2em; - font-size: smaller; -} -#navcolumn li.expanded { - background-image: url(../images/expanded.gif); -} -#navcolumn li.collapsed { - background-image: url(../images/collapsed.gif); -} -#navcolumn li.none { - text-indent: -1em; - margin-left: 1em; -} -#poweredBy { - text-align: center; -} -#navcolumn img { - margin-top: 10px; - margin-bottom: 3px; -} -#poweredBy img { - display:block; - margin: 20px 0 20px 17px; -} -#search img { - margin: 0px; - display: block; -} -#search #q, #search #btnG { - border: 1px solid #999; - margin-bottom:10px; -} -#search form { - margin: 0px; -} -#lastPublished { - font-size: x-small; -} -.navSection { - margin-bottom: 2px; - padding: 8px; -} -.navSectionHead { - font-weight: bold; - font-size: x-small; -} -.section { - padding: 4px; -} -#footer { - padding: 3px 10px 3px 10px; - font-size: x-small; -} -#breadcrumbs { - font-size: x-small; - margin: 0pt; -} -.source { - padding: 12px; - margin: 1em 7px 1em 7px; -} -.source pre { - margin: 0px; - padding: 0px; -} -#navcolumn img.imageLink, .imageLink { - padding-left: 0px; - padding-bottom: 0px; - padding-top: 0px; - padding-right: 2px; - border: 0px; - margin: 0px; -} diff --git a/dist/http-resources/2.0.0/site/css/maven-theme.css b/dist/http-resources/2.0.0/site/css/maven-theme.css deleted file mode 100644 index 4e2bdfbe..00000000 --- a/dist/http-resources/2.0.0/site/css/maven-theme.css +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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. - */ - -body { - padding: 0px 0px 10px 0px; -} -body, td, select, input, li{ - font-family: Verdana, Helvetica, Arial, sans-serif; - font-size: 13px; -} -code{ - font-family: Courier, monospace; - font-size: 13px; -} -a { - text-decoration: none; -} -a:link { - color:#36a; -} -a:visited { - color:#47a; -} -a:active, a:hover { - color:#69c; -} -#legend li.externalLink { - background: url(../images/external.png) left top no-repeat; - padding-left: 18px; -} -a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover { - background: url(../images/external.png) right center no-repeat; - padding-right: 18px; -} -#legend li.newWindow { - background: url(../images/newwindow.png) left top no-repeat; - padding-left: 18px; -} -a.newWindow, a.newWindow:link, a.newWindow:visited, a.newWindow:active, a.newWindow:hover { - background: url(../images/newwindow.png) right center no-repeat; - padding-right: 18px; -} -h2 { - padding: 4px 4px 4px 6px; - border: 1px solid #999; - color: #900; - background-color: #ddd; - font-weight:900; - font-size: x-large; -} -h3 { - padding: 4px 4px 4px 6px; - border: 1px solid #aaa; - color: #900; - background-color: #eee; - font-weight: normal; - font-size: large; -} -h4 { - padding: 4px 4px 4px 6px; - border: 1px solid #bbb; - color: #900; - background-color: #fff; - font-weight: normal; - font-size: large; -} -h5 { - padding: 4px 4px 4px 6px; - color: #900; - font-size: medium; -} -p { - line-height: 1.3em; - font-size: small; -} -#breadcrumbs { - border-top: 1px solid #aaa; - border-bottom: 1px solid #aaa; - background-color: #ccc; -} -#leftColumn { - margin: 10px 0 0 5px; - border: 1px solid #999; - background-color: #eee; - padding-bottom: 3px; /* IE-9 scrollbar-fix */ -} -#navcolumn h5 { - font-size: smaller; - border-bottom: 1px solid #aaaaaa; - padding-top: 2px; - color: #000; -} - -table.bodyTable th { - color: white; - background-color: #bbb; - text-align: left; - font-weight: bold; -} - -table.bodyTable th, table.bodyTable td { - font-size: 1em; -} - -table.bodyTable tr.a { - background-color: #ddd; -} - -table.bodyTable tr.b { - background-color: #eee; -} - -.source { - border: 1px solid #999; -} -dl { - padding: 4px 4px 4px 6px; - border: 1px solid #aaa; - background-color: #ffc; -} -dt { - color: #900; -} -#organizationLogo img, #projectLogo img, #projectLogo span{ - margin: 8px; -} -#banner { - border-bottom: 1px solid #fff; -} -.errormark, .warningmark, .donemark, .infomark { - background: url(../images/icon_error_sml.gif) no-repeat; -} - -.warningmark { - background-image: url(../images/icon_warning_sml.gif); -} - -.donemark { - background-image: url(../images/icon_success_sml.gif); -} - -.infomark { - background-image: url(../images/icon_info_sml.gif); -} - diff --git a/dist/http-resources/2.0.0/site/css/print.css b/dist/http-resources/2.0.0/site/css/print.css deleted file mode 100644 index 18fcbad7..00000000 --- a/dist/http-resources/2.0.0/site/css/print.css +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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. - */ - -#banner, #footer, #leftcol, #breadcrumbs, .docs #toc, .docs .courtesylinks, #leftColumn, #navColumn { - display: none !important; -} -#bodyColumn, body.docs div.docs { - margin: 0 !important; - border: none !important -} diff --git a/dist/http-resources/2.0.0/site/css/site.css b/dist/http-resources/2.0.0/site/css/site.css deleted file mode 100644 index 055e7e28..00000000 --- a/dist/http-resources/2.0.0/site/css/site.css +++ /dev/null @@ -1 +0,0 @@ -/* You can override this file with your own styles */ \ No newline at end of file diff --git a/dist/http-resources/2.0.0/site/dependencies.html b/dist/http-resources/2.0.0/site/dependencies.html deleted file mode 100644 index 3b0cabbb..00000000 --- a/dist/http-resources/2.0.0/site/dependencies.html +++ /dev/null @@ -1,3494 +0,0 @@ - - - - - - - - HttpResources – Project Dependencies - - - - - - - - - -
    -
    -
    -

    Project Dependencies

    -

    compile

    -

    The following is a list of compile dependencies for this project. These dependencies are required to compile and run the application:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    GroupIdArtifactIdVersionTypeLicensesOptional
    javax.servletjavax.servlet-api4.0.1jarCDDL + GPLv2 with classpath exceptionNo
    org.slf4jslf4j-api1.7.30jarMIT LicenseNo
    org.springframeworkspring-webmvc5.2.10.RELEASEjarApache License, Version 2.0No
    org.springframework.bootspring-boot-autoconfigure2.3.5.RELEASEjarApache License, Version 2.0Yes
    -

    test

    -

    The following is a list of test dependencies for this project. These dependencies are only required to compile and run unit tests for the application:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    GroupIdArtifactIdVersionTypeLicenses
    org.apache.httpcomponentshttpclient4.5.13jarApache License, Version 2.0
    org.jmockitjmockit1.49jarThe MIT License
    org.mock-servermockserver-netty5.11.1jarThe Apache Software License, Version 2.0
    org.springframework.bootspring-boot-starter-logging2.3.5.RELEASEjarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-test2.3.5.RELEASEjarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-thymeleaf2.3.5.RELEASEjarApache License, Version 2.0
    org.testcontainersnginx1.14.3jarMIT
    -

    Project Transitive Dependencies

    -

    The following is a list of transitive dependencies for this project. Transitive dependencies are the dependencies of the project dependencies.

    -

    compile

    -

    The following is a list of compile dependencies for this project. These dependencies are required to compile and run the application:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    GroupIdArtifactIdVersionTypeLicenses
    org.springframeworkspring-aop5.2.10.RELEASEjarApache License, Version 2.0
    org.springframeworkspring-beans5.2.10.RELEASEjarApache License, Version 2.0
    org.springframeworkspring-context5.2.10.RELEASEjarApache License, Version 2.0
    org.springframeworkspring-core5.2.10.RELEASEjarApache License, Version 2.0
    org.springframeworkspring-expression5.2.10.RELEASEjarApache License, Version 2.0
    org.springframeworkspring-jcl5.2.10.RELEASEjarApache License, Version 2.0
    org.springframeworkspring-web5.2.10.RELEASEjarApache License, Version 2.0
    org.springframework.bootspring-boot2.3.5.RELEASEjarApache License, Version 2.0
    -

    test

    -

    The following is a list of test dependencies for this project. These dependencies are only required to compile and run unit tests for the application:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    GroupIdArtifactIdVersionTypeLicenses
    ch.qos.logbacklogback-classic1.2.3jarEclipse Public License - v 1.0GNU Lesser General Public License
    ch.qos.logbacklogback-core1.2.3jarEclipse Public License - v 1.0GNU Lesser General Public License
    com.fasterxml.jackson.corejackson-annotations2.11.3jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.corejackson-core2.11.3jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.corejackson-databind2.11.3jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-yaml2.11.3jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-jsr3102.11.3jarThe Apache Software License, Version 2.0
    com.fasterxml.uuidjava-uuid-generator4.0jarThe Apache Software License, Version 2.0
    com.github.java-json-toolsbtf1.3jarLesser General Public License, version 3 or greaterApache Software License, version 2.0
    com.github.java-json-toolsjackson-coreutils2.0jarLesser General Public License, version 3 or greaterApache Software License, version 2.0
    com.github.java-json-toolsjackson-coreutils-equivalence1.0jarLesser General Public License, version 3 or greaterApache Software License, version 2.0
    com.github.java-json-toolsjson-schema-core1.2.14jarLesser General Public License, version 3 or greaterApache Software License, version 2.0
    com.github.java-json-toolsjson-schema-validator2.2.14jarLesser General Public License, version 3 or greaterApache Software License, version 2.0
    com.github.java-json-toolsmsg-simple1.2jarLesser General Public License, version 3 or greaterApache Software License, version 2.0
    com.github.java-json-toolsuri-template0.10jarLesser General Public License, version 3 or greaterApache Software License, version 2.0
    com.google.code.findbugsjsr3053.0.2jarThe Apache Software License, Version 2.0
    com.google.errorproneerror_prone_annotations2.3.4jarApache 2.0
    com.google.guavafailureaccess1.0.1jarThe Apache Software License, Version 2.0
    com.google.guavaguava28.2-androidjarApache License, Version 2.0
    com.google.guavalistenablefuture9999.0-empty-to-avoid-conflict-with-guavajarThe Apache Software License, Version 2.0
    com.google.j2objcj2objc-annotations1.3jarThe Apache Software License, Version 2.0
    com.googlecode.libphonenumberlibphonenumber8.11.1jarThe Apache Software License, Version 2.0
    com.jayway.jsonpathjson-path2.4.0jarThe Apache Software License, Version 2.0
    com.jcraftjzlib1.1.3jarBSD
    com.kohlschutter.junixsocketjunixsocket-common2.0.4jarApache License, Version 2.0
    com.kohlschutter.junixsocketjunixsocket-native-common2.0.4jarApache License, Version 2.0
    com.lmaxdisruptor3.4.2jarThe Apache Software License, Version 2.0
    com.sun.mailmailapi1.6.2jarCDDL/GPLv2+CE
    com.vaadin.external.googleandroid-json0.0.20131108.vaadin1jarApache License 2.0
    commons-codeccommons-codec1.14jarApache License, Version 2.0
    commons-iocommons-io2.7jarApache License, Version 2.0
    io.nettynetty-buffer4.1.53.FinaljarApache License, Version 2.0
    io.nettynetty-codec4.1.53.FinaljarApache License, Version 2.0
    io.nettynetty-codec-http4.1.53.FinaljarApache License, Version 2.0
    io.nettynetty-codec-socks4.1.53.FinaljarApache License, Version 2.0
    io.nettynetty-common4.1.53.FinaljarApache License, Version 2.0
    io.nettynetty-handler4.1.53.FinaljarApache License, Version 2.0
    io.nettynetty-handler-proxy4.1.53.FinaljarApache License, Version 2.0
    io.nettynetty-resolver4.1.53.FinaljarApache License, Version 2.0
    io.nettynetty-transport4.1.53.FinaljarApache License, Version 2.0
    io.swaggerswagger-annotations1.6.1jarApache License 2.0
    io.swaggerswagger-compat-spec-parser1.0.51jarApache License 2.0
    io.swaggerswagger-core1.6.1jarApache License 2.0
    io.swaggerswagger-models1.6.1jarApache License 2.0
    io.swaggerswagger-parser1.0.51jarApache License 2.0
    io.swagger.core.v3swagger-annotations2.1.2jarApache License 2.0
    io.swagger.core.v3swagger-core2.1.2jarApache License 2.0
    io.swagger.core.v3swagger-models2.1.2jarApache License 2.0
    io.swagger.parser.v3swagger-parser2.0.20jarApache License 2.0
    io.swagger.parser.v3swagger-parser-core2.0.20jarApache License 2.0
    io.swagger.parser.v3swagger-parser-v2-converter2.0.20jarApache License 2.0
    io.swagger.parser.v3swagger-parser-v32.0.20jarApache License 2.0
    jakarta.activationjakarta.activation-api1.2.2jarEDL 1.0
    jakarta.annotationjakarta.annotation-api1.3.5jarEPL 2.0GPL2 w/ CPE
    jakarta.validationjakarta.validation-api2.0.2jarApache License 2.0
    jakarta.xml.bindjakarta.xml.bind-api2.3.3jarEclipse Distribution License - v 1.0
    javax.activationjavax.activation-api1.2.0jarCDDL/GPLv2+CE
    javax.validationvalidation-api2.0.1.FinaljarApache License 2.0
    javax.xml.bindjaxb-api2.3.1jarCDDL 1.1GPL2 w/ CPE
    joda-timejoda-time2.10.5jarApache License, Version 2.0
    junitjunit4.13.1jarEclipse Public License 1.0
    net.bytebuddybyte-buddy1.10.17jarApache License, Version 2.0
    net.bytebuddybyte-buddy-agent1.10.17jarApache License, Version 2.0
    net.java.dev.jnajna5.5.0jarLGPL, version 2.1Apache License v2.0
    net.java.dev.jnajna-platform5.5.0jarLGPL, version 2.1Apache License v2.0
    net.javacrumbs.json-unitjson-unit-core2.14.0jarThe Apache Software License, Version 2.0
    net.minidevaccessors-smart1.2jarThe Apache Software License, Version 2.0
    net.minidevjson-smart2.3jarThe Apache Software License, Version 2.0
    net.sf.jopt-simplejopt-simple5.0.4jarThe MIT License
    org.apache.commonscommons-compress1.20jarApache License, Version 2.0
    org.apache.commonscommons-lang33.10jarApache License, Version 2.0
    org.apache.commonscommons-text1.8jarApache License, Version 2.0
    org.apache.httpcomponentshttpcore4.4.13jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-api2.13.3jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-to-slf4j2.13.3jarApache License, Version 2.0
    org.apache.velocityvelocity-engine-core2.2jarApache License, Version 2.0
    org.apache.velocityvelocity-engine-scripting2.2jarApache License, Version 2.0
    org.apiguardianapiguardian-api1.1.0jarThe Apache License, Version 2.0
    org.assertjassertj-core3.16.1jarApache License, Version 2.0
    org.attoparserattoparser2.0.5.RELEASEjarThe Apache Software License, Version 2.0
    org.checkerframeworkchecker-compat-qual2.5.5jarGNU General Public License, version 2 (GPL2), with the classpath exceptionThe MIT License
    org.hamcresthamcrest2.2jarBSD License 3
    org.hamcresthamcrest-core2.2jarBSD License 3
    org.jetbrainsannotations19.0.0jarThe Apache Software License, Version 2.0
    org.junit.jupiterjunit-jupiter5.6.3jarEclipse Public License v2.0
    org.junit.jupiterjunit-jupiter-api5.6.3jarEclipse Public License v2.0
    org.junit.jupiterjunit-jupiter-engine5.6.3jarEclipse Public License v2.0
    org.junit.jupiterjunit-jupiter-params5.6.3jarEclipse Public License v2.0
    org.junit.platformjunit-platform-commons1.6.3jarEclipse Public License v2.0
    org.junit.platformjunit-platform-engine1.6.3jarEclipse Public License v2.0
    org.junit.vintagejunit-vintage-engine5.6.3jarEclipse Public License v2.0
    org.mock-servermockserver-client-java5.11.1jarThe Apache Software License, Version 2.0
    org.mock-servermockserver-core5.11.1jarThe Apache Software License, Version 2.0
    org.mockitomockito-core3.3.3jarThe MIT License
    org.mockitomockito-junit-jupiter3.3.3jarThe MIT License
    org.mozillarhino1.7.7.2jarMozilla Public License, Version 2.0
    org.objenesisobjenesis2.6jarApache 2
    org.opentest4jopentest4j1.2.0jarThe Apache License, Version 2.0
    org.ow2.asmasm5.0.4jarBSD
    org.rnorthtcp-unix-socket-proxy1.0.2jarMIT
    org.rnorth.duct-tapeduct-tape1.0.8jarMIT
    org.rnorth.visible-assertionsvisible-assertions2.1.2jarMIT
    org.scijavanative-lib-loader2.0.2jarCC0 1.0 Universal License
    org.skyscreamerjsonassert1.5.0jarThe Apache Software License, Version 2.0
    org.slf4jjul-to-slf4j1.7.30jarMIT License
    org.slf4jslf4j-ext1.7.30jarMIT License
    org.springframeworkspring-test5.2.10.RELEASEjarApache License, Version 2.0
    org.springframework.bootspring-boot-starter2.3.5.RELEASEjarApache License, Version 2.0
    org.springframework.bootspring-boot-test2.3.5.RELEASEjarApache License, Version 2.0
    org.springframework.bootspring-boot-test-autoconfigure2.3.5.RELEASEjarApache License, Version 2.0
    org.testcontainerstestcontainers1.14.3jarMIT
    org.thymeleafthymeleaf3.0.11.RELEASEjarThe Apache Software License, Version 2.0
    org.thymeleafthymeleaf-spring53.0.11.RELEASEjarThe Apache Software License, Version 2.0
    org.thymeleaf.extrasthymeleaf-extras-java8time3.0.4.RELEASEjarThe Apache Software License, Version 2.0
    org.unbescapeunbescape1.1.6.RELEASEjarThe Apache Software License, Version 2.0
    org.xmlunitxmlunit-core2.7.0jarThe Apache Software License, Version 2.0
    org.xmlunitxmlunit-placeholders2.7.0jarThe Apache Software License, Version 2.0
    org.yamlsnakeyaml1.26jarApache License, Version 2.0
    -

    Project Dependency Graph

    - -
    -

    Dependency Tree

    -
    -

    Licenses

    -

    The Apache License, Version 2.0: org.apiguardian:apiguardian-api, org.opentest4j:opentest4j

    -

    Eclipse Public License 1.0: JUnit

    -

    Apache 2.0: error-prone annotations

    -

    MIT License: JUL to SLF4J bridge, SLF4J API Module, SLF4J Extensions Module

    -

    BSD License 3: Hamcrest, Hamcrest Core

    -

    Mozilla Public License, Version 2.0: Mozilla Rhino

    -

    Eclipse Public License v2.0: JUnit Jupiter (Aggregator), JUnit Jupiter API, JUnit Jupiter Engine, JUnit Jupiter Params, JUnit Platform Commons, JUnit Platform Engine API, JUnit Vintage Engine

    -

    GPL2 w/ CPE: Jakarta Annotations API, jaxb-api

    -

    Apache 2: Objenesis

    -

    CDDL/GPLv2+CE: JavaBeans Activation Framework API jar, JavaMail API (no providers)

    -

    BSD: ASM Core, JZlib

    -

    Apache License 2.0: Bean Validation API, JSON library from Android SDK, Jakarta Bean Validation API, swagger-annotations, swagger-compat-spec-parser, swagger-core, swagger-models, swagger-parser, swagger-parser-v2-converter, swagger-parser-v3

    -

    The MIT License: Checker Qual, JMockit, JOpt Simple, mockito-core, mockito-junit-jupiter

    -

    Apache License, Version 2.0: Apache Commons Codec, Apache Commons Compress, Apache Commons IO, Apache Commons Lang, Apache Commons Text, Apache HttpClient, Apache HttpCore, Apache Log4j API, Apache Log4j to SLF4J Adapter, Apache Velocity - Engine, Apache Velocity - JSR 223 Scripting, AssertJ fluent assertions, Byte Buddy (without dependencies), Byte Buddy agent, Guava: Google Core Libraries for Java, HttpResources, Joda-Time, Netty/Buffer, Netty/Codec, Netty/Codec/HTTP, Netty/Codec/Socks, Netty/Common, Netty/Handler, Netty/Handler/Proxy, Netty/Resolver, Netty/Transport, SnakeYAML, Spring AOP, Spring Beans, Spring Commons Logging Bridge, Spring Context, Spring Core, Spring Expression Language (SpEL), Spring TestContext Framework, Spring Web, Spring Web MVC, junixsocket-common, junixsocket-native-common, spring-boot, spring-boot-autoconfigure, spring-boot-starter, spring-boot-starter-logging, spring-boot-starter-test, spring-boot-starter-thymeleaf, spring-boot-test, spring-boot-test-autoconfigure

    -

    GNU General Public License, version 2 (GPL2), with the classpath exception: Checker Qual

    -

    EPL 2.0: Jakarta Annotations API

    -

    CC0 1.0 Universal License: Native Library Loader

    -

    LGPL, version 2.1: Java Native Access, Java Native Access Platform

    -

    Apache License v2.0: Java Native Access, Java Native Access Platform

    -

    CDDL 1.1: jaxb-api

    -

    GNU Lesser General Public License: Logback Classic Module, Logback Core Module

    -

    Lesser General Public License, version 3 or greater: btf, jackson-coreutils, jackson-coreutils-equivalence, json-schema-core, json-schema-validator, msg-simple, uri-template

    -

    EDL 1.0: Jakarta Activation API jar

    -

    Eclipse Distribution License - v 1.0: Jakarta XML Binding API

    -

    MIT: Duct Tape, TCP to Unix Socket Proxy, Testcontainers :: Nginx, Testcontainers Core, Visible Assertions

    -

    CDDL + GPLv2 with classpath exception: Java Servlet API

    -

    The Apache Software License, Version 2.0: ASM based accessors helper used by json-smart, Disruptor Framework, FindBugs-jsr305, Guava InternalFutureFailureAccess and InternalFutures, Guava ListenableFuture only, J2ObjC Annotations, JSON Small and Fast Parser, JSONassert, Jackson datatype: JSR310, Jackson-annotations, Jackson-core, Jackson-dataformat-YAML, Java UUID Generator, JetBrains Java Annotations, MockServer & Proxy Netty, MockServer Core, MockServer Java Client, attoparser, jackson-databind, json-unit-core, libphonenumber, org.xmlunit:xmlunit-core, org.xmlunit:xmlunit-placeholders, project ':json-path', thymeleaf, thymeleaf-extras-java8time, thymeleaf-spring5, unbescape

    -

    Apache Software License, version 2.0: btf, jackson-coreutils, jackson-coreutils-equivalence, json-schema-core, json-schema-validator, msg-simple, uri-template

    -

    Eclipse Public License - v 1.0: Logback Classic Module, Logback Core Module

    -

    Dependency File Details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FilenameSizeEntriesClassesPackagesJava VersionDebug Information
    logback-classic-1.2.3.jar290.3 kB234175271.6Yes
    logback-core-1.2.3.jar471.9 kB419373361.6Yes
    jackson-annotations-2.11.3.jar68.2 kB81692-Yes
    jackson-core-2.11.3.jar351.5 kB14411813-Yes
    jackson-databind-2.11.3.jar1.4 MB69365822-Yes
    jackson-dataformat-yaml-2.11.3.jar46.9 kB35163-Yes
    jackson-datatype-jsr310-2.11.3.jar111 kB76576-Yes
    java-uuid-generator-4.0.jar37.5 kB34204-Yes
    btf-1.3.jar9 kB11311.7No
    jackson-coreutils-2.0.jar31.8 kB261421.7Yes
    jackson-coreutils-equivalence-1.0.jar1.9 kB7111.7Yes
    json-schema-core-1.2.14.jar175.8 kB164125221.7Yes
    json-schema-validator-2.2.14.jar238.7 kB226159311.7Yes
    msg-simple-1.2.jar36.9 kB372361.7Yes
    uri-template-0.10.jar58.2 kB573971.7Yes
    jsr305-3.0.2.jar19.9 kB463531.5Yes
    error_prone_annotations-2.3.4.jar13.9 kB342221.7No
    failureaccess-1.0.1.jar4.6 kB15211.7Yes
    guava-28.2-android.jar2.6 MB19221892181.7Yes
    listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar2.2 kB700-No
    j2objc-annotations-1.3.jar8.8 kB231211.5Yes
    libphonenumber-8.11.1.jar344.5 kB6065121.6Yes
    json-path-2.4.0.jar223.2 kB191174121.6Yes
    jzlib-1.1.3.jar72 kB362611.5Yes
    junixsocket-common-2.0.4.jar18.2 kB221111.7Yes
    junixsocket-native-common-2.0.4.jar27.8 kB31221.7Yes
    disruptor-3.4.2.jar83.1 kB878031.7Yes
    mailapi-1.6.2.jar301.5 kB21418981.7Yes
    android-json-0.0.20131108.vaadin1.jar18.3 kB12811.5Yes
    commons-codec-1.14.jar347.7 kB24910271.7Yes
    commons-io-2.7.jar276.4 kB198176101.8Yes
    netty-buffer-4.1.53.Final.jar296 kB15013321.6Yes
    netty-codec-4.1.53.Final.jar320.3 kB220198101.6Yes
    netty-codec-http-4.1.53.Final.jar620.2 kB39536991.6Yes
    netty-codec-socks-4.1.53.Final.jar119.1 kB12410741.6Yes
    netty-common-4.1.53.Final.jar638.6 kB50447291.6Yes
    netty-handler-4.1.53.Final.jar473.4 kB324296121.6Yes
    netty-handler-proxy-4.1.53.Final.jar24 kB251211.6Yes
    netty-resolver-4.1.53.Final.jar33.2 kB382611.6Yes
    netty-transport-4.1.53.Final.jar474.2 kB386358121.6Yes
    swagger-annotations-1.6.1.jar21.8 kB413111.7Yes
    swagger-compat-spec-parser-1.0.51.jar148.8 kB15283131.7Yes
    swagger-core-1.6.1.jar117.3 kB937671.7Yes
    swagger-models-1.6.1.jar155.2 kB1099461.7Yes
    swagger-parser-1.0.51.jar85.3 kB513731.7Yes
    swagger-annotations-2.1.2.jar34.8 kB6844131.8Yes
    swagger-core-2.1.2.jar165.1 kB988161.8Yes
    swagger-models-2.1.2.jar118.2 kB8562121.8Yes
    swagger-parser-2.0.20.jar3.3 kB11111.8Yes
    swagger-parser-core-2.0.20.jar6.5 kB18421.8Yes
    swagger-parser-v2-converter-2.0.20.jar25.5 kB16211.8Yes
    swagger-parser-v3-2.0.20.jar133.1 kB614741.8Yes
    jakarta.activation-api-1.2.2.jar46.6 kB43322-Yes
    jakarta.annotation-api-1.3.5.jar25.1 kB281531.8Yes
    jakarta.validation-api-2.0.2.jar91.9 kB16014391.8Yes
    jakarta.xml.bind-api-2.3.3.jar115.6 kB1371117-Yes
    javax.activation-api-1.2.0.jar56.7 kB413111.5Yes
    javax.servlet-api-4.0.1.jar95.5 kB1098541.8Yes
    validation-api-2.0.1.Final.jar93.1 kB16314391.8Yes
    jaxb-api-2.3.1.jar128.1 kB1361117-Yes
    joda-time-2.10.5.jar643 kB76524771.5Yes
    junit-4.13.1.jar382.7 kB387348321.5Yes
    byte-buddy-1.10.17.jar3.5 MB2507245237-Yes
    byte-buddy-agent-1.10.17.jar259.2 kB81632-Yes
    jna-5.5.0.jar1.5 MB17011541.6Yes
    jna-platform-5.5.0.jar2.7 MB12151173131.6Yes
    json-unit-core-2.14.0.jar130.3 kB12310761.8Yes
    accessors-smart-1.2.jar30 kB241321.6Yes
    json-smart-2.3.jar120.3 kB1069251.6Yes
    jopt-simple-5.0.4.jar78.1 kB715931.7Yes
    commons-compress-1.20.jar632.4 kB400359291.7Yes
    commons-lang3-3.10.jar523.4 kB314288141.8Yes
    commons-text-1.8.jar207 kB15213461.8Yes
    httpclient-4.5.13.jar780.3 kB511470241.6Yes
    httpcore-4.4.13.jar328.6 kB283253171.6Yes
    log4j-api-2.13.3.jar292.3 kB2141809-Yes
    log4j-to-slf4j-2.13.3.jar17.5 kB22611.8Yes
    velocity-engine-core-2.2.jar525.2 kB299256191.8Yes
    velocity-engine-scripting-2.2.jar15.2 kB20411.8Yes
    apiguardian-api-1.1.0.jar2.4 kB832-Yes
    assertj-core-3.16.1.jar4.7 MB3215312861-Yes
    attoparser-2.0.5.RELEASE.jar245 kB165147121.6Yes
    checker-compat-qual-2.5.5.jar5.9 kB171011.6No
    hamcrest-2.2.jar123.4 kB122108111.7Yes
    hamcrest-core-2.2.jar1.5 kB8111.7Yes
    annotations-19.0.0.jar24.8 kB585021.8Yes
    jmockit-1.49.jar697.8 kB424357481.7Yes
    junit-jupiter-5.6.3.jar6.4 kB511-No
    junit-jupiter-api-5.6.3.jar154 kB1501358-Yes
    junit-jupiter-engine-5.6.3.jar209.3 kB1301139-Yes
    junit-jupiter-params-5.6.3.jar562.3 kB37033622-Yes
    junit-platform-commons-1.6.3.jar96.7 kB61417-Yes
    junit-platform-engine-1.6.3.jar174.1 kB1391239-Yes
    junit-vintage-engine-5.6.3.jar63.8 kB47336-Yes
    mockserver-client-java-5.11.1.jar20.2 kB19821.8Yes
    mockserver-core-5.11.1.jar792.1 kB548425741.8Yes
    mockserver-netty-5.11.1.jar1.1 MB8642141.8Yes
    mockito-core-3.3.3.jar592.3 kB636563651.8Yes
    mockito-junit-jupiter-3.3.3.jar4.5 kB9211.8Yes
    rhino-1.7.7.2.jar1.2 MB521482231.6Yes
    objenesis-2.6.jar55.7 kB5943101.6Yes
    opentest4j-1.2.0.jar7.7 kB1172-Yes
    asm-5.0.4.jar53.3 kB302521.2No
    tcp-unix-socket-proxy-1.0.2.jar7.2 kB13311.8Yes
    duct-tape-1.0.8.jar25.4 kB372261.8Yes
    visible-assertions-2.1.2.jar11.6 kB17631.7Yes
    native-lib-loader-2.0.2.jar17.1 kB211111.5Yes
    jsonassert-1.5.0.jar30.3 kB322031.6Yes
    jul-to-slf4j-1.7.30.jar4.6 kB11111.5Yes
    slf4j-api-1.7.30.jar41.5 kB463441.5Yes
    slf4j-ext-1.7.30.jar38 kB402661.5Yes
    spring-aop-5.2.10.RELEASE.jar372.8 kB306277171.8Yes
    spring-beans-5.2.10.RELEASE.jar688.4 kB414384131.8Yes
    spring-context-5.2.10.RELEASE.jar1.2 MB967880641.8Yes
    spring-core-5.2.10.RELEASE.jar1.4 MB1023965471.8Yes
    spring-expression-5.2.10.RELEASE.jar282.2 kB16415061.8Yes
    spring-jcl-5.2.10.RELEASE.jar24 kB281721.8Yes
    spring-test-5.2.10.RELEASE.jar685.5 kB516462391.8Yes
    spring-web-5.2.10.RELEASE.jar1.4 MB997927551.8Yes
    spring-webmvc-5.2.10.RELEASE.jar956.8 kB586541281.8Yes
    spring-boot-2.3.5.RELEASE.jar1.1 MB837725711.8Yes
    spring-boot-starter-2.3.5.RELEASE.jar4.8 kB400-No
    spring-boot-starter-logging-2.3.5.RELEASE.jar4.8 kB400-No
    spring-boot-starter-test-2.3.5.RELEASE.jar4.8 kB400-No
    spring-boot-starter-thymeleaf-2.3.5.RELEASE.jar4.8 kB400-No
    spring-boot-test-2.3.5.RELEASE.jar216.2 kB164138141.8Yes
    spring-boot-test-autoconfigure-2.3.5.RELEASE.jar175.2 kB186153191.8Yes
    nginx-1.14.3.jar2 kB6111.8Yes
    testcontainers-1.14.3.jar12.4 MB907686723571.8Yes
    thymeleaf-3.0.11.RELEASE.jar869.7 kB599552381.6Yes
    thymeleaf-spring5-3.0.11.RELEASE.jar177.2 kB12698171.8Yes
    thymeleaf-extras-java8time-3.0.4.RELEASE.jar40.1 kB22931.8Yes
    unbescape-1.1.6.RELEASE.jar173.9 kB8569101.6Yes
    xmlunit-core-2.7.0.jar168.4 kB17115581.6Yes
    xmlunit-placeholders-2.7.0.jar13.5 kB19711.6Yes
    snakeyaml-1.26.jar309 kB253216201.7Yes
    spring-boot-autoconfigure-2.3.5.RELEASE.jar1.5 MB12151099991.8Yes
    TotalSizeEntriesClassesPackagesJava VersionDebug Information
    13760.5 MB422183725820041.8127
    compile: 12compile: 9.2 MBcompile: 6692compile: 6084compile: 410-compile: 12
    test: 125test: 51.3 MBtest: 35526test: 31174test: 1594-test: 115
    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/dependency-info.html b/dist/http-resources/2.0.0/site/dependency-info.html deleted file mode 100644 index 1ae69968..00000000 --- a/dist/http-resources/2.0.0/site/dependency-info.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - HttpResources – Dependency Information - - - - - - - - - -
    -
    -
    -

    Dependency Information

    -

    Apache Maven

    -
    -
    <dependency>
    -  <groupId>de.juplo</groupId>
    -  <artifactId>http-resources</artifactId>
    -  <version>2.0.0</version>
    -</dependency>
    -

    Apache Buildr

    -
    -
    'de.juplo:http-resources:jar:2.0.0'
    -

    Apache Ivy

    -
    -
    <dependency org="de.juplo" name="http-resources" rev="2.0.0">
    -  <artifact name="http-resources" type="jar" />
    -</dependency>
    -

    Groovy Grape

    -
    -
    @Grapes(
    -@Grab(group='de.juplo', module='http-resources', version='2.0.0')
    -)
    -

    Gradle/Grails

    -
    -
    compile 'de.juplo:http-resources:2.0.0'
    -

    Scala SBT

    -
    -
    libraryDependencies += "de.juplo" % "http-resources" % "2.0.0"
    -

    Leiningen

    -
    -
    [de.juplo/http-resources "2.0.0"]
    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/dependency-management.html b/dist/http-resources/2.0.0/site/dependency-management.html deleted file mode 100644 index f9ff75d7..00000000 --- a/dist/http-resources/2.0.0/site/dependency-management.html +++ /dev/null @@ -1,7178 +0,0 @@ - - - - - - - - HttpResources – Project Dependency Management - - - - - - - - - -
    -
    -
    -

    Project Dependency Management

    -

    compile

    -

    The following is a list of compile dependencies in the DependencyManagement of this project. These dependencies can be included in the submodules to compile and run the submodule:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    GroupIdArtifactIdVersionClassifierTypeLicense
    antlrantlr2.7.7-jarBSD License
    ch.qos.logbacklogback-access1.2.3-jarEclipse Public License - v 1.0, GNU Lesser General Public License
    ch.qos.logbacklogback-classic1.2.3-jarEclipse Public License - v 1.0, GNU Lesser General Public License
    ch.qos.logbacklogback-core1.2.3-jarEclipse Public License - v 1.0, GNU Lesser General Public License
    com.atomikostransactions-jdbc4.0.6-jarAtomikos Multiple Licensing Scheme
    com.atomikostransactions-jms4.0.6-jarAtomikos Multiple Licensing Scheme
    com.atomikostransactions-jta4.0.6-jarAtomikos Multiple Licensing Scheme
    com.couchbase.clientjava-client3.0.9-jarThe Apache Software License, Version 2.0
    com.datastax.ossjava-driver-core4.6.1-jarApache 2
    com.datastax.ossjava-driver-core-shaded4.6.1-jarApache 2
    com.datastax.ossjava-driver-mapper-processor4.6.1-jarApache 2
    com.datastax.ossjava-driver-mapper-runtime4.6.1-jarApache 2
    com.datastax.ossjava-driver-query-builder4.6.1-jarApache 2
    com.datastax.ossjava-driver-shaded-guava25.1-jre-jarApache 2
    com.datastax.ossjava-driver-test-infra4.6.1-jarApache 2
    com.datastax.ossnative-protocol1.4.10-jarApache 2
    com.fasterxmlclassmate1.5.1-jarApache License, Version 2.0
    com.fasterxml.jackson.corejackson-annotations2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.corejackson-core2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.corejackson-databind2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-avro2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-cbor2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-csv2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-ion2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-properties2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-protobuf2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-smile2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-xml2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.dataformatjackson-dataformat-yaml2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-eclipse-collections2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-guava2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-hibernate32.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-hibernate42.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-hibernate52.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-hppc2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-jaxrs2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-jdk82.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-joda2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-joda-money2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-json-org2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-jsr3102.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-jsr3532.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.datatypejackson-datatype-pcollections2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jaxrsjackson-jaxrs-base2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jaxrsjackson-jaxrs-cbor-provider2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jaxrsjackson-jaxrs-json-provider2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jaxrsjackson-jaxrs-smile-provider2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jaxrsjackson-jaxrs-xml-provider2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jaxrsjackson-jaxrs-yaml-provider2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jrjackson-jr-all2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jrjackson-jr-objects2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jrjackson-jr-retrofit22.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.jrjackson-jr-stree2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-afterburner2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-guice2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-jaxb-annotations2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-jsonSchema2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-kotlin2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-mrbean2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-osgi2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-parameter-names2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-paranamer2.11.3-jarThe Apache Software License, Version 2.0
    com.fasterxml.jackson.modulejackson-module-scala_2.102.11.3-jar-
    com.fasterxml.jackson.modulejackson-module-scala_2.112.11.3-jar-
    com.fasterxml.jackson.modulejackson-module-scala_2.122.11.3-jar-
    com.fasterxml.jackson.modulejackson-module-scala_2.132.11.3-jar-
    com.github.ben-manes.caffeinecaffeine2.8.6-jarApache License, Version 2.0
    com.github.ben-manes.caffeineguava2.8.6-jarApache License, Version 2.0
    com.github.ben-manes.caffeinejcache2.8.6-jarApache License, Version 2.0
    com.github.ben-manes.caffeinesimulator2.8.6-jarApache License, Version 2.0
    com.github.mxab.thymeleaf.extrasthymeleaf-extras-data-attribute2.0.1-jarThe Apache Software License, Version 2.0
    com.google.appengineappengine-api-1.0-sdk1.9.82-jarApache License, Version 2.0, CDDL/GPLv2+CE, JSR-000107 JCACHE 2.9 Public Review - Updated Specification License
    com.google.cloudcloud-spanner-r2dbc0.2.0-jarThe Apache License, Version 2.0
    com.google.code.gsongson2.8.6-jarApache 2.0
    com.h2databaseh21.4.200-jarMPL 2.0 or EPL 1.0
    com.hazelcasthazelcast3.12.10-jarThe Apache Software License, Version 2.0
    com.hazelcasthazelcast-client3.12.10-jarThe Apache Software License, Version 2.0
    com.hazelcasthazelcast-hibernate521.3.2-jarThe Apache Software License, Version 2.0
    com.hazelcasthazelcast-hibernate531.3.2-jarThe Apache Software License, Version 2.0
    com.hazelcasthazelcast-spring3.12.10-jarThe Apache Software License, Version 2.0
    com.ibm.db2jcc11.5.4.0-jarInternational Program License Agreement (IPLA)
    com.jayway.jsonpathjson-path2.4.0-jarThe Apache Software License, Version 2.0
    com.jayway.jsonpathjson-path-assert2.4.0-jarThe Apache Software License, Version 2.0
    com.microsoft.sqlservermssql-jdbc7.4.1.jre8-jarMIT License
    com.nimbusdsnimbus-jose-jwt8.19-jarThe Apache Software License, Version 2.0
    com.nimbusdsoauth2-oidc-sdk7.1.1-jarApache License, version 2.0
    com.oracle.database.haons19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.hasimplefan19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbcojdbc1019.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbcojdbc10dms19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbcojdbc819.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbcojdbc8dms19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbcucp19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbc.debugojdbc10_g19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbc.debugojdbc10dms_g19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbc.debugojdbc8_g19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.jdbc.debugojdbc8dms_g19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.nlsorai18n19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.observabilitydms19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.securityoraclepki19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.securityosdt_cert19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.securityosdt_core19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.xmlxdb19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.database.xmlxmlparserv219.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcdms19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcojdbc1019.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcojdbc10_g19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcojdbc10dms19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcojdbc10dms_g19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcojdbc819.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcojdbc8_g19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcojdbc8dms19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcojdbc8dms_g19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcons19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcoraclepki19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcorai18n19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcosdt_cert19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcosdt_core19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcsimplefan19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcucp19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcxdb19.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.oracle.ojdbcxmlparserv219.3.0.0-jarOracle Free Use Terms and Conditions (FUTC)
    com.querydslquerydsl-apt4.3.1-jarApache License, Version 2.0
    com.querydslquerydsl-collections4.3.1-jarApache License, Version 2.0
    com.querydslquerydsl-core4.3.1-jarApache License, Version 2.0
    com.querydslquerydsl-jpa4.3.1-jarApache License, Version 2.0
    com.querydslquerydsl-mongodb4.3.1-jarApache License, Version 2.0
    com.rabbitmqamqp-client5.9.0-jarASL 2.0, GPL v2, MPL 1.1
    com.samskivertjmustache1.15-jarThe (New) BSD License
    com.sendgridsendgrid-java4.4.8-jarThe MIT License (MIT)
    com.squareup.okhttp3logging-interceptor3.14.9-jarApache 2.0
    com.squareup.okhttp3mockwebserver3.14.9-jarApache 2.0
    com.squareup.okhttp3okcurl3.14.9-jarApache 2.0
    com.squareup.okhttp3okhttp3.14.9-jarApache 2.0
    com.squareup.okhttp3okhttp-dnsoverhttps3.14.9-jarApache 2.0
    com.squareup.okhttp3okhttp-sse3.14.9-jarApache 2.0
    com.squareup.okhttp3okhttp-testing-support3.14.9-jarApache 2.0
    com.squareup.okhttp3okhttp-tls3.14.9-jarApache 2.0
    com.squareup.okhttp3okhttp-urlconnection3.14.9-jarApache 2.0
    com.sun.activationjakarta.activation1.2.2-jarEDL 1.0
    com.sun.mailjakarta.mail1.6.5-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0
    com.sun.xml.messaging.saajsaaj-impl1.5.2-jarEclipse Distribution License - v 1.0
    com.unboundidunboundid-ldapsdk4.0.14-jarGNU General Public License version 2 (GPLv2), GNU Lesser General Public License version 2.1 (LGPLv2.1), UnboundID LDAP SDK Free Use License
    com.zaxxerHikariCP3.4.5-jarThe Apache Software License, Version 2.0
    commons-codeccommons-codec1.14-jarApache License, Version 2.0
    commons-poolcommons-pool1.6-jarThe Apache Software License, Version 2.0
    de.flapdoodle.embedde.flapdoodle.embed.mongo2.2.0-jarThe Apache Software License, Version 2.0
    dev.mikur2dbc-mysql0.8.2.RELEASE-jarThe Apache License, Version 2.0
    io.dropwizard.metricsmetrics-annotation4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-caffeine4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-collectd4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-core4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-ehcache4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-graphite4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-healthchecks4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-httpasyncclient4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-httpclient4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-jcache4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-jdbi4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-jdbi34.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-jersey24.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-jetty94.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-jmx4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-json4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-jvm4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-log4j24.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-logback4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-servlet4.1.14-jarApache License 2.0
    io.dropwizard.metricsmetrics-servlets4.1.14-jarApache License 2.0
    io.lettucelettuce-core5.3.5.RELEASE-jarApache License, Version 2.0
    io.micrometermicrometer-core1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-jersey21.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-appoptics1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-atlas1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-azure-monitor1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-cloudwatch1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-cloudwatch21.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-datadog1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-dynatrace1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-elastic1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-ganglia1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-graphite1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-humio1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-influx1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-jmx1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-kairos1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-new-relic1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-opentsdb1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-prometheus1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-signalfx1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-stackdriver1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-statsd1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-registry-wavefront1.5.6-jarThe Apache Software License, Version 2.0
    io.micrometermicrometer-test1.5.6-jarThe Apache Software License, Version 2.0
    io.nettynetty-all4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-buffer4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-dns4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-haproxy4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-http4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-http24.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-memcache4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-mqtt4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-redis4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-smtp4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-socks4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-stomp4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-codec-xml4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-common4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-dev-tools4.1.53.Final-jar-
    io.nettynetty-example4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-handler4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-handler-proxy4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-resolver4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-resolver-dns4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-resolver-dns-native-macos4.1.53.Finalosx-x86_64jarApache License, Version 2.0
    io.nettynetty-resolver-dns-native-macos4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-tcnative2.0.34.Final-jarApache License, Version 2.0
    io.nettynetty-tcnative-boringssl-static2.0.34.Final-jarApache License, Version 2.0
    io.nettynetty-transport4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-transport-native-epoll4.1.53.Finallinux-aarch64jarApache License, Version 2.0
    io.nettynetty-transport-native-epoll4.1.53.Finallinux-x86_64jarApache License, Version 2.0
    io.nettynetty-transport-native-epoll4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-transport-native-kqueue4.1.53.Finalosx-x86_64jarApache License, Version 2.0
    io.nettynetty-transport-native-kqueue4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-transport-native-unix-common4.1.53.Finallinux-aarch64jarApache License, Version 2.0
    io.nettynetty-transport-native-unix-common4.1.53.Finallinux-x86_64jarApache License, Version 2.0
    io.nettynetty-transport-native-unix-common4.1.53.Finalosx-x86_64jarApache License, Version 2.0
    io.nettynetty-transport-native-unix-common4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-transport-rxtx4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-transport-sctp4.1.53.Final-jarApache License, Version 2.0
    io.nettynetty-transport-udt4.1.53.Final-jarApache License, Version 2.0
    io.projectreactorreactor-core3.3.11.RELEASE-jarApache License, Version 2.0
    io.projectreactorreactor-test3.3.11.RELEASE-jarApache License, Version 2.0
    io.projectreactorreactor-tools3.3.11.RELEASE-jarApache License, Version 2.0
    io.projectreactor.addonsreactor-adapter3.3.4.RELEASE-jarApache License, Version 2.0
    io.projectreactor.addonsreactor-extra3.3.4.RELEASE-jarApache License, Version 2.0
    io.projectreactor.addonsreactor-pool0.1.7.RELEASE-jarThe Apache Software License, Version 2.0
    io.projectreactor.kafkareactor-kafka1.2.4.RELEASE-jarThe Apache Software License, Version 2.0
    io.projectreactor.kotlinreactor-kotlin-extensions1.0.2.RELEASE-jarThe Apache Software License, Version 2.0
    io.projectreactor.nettyreactor-netty0.9.13.RELEASE-jarThe Apache Software License, Version 2.0
    io.projectreactor.rabbitmqreactor-rabbitmq1.4.4.RELEASE-jarThe Apache Software License, Version 2.0
    io.prometheussimpleclient_pushgateway0.9.0-jarThe Apache Software License, Version 2.0
    io.r2dbcr2dbc-h20.8.4.RELEASE-jarApache License 2.0
    io.r2dbcr2dbc-mssql0.8.5.RELEASE-jarApache License 2.0
    io.r2dbcr2dbc-pool0.8.5.RELEASE-jarApache License 2.0
    io.r2dbcr2dbc-postgresql0.8.6.RELEASE-jarApache License 2.0
    io.r2dbcr2dbc-proxy0.8.3.RELEASE-jarApache License 2.0
    io.r2dbcr2dbc-spi0.8.3.RELEASE-jarApache License 2.0
    io.reactivexrxjava1.3.8-jarThe Apache Software License, Version 2.0
    io.reactivexrxjava-reactive-streams1.2.1-jarThe Apache Software License, Version 2.0
    io.reactivex.rxjava2rxjava2.2.20-jarThe Apache Software License, Version 2.0
    io.rest-assuredjson-path3.3.0-jarApache 2.0
    io.rest-assuredjson-schema-validator3.3.0-jarApache 2.0
    io.rest-assuredrest-assured3.3.0-jarApache 2.0
    io.rest-assuredscala-support3.3.0-jarApache 2.0
    io.rest-assuredspring-mock-mvc3.3.0-jarApache 2.0
    io.rest-assuredspring-web-test-client3.3.0-jarApache 2.0
    io.rest-assuredxml-path3.3.0-jarApache 2.0
    io.rsocketrsocket-core1.0.3-jarThe Apache Software License, Version 2.0
    io.rsocketrsocket-load-balancer1.0.3-jarThe Apache Software License, Version 2.0
    io.rsocketrsocket-micrometer1.0.3-jarThe Apache Software License, Version 2.0
    io.rsocketrsocket-test1.0.3-jarThe Apache Software License, Version 2.0
    io.rsocketrsocket-transport-local1.0.3-jarThe Apache Software License, Version 2.0
    io.rsocketrsocket-transport-netty1.0.3-jarThe Apache Software License, Version 2.0
    io.spring.gradledependency-management-plugin1.0.10.RELEASE-jarThe Apache Software License, Version 2.0
    io.undertowundertow-core2.1.4.Final-jarApache License Version 2.0
    io.undertowundertow-servlet2.1.4.Final-jarApache License Version 2.0
    io.undertowundertow-websockets-jsr2.1.4.Final-jarApache License Version 2.0
    jakarta.activationjakarta.activation-api1.2.2-jarEDL 1.0
    jakarta.annotationjakarta.annotation-api1.3.5-jarEPL 2.0, GPL2 w/ CPE
    jakarta.jmsjakarta.jms-api2.0.3-jarEclipse Public License 2.0, GNU General Public License, version 2 with the GNU Classpath Exception
    jakarta.jsonjakarta.json-api1.1.6-jarEclipse Public License 2.0, GNU General Public License, version 2 with the GNU Classpath Exception
    jakarta.json.bindjakarta.json.bind-api1.0.2-jarEclipse Public License 2.0, GNU General Public License, version 2 with the GNU Classpath Exception
    jakarta.mailjakarta.mail-api1.6.5-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0
    jakarta.persistencejakarta.persistence-api2.2.3-jarEclipse Public License v. 2.0, Eclipse Distribution License v. 1.0
    jakarta.servletjakarta.servlet-api4.0.4-jarEPL 2.0, GPL2 w/ CPE
    jakarta.servlet.jsp.jstljakarta.servlet.jsp.jstl-api1.2.7-jarEPL 2.0, GPL2 w/ CPE
    jakarta.transactionjakarta.transaction-api1.3.3-jarEPL 2.0, GPL2 w/ CPE
    jakarta.validationjakarta.validation-api2.0.2-jarApache License 2.0
    jakarta.websocketjakarta.websocket-api1.1.2-jarEclipse Public License 2.0, GNU General Public License, version 2 with the GNU Classpath Exception
    jakarta.ws.rsjakarta.ws.rs-api2.1.6-jarEPL 2.0, GPL2 w/ CPE
    jakarta.xml.bindjakarta.xml.bind-api2.3.3-jarEclipse Distribution License - v 1.0
    jakarta.xml.soapjakarta.xml.soap-api1.4.2-jarEclipse Distribution License - v 1.0
    jakarta.xml.wsjakarta.xml.ws-api2.3.3-jarEclipse Distribution License - v 1.0
    javax.activationjavax.activation-api1.2.0-jarCDDL/GPLv2+CE
    javax.annotationjavax.annotation-api1.3.2-jarCDDL + GPLv2 with classpath exception
    javax.cachecache-api1.1.1-jarApache License, Version 2.0
    javax.jmsjavax.jms-api2.0.1-jarCDDL + GPLv2 with classpath exception
    javax.jsonjavax.json-api1.1.4-jarDual license consisting of the CDDL v1.1 and GPL v2
    javax.json.bindjavax.json.bind-api1.0-jarDual license consisting of the CDDL v1.1 and GPL v2
    javax.mailjavax.mail-api1.6.2-jarCDDL/GPLv2+CE
    javax.moneymoney-api1.0.3-jarSpec Evaluation License, Spec Implementation License
    javax.persistencejavax.persistence-api2.2-jarEclipse Public License v1.0, Eclipse Distribution License v. 1.0
    javax.servletjavax.servlet-api4.0.1-jarCDDL + GPLv2 with classpath exception
    javax.servletjstl1.2-jar-
    javax.transactionjavax.transaction-api1.3-jarCDDL + GPLv2 with classpath exception
    javax.validationvalidation-api2.0.1.Final-jarApache License 2.0
    javax.websocketjavax.websocket-api1.1-jarDual license consisting of the CDDL v1.1 and GPL v2
    javax.xml.bindjaxb-api2.3.1-jarCDDL 1.1, GPL2 w/ CPE
    javax.xml.wsjaxws-api2.3.1-jarCDDL + GPLv2 with classpath exception
    jaxenjaxen1.2.0-jarBSD License 2.0
    junitjunit4.13.1-jarEclipse Public License 1.0
    mysqlmysql-connector-java8.0.22-jarThe GNU General Public License, v2 with FOSS exception
    net.bytebuddybyte-buddy1.10.17-jarApache License, Version 2.0
    net.bytebuddybyte-buddy-agent1.10.17-jarApache License, Version 2.0
    net.minidevjson-smart2.3-jarThe Apache Software License, Version 2.0
    net.sf.ehcacheehcache2.10.6-jarThe Apache Software License, Version 2.0
    net.sourceforge.htmlunithtmlunit2.40.0-jarApache License, Version 2.0
    net.sourceforge.jtdsjtds1.3.1-jarLGPL
    net.sourceforge.nekohtmlnekohtml1.9.22-jarThe Apache Software License, Version 2.0
    nz.net.ultraq.thymeleafthymeleaf-layout-dialect2.4.1-jarThe Apache Software License, Version 2.0
    org.apache.activemqactivemq-amqp5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-blueprint5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-broker5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-camel5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-client5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-console5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-http5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-jaas5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-jdbc-store5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-jms-pool5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-kahadb-store5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-karaf5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-leveldb-store5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-log4j-appender5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-mqtt5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-openwire-generator5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-openwire-legacy5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-osgi5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-partition5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-pool5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-ra5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-run5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-runtime-config5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-shiro5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-spring5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-stomp5.15.13-jarApache License, Version 2.0
    org.apache.activemqactivemq-web5.15.13-jarApache License, Version 2.0
    org.apache.activemqartemis-amqp-protocol2.12.0-jarApache License, Version 2.0
    org.apache.activemqartemis-commons2.12.0-jarApache License, Version 2.0
    org.apache.activemqartemis-core-client2.12.0-jarApache License, Version 2.0
    org.apache.activemqartemis-jms-client2.12.0-jarApache License, Version 2.0
    org.apache.activemqartemis-jms-server2.12.0-jarApache License, Version 2.0
    org.apache.activemqartemis-journal2.12.0-jarApache License, Version 2.0
    org.apache.activemqartemis-selector2.12.0-jarApache License, Version 2.0
    org.apache.activemqartemis-server2.12.0-jarApache License, Version 2.0
    org.apache.activemqartemis-service-extensions2.12.0-jarApache License, Version 2.0
    org.apache.commonscommons-dbcp22.7.0-jarApache License, Version 2.0
    org.apache.commonscommons-lang33.10-jarApache License, Version 2.0
    org.apache.commonscommons-pool22.8.1-jarApache License, Version 2.0
    org.apache.derbyderby10.14.2.0-jarApache 2
    org.apache.derbyderbyclient10.14.2.0-jarApache 2
    org.apache.httpcomponentsfluent-hc4.5.13-jarApache License, Version 2.0
    org.apache.httpcomponentshttpasyncclient4.1.4-jarApache License, Version 2.0
    org.apache.httpcomponentshttpclient4.5.13-jarApache License, Version 2.0
    org.apache.httpcomponentshttpclient-cache4.5.13-jarApache License, Version 2.0
    org.apache.httpcomponentshttpclient-osgi4.5.13-jarApache License, Version 2.0
    org.apache.httpcomponentshttpclient-win4.5.13-jarApache License, Version 2.0
    org.apache.httpcomponentshttpcore4.4.13-jarApache License, Version 2.0
    org.apache.httpcomponentshttpcore-nio4.4.13-jarApache License, Version 2.0
    org.apache.httpcomponentshttpmime4.5.13-jarApache License, Version 2.0
    org.apache.johnzonjohnzon-core1.2.8-jarThe Apache Software License, Version 2.0
    org.apache.johnzonjohnzon-jaxrs1.2.8-jarThe Apache Software License, Version 2.0
    org.apache.johnzonjohnzon-jsonb1.2.8-jarThe Apache Software License, Version 2.0
    org.apache.johnzonjohnzon-jsonb-extras1.2.8-jarThe Apache Software License, Version 2.0
    org.apache.johnzonjohnzon-jsonschema1.2.8-jarThe Apache Software License, Version 2.0
    org.apache.johnzonjohnzon-mapper1.2.8-jarThe Apache Software License, Version 2.0
    org.apache.johnzonjohnzon-websocket1.2.8-jarThe Apache Software License, Version 2.0
    org.apache.kafkaconnect-api2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkaconnect-basic-auth-extension2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkaconnect-file2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkaconnect-json2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkaconnect-runtime2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkaconnect-transforms2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka-clients2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka-log4j-appender2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka-streams2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka-streams-scala_2.122.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka-streams-scala_2.132.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka-streams-test-utils2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka-tools2.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka_2.122.5.1-jarThe Apache Software License, Version 2.0
    org.apache.kafkakafka_2.132.5.1-jarThe Apache Software License, Version 2.0
    org.apache.logging.log4jlog4j-1.2-api2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-api2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-appserver2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-cassandra2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-core2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-couchdb2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-docker2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-flume-ng2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-iostreams2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-jcl2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-jmx-gui2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-jpa2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-jpl2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-jul2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-kubernetes2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-liquibase2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-mongodb22.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-mongodb32.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-slf4j-impl2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-slf4j18-impl2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-spring-cloud-config-client2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-taglib2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-to-slf4j2.13.3-jarApache License, Version 2.0
    org.apache.logging.log4jlog4j-web2.13.3-jarApache License, Version 2.0
    org.apache.solrsolr-analysis-extras8.5.2-jarApache 2
    org.apache.solrsolr-analytics8.5.2-jarApache 2
    org.apache.solrsolr-cell8.5.2-jarApache 2
    org.apache.solrsolr-clustering8.5.2-jarApache 2
    org.apache.solrsolr-core8.5.2-jarApache 2
    org.apache.solrsolr-dataimporthandler8.5.2-jarApache 2
    org.apache.solrsolr-dataimporthandler-extras8.5.2-jarApache 2
    org.apache.solrsolr-langid8.5.2-jarApache 2
    org.apache.solrsolr-ltr8.5.2-jarApache 2
    org.apache.solrsolr-solrj8.5.2-jarApache 2
    org.apache.solrsolr-test-framework8.5.2-jarApache 2
    org.apache.solrsolr-velocity8.5.2-jarApache 2
    org.apache.tomcattomcat-annotations-api9.0.39-jarApache License, Version 2.0
    org.apache.tomcattomcat-jdbc9.0.39-jarApache License, Version 2.0
    org.apache.tomcattomcat-jsp-api9.0.39-jarApache License, Version 2.0
    org.apache.tomcat.embedtomcat-embed-core9.0.39-jarApache License, Version 2.0
    org.apache.tomcat.embedtomcat-embed-el9.0.39-jarApache License, Version 2.0
    org.apache.tomcat.embedtomcat-embed-jasper9.0.39-jarApache License, Version 2.0
    org.apache.tomcat.embedtomcat-embed-websocket9.0.39-jarApache License, Version 2.0
    org.aspectjaspectjrt1.9.6-jarEclipse Public License - v 1.0
    org.aspectjaspectjtools1.9.6-jarEclipse Public License - v 1.0
    org.aspectjaspectjweaver1.9.6-jarEclipse Public License - v 1.0
    org.assertjassertj-core3.16.1-jarApache License, Version 2.0
    org.awaitilityawaitility4.0.3-jarApache 2.0
    org.awaitilityawaitility-groovy4.0.3-jarApache 2.0
    org.awaitilityawaitility-kotlin4.0.3-jarApache 2.0
    org.awaitilityawaitility-scala4.0.3-jarApache 2.0
    org.codehaus.btmbtm2.1.4-jarGNU Lesser General Public License v3.0
    org.codehaus.groovygroovy2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-ant2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-bsf2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-cli-commons2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-cli-picocli2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-console2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-datetime2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-dateutil2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-docgenerator2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-groovydoc2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-groovysh2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-jaxb2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-jmx2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-json2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-json-direct2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-jsr2232.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-macro2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-nio2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-servlet2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-sql2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-swing2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-templates2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-test2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-test-junit52.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-testng2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.groovygroovy-xml2.5.13-jarThe Apache Software License, Version 2.0
    org.codehaus.janinocommons-compiler3.1.2-jarNew BSD License
    org.codehaus.janinocommons-compiler-jdk3.1.2-jarNew BSD License
    org.codehaus.janinojanino3.1.2-jarNew BSD License
    org.eclipse.jettyapache-jsp9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyapache-jstl9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyinfinispan-common9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyinfinispan-embedded-query9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyinfinispan-remote-query9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-alpn-client9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-alpn-conscrypt-client9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-alpn-conscrypt-server9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-alpn-java-client9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-alpn-java-server9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-alpn-openjdk8-client9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-alpn-openjdk8-server9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-alpn-server9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-annotations9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-ant9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-client9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-continuation9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-deploy9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-distribution9.4.33.v20201020-tar.gzApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-distribution9.4.33.v20201020-zipApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-hazelcast9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-home9.4.33.v20201020-tar.gzApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-home9.4.33.v20201020-zipApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-http9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-http-spi9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-io9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-jaas9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-jaspi9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-jmx9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-jndi9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-nosql9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-openid9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-plus9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-proxy9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-quickstart9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-reactive-httpclient1.1.4-jarApache License Version 2.0
    org.eclipse.jettyjetty-rewrite9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-security9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-server9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-servlet9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-servlets9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-spring9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-unixsocket9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-util9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-util-ajax9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-webapp9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jettyjetty-xml9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.fcgifcgi-client9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.fcgifcgi-server9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.gcloudjetty-gcloud-session-manager9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.http2http2-client9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.http2http2-common9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.http2http2-hpack9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.http2http2-http-client-transport9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.http2http2-server9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.memcachedjetty-memcached-sessions9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.orbitjavax.servlet.jsp2.2.0.v201112011158-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.osgijetty-httpservice9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.osgijetty-osgi-boot9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.osgijetty-osgi-boot-jsp9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.osgijetty-osgi-boot-warurl9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.websocketjavax-websocket-client-impl9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.websocketjavax-websocket-server-impl9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.websocketwebsocket-api9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.websocketwebsocket-client9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.websocketwebsocket-common9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.websocketwebsocket-server9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.eclipse.jetty.websocketwebsocket-servlet9.4.33.v20201020-jarApache Software License - Version 2.0, Eclipse Public License - Version 1.0
    org.ehcacheehcache3.8.1-jarThe Apache Software License, Version 2.0
    org.ehcacheehcache-clustered3.8.1-jarThe Apache Software License, Version 2.0
    org.ehcacheehcache-transactions3.8.1-jarThe Apache Software License, Version 2.0
    org.elasticsearchelasticsearch7.6.2-jarThe Apache Software License, Version 2.0
    org.elasticsearch.clientelasticsearch-rest-client7.6.2-jarThe Apache Software License, Version 2.0
    org.elasticsearch.clientelasticsearch-rest-high-level-client7.6.2-jarThe Apache Software License, Version 2.0
    org.elasticsearch.clienttransport7.6.2-jarThe Apache Software License, Version 2.0
    org.elasticsearch.distribution.integ-test-zipelasticsearch7.6.2-jar-
    org.elasticsearch.plugintransport-netty4-client7.6.2-jarThe Apache Software License, Version 2.0
    org.firebirdsql.jdbcjaybird-jdk173.0.9-jarGNU Lesser General Public License, Modified BSD (3-clause) License
    org.firebirdsql.jdbcjaybird-jdk183.0.9-jarGNU Lesser General Public License, Modified BSD (3-clause) License
    org.flywaydbflyway-core6.4.4-jarApache License, Version 2.0
    org.freemarkerfreemarker2.3.30-jarApache License, Version 2.0
    org.glassfishjakarta.el3.0.3-jarEPL 2.0, GPL2 w/ CPE
    org.glassfish.jaxbcodemodel2.3.3-jarEclipse Public License v. 2.0, GNU General Public License, version 2 with the GNU Classpath Exception
    org.glassfish.jaxbcodemodel-annotation-compiler2.3.3-jarEclipse Public License v. 2.0, GNU General Public License, version 2 with the GNU Classpath Exception
    org.glassfish.jaxbjaxb-jxc2.3.3-jarEclipse Distribution License - v 1.0
    org.glassfish.jaxbjaxb-runtime2.3.3-jarEclipse Distribution License - v 1.0
    org.glassfish.jaxbjaxb-xjc2.3.3-jarEclipse Distribution License - v 1.0
    org.glassfish.jaxbtxw22.3.3-jarEclipse Distribution License - v 1.0
    org.glassfish.jaxbtxwc22.3.3-jarEclipse Distribution License - v 1.0
    org.glassfish.jaxbxsom2.3.3-jarEclipse Public License v. 2.0, GNU General Public License, version 2 with the GNU Classpath Exception
    org.glassfish.jersey.bundlesjaxrs-ri2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.connectorsjersey-apache-connector2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.connectorsjersey-grizzly-connector2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.connectorsjersey-jdk-connector2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.connectorsjersey-jetty-connector2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.connectorsjersey-netty-connector2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-grizzly2-http2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-grizzly2-servlet2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-jdk-http2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-jetty-http2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-jetty-servlet2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-netty-http2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-servlet2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-servlet-core2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containersjersey-container-simple-http2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.containers.glassfishjersey-gf-ejb2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.corejersey-client2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.corejersey-common2.30.1-jarEPL 2.0, The GNU General Public License (GPL), Version 2, With Classpath Exception, Apache License, 2.0, Public Domain
    org.glassfish.jersey.corejersey-server2.30.1-jarEPL 2.0, The GNU General Public License (GPL), Version 2, With Classpath Exception, Apache License, 2.0, Modified BSD
    org.glassfish.jersey.extjersey-bean-validation2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-declarative-linking2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-entity-filtering2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-metainf-services2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-mvc2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-mvc-bean-validation2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-mvc-freemarker2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-mvc-jsp2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-mvc-mustache2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-proxy-client2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-servlet-portability2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-spring42.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-spring52.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.extjersey-wadl-doclet2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.cdijersey-cdi1x2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.cdijersey-cdi1x-ban-custom-hk2-binding2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.cdijersey-cdi1x-servlet2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.cdijersey-cdi1x-transaction2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.cdijersey-cdi1x-validation2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.cdijersey-weld2-se2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.microprofilejersey-mp-config2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.microprofilejersey-mp-rest-client2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.rxjersey-rx-client-guava2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.rxjersey-rx-client-rxjava2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.ext.rxjersey-rx-client-rxjava22.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.injectjersey-cdi2-se2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.injectjersey-hk22.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-jaxb2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-json-binding2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-json-jackson2.30.1-jarEPL 2.0, The GNU General Public License (GPL), Version 2, With Classpath Exception, Apache License, 2.0
    org.glassfish.jersey.mediajersey-media-json-jackson12.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-json-jettison2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-json-processing2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-kryo2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-moxy2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-multipart2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.mediajersey-media-sse2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.securityoauth1-client2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.securityoauth1-server2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.securityoauth1-signature2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.securityoauth2-client2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-frameworkjersey-test-framework-core2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-frameworkjersey-test-framework-util2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-framework.providersjersey-test-framework-provider-bundle2.30.1-pomEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-framework.providersjersey-test-framework-provider-external2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-framework.providersjersey-test-framework-provider-grizzly22.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-framework.providersjersey-test-framework-provider-inmemory2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-framework.providersjersey-test-framework-provider-jdk-http2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-framework.providersjersey-test-framework-provider-jetty2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.glassfish.jersey.test-framework.providersjersey-test-framework-provider-simple2.30.1-jarEPL 2.0, GPL2 w/ CPE, EDL 1.0, BSD 2-Clause, Apache License, 2.0, Public Domain, Modified BSD, jQuery license, MIT license, W3C license
    org.hamcresthamcrest2.2-jarBSD License 3
    org.hamcresthamcrest-core2.2-jarBSD License 3
    org.hamcresthamcrest-library2.2-jarBSD License 3
    org.hibernatehibernate-c3p05.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-core5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-ehcache5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-entitymanager5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-envers5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-hikaricp5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-java85.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-jcache5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-jpamodelgen5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-proxool5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-spatial5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-testing5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernatehibernate-vibur5.4.22.Final-jarGNU Library General Public License v2.1 or later
    org.hibernate.validatorhibernate-validator6.1.6.Final-jarApache License 2.0
    org.hibernate.validatorhibernate-validator-annotation-processor6.1.6.Final-jarApache License 2.0
    org.hsqldbhsqldb2.5.1-jarHSQLDB License, a BSD open source license
    org.infinispaninfinispan-api10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-cachestore-jdbc10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-cachestore-jpa10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-cachestore-remote10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-cachestore-rest10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-cachestore-rocksdb10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-cdi-common10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-cdi-embedded10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-cdi-remote10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-client-hotrod10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-client-rest10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-clustered-counter10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-clustered-lock10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-commons10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-component-annotations10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-core10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-directory-provider10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-hibernate-cache-v5310.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-jboss-marshalling10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-jcache10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-jcache-commons10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-jcache-remote10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-key-value-store-client10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-lucene-directory10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-objectfilter10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-osgi10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-persistence-soft-index10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-query10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-query-core10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-query-dsl10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-remote-query-client10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-remote-query-server10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-scripting10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-server-core10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-server-hotrod10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-server-memcached10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-server-rest10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-server-router10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-spring5-common10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-spring5-embedded10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-spring5-remote10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-tasks10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-tasks-api10.1.8.Final-jarApache License 2.0
    org.infinispaninfinispan-tools10.1.8.Final-jarApache License 2.0
    org.influxdbinfluxdb-java2.18-jarThe MIT License (MIT)
    org.jbossjboss-transaction-spi7.6.0.Final-jarPublic Domain
    org.jboss.loggingjboss-logging3.4.1.Final-jarApache License, version 2.0
    org.jdomjdom22.0.6-jarSimilar to Apache License but with the acknowledgment clause removed
    org.jetbrains.kotlinkotlin-compiler1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-compiler-embeddable1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-daemon-client1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-main-kts1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-osgi-bundle1.3.72-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinkotlin-reflect1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-script-runtime1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-script-util1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-scripting-common1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-scripting-jvm1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-scripting-jvm-host1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-stdlib1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-stdlib-common1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-stdlib-jdk71.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-stdlib-jdk81.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-stdlib-js1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-test1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-test-annotations-common1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-test-common1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-test-js1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-test-junit1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-test-junit51.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinkotlin-test-testng1.3.72-jarThe Apache License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-android1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-core1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-core-common1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-core-js1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-core-native1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-debug1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-guava1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-javafx1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-jdk81.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-jdk91.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-play-services1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-reactive1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-reactor1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-rx21.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-rx31.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-slf4j1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-swing1.3.8-jarThe Apache Software License, Version 2.0
    org.jetbrains.kotlinxkotlinx-coroutines-test1.3.8-jarThe Apache Software License, Version 2.0
    org.jolokiajolokia-core1.6.2-jarApache 2
    org.jooqjooq3.13.5-jarApache License, Version 2.0
    org.jooqjooq-codegen3.13.5-jarApache License, Version 2.0
    org.jooqjooq-meta3.13.5-jarApache License, Version 2.0
    org.junit.jupiterjunit-jupiter5.6.3-jarEclipse Public License v2.0
    org.junit.jupiterjunit-jupiter-api5.6.3-jarEclipse Public License v2.0
    org.junit.jupiterjunit-jupiter-engine5.6.3-jarEclipse Public License v2.0
    org.junit.jupiterjunit-jupiter-migrationsupport5.6.3-jarEclipse Public License v2.0
    org.junit.jupiterjunit-jupiter-params5.6.3-jarEclipse Public License v2.0
    org.junit.platformjunit-platform-commons1.6.3-jarEclipse Public License v2.0
    org.junit.platformjunit-platform-console1.6.3-jarEclipse Public License v2.0
    org.junit.platformjunit-platform-engine1.6.3-jarEclipse Public License v2.0
    org.junit.platformjunit-platform-launcher1.6.3-jarEclipse Public License v2.0
    org.junit.platformjunit-platform-reporting1.6.3-jarEclipse Public License v2.0
    org.junit.platformjunit-platform-runner1.6.3-jarEclipse Public License v2.0
    org.junit.platformjunit-platform-suite-api1.6.3-jarEclipse Public License v2.0
    org.junit.platformjunit-platform-testkit1.6.3-jarEclipse Public License v2.0
    org.junit.vintagejunit-vintage-engine5.6.3-jarEclipse Public License v2.0
    org.jvnet.mimepullmimepull1.9.13-jarEclipse Distribution License - v 1.0
    org.liquibaseliquibase-core3.8.9-jarApache License, Version 2.0
    org.mariadbr2dbc-mariadb0.8.4-rc-jarApache License 2.0
    org.mariadb.jdbcmariadb-java-client2.6.2-jarLGPL-2.1
    org.messaginghubpooled-jms1.1.2-jarThe Apache License, Version 2.0
    org.mockitomockito-core3.3.3-jarThe MIT License
    org.mockitomockito-inline3.3.3-jarThe MIT License
    org.mockitomockito-junit-jupiter3.3.3-jarThe MIT License
    org.mongodbbson4.0.5-jarThe Apache License, Version 2.0
    org.mongodbmongodb-driver-core4.0.5-jarThe Apache License, Version 2.0
    org.mongodbmongodb-driver-legacy4.0.5-jarThe Apache License, Version 2.0
    org.mongodbmongodb-driver-reactivestreams4.0.5-jarThe Apache License, Version 2.0
    org.mongodbmongodb-driver-sync4.0.5-jarThe Apache License, Version 2.0
    org.mortbay.jasperapache-el8.5.54-jarApache License Version 2.0
    org.neo4jneo4j-ogm-api3.2.17-jarThe Apache Software License, Version 2.0
    org.neo4jneo4j-ogm-bolt-driver3.2.17-jarThe Apache Software License, Version 2.0
    org.neo4jneo4j-ogm-bolt-native-types3.2.17-jarThe Apache Software License, Version 2.0
    org.neo4jneo4j-ogm-core3.2.17-jarThe Apache Software License, Version 2.0
    org.neo4jneo4j-ogm-embedded-driver3.2.17-jarThe Apache Software License, Version 2.0
    org.neo4jneo4j-ogm-embedded-native-types3.2.17-jarThe Apache Software License, Version 2.0
    org.neo4jneo4j-ogm-http-driver3.2.17-jarThe Apache Software License, Version 2.0
    org.postgresqlpostgresql42.2.18-jarBSD-2-Clause
    org.projectlomboklombok1.18.16-jarThe MIT License
    org.quartz-schedulerquartz2.3.2-jarThe Apache Software License, Version 2.0
    org.quartz-schedulerquartz-jobs2.3.2-jarThe Apache Software License, Version 2.0
    org.reactivestreamsreactive-streams1.0.3-jarCC0
    org.seleniumhq.seleniumhtmlunit-driver2.40.0-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-api3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-chrome-driver3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-edge-driver3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-firefox-driver3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-ie-driver3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-java3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-opera-driver3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-remote-driver3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-safari-driver3.141.59-jarThe Apache Software License, Version 2.0
    org.seleniumhq.seleniumselenium-support3.141.59-jarThe Apache Software License, Version 2.0
    org.skyscreamerjsonassert1.5.0-jarThe Apache Software License, Version 2.0
    org.slf4jjcl-over-slf4j1.7.30-jarApache License, Version 2.0
    org.slf4jjul-to-slf4j1.7.30-jarMIT License
    org.slf4jlog4j-over-slf4j1.7.30-jarApache Software Licenses
    org.slf4jslf4j-api1.7.30-jarMIT License
    org.slf4jslf4j-ext1.7.30-jarMIT License
    org.slf4jslf4j-jcl1.7.30-jarMIT License
    org.slf4jslf4j-jdk141.7.30-jarMIT License
    org.slf4jslf4j-log4j121.7.30-jarMIT License
    org.slf4jslf4j-nop1.7.30-jarMIT License
    org.slf4jslf4j-simple1.7.30-jarMIT License
    org.springframeworkspring-aop5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-aspects5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-beans5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-context5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-context-indexer5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-context-support5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-core5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-expression5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-instrument5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-jcl5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-jdbc5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-jms5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-messaging5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-orm5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-oxm5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-test5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-tx5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-web5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-webflux5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-webmvc5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframeworkspring-websocket5.2.10.RELEASE-jarApache License, Version 2.0
    org.springframework.amqpspring-amqp2.2.12.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.amqpspring-rabbit2.2.12.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.amqpspring-rabbit-junit2.2.12.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.amqpspring-rabbit-test2.2.12.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.batchspring-batch-core4.2.4.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.batchspring-batch-infrastructure4.2.4.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.batchspring-batch-integration4.2.4.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.batchspring-batch-test4.2.4.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.bootspring-boot2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-actuator2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-actuator-autoconfigure2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-autoconfigure2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-autoconfigure-processor2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-buildpack-platform2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-configuration-metadata2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-configuration-processor2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-devtools2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-jarmode-layertools2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-loader2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-loader-tools2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-properties-migrator2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-activemq2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-actuator2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-amqp2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-aop2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-artemis2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-batch2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-cache2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-cassandra2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-cassandra-reactive2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-couchbase2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-couchbase-reactive2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-elasticsearch2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-jdbc2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-jpa2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-ldap2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-mongodb2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-mongodb-reactive2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-neo4j2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-r2dbc2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-redis2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-redis-reactive2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-rest2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-data-solr2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-freemarker2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-groovy-templates2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-hateoas2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-integration2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-jdbc2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-jersey2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-jetty2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-jooq2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-json2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-jta-atomikos2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-jta-bitronix2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-log4j22.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-logging2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-mail2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-mustache2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-oauth2-client2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-oauth2-resource-server2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-quartz2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-reactor-netty2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-rsocket2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-security2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-test2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-thymeleaf2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-tomcat2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-undertow2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-validation2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-web2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-web-services2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-webflux2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-starter-websocket2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-test2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.bootspring-boot-test-autoconfigure2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-cassandra3.0.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-commons2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-couchbase4.0.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-elasticsearch4.0.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-envers2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-gemfire2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-geode2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-jdbc2.0.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-jpa2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-keyvalue2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-ldap2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-mongodb3.0.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-neo4j5.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-r2dbc1.1.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-redis2.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-relational2.0.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-rest-core3.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-rest-hal-browser3.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-rest-hal-explorer3.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-rest-webmvc3.3.5.RELEASE-jarApache License, Version 2.0
    org.springframework.dataspring-data-solr4.2.5.RELEASE-jarApache License, Version 2.0
    org.springframework.hateoasspring-hateoas1.1.2.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-amqp5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-core5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-event5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-feed5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-file5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-ftp5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-gemfire5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-groovy5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-http5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-ip5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-jdbc5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-jms5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-jmx5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-jpa5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-mail5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-mongodb5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-mqtt5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-redis5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-rmi5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-rsocket5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-scripting5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-security5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-sftp5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-stomp5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-stream5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-syslog5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-test5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-test-support5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-webflux5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-websocket5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-ws5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-xml5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-xmpp5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.integrationspring-integration-zookeeper5.3.3.RELEASE-jarApache License, Version 2.0
    org.springframework.kafkaspring-kafka2.5.7.RELEASE-jarApache License, Version 2.0
    org.springframework.kafkaspring-kafka-test2.5.7.RELEASE-jarApache License, Version 2.0
    org.springframework.ldapspring-ldap-core2.3.3.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.ldapspring-ldap-core-tiger2.3.3.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.ldapspring-ldap-ldif-batch2.3.3.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.ldapspring-ldap-ldif-core2.3.3.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.ldapspring-ldap-odm2.3.3.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.ldapspring-ldap-test2.3.3.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.restdocsspring-restdocs-asciidoctor2.0.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.restdocsspring-restdocs-core2.0.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.restdocsspring-restdocs-mockmvc2.0.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.restdocsspring-restdocs-restassured2.0.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.restdocsspring-restdocs-webtestclient2.0.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.retryspring-retry1.2.5.RELEASE-jarApache 2.0
    org.springframework.securityspring-security-acl5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-aspects5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-cas5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-config5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-core5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-crypto5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-data5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-ldap5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-messaging5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-oauth2-client5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-oauth2-core5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-oauth2-jose5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-oauth2-resource-server5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-openid5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-remoting5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-rsocket5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-saml2-service-provider5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-taglibs5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-test5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.securityspring-security-web5.3.5.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.sessionspring-session-core2.3.1.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.sessionspring-session-data-geode2.3.1.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.sessionspring-session-data-mongodb2.3.0.RELEASE-jarApache License, Version 2.0
    org.springframework.sessionspring-session-data-redis2.3.1.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.sessionspring-session-hazelcast2.3.1.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.sessionspring-session-jdbc2.3.1.RELEASE-jarThe Apache Software License, Version 2.0
    org.springframework.wsspring-ws-core3.0.10.RELEASE-jarApache License, Version 2.0
    org.springframework.wsspring-ws-security3.0.10.RELEASE-jarApache License, Version 2.0
    org.springframework.wsspring-ws-support3.0.10.RELEASE-jarApache License, Version 2.0
    org.springframework.wsspring-ws-test3.0.10.RELEASE-jarApache License, Version 2.0
    org.springframework.wsspring-xml3.0.10.RELEASE-jarApache License, Version 2.0
    org.synchronoss.cloudnio-multipart-parser1.1.0-jarThe Apache Software License, Version 2.0
    org.thymeleafthymeleaf3.0.11.RELEASE-jarThe Apache Software License, Version 2.0
    org.thymeleafthymeleaf-spring53.0.11.RELEASE-jarThe Apache Software License, Version 2.0
    org.thymeleaf.extrasthymeleaf-extras-java8time3.0.4.RELEASE-jarThe Apache Software License, Version 2.0
    org.thymeleaf.extrasthymeleaf-extras-springsecurity53.0.4.RELEASE-jarThe Apache Software License, Version 2.0
    org.webjarshal-browser3325375-jarMIT License
    org.webjarswebjars-locator-core0.45-jarMIT
    org.xerialsqlite-jdbc3.31.1-jarThe Apache Software License, Version 2.0
    org.xmlunitxmlunit-assertj2.7.0-jarThe Apache Software License, Version 2.0
    org.xmlunitxmlunit-core2.7.0-jarThe Apache Software License, Version 2.0
    org.xmlunitxmlunit-legacy2.7.0-jarThe BSD 3-Clause License
    org.xmlunitxmlunit-matchers2.7.0-jarThe Apache Software License, Version 2.0
    org.xmlunitxmlunit-placeholders2.7.0-jarThe Apache Software License, Version 2.0
    org.yamlsnakeyaml1.26-jarApache License, Version 2.0
    redis.clientsjedis3.3.0-jarMIT
    wsdl4jwsdl4j1.6.3-jarCPL
    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/distribution-management.html b/dist/http-resources/2.0.0/site/distribution-management.html deleted file mode 100644 index f48234b7..00000000 --- a/dist/http-resources/2.0.0/site/distribution-management.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - HttpResources – Project Distribution Management - - - - - - - - - -
    -
    -
    -

    Overview

    -

    The following is the distribution management information used by this project.

    -

    Repository - juplo

    -

    scpexe://juplo.de/var/www/juplo.de/maven2

    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/images/close.gif b/dist/http-resources/2.0.0/site/images/close.gif deleted file mode 100644 index 1c26bbc5..00000000 Binary files a/dist/http-resources/2.0.0/site/images/close.gif and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/collapsed.gif b/dist/http-resources/2.0.0/site/images/collapsed.gif deleted file mode 100644 index 6e710840..00000000 Binary files a/dist/http-resources/2.0.0/site/images/collapsed.gif and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/expanded.gif b/dist/http-resources/2.0.0/site/images/expanded.gif deleted file mode 100644 index 0fef3d89..00000000 Binary files a/dist/http-resources/2.0.0/site/images/expanded.gif and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/external.png b/dist/http-resources/2.0.0/site/images/external.png deleted file mode 100644 index 3f999fc8..00000000 Binary files a/dist/http-resources/2.0.0/site/images/external.png and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/icon_error_sml.gif b/dist/http-resources/2.0.0/site/images/icon_error_sml.gif deleted file mode 100644 index 61132ef2..00000000 Binary files a/dist/http-resources/2.0.0/site/images/icon_error_sml.gif and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/icon_info_sml.gif b/dist/http-resources/2.0.0/site/images/icon_info_sml.gif deleted file mode 100644 index c6cb9ad7..00000000 Binary files a/dist/http-resources/2.0.0/site/images/icon_info_sml.gif and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/icon_success_sml.gif b/dist/http-resources/2.0.0/site/images/icon_success_sml.gif deleted file mode 100644 index 52e85a43..00000000 Binary files a/dist/http-resources/2.0.0/site/images/icon_success_sml.gif and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/icon_warning_sml.gif b/dist/http-resources/2.0.0/site/images/icon_warning_sml.gif deleted file mode 100644 index 873bbb52..00000000 Binary files a/dist/http-resources/2.0.0/site/images/icon_warning_sml.gif and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/logos/build-by-maven-black.png b/dist/http-resources/2.0.0/site/images/logos/build-by-maven-black.png deleted file mode 100644 index 919fd0f6..00000000 Binary files a/dist/http-resources/2.0.0/site/images/logos/build-by-maven-black.png and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/logos/build-by-maven-white.png b/dist/http-resources/2.0.0/site/images/logos/build-by-maven-white.png deleted file mode 100644 index 7d44c9c2..00000000 Binary files a/dist/http-resources/2.0.0/site/images/logos/build-by-maven-white.png and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/logos/maven-feather.png b/dist/http-resources/2.0.0/site/images/logos/maven-feather.png deleted file mode 100644 index b5ada836..00000000 Binary files a/dist/http-resources/2.0.0/site/images/logos/maven-feather.png and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/images/newwindow.png b/dist/http-resources/2.0.0/site/images/newwindow.png deleted file mode 100644 index 6287f72b..00000000 Binary files a/dist/http-resources/2.0.0/site/images/newwindow.png and /dev/null differ diff --git a/dist/http-resources/2.0.0/site/index.html b/dist/http-resources/2.0.0/site/index.html deleted file mode 100644 index 58fede5f..00000000 --- a/dist/http-resources/2.0.0/site/index.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - HttpResources – About - - - - - - - - - -
    -
    -
    -

    About HttpResources

    -

    A library to serve remote content as Spring Resource

    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/issue-tracking.html b/dist/http-resources/2.0.0/site/issue-tracking.html deleted file mode 100644 index 70af9ff6..00000000 --- a/dist/http-resources/2.0.0/site/issue-tracking.html +++ /dev/null @@ -1,450 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HttpResources — $pages.get($alignedFileName).name - - - - -

    Path

    -

    -

      -
    -

    -
    -
    - - - - -

    Issue Tracking

    - There is no bug-tracking system set up for this project! - -

    - Please send your bug-reports, questions or feature-requests directly - to the developer. -

    - - -
    -
    -

    Pages

    -

    -

    -

    - - diff --git a/dist/http-resources/2.0.0/site/licenses.html b/dist/http-resources/2.0.0/site/licenses.html deleted file mode 100644 index 5c4f5ad7..00000000 --- a/dist/http-resources/2.0.0/site/licenses.html +++ /dev/null @@ -1,691 +0,0 @@ - - - - - - - - HttpResources – Project Licenses - - - - - - - - - -
    -
    -
    -

    Overview

    -

    Typically the licenses listed for the project are that of the project itself, and not of dependencies.

    -

    Project Licenses

    -

    Apache License, Version 2.0

    [Original text] -

    Copy of the license follows:

    - -
    - -
    - -
    -
    - ApacheCon is Coming 9-12 Sept. 2019 - Las Vegas - The Apache Software Foundation -
    - -
    - Apache Support Logo -
    -
    -
    -

    Apache License, Version 2.0

    - -

    The 2.0 version of the Apache License, approved by the ASF in 2004, helps us achieve our goal of providing -reliable and long-lived software products through collaborative open source software development.

    -

    All packages produced by the ASF are implicitly licensed under the Apache -License, Version 2.0, unless otherwise explicitly stated.

    -
    - -

    -Apache License

    Version 2.0, January 2004

    -http://www.apache.org/licenses/ -

    - -

    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

    - -

    1. Definitions.

    - -
    - -

    "License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document.

    - -

    "Licensor" shall mean the copyright owner or entity authorized by the -copyright owner that is granting the License.

    - -

    "Legal Entity" shall mean the union of the acting entity and all other -entities that control, are controlled by, or are under common control with -that entity. For the purposes of this definition, "control" means (i) the -power, direct or indirect, to cause the direction or management of such -entity, whether by contract or otherwise, or (ii) ownership of fifty -percent (50%) or more of the outstanding shares, or (iii) beneficial -ownership of such entity.

    - -

    "You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License.

    - -

    "Source" form shall mean the preferred form for making modifications, -including but not limited to software source code, documentation source, -and configuration files.

    - -

    "Object" form shall mean any form resulting from mechanical transformation -or translation of a Source form, including but not limited to compiled -object code, generated documentation, and conversions to other media types.

    - -

    "Work" shall mean the work of authorship, whether in Source or Object form, -made available under the License, as indicated by a copyright notice that -is included in or attached to the work (an example is provided in the -Appendix below).

    - -

    "Derivative Works" shall mean any work, whether in Source or Object form, -that is based on (or derived from) the Work and for which the editorial -revisions, annotations, elaborations, or other modifications represent, as -a whole, an original work of authorship. For the purposes of this License, -Derivative Works shall not include works that remain separable from, or -merely link (or bind by name) to the interfaces of, the Work and Derivative -Works thereof.

    - -

    "Contribution" shall mean any work of authorship, including the original -version of the Work and any modifications or additions to that Work or -Derivative Works thereof, that is intentionally submitted to Licensor for -inclusion in the Work by the copyright owner or by an individual or Legal -Entity authorized to submit on behalf of the copyright owner. For the -purposes of this definition, "submitted" means any form of electronic, -verbal, or written communication sent to the Licensor or its -representatives, including but not limited to communication on electronic -mailing lists, source code control systems, and issue tracking systems that -are managed by, or on behalf of, the Licensor for the purpose of discussing -and improving the Work, but excluding communication that is conspicuously -marked or otherwise designated in writing by the copyright owner as "Not a -Contribution."

    - -

    "Contributor" shall mean Licensor and any individual or Legal Entity on -behalf of whom a Contribution has been received by Licensor and -subsequently incorporated within the Work.

    - -
    - -

    2. Grant of Copyright License. Subject to the -terms and conditions of this License, each Contributor hereby grants to You -a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable -copyright license to reproduce, prepare Derivative Works of, publicly -display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form.

    - -

    3. Grant of Patent License. Subject to the terms -and conditions of this License, each Contributor hereby grants to You a -perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable -(except as stated in this section) patent license to make, have made, use, -offer to sell, sell, import, and otherwise transfer the Work, where such -license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by -combination of their Contribution(s) with the Work to which such -Contribution(s) was submitted. If You institute patent litigation against -any entity (including a cross-claim or counterclaim in a lawsuit) alleging -that the Work or a Contribution incorporated within the Work constitutes -direct or contributory patent infringement, then any patent licenses -granted to You under this License for that Work shall terminate as of the -date such litigation is filed.

    - -

    4. Redistribution. You may reproduce and -distribute copies of the Work or Derivative Works thereof in any medium, -with or without modifications, and in Source or Object form, provided that -You meet the following conditions:

    - -
      -
    1. You must give any other recipients of the Work or Derivative Works a -copy of this License; and
    2. - -
    3. You must cause any modified files to carry prominent notices stating -that You changed the files; and
    4. - -
    5. You must retain, in the Source form of any Derivative Works that You -distribute, all copyright, patent, trademark, and attribution notices from -the Source form of the Work, excluding those notices that do not pertain to -any part of the Derivative Works; and
    6. - -
    7. If the Work includes a "NOTICE" text file as part of its distribution, -then any Derivative Works that You distribute must include a readable copy -of the attribution notices contained within such NOTICE file, excluding -those notices that do not pertain to any part of the Derivative Works, in -at least one of the following places: within a NOTICE text file distributed -as part of the Derivative Works; within the Source form or documentation, -if provided along with the Derivative Works; or, within a display generated -by the Derivative Works, if and wherever such third-party notices normally -appear. The contents of the NOTICE file are for informational purposes only -and do not modify the License. You may add Your own attribution notices -within Derivative Works that You distribute, alongside or as an addendum to -the NOTICE text from the Work, provided that such additional attribution -notices cannot be construed as modifying the License. -
      -
      -You may add Your own copyright statement to Your modifications and may -provide additional or different license terms and conditions for use, -reproduction, or distribution of Your modifications, or for any such -Derivative Works as a whole, provided Your use, reproduction, and -distribution of the Work otherwise complies with the conditions stated in -this License. -
    8. - -
    - -

    5. Submission of Contributions. Unless You -explicitly state otherwise, any Contribution intentionally submitted for -inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the -terms of any separate license agreement you may have executed with Licensor -regarding such Contributions.

    - -

    6. Trademarks. This License does not grant -permission to use the trade names, trademarks, service marks, or product -names of the Licensor, except as required for reasonable and customary use -in describing the origin of the Work and reproducing the content of the -NOTICE file.

    - -

    7. Disclaimer of Warranty. Unless required by -applicable law or agreed to in writing, Licensor provides the Work (and -each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, -without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You -are solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise -of permissions under this License.

    - -

    8. Limitation of Liability. In no event and -under no legal theory, whether in tort (including negligence), contract, or -otherwise, unless required by applicable law (such as deliberate and -grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, -incidental, or consequential damages of any character arising as a result -of this License or out of the use or inability to use the Work (including -but not limited to damages for loss of goodwill, work stoppage, computer -failure or malfunction, or any and all other commercial damages or losses), -even if such Contributor has been advised of the possibility of such -damages.

    - -

    9. Accepting Warranty or Additional Liability. -While redistributing the Work or Derivative Works thereof, You may choose -to offer, and charge a fee for, acceptance of support, warranty, indemnity, -or other liability obligations and/or rights consistent with this License. -However, in accepting such obligations, You may act only on Your own behalf -and on Your sole responsibility, not on behalf of any other Contributor, -and only if You agree to indemnify, defend, and hold each Contributor -harmless for any liability incurred by, or claims asserted against, such -Contributor by reason of your accepting any such warranty or additional -liability.

    - -

    END OF TERMS AND CONDITIONS

    - -
    - -

    How to apply the Apache License to your work

    -

    You should include a copy of the Apache License, typically in a file called -LICENSE, in your work, and consider also including a NOTICE file.

    -

    To apply the Apache License to specific files in your work, attach the following boilerplate -declaration, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included -on the same "printed page" as the copyright notice for easier -identification within third-party archives.

    -
    Copyright [yyyy] [name of copyright owner]
    -
    -Licensed 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.
    -
    - - - - - - - - - - -
    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/mail-lists.html b/dist/http-resources/2.0.0/site/mail-lists.html deleted file mode 100644 index f86643ca..00000000 --- a/dist/http-resources/2.0.0/site/mail-lists.html +++ /dev/null @@ -1,450 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HttpResources — $pages.get($alignedFileName).name - - - - -

    Path

    -

    -

      -
    -

    -
    -
    - - - - -

    Mailing Lists

    - There are no mailinglists defined for this project! - -

    - Please send your bug-reports, questions or feature-requests directly - to the developer. -

    - - -
    -
    -

    Pages

    -

    -

    -

    - - diff --git a/dist/http-resources/2.0.0/site/plugin-management.html b/dist/http-resources/2.0.0/site/plugin-management.html deleted file mode 100644 index c177a3f8..00000000 --- a/dist/http-resources/2.0.0/site/plugin-management.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - HttpResources – Project Plugin Management - - - - - - - - - -
    -
    -
    -

    Project Plugin Management

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    GroupIdArtifactIdVersion
    org.apache.johnzonjohnzon-maven-plugin1.2.8
    org.apache.maven.pluginsmaven-antrun-plugin1.8
    org.apache.maven.pluginsmaven-assembly-plugin3.3.0
    org.apache.maven.pluginsmaven-clean-plugin3.1.0
    org.apache.maven.pluginsmaven-compiler-plugin3.8.1
    org.apache.maven.pluginsmaven-dependency-plugin3.1.2
    org.apache.maven.pluginsmaven-deploy-plugin2.8.2
    org.apache.maven.pluginsmaven-enforcer-plugin3.0.0-M3
    org.apache.maven.pluginsmaven-failsafe-plugin2.22.2
    org.apache.maven.pluginsmaven-help-plugin3.2.0
    org.apache.maven.pluginsmaven-install-plugin2.5.2
    org.apache.maven.pluginsmaven-invoker-plugin3.2.1
    org.apache.maven.pluginsmaven-jar-plugin3.2.0
    org.apache.maven.pluginsmaven-javadoc-plugin3.2.0
    org.apache.maven.pluginsmaven-project-info-plugin${maven-project-info-plugin.version}
    org.apache.maven.pluginsmaven-release-plugin2.5.3
    org.apache.maven.pluginsmaven-resources-plugin3.1.0
    org.apache.maven.pluginsmaven-shade-plugin3.2.4
    org.apache.maven.pluginsmaven-site-plugin3.9.1
    org.apache.maven.pluginsmaven-source-plugin3.2.1
    org.apache.maven.pluginsmaven-surefire-plugin2.22.2
    org.apache.maven.pluginsmaven-war-plugin3.2.3
    org.codehaus.mojobuild-helper-maven-plugin3.1.0
    org.codehaus.mojoexec-maven-plugin1.6.0
    org.codehaus.mojoflatten-maven-plugin1.2.5
    org.codehaus.mojoversions-maven-plugin2.7
    org.codehaus.mojoxml-maven-plugin1.0.2
    org.flywaydbflyway-maven-plugin6.4.4
    org.jetbrains.kotlinkotlin-maven-plugin1.3.72
    org.jooqjooq-codegen-maven3.13.5
    org.springframework.bootspring-boot-maven-plugin2.3.5.RELEASE
    pl.project13.mavengit-commit-id-plugin3.0.1
    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/plugins.html b/dist/http-resources/2.0.0/site/plugins.html deleted file mode 100644 index a0d1c42a..00000000 --- a/dist/http-resources/2.0.0/site/plugins.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - HttpResources – Project Plugins - - - - - - - - - -
    -
    -
    -

    Project Build Plugins

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    GroupIdArtifactIdVersion
    org.apache.maven.pluginsmaven-clean-plugin3.1.0
    org.apache.maven.pluginsmaven-compiler-plugin3.8.1
    org.apache.maven.pluginsmaven-deploy-plugin2.8.2
    org.apache.maven.pluginsmaven-failsafe-plugin2.22.2
    org.apache.maven.pluginsmaven-install-plugin2.5.2
    org.apache.maven.pluginsmaven-jar-plugin3.2.0
    org.apache.maven.pluginsmaven-resources-plugin3.1.0
    org.apache.maven.pluginsmaven-site-plugin3.9.1
    org.apache.maven.pluginsmaven-source-plugin3.0.1
    org.apache.maven.pluginsmaven-surefire-plugin2.22.2
    -

    Project Report Plugins

    - - - - - - - - -
    GroupIdArtifactIdVersion
    org.apache.maven.pluginsmaven-project-info-reports-plugin3.1.1
    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/project-info.html b/dist/http-resources/2.0.0/site/project-info.html deleted file mode 100644 index 288ffcff..00000000 --- a/dist/http-resources/2.0.0/site/project-info.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - HttpResources – Project Information - - - - - - - - - -
    -
    -
    -

    Project Information

    -

    This document provides an overview of the various documents and links that are part of this project's general information. All of this content is automatically generated by Maven on behalf of the project.

    -

    Overview

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    DocumentDescription
    DependenciesThis document lists the project's dependencies and provides information on each dependency.
    Dependency InformationThis document describes how to include this project as a dependency using various dependency management tools.
    Dependency ManagementThis document lists the dependencies that are defined through dependencyManagement.
    Distribution ManagementThis document provides informations on the distribution management of this project.
    AboutA library to serve remote content as Spring Resource
    LicensesThis document lists the project license(s).
    Plugin ManagementThis document lists the plugins that are defined through pluginManagement.
    PluginsThis document lists the build plugins and the report plugins used by this project.
    Source Code ManagementThis document lists ways to access the online source repository.
    SummaryThis document lists other related information of this project
    TeamThis document provides information on the members of this project. These are the individuals who have contributed to the project in one form or another.
    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/scm.html b/dist/http-resources/2.0.0/site/scm.html deleted file mode 100644 index d3bd6924..00000000 --- a/dist/http-resources/2.0.0/site/scm.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - HttpResources – Source Code Management - - - - - - - - - -
    -
    -
    -

    Overview

    -

    This project uses a source code management system to manage its source code.

    -

    Web Browser Access

    -

    The following is a link to a browsable version of the source repository:

    -
    -

    Access from Behind a Firewall

    -

    Refer to the documentation of the SCM used for more information about access behind a firewall.

    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/summary.html b/dist/http-resources/2.0.0/site/summary.html deleted file mode 100644 index b9b3bbbc..00000000 --- a/dist/http-resources/2.0.0/site/summary.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - HttpResources – Project Summary - - - - - - - - - -
    -
    -
    -

    Project Summary

    -

    Project Information

    - - - - - - - - - - - - -
    FieldValue
    NameHttpResources
    DescriptionA library to serve remote content as Spring Resource
    Homepagehttps://spring.io/projects/spring-boot/http-resources
    -

    Project Organization

    -

    This project does not belong to an organization.

    -

    Build Information

    - - - - - - - - - - - - - - - - - - -
    FieldValue
    GroupIdde.juplo
    ArtifactIdhttp-resources
    Version2.0.0
    Typejar
    Java Version9
    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/site/team.html b/dist/http-resources/2.0.0/site/team.html deleted file mode 100644 index 4275bd26..00000000 --- a/dist/http-resources/2.0.0/site/team.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - HttpResources – Project Team - - - - - - - - - -
    -
    -
    -

    Project Team

    -

    A successful project requires many people to play many roles. Some members write code or documentation, while others are valuable as testers, submitting patches and suggestions.

    -

    The project team is comprised of Members and Contributors. Members have direct access to the source of a project and actively evolve the code-base. Contributors improve the project through submission of patches and suggestions to the Members. The number of Contributors to the project is unbounded. Get involved today. All contributions to the project are greatly appreciated.

    -

    Members

    -

    The following is a list of developers with commit privileges that have directly contributed to the project in one way or another.

    - - - - - - - - - - - - -
    ImageNameEmailOrganizationOrganization URL
    Pivotalinfo@pivotal.ioPivotal Software, Inc.https://www.spring.io
    -

    Contributors

    -

    There are no contributors listed for this project. Please check back again later.

    -
    -
    -
    -
    -
    - - - diff --git a/dist/http-resources/2.0.0/summary.html b/dist/http-resources/2.0.0/summary.html index 2163404f..131b4929 100644 --- a/dist/http-resources/2.0.0/summary.html +++ b/dist/http-resources/2.0.0/summary.html @@ -1,6 +1,6 @@ - + @@ -15,62 +15,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -82,33 +29,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -118,9 +41,9 @@ - + - + @@ -130,9 +53,9 @@ - + - + @@ -142,27 +65,12 @@ - - - - - - - - - - + - - - - - - - + @@ -171,7 +79,7 @@ - + @@ -183,7 +91,7 @@ - + @@ -202,15 +110,15 @@ - + - + - + @@ -218,178 +126,71 @@ xmlns="http://www.w3.org/1999/xhtml" th:replace="~{/templates/layout.html :: layout( uri='/http-resources/2.0.0/summary.html', + title=~{:: title}, + maincontent=~{:: .maincontent}, json='MERGE: { - "_names": { + "_titles": { - "/http-resources/2.0.0/dependencies.html": "Dependencies" - , - "/http-resources/2.0.0/dependency-info.html": "Dependency Information" - , - "/http-resources/2.0.0/dependency-management.html": "Dependency Management" - , - "/http-resources/2.0.0/distribution-management.html": "Distribution Management" - , - "/http-resources/2.0.0/index.html": "HttpResources" - , - "/http-resources/2.0.0/licenses.html": "Licenses" - , - "/http-resources/2.0.0/plugin-management.html": "Plugin Management" - , - "/http-resources/2.0.0/plugins.html": "Plugins" + "/http-resources/2.0.0/index.html": "Franz" , - "/http-resources/2.0.0/scm.html": "Source Code Management" + "/http-resources/2.0.0/getting-started.html": "Getting Started" , - "/http-resources/2.0.0/summary.html": "Summary" + "/http-resources/2.0.0/configuration-properties.html": "Configuration-Properties" , - "/http-resources/2.0.0/team.html": "Team" + "/http-resources/2.0.0/auto-configuration.html": "Auto-Configuration" , "/http-resources/2.0.0/project-info.html": "Project Information" , "/http-resources/2.0.0/project-reports.html": "Project Reports" }, "_childs": { - + "/http-resources/2.0.0/index.html": [ "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/project-reports.html" - ] - , - "/http-resources/2.0.0/project-info.html": [ - - "/http-resources/2.0.0/dependencies.html" - , - "/http-resources/2.0.0/dependency-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - , - "/http-resources/2.0.0/distribution-management.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/licenses.html" - , - "/http-resources/2.0.0/plugin-management.html" + "/http-resources/2.0.0/getting-started.html" , - "/http-resources/2.0.0/plugins.html" + "/http-resources/2.0.0/configuration-properties.html" , - "/http-resources/2.0.0/scm.html" + "/http-resources/2.0.0/auto-configuration.html" , - "/http-resources/2.0.0/summary.html" + "/http-resources/2.0.0/project-info.html" , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/project-reports.html" ] - }, + }, "_crumbs": { - "/http-resources/2.0.0/dependencies.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependencies.html" - ] - , - "/http-resources/2.0.0/dependency-info.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-info.html" - ] - , - "/http-resources/2.0.0/dependency-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - ] - , - "/http-resources/2.0.0/distribution-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/distribution-management.html" - ] - , "/http-resources/2.0.0/index.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" ] , - "/http-resources/2.0.0/licenses.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/licenses.html" - ] - , - "/http-resources/2.0.0/plugin-management.html": [ + "/http-resources/2.0.0/getting-started.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugin-management.html" + "/http-resources/2.0.0/getting-started.html" ] , - "/http-resources/2.0.0/plugins.html": [ + "/http-resources/2.0.0/configuration-properties.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugins.html" + "/http-resources/2.0.0/configuration-properties.html" ] , - "/http-resources/2.0.0/scm.html": [ + "/http-resources/2.0.0/auto-configuration.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/scm.html" - ] - , - "/http-resources/2.0.0/summary.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/summary.html" - ] - , - "/http-resources/2.0.0/team.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/auto-configuration.html" ] , "/http-resources/2.0.0/project-info.html": [ @@ -420,7 +221,7 @@

    Path

      -
    1. HttpResources
    2. Project Information
    3. Summary
    +


    @@ -436,12 +237,21 @@ HttpResources Description -A library to serve remote content as Spring Resource +A library to serve remote content as Spring Resources Homepage -https://spring.io/projects/spring-boot/http-resources
    +https://juplo.de/http-resources/

    Project Organization

    -

    This project does not belong to an organization.

    + + + + + + + + + +
    FieldValue
    Namejuplo
    URLhttps://juplo.de

    Build Information

    @@ -467,7 +277,7 @@

    Pages

    +
  • Franz
  • Getting Started
  • Configuration-Properties
  • Auto-Configuration
  • Project Information
  • Project Reports
  • diff --git a/dist/http-resources/2.0.0/team.html b/dist/http-resources/2.0.0/team.html index 999b046c..eecc1742 100644 --- a/dist/http-resources/2.0.0/team.html +++ b/dist/http-resources/2.0.0/team.html @@ -1,6 +1,6 @@ - + @@ -15,62 +15,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -82,33 +29,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -118,9 +41,9 @@ - + - + @@ -130,9 +53,9 @@ - + - + @@ -142,27 +65,12 @@ - - - - - - - - - - - - - - + - - - + @@ -171,7 +79,7 @@ - + @@ -183,7 +91,7 @@ - + @@ -202,15 +110,15 @@ - + - + - + @@ -218,178 +126,71 @@ xmlns="http://www.w3.org/1999/xhtml" th:replace="~{/templates/layout.html :: layout( uri='/http-resources/2.0.0/team.html', + title=~{:: title}, + maincontent=~{:: .maincontent}, json='MERGE: { - "_names": { + "_titles": { - "/http-resources/2.0.0/dependencies.html": "Dependencies" - , - "/http-resources/2.0.0/dependency-info.html": "Dependency Information" - , - "/http-resources/2.0.0/dependency-management.html": "Dependency Management" - , - "/http-resources/2.0.0/distribution-management.html": "Distribution Management" + "/http-resources/2.0.0/index.html": "Franz" , - "/http-resources/2.0.0/index.html": "HttpResources" + "/http-resources/2.0.0/getting-started.html": "Getting Started" , - "/http-resources/2.0.0/licenses.html": "Licenses" + "/http-resources/2.0.0/configuration-properties.html": "Configuration-Properties" , - "/http-resources/2.0.0/plugin-management.html": "Plugin Management" - , - "/http-resources/2.0.0/plugins.html": "Plugins" - , - "/http-resources/2.0.0/scm.html": "Source Code Management" - , - "/http-resources/2.0.0/summary.html": "Summary" - , - "/http-resources/2.0.0/team.html": "Team" + "/http-resources/2.0.0/auto-configuration.html": "Auto-Configuration" , "/http-resources/2.0.0/project-info.html": "Project Information" , "/http-resources/2.0.0/project-reports.html": "Project Reports" }, "_childs": { - + "/http-resources/2.0.0/index.html": [ "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/project-reports.html" - ] - , - "/http-resources/2.0.0/project-info.html": [ - - "/http-resources/2.0.0/dependencies.html" - , - "/http-resources/2.0.0/dependency-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - , - "/http-resources/2.0.0/distribution-management.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/licenses.html" - , - "/http-resources/2.0.0/plugin-management.html" + "/http-resources/2.0.0/getting-started.html" , - "/http-resources/2.0.0/plugins.html" + "/http-resources/2.0.0/configuration-properties.html" , - "/http-resources/2.0.0/scm.html" + "/http-resources/2.0.0/auto-configuration.html" , - "/http-resources/2.0.0/summary.html" + "/http-resources/2.0.0/project-info.html" , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/project-reports.html" ] - }, + }, "_crumbs": { - "/http-resources/2.0.0/dependencies.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependencies.html" - ] - , - "/http-resources/2.0.0/dependency-info.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-info.html" - ] - , - "/http-resources/2.0.0/dependency-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/dependency-management.html" - ] - , - "/http-resources/2.0.0/distribution-management.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/distribution-management.html" - ] - , "/http-resources/2.0.0/index.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" ] , - "/http-resources/2.0.0/licenses.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/licenses.html" - ] - , - "/http-resources/2.0.0/plugin-management.html": [ + "/http-resources/2.0.0/getting-started.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugin-management.html" + "/http-resources/2.0.0/getting-started.html" ] , - "/http-resources/2.0.0/plugins.html": [ + "/http-resources/2.0.0/configuration-properties.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/plugins.html" + "/http-resources/2.0.0/configuration-properties.html" ] , - "/http-resources/2.0.0/scm.html": [ + "/http-resources/2.0.0/auto-configuration.html": [ "/projects.html" , "/http-resources/2.0.0/index.html" , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/scm.html" - ] - , - "/http-resources/2.0.0/summary.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/summary.html" - ] - , - "/http-resources/2.0.0/team.html": [ - "/projects.html" - , - "/http-resources/2.0.0/index.html" - , - "/http-resources/2.0.0/project-info.html" - , - "/http-resources/2.0.0/team.html" + "/http-resources/2.0.0/auto-configuration.html" ] , "/http-resources/2.0.0/project-info.html": [ @@ -420,7 +221,7 @@

    Path

      -
    1. HttpResources
    2. Project Information
    3. Team
    +


    @@ -435,14 +236,14 @@
    - - + + - - - - -
    Image Name EmailOrganizationOrganization URL
    URLTime Zone
    Pivotalinfo@pivotal.ioPivotal Software, Inc.https://www.spring.io
    +
    +Kai Moritz +kai@juplo.de +https://juplo.de/contact.html +Europe/Berlin

    Contributors

    There are no contributors listed for this project. Please check back again later.

    @@ -450,7 +251,7 @@

    Pages

    +
  • Franz
  • Getting Started
  • Configuration-Properties
  • Auto-Configuration
  • Project Information
  • Project Reports
  • diff --git a/dist/http-resources/2.0.0/testapidocs/allclasses-index.html b/dist/http-resources/2.0.0/testapidocs/allclasses-index.html new file mode 100644 index 00000000..1bbd58b0 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/allclasses-index.html @@ -0,0 +1,309 @@ + + + + + +All Classes (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Classes

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/allclasses.html b/dist/http-resources/2.0.0/testapidocs/allclasses.html new file mode 100644 index 00000000..d7209d99 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/allclasses.html @@ -0,0 +1,60 @@ + + + + + +All Classes (HttpResources 2.0.0 Test API) + + + + + + + + + + + + +

    All Classes

    +
    + +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/allpackages-index.html b/dist/http-resources/2.0.0/testapidocs/allpackages-index.html new file mode 100644 index 00000000..1a1dee73 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/allpackages-index.html @@ -0,0 +1,165 @@ + + + + + +All Packages (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    All Packages

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/constant-values.html b/dist/http-resources/2.0.0/testapidocs/constant-values.html new file mode 100644 index 00000000..01f09ac0 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/constant-values.html @@ -0,0 +1,180 @@ + + + + + +Constant Field Values (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Constant Field Values

    +
    +

    Contents

    + +
    +
    +
    + + +
    +

    de.juplo.*

    + +
    +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ConfigurableNginxContainer.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ConfigurableNginxContainer.html new file mode 100644 index 00000000..67449061 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ConfigurableNginxContainer.html @@ -0,0 +1,528 @@ + + + + + +ConfigurableNginxContainer (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class ConfigurableNginxContainer

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • org.testcontainers.containers.FailureDetectingExternalResource
      • +
      • +
          +
        • org.testcontainers.containers.GenericContainer<SELF>
        • +
        • +
            +
          • org.testcontainers.containers.NginxContainer
          • +
          • +
              +
            • de.juplo.httpresources.ConfigurableNginxContainer
            • +
            +
          • +
          +
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      AutoCloseable, org.junit.rules.TestRule, org.testcontainers.containers.Container, org.testcontainers.containers.ContainerState, org.testcontainers.containers.traits.LinkableContainer, org.testcontainers.containers.wait.strategy.WaitStrategyTarget, org.testcontainers.lifecycle.Startable
      +
      +
      +
      public class ConfigurableNginxContainer
      +extends org.testcontainers.containers.NginxContainer
      +
      A configurable subclass of the NginxContainer.
      +
      +
      Author:
      +
      Kai Moritz
      +
      +
    • +
    +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Nested Class Summary

        +
          +
        • + + +

          Nested classes/interfaces inherited from class org.testcontainers.containers.GenericContainer

          +org.testcontainers.containers.GenericContainer.AbstractWaitStrategy
        • +
        +
          +
        • + + +

          Nested classes/interfaces inherited from interface org.testcontainers.containers.Container

          +org.testcontainers.containers.Container.ExecResult
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Field Summary

        + + + + + + + + + + + + +
        Fields 
        Modifier and TypeFieldDescription
        static intDEFAULT_NGINX_PORT 
        +
          +
        • + + +

          Fields inherited from class org.testcontainers.containers.GenericContainer

          +CONTAINER_RUNNING_TIMEOUT_SEC, containerId, containerName, dependencies, dockerClient, dockerDaemonInfo, INTERNAL_HOST_HOSTNAME, waitStrategy
        • +
        +
          +
        • + + +

          Fields inherited from interface org.testcontainers.containers.ContainerState

          +STATE_HEALTHY
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Constructor Summary

        + + + + + + + + + + +
        Constructors 
        ConstructorDescription
        ConfigurableNginxContainer() +
        Creates an instance with a default-configuration, that matches the + static configuration of the base-class NginxContainer
        +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethodDescription
        protected voidconfigure() 
        Map<String,​String>getGlobalDirectives() 
        ConfigurableNginxContainerwithConfiguration​(String path) 
        ConfigurableNginxContainerwithGlobalDirective​(String key, + String value) +
        Adds a global directive to the configuration-map.
        +
        +
          +
        • + + +

          Methods inherited from class org.testcontainers.containers.NginxContainer

          +getBaseUrl, getLivenessCheckPorts, setCustomContent, withCustomContent
        • +
        +
          +
        • + + +

          Methods inherited from class org.testcontainers.containers.GenericContainer

          +addEnv, addExposedPort, addExposedPorts, addFileSystemBind, addFixedExposedPort, addFixedExposedPort, addLink, apply, canBeReused, containerIsCreated, containerIsStarted, containerIsStarted, containerIsStarting, containerIsStarting, containerIsStopped, containerIsStopping, copyFileFromContainer, createVolumeDirectory, dependsOn, dependsOn, dependsOn, doStart, equals, failed, fetchDockerDaemonInfo, finished, getBinds, getCommandParts, getContainerId, getContainerInfo, getContainerName, getCopyToFileContainerPathMap, getCreateContainerCmdModifiers, getDependencies, getDockerClient, getDockerDaemonInfo, getDockerImageName, getEnv, getEnvMap, getExposedPorts, getExtraHosts, getImage, getIpAddress, getLabels, getLinkedContainers, getLivenessCheckPort, getLivenessCheckPortNumbers, getLogConsumers, getNetwork, getNetworkAliases, getNetworkMode, getPortBindings, getShmSize, getStartupAttempts, getStartupCheckStrategy, getTestHostIpAddress, getTmpFsMapping, getVolumesFroms, getWaitStrategy, getWorkingDirectory, hashCode, isPrivilegedMode, isShouldBeReused, logger, setBinds, setCommand, setCommand, setCommandParts, setCopyToFileContainerPathMap, setDockerImageName, setEnv, setExposedPorts, setExtraHosts, setImage, setLabels, setLinkedContainers, setLogConsumers, setNetwork, setNetworkAliases, setNetworkMode, setPortBindings, setPrivilegedMode, setShmSize, setStartupAttempts, setStartupCheckStrategy, setTmpFsMapping, setVolumesFroms, setWaitStrategy, setWorkingDirectory, start, starting, stop, succeeded, toString, waitingFor, waitUntilContainerStarted, withClasspathResourceMapping, withClasspathResourceMapping, withCommand, withCommand, withCopyFileToContainer, withCreateContainerCmdModifier, withEnv, withEnv, withExposedPorts, withExtraHost, withFileSystemBind, withImagePullPolicy, withLabel, withLabels, withLogConsumer, withMinimumRunningDuration, withNetwork, withNetworkAliases, withNetworkMode, withPrivilegedMode, withReuse, withSharedMemorySize, withStartupAttempts, withStartupCheckStrategy, withStartupTimeout, withTmpFs, withVolumesFrom, withWorkingDirectory
        • +
        + +
          +
        • + + +

          Methods inherited from interface org.testcontainers.containers.Container

          +addFileSystemBind, followOutput, followOutput, self, withEnv, withFileSystemBind
        • +
        +
          +
        • + + +

          Methods inherited from interface org.testcontainers.containers.ContainerState

          +copyFileFromContainer, copyFileToContainer, copyFileToContainer, execInContainer, execInContainer, getBoundPortNumbers, getContainerIpAddress, getCurrentContainerInfo, getFirstMappedPort, getHost, getLogs, getLogs, getMappedPort, isCreated, isHealthy, isRunning
        • +
        +
          +
        • + + +

          Methods inherited from interface org.testcontainers.containers.traits.LinkableContainer

          +getContainerName
        • +
        +
          +
        • + + +

          Methods inherited from interface org.testcontainers.lifecycle.Startable

          +close
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
      +
    • + +
      + +
      + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ConfigurableNginxContainer

          +
          public ConfigurableNginxContainer()
          +
          Creates an instance with a default-configuration, that matches the + static configuration of the base-class NginxContainer
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          withGlobalDirective

          +
          public ConfigurableNginxContainer withGlobalDirective​(String key,
          +                                                      String value)
          +
          Adds a global directive to the configuration-map. +

          + This method can only be used to add global directives. + Global directives are all directives, that are marked with the context + Main in the {@link http://nginx.org/en/docs/ngx_core_module.html + Nginx-documentation}, for example daemon, user + and env. +

          + If you need to modify contexts, like server or + http, you have to + pass in a complete configuration.

          +
          +
          Parameters:
          +
          key - The key of the directive
          +
          value - The value of the directive (the ; is added automatically)
          +
          Returns:
          +
          this instance, to enable a fluid API.
          +
          +
        • +
        + + + +
          +
        • +

          getGlobalDirectives

          +
          public Map<String,​String> getGlobalDirectives()
          +
        • +
        + + + + + + + +
          +
        • +

          configure

          +
          protected void configure()
          +
          +
          Overrides:
          +
          configure in class org.testcontainers.containers.GenericContainer
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderIT.html new file mode 100644 index 00000000..cb2eefc3 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderIT.html @@ -0,0 +1,532 @@ + + + + + +HttpResourceChainAwareResourceLoaderIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceChainAwareResourceLoaderIT

    +
    +
    + +
    +
      +
    • +
      +
      @SpringBootTest({"juplo.http-resources.protocol-resolver.enabled=true","juplo.http-resources.resolver.enabled=false","juplo.http-resources.resolver.exclusion-patterns=**.txt"})
      +public class HttpResourceChainAwareResourceLoaderIT
      +extends IntegrationTestBase
      +
      +
      Author:
      +
      Kai Moritz
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceChainAwareResourceLoaderIT

          +
          public HttpResourceChainAwareResourceLoaderIT()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
        • +
        + + + +
          +
        • +

          testResourceHandling

          +
          @Test
          +public void testResourceHandling()
          +                          throws Exception
          +
          In contrast to HttpResourceResolverIT and + HttpResourceProtocolResolverIT it does not + make sense to test through the web-layer here, + because the HttpResourceChainAwareResourceLoader + is intended to mimic the look-upp through the source, + that are configured for resource-chain for static + http-resources for the look-up of local resources.
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testFetchExistent

          +
          @Test
          +public void testFetchExistent()
          +                       throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testCachingOfExisting

          +
          @Test
          +public void testCachingOfExisting()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testCachingOfModified

          +
          @Test
          +public void testCachingOfModified()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testFetchNonExistent

          +
          @Test
          +public void testFetchNonExistent()
          +                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testCachingOfNonExistent

          +
          @Test
          +public void testCachingOfNonExistent()
          +                              throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testFetchServerResponse500

          +
          @Test
          +public void testFetchServerResponse500()
          +                                throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testCaching

          +
          @Test
          +public void testCaching()
          +                 throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderTest.html new file mode 100644 index 00000000..286eb1a0 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderTest.html @@ -0,0 +1,424 @@ + + + + + +HttpResourceChainAwareResourceLoaderTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceChainAwareResourceLoaderTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @ExtendWith(org.mockito.junit.jupiter.MockitoExtension.class)
      +public class HttpResourceChainAwareResourceLoaderTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceChainAwareResourceLoaderTest

          +
          public HttpResourceChainAwareResourceLoaderTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          testResourceExistsForaLocation

          +
          @Test
          +public void testResourceExistsForaLocation​(@Mock
          +                                           org.springframework.web.context.WebApplicationContext context,
          +                                           @Mock
          +                                           org.springframework.core.io.Resource existing,
          +                                           @Mock
          +                                           org.springframework.core.io.Resource nonExisting)
          +
        • +
        + + + +
          +
        • +

          testResourceExistsForSecondLocation

          +
          @Test
          +public void testResourceExistsForSecondLocation​(@Mock
          +                                                org.springframework.web.context.WebApplicationContext context,
          +                                                @Mock
          +                                                org.springframework.core.io.Resource existing,
          +                                                @Mock
          +                                                org.springframework.core.io.Resource nonExisting)
          +
        • +
        + + + +
          +
        • +

          testResourceExistsForThirdLocation

          +
          @Test
          +public void testResourceExistsForThirdLocation​(@Mock
          +                                               org.springframework.web.context.WebApplicationContext context,
          +                                               @Mock
          +                                               org.springframework.core.io.Resource existing,
          +                                               @Mock
          +                                               org.springframework.core.io.Resource nonExisting)
          +
        • +
        + + + +
          +
        • +

          testResourceDoesNotExist

          +
          @Test
          +public void testResourceDoesNotExist​(@Mock
          +                                     org.springframework.web.context.WebApplicationContext context,
          +                                     @Mock
          +                                     org.springframework.core.io.Resource nonExisting,
          +                                     @Mock
          +                                     org.springframework.core.io.Resource other)
          +
        • +
        + + + +
          +
        • +

          testHandlingOfLeadingSlashesInResourceNames

          +
          @Test
          +public void testHandlingOfLeadingSlashesInResourceNames​(@Mock
          +                                                        org.springframework.web.context.WebApplicationContext context,
          +                                                        @Mock
          +                                                        org.springframework.core.io.Resource nonExisting,
          +                                                        @Mock
          +                                                        org.springframework.core.io.Resource other)
          +
        • +
        + + + +
          +
        • +

          testHandlingOfTrailingSlashesInResourceLocations

          +
          @Test
          +public void testHandlingOfTrailingSlashesInResourceLocations​(@Mock
          +                                                             org.springframework.web.context.WebApplicationContext context,
          +                                                             @Mock
          +                                                             org.springframework.core.io.Resource nonExisting,
          +                                                             @Mock
          +                                                             org.springframework.core.io.Resource other)
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchModifiedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchModifiedTest.html new file mode 100644 index 00000000..f695bd0e --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchModifiedTest.html @@ -0,0 +1,487 @@ + + + + + +HttpResourceExpiredFetchModifiedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceExpiredFetchModifiedTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Expired - Fetch: Modified")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceExpiredFetchModifiedTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceExpiredFetchModifiedTest

          +
          public HttpResourceExpiredFetchModifiedTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReportsModifications

          +
          @Test
          +@DisplayName("fetch() reports modifications")
          +public void test_fetch_ReportsModifications()
          +
          Results for calls, that did trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_IsTrue

          +
          @Test
          +@DisplayName("exists() is true")
          +public void test_exists_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_IsTrue

          +
          @Test
          +@DisplayName("readable() is true")
          +public void test_isReadable_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_isModified_ReportsModifications

          +
          @Test
          +@DisplayName("isModified() reports modifications")
          +public void test_isModified_ReportsModifications()
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedContent

          +
          @Test
          +@DisplayName("getInputStream() returns expected content")
          +public void test_hasExpectedContent()
          +                             throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls, that did trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_UpdatesData

          +
          @Test
          +@DisplayName("exists() updates data")
          +public void test_exists_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_UpdatesData

          +
          @Test
          +@DisplayName("isReadable() updates data")
          +public void test_isReadable_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isModified_UpdatesData

          +
          @Test
          +@DisplayName("isModified() updates data")
          +public void test_isModified_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_UpdatesData

          +
          @Test
          +@DisplayName("getInputStream() updates data")
          +public void test_getInputStream_UpdatesData()
          +                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchNotFoundTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchNotFoundTest.html new file mode 100644 index 00000000..cf2f89b5 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchNotFoundTest.html @@ -0,0 +1,477 @@ + + + + + +HttpResourceExpiredFetchNotFoundTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceExpiredFetchNotFoundTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Expired - Fetch: Not Found")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceExpiredFetchNotFoundTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceExpiredFetchNotFoundTest

          +
          public HttpResourceExpiredFetchNotFoundTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReportsModifications

          +
          @Test
          +@DisplayName("fetch() reports modifications")
          +public void test_fetch_ReportsModifications()
          +
          Results for calls, that did trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_ReportsFalse

          +
          @Test
          +@DisplayName("exists() is false")
          +public void test_exists_ReportsFalse()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_ReportsFalse

          +
          @Test
          +@DisplayName("isReadable() is false")
          +public void test_isReadable_ReportsFalse()
          +
        • +
        + + + +
          +
        • +

          test_isModified_ReportsModifications

          +
          @Test
          +@DisplayName("isModified() reports modifications")
          +public void test_isModified_ReportsModifications()
          +
        • +
        + + + +
          +
        • +

          test_HasNoContent

          +
          @Test
          +@DisplayName("getInputStream() throws FileNotFoundException")
          +public void test_HasNoContent()
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls, that did trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_UpdatesData

          +
          @Test
          +@DisplayName("exists() updates data")
          +public void test_exists_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_UpdatesData

          +
          @Test
          +@DisplayName("isReadable() updates data")
          +public void test_isReadable_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isModified_UpdatesData

          +
          @Test
          +@DisplayName("isModified() updates data")
          +public void test_isModified_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_UpdatesData

          +
          @Test
          +@DisplayName("getInputStream() updates data")
          +public void test_getInputStream_UpdatesData()
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchServerErrorTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchServerErrorTest.html new file mode 100644 index 00000000..cb769b73 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchServerErrorTest.html @@ -0,0 +1,477 @@ + + + + + +HttpResourceExpiredFetchServerErrorTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceExpiredFetchServerErrorTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Expired - Fetch: Server Error")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceExpiredFetchServerErrorTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceExpiredFetchServerErrorTest

          +
          public HttpResourceExpiredFetchServerErrorTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReportsModifications

          +
          @Test
          +@DisplayName("fetch() reports modifications")
          +public void test_fetch_ReportsModifications()
          +
          Results for calls, that did trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_ReportsFalse

          +
          @Test
          +@DisplayName("exists() is false")
          +public void test_exists_ReportsFalse()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_ReportsFalse

          +
          @Test
          +@DisplayName("isReadable() is false")
          +public void test_isReadable_ReportsFalse()
          +
        • +
        + + + +
          +
        • +

          test_isModified_ReportsModifications

          +
          @Test
          +@DisplayName("isModified() reports modifications")
          +public void test_isModified_ReportsModifications()
          +
        • +
        + + + +
          +
        • +

          test_HasNoContent

          +
          @Test
          +@DisplayName("getInputStream() throws FileNotFoundException")
          +public void test_HasNoContent()
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls, that did trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_UpdatesData

          +
          @Test
          +@DisplayName("exists() updates data")
          +public void test_exists_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_UpdatesData

          +
          @Test
          +@DisplayName("isReadable() updates data")
          +public void test_isReadable_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isModified_UpdatesData

          +
          @Test
          +@DisplayName("isModified() updates data")
          +public void test_isModified_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_UpdatesData

          +
          @Test
          +@DisplayName("getInputStream() updates data")
          +public void test_getInputStream_UpdatesData()
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchUnmodifiedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchUnmodifiedTest.html new file mode 100644 index 00000000..a0154923 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredFetchUnmodifiedTest.html @@ -0,0 +1,466 @@ + + + + + +HttpResourceExpiredFetchUnmodifiedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceExpiredFetchUnmodifiedTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Expired - Fetch: Unmodified")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceExpiredFetchUnmodifiedTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceExpiredFetchUnmodifiedTest

          +
          public HttpResourceExpiredFetchUnmodifiedTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReportsNoModifications

          +
          @Test
          +@DisplayName("fetch() reports no modification")
          +public void test_fetch_ReportsNoModifications()
          +
          Results for calls, that did trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_IsTrue

          +
          @Test
          +@DisplayName("exists() is true")
          +public void test_exists_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_IsTrue

          +
          @Test
          +@DisplayName("readable() is true")
          +public void test_isReadable_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_isModified_ReportsNoModifications

          +
          @Test
          +@DisplayName("isModified() reports no modification")
          +public void test_isModified_ReportsNoModifications()
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls, that did trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_UpdatesData

          +
          @Test
          +@DisplayName("exists() updates data")
          +public void test_exists_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_UpdatesData

          +
          @Test
          +@DisplayName("isReadable() updates data")
          +public void test_isReadable_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isModified_UpdatesData

          +
          @Test
          +@DisplayName("isModified() updates data")
          +public void test_isModified_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_UpdatesData

          +
          @Test
          +@DisplayName("getInputStream() updates data")
          +public void test_getInputStream_UpdatesData()
          +                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredTest.html new file mode 100644 index 00000000..612070d2 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceExpiredTest.html @@ -0,0 +1,715 @@ + + + + + +HttpResourceExpiredTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceExpiredTest

    +
    +
    + +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Expired")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceExpiredTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceExpiredTest

          +
          public HttpResourceExpiredTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_TriggersFetch

          +
          @Test
          +@DisplayName("call to fetch() triggers fetch")
          +public void test_fetch_TriggersFetch()
          +
          Calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_TriggersFetch

          +
          @Test
          +@DisplayName("call to exists() triggers fetch")
          +public void test_exists_TriggersFetch()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_TriggersFetch

          +
          @Test
          +@DisplayName("call to isReadable() triggers fetch")
          +public void test_isReadable_TriggersFetch()
          +
        • +
        + + + +
          +
        • +

          test_isModified_TriggersFetch

          +
          @Test
          +@DisplayName("call to isModified() triggers fetch")
          +public void test_isModified_TriggersFetch()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_TriggersFetch

          +
          @Test
          +@DisplayName("call to getInputStream() triggers fetch")
          +public void test_getInputStream_TriggersFetch()
          +                                       throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_fetched_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to fetched() does not trigger fetch")
          +public void test_fetched_DoesNotTriggerFetch()
          +                                      throws Exception
          +
          Calls, that do not trigger a fetch
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_lastModified_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to lastModified() does not trigger fetch")
          +public void test_lastModified_DoesNotTriggerFetch()
          +                                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to contentLength() does not trigger fetch")
          +public void test_contentLength_DoesNotTriggerFetch()
          +                                            throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_expires_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to expires() does not trigger fetch")
          +public void test_expires_DoesNotTriggerFetch()
          +                                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isExpired_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to isExpired() does not trigger fetch")
          +public void test_isExpired_DoesNotTriggerFetch()
          +                                        throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_eTag_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to eTag() does not trigger fetch")
          +public void test_eTag_DoesNotTriggerFetch()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentType_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to contentType() does not trigger fetch")
          +public void test_contentType_DoesNotTriggerFetch()
          +                                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isNotFetched

          +
          @Test
          +@DisplayName("is fetched")
          +public void test_isNotFetched()
          +                       throws Exception
          +
          Results for calls, that does never trigger a fetch
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedLastModification

          +
          @Test
          +@DisplayName("has expected value for last modification")
          +public void test_hasExpectedLastModification()
          +                                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isNotModified

          +
          @Test
          +@DisplayName("is not modified")
          +public void test_isNotModified()
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedContentLength

          +
          @Test
          +@DisplayName("has expected content-length")
          +public void test_hasExpectedContentLength()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasInitialExpirationValue

          +
          @Test
          +@DisplayName("has expected expiration value")
          +public void test_hasInitialExpirationValue()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isNotExpired

          +
          @Test
          +@DisplayName("is expired")
          +public void test_isNotExpired()
          +                       throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedETag

          +
          @Test
          +@DisplayName("has expected eTag")
          +public void test_hasExpectedETag()
          +                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedContentType

          +
          @Test
          +@DisplayName("has expected content-type")
          +public void test_hasExpectedContentType()
          +                                 throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceFetcherTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceFetcherTest.html new file mode 100644 index 00000000..56ed5397 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceFetcherTest.html @@ -0,0 +1,1052 @@ + + + + + +HttpResourceFetcherTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceFetcherTest

    +
    +
    + +
    +
      +
    • +
      +
      public class HttpResourceFetcherTest
      +extends Object
      +
      Tests the inner class HttpResourceFetcher.
      +
      +
      Author:
      +
      Kai Moritz
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceFetcherTest

          +
          public HttpResourceFetcherTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          withServeStaleFalse

          +
          public void withServeStaleFalse()
          +
        • +
        + + + +
          +
        • +

          withServeStaleFalseAndMinTTL

          +
          public void withServeStaleFalseAndMinTTL()
          +
        • +
        + + + +
          +
        • +

          withServeStaleTrue

          +
          public void withServeStaleTrue()
          +
        • +
        + + + +
          +
        • +

          test_Fetch_Cached_Valid

          +
          @Test
          +@DisplayName("first request -- cached - valid")
          +public void test_Fetch_Cached_Valid()
          +                             throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_Cached_Expired

          +
          @Test
          +@DisplayName("first request -- cached - expired")
          +public void test_Fetch_Cached_Expired()
          +                               throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_Cached_NotFound

          +
          @Test
          +@DisplayName("first request -- cached - not found")
          +public void test_Fetch_Cached_NotFound()
          +                                throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_Cached_ServerError

          +
          @Test
          +@DisplayName("first request -- cached - server error")
          +public void test_Fetch_Cached_ServerError()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_NoHeaders_NoBody

          +
          @Test
          +@DisplayName("first request -- 200 - no headers / no body")
          +public void test_Fetch_200_NoHeaders_NoBody()
          +                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_NoHeaders

          +
          @Test
          +@DisplayName("first request -- 200 - no headers")
          +public void test_Fetch_200_NoHeaders()
          +                              throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP11

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.1")
          +public void test_Fetch_200_HTTP11()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP11_MinTTL

          +
          @Test
          +@DisplayName("first request + min-TTL -- 200 - HTTP/1.1")
          +public void test_Fetch_200_HTTP11_MinTTL()
          +                                  throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP11_DateMissing_

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.1 / Date-Header is missing")
          +public void test_Fetch_200_HTTP11_DateMissing_()
          +                                        throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP11_MaxAge0

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.1 / Cache-Control: public, max-age=0")
          +public void test_Fetch_200_HTTP11_MaxAge0()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP11_NoCache

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.1 / Cache-Control: no-cache")
          +public void test_Fetch_200_HTTP11_NoCache()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP11_NoCacheQualified

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.1 / Cache-Control: no-cache=\"Cookie\"")
          +public void test_Fetch_200_HTTP11_NoCacheQualified()
          +                                            throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP10

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.0")
          +public void test_Fetch_200_HTTP10()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP10_InvalidExpires

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.0 / invalid Expires-Header")
          +public void test_Fetch_200_HTTP10_InvalidExpires()
          +                                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_Mixed

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/mixed: Expires + Cache-Control: private")
          +public void test_Fetch_200_Mixed()
          +                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_Mixed_ExpiresOverwritten

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/mixed: Expires + Cache-Control: max-age")
          +public void test_Fetch_200_Mixed_ExpiresOverwritten()
          +                                             throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP11_Encoding

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.1 + Content-Encoding: gzip")
          +public void test_Fetch_200_HTTP11_Encoding()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_200_HTTP11_MustRevalidate

          +
          @Test
          +@DisplayName("first request -- 200 - HTTP/1.1 + Cache-Control: must-revalidate")
          +public void test_Fetch_200_HTTP11_MustRevalidate()
          +                                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_404_HTTP11

          +
          @Test
          +@DisplayName("first request -- 400 - HTTP/1.1")
          +public void test_Fetch_404_HTTP11()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_404_HTTP11_Cacheable

          +
          @Test
          +@DisplayName("first request -- 404 - HTTP/1.1 + Cache-Control: max-age")
          +public void test_Fetch_404_HTTP11_Cacheable()
          +                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_500_HTTP11

          +
          @Test
          +@DisplayName("first request -- 500 - HTTP/1.1")
          +public void test_Fetch_500_HTTP11()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Fetch_ServerDown

          +
          @Test
          +@DisplayName("first request -- server is down")
          +public void test_Fetch_ServerDown()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_Cached_Same_RequestIsExecuted

          +
          @Test
          +@DisplayName("update request -- cached - same -> request is executed")
          +public void test_Update_Cached_Same_RequestIsExecuted()
          +                                               throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_Cached_Valid

          +
          @Test
          +@DisplayName("update request -- cached - valid")
          +public void test_Update_Cached_Valid()
          +                              throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_Cached_Expired_RequestIsExecuted

          +
          @Test
          +@DisplayName("update request -- cached - expired -> request is executed")
          +public void test_Update_Cached_Expired_RequestIsExecuted()
          +                                                  throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_304

          +
          @Test
          +@DisplayName("update request -- 304: not modified")
          +public void test_Update_304()
          +                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_200

          +
          @Test
          +@DisplayName("update request -- 200: modified")
          +public void test_Update_200()
          +                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_404

          +
          @Test
          +@DisplayName("update request -- 404: not found")
          +public void test_Update_404()
          +                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_500

          +
          @Test
          +@DisplayName("update request -- 500: server error")
          +public void test_Update_500()
          +                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_MustRevalidate_304

          +
          @Test
          +@DisplayName("update request -- must revalidate / 304: not modified")
          +public void test_Update_MustRevalidate_304()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_MustRevalidate_500

          +
          @Test
          +@DisplayName("update request -- must-revalidate / 500: server error")
          +public void test_Update_MustRevalidate_500()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_404_ServeStale

          +
          @Test
          +@DisplayName("update request + serve-stale -- 404: not found")
          +public void test_Update_404_ServeStale()
          +                                throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_500_MustRevalidate_ServeStale

          +
          @Test
          +@DisplayName("update request + serve-stale -- must-revalidate / 500: server error")
          +public void test_Update_500_MustRevalidate_ServeStale()
          +                                               throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_Update_ServerDown

          +
          @Test
          +@DisplayName("update request -- server is down")
          +public void test_Update_ServerDown()
          +                            throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchModifiedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchModifiedTest.html new file mode 100644 index 00000000..682aa220 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchModifiedTest.html @@ -0,0 +1,368 @@ + + + + + +HttpResourceNotExpiredFetchModifiedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotExpiredFetchModifiedTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Fetched - Not Expired - Fetch: Modified")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotExpiredFetchModifiedTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotExpiredFetchModifiedTest

          +
          public HttpResourceNotExpiredFetchModifiedTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_TriggersFetch

          +
          @Test
          +@DisplayName("call to fetch() triggers fetch")
          +public void test_fetch_TriggersFetch()
          +
          Calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReturnsTrueIfFetcherReturnedFalse

          +
          @Test
          +@DisplayName("fetch() returns true, if fetcher returned true")
          +public void test_fetch_ReturnsTrueIfFetcherReturnedFalse()
          +
          Results for calls, that does trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls that trigger a fetch
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchNotFoundTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchNotFoundTest.html new file mode 100644 index 00000000..d34d353e --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchNotFoundTest.html @@ -0,0 +1,368 @@ + + + + + +HttpResourceNotExpiredFetchNotFoundTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotExpiredFetchNotFoundTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Fetched - Not Expired - Fetch: NotFound")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotExpiredFetchNotFoundTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotExpiredFetchNotFoundTest

          +
          public HttpResourceNotExpiredFetchNotFoundTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_TriggersFetch

          +
          @Test
          +@DisplayName("call to fetch() triggers fetch")
          +public void test_fetch_TriggersFetch()
          +
          Calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReturnsTrueIfFetcherReturnedFalse

          +
          @Test
          +@DisplayName("fetch() returns true, if fetcher returned true")
          +public void test_fetch_ReturnsTrueIfFetcherReturnedFalse()
          +
          Results for calls, that does trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls that trigger a fetch
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchServerErrorTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchServerErrorTest.html new file mode 100644 index 00000000..80c775f6 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchServerErrorTest.html @@ -0,0 +1,368 @@ + + + + + +HttpResourceNotExpiredFetchServerErrorTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotExpiredFetchServerErrorTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Fetched - Not Expired - Fetch: Server Error")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotExpiredFetchServerErrorTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotExpiredFetchServerErrorTest

          +
          public HttpResourceNotExpiredFetchServerErrorTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_TriggersFetch

          +
          @Test
          +@DisplayName("call to fetch() triggers fetch")
          +public void test_fetch_TriggersFetch()
          +
          Calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReturnsTrueIfFetcherReturnedFalse

          +
          @Test
          +@DisplayName("fetch() returns true, if fetcher returned true")
          +public void test_fetch_ReturnsTrueIfFetcherReturnedFalse()
          +
          Results for calls, that does trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls that trigger a fetch
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchUnmodifiedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchUnmodifiedTest.html new file mode 100644 index 00000000..6a05e444 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredFetchUnmodifiedTest.html @@ -0,0 +1,349 @@ + + + + + +HttpResourceNotExpiredFetchUnmodifiedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotExpiredFetchUnmodifiedTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceNotExpiredFetchUnmodifiedTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Fetched - Not Expired - Fetch: Unmodified")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotExpiredFetchUnmodifiedTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotExpiredFetchUnmodifiedTest

          +
          public HttpResourceNotExpiredFetchUnmodifiedTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReturnsFalseIfFetcherReturnedFalse

          +
          @Test
          +@DisplayName("fetch() returns false, if fetcher returned false")
          +public void test_fetch_ReturnsFalseIfFetcherReturnedFalse()
          +
          Results for calls, that does trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls that trigger a fetch
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredTest.html new file mode 100644 index 00000000..5b8f7c71 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotExpiredTest.html @@ -0,0 +1,741 @@ + + + + + +HttpResourceNotExpiredTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotExpiredTest

    +
    +
    + +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Not Expired")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotExpiredTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotExpiredTest

          +
          public HttpResourceNotExpiredTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_TriggersFetch

          +
          @Test
          +@DisplayName("call to fetch() triggers fetch")
          +public void test_fetch_TriggersFetch()
          +
          Calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_fetched_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to fetched() does not trigger fetch")
          +public void test_fetched_DoesNotTriggerFetch()
          +                                      throws Exception
          +
          Calls, that do not trigger a fetch
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_lastModified_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to lastModified() does not trigger fetch")
          +public void test_lastModified_DoesNotTriggerFetch()
          +                                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isModified_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to isModified() does not trigger fetch")
          +public void test_isModified_DoesNotTriggerFetch()
          +                                         throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to getInputStream() does not trigger fetch")
          +public void test_getInputStream_DoesNotTriggerFetch()
          +                                             throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to contentLength() does not trigger fetch")
          +public void test_contentLength_DoesNotTriggerFetch()
          +                                            throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_expires_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to expires() does not trigger fetch")
          +public void test_expires_DoesNotTriggerFetch()
          +                                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isExpired_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to isExpired() does not trigger fetch")
          +public void test_isExpired_DoesNotTriggerFetch()
          +                                        throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_eTag_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to eTag() does not trigger fetch")
          +public void test_eTag_DoesNotTriggerFetch()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentType_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to contentType() does not trigger fetch")
          +public void test_contentType_DoesNotTriggerFetch()
          +                                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isNotFetched

          +
          @Test
          +@DisplayName("is fetched")
          +public void test_isNotFetched()
          +                       throws Exception
          +
          Results for calls, that does never trigger a fetch
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_exists_IsTrue

          +
          @Test
          +@DisplayName("exists")
          +public void test_exists_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_IsTrue

          +
          @Test
          +@DisplayName("is readable")
          +public void test_isReadable_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedLastModification

          +
          @Test
          +@DisplayName("has expected value for last modification")
          +public void test_hasExpectedLastModification()
          +                                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isNotModified

          +
          @Test
          +@DisplayName("is not modified")
          +public void test_isNotModified()
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedContent

          +
          @Test
          +@DisplayName("has expected content")
          +public void test_hasExpectedContent()
          +                             throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedContentLength

          +
          @Test
          +@DisplayName("has expected content-length")
          +public void test_hasExpectedContentLength()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasInitialExpirationValue

          +
          @Test
          +@DisplayName("has expected expiration value")
          +public void test_hasInitialExpirationValue()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isNotExpired

          +
          @Test
          +@DisplayName("is not expired")
          +public void test_isNotExpired()
          +                       throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedETag

          +
          @Test
          +@DisplayName("has expected eTag")
          +public void test_hasExpectedETag()
          +                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasExpectedContentType

          +
          @Test
          +@DisplayName("has expected content-type")
          +public void test_hasExpectedContentType()
          +                                 throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchNotFoundTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchNotFoundTest.html new file mode 100644 index 00000000..2f005946 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchNotFoundTest.html @@ -0,0 +1,571 @@ + + + + + +HttpResourceNotFetchedFirstFetchNotFoundTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotFetchedFirstFetchNotFoundTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Not Fetched - First Fetch: Not Found")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotFetchedFirstFetchNotFoundTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotFetchedFirstFetchNotFoundTest

          +
          public HttpResourceNotFetchedFirstFetchNotFoundTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReportsModifications

          +
          @Test
          +@DisplayName("fetch() reports modifications")
          +public void test_fetch_ReportsModifications()
          +
          Results for calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_IsFalse

          +
          @Test
          +@DisplayName("exists() is false")
          +public void test_exists_IsFalse()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_IsFalse

          +
          @Test
          +@DisplayName("isReadable() is false")
          +public void test_isReadable_IsFalse()
          +
        • +
        + + + +
          +
        • +

          test_lastModified_ReturnsExpectedTime

          +
          @Test
          +@DisplayName("lastModified() returns the expected time")
          +public void test_lastModified_ReturnsExpectedTime()
          +                                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isModified_IsTrue

          +
          @Test
          +@DisplayName("isModified() if true")
          +public void test_isModified_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_ThrowsFileNotFoundException

          +
          @Test
          +@DisplayName("getInputStream() throws FileNotFoundException")
          +public void test_getInputStream_ThrowsFileNotFoundException()
          +                                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_ThrowsFileNotFoundException

          +
          @Test
          +@DisplayName("contentLength() throws FileNotFoundException")
          +public void test_contentLength_ThrowsFileNotFoundException()
          +                                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("call to fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_UpdatesData

          +
          @Test
          +@DisplayName("call to exists() updates data")
          +public void test_exists_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_UpdatesData

          +
          @Test
          +@DisplayName("call to isReadable() updates data")
          +public void test_isReadable_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_lastModified_UpdatesData

          +
          @Test
          +@DisplayName("call to lastModified() updates data")
          +public void test_lastModified_UpdatesData()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isModified_UpdatesData

          +
          @Test
          +@DisplayName("call to isModified() updates data")
          +public void test_isModified_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_UpdatesData

          +
          @Test
          +@DisplayName("call to getInputStream() updates data")
          +public void test_getInputStream_UpdatesData()
          +                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_UpdatesData

          +
          @Test
          +@DisplayName("call to contentLength() updates data")
          +public void test_contentLength_UpdatesData()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchServerErrorTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchServerErrorTest.html new file mode 100644 index 00000000..9502dac2 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchServerErrorTest.html @@ -0,0 +1,571 @@ + + + + + +HttpResourceNotFetchedFirstFetchServerErrorTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotFetchedFirstFetchServerErrorTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Not Fetched - First Fetch: Server Error")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotFetchedFirstFetchServerErrorTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotFetchedFirstFetchServerErrorTest

          +
          public HttpResourceNotFetchedFirstFetchServerErrorTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReportsModifications

          +
          @Test
          +@DisplayName("fetch() reports modifications")
          +public void test_fetch_ReportsModifications()
          +
          Results for calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_IsFalse

          +
          @Test
          +@DisplayName("exists() is false")
          +public void test_exists_IsFalse()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_IsFalse

          +
          @Test
          +@DisplayName("isReadable() is false")
          +public void test_isReadable_IsFalse()
          +
        • +
        + + + +
          +
        • +

          test_lastModified_ReturnsExpectedTime

          +
          @Test
          +@DisplayName("lastModified() returns the expected time")
          +public void test_lastModified_ReturnsExpectedTime()
          +                                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isModified_IsTrue

          +
          @Test
          +@DisplayName("isModified() if true")
          +public void test_isModified_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_ThrowsFileNotFoundException

          +
          @Test
          +@DisplayName("getInputStream() throws FileNotFoundException")
          +public void test_getInputStream_ThrowsFileNotFoundException()
          +                                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_ThrowsFileNotFoundException

          +
          @Test
          +@DisplayName("contentLength() throws FileNotFoundException")
          +public void test_contentLength_ThrowsFileNotFoundException()
          +                                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("call to fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_UpdatesData

          +
          @Test
          +@DisplayName("call to exists() updates data")
          +public void test_exists_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_UpdatesData

          +
          @Test
          +@DisplayName("call to isReadable() updates data")
          +public void test_isReadable_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_lastModified_UpdatesData

          +
          @Test
          +@DisplayName("call to lastModified() updates data")
          +public void test_lastModified_UpdatesData()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isModified_UpdatesData

          +
          @Test
          +@DisplayName("call to isModified() updates data")
          +public void test_isModified_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_UpdatesData

          +
          @Test
          +@DisplayName("call to getInputStream() updates data")
          +public void test_getInputStream_UpdatesData()
          +                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_UpdatesData

          +
          @Test
          +@DisplayName("call to contentLength() updates data")
          +public void test_contentLength_UpdatesData()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchSuccessfulTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchSuccessfulTest.html new file mode 100644 index 00000000..48502e36 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchSuccessfulTest.html @@ -0,0 +1,571 @@ + + + + + +HttpResourceNotFetchedFirstFetchSuccessfulTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotFetchedFirstFetchSuccessfulTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Not Fetched - First Fetch: Successfull")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotFetchedFirstFetchSuccessfulTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotFetchedFirstFetchSuccessfulTest

          +
          public HttpResourceNotFetchedFirstFetchSuccessfulTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_ReportsModifications

          +
          @Test
          +@DisplayName("fetch() reports modifications")
          +public void test_fetch_ReportsModifications()
          +
          Results for calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_IsTrue

          +
          @Test
          +@DisplayName("exists() is true")
          +public void test_exists_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_IsTrue

          +
          @Test
          +@DisplayName("isReadable() is true")
          +public void test_isReadable_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_lastModified_ReturnsExpectedTime

          +
          @Test
          +@DisplayName("lastModified() returns the expected time")
          +public void test_lastModified_ReturnsExpectedTime()
          +                                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isModified_IsTrue

          +
          @Test
          +@DisplayName("isModified() is true")
          +public void test_isModified_IsTrue()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_TriggersFetch

          +
          @Test
          +@DisplayName("getInputStream() returns expected content")
          +public void test_getInputStream_TriggersFetch()
          +                                       throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_ReturnsExpectedLength

          +
          @Test
          +@DisplayName("contentLength() returns expected content-length")
          +public void test_contentLength_ReturnsExpectedLength()
          +                                              throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_fetch_UpdatesData

          +
          @Test
          +@DisplayName("call to fetch() updates data")
          +public void test_fetch_UpdatesData()
          +
          Expected state after calls that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_UpdatesData

          +
          @Test
          +@DisplayName("call to exists() updates data")
          +public void test_exists_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_UpdatesData

          +
          @Test
          +@DisplayName("call to isReadable() updates data")
          +public void test_isReadable_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_lastModified_UpdatesData

          +
          @Test
          +@DisplayName("call to lastModified() updates data")
          +public void test_lastModified_UpdatesData()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isModified_UpdatesData

          +
          @Test
          +@DisplayName("call to isModified() updates data")
          +public void test_isModified_UpdatesData()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_UpdatesData

          +
          @Test
          +@DisplayName("call to getInputStream() updates data")
          +public void test_getInputStream_UpdatesData()
          +                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_UpdatesData

          +
          @Test
          +@DisplayName("call to contentLength() updates data")
          +public void test_contentLength_UpdatesData()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedTest.html new file mode 100644 index 00000000..b8ee013f --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceNotFetchedTest.html @@ -0,0 +1,657 @@ + + + + + +HttpResourceNotFetchedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceNotFetchedTest

    +
    +
    + +
    +
      +
    • +
      +
      @DisplayName("HttpResource - Not Fetched")
      +@ExtendWith({org.springframework.test.context.junit.jupiter.SpringExtension.class,org.mockito.junit.jupiter.MockitoExtension.class})
      +public class HttpResourceNotFetchedTest
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceNotFetchedTest

          +
          public HttpResourceNotFetchedTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
          SETUP
          +
        • +
        + + + +
          +
        • +

          test_fetch_TriggersFetch

          +
          @Test
          +@DisplayName("call to fetch() triggers fetch")
          +public void test_fetch_TriggersFetch()
          +
          Calls, that trigger a fetch
          +
        • +
        + + + +
          +
        • +

          test_exists_TriggersFetch

          +
          @Test
          +@DisplayName("call to exists() triggers fetch")
          +public void test_exists_TriggersFetch()
          +
        • +
        + + + +
          +
        • +

          test_isReadable_TriggersFetch

          +
          @Test
          +@DisplayName("call to isReadable() triggers fetch")
          +public void test_isReadable_TriggersFetch()
          +
        • +
        + + + +
          +
        • +

          test_lastModified_TriggersFetch

          +
          @Test
          +@DisplayName("call to lastModified() triggers fetch")
          +public void test_lastModified_TriggersFetch()
          +                                     throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isModified_TriggersFetch

          +
          @Test
          +@DisplayName("call to isModified() triggers fetch")
          +public void test_isModified_TriggersFetch()
          +
        • +
        + + + +
          +
        • +

          test_getInputStream_TriggersFetch

          +
          @Test
          +@DisplayName("call to getInputStream() triggers fetch")
          +public void test_getInputStream_TriggersFetch()
          +                                       throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentLength_TriggersFetch

          +
          @Test
          +@DisplayName("call to contentLength() does trigger fetch")
          +public void test_contentLength_TriggersFetch()
          +                                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_fetched_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to fetched() does not trigger fetch")
          +public void test_fetched_DoesNotTriggerFetch()
          +                                      throws Exception
          +
          Calls, that do not trigger a fetch
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_expires_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to expires() does not trigger fetch")
          +public void test_expires_DoesNotTriggerFetch()
          +                                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isExpired_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to isExpired() does not trigger fetch")
          +public void test_isExpired_DoesNotTriggerFetch()
          +                                        throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_eTag_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to eTag() does not trigger fetch")
          +public void test_eTag_DoesNotTriggerFetch()
          +                                   throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_contentType_DoesNotTriggerFetch

          +
          @Test
          +@DisplayName("call to contentType() does not trigger fetch")
          +public void test_contentType_DoesNotTriggerFetch()
          +                                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isNotFetched

          +
          @Test
          +@DisplayName("is not fetched")
          +public void test_isNotFetched()
          +                       throws Exception
          +
          Initial results for calls, that does not trigger a fetch
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasInitialExpirationValue

          +
          @Test
          +@DisplayName("has Long.MIN_VALUE as initial expiration value")
          +public void test_hasInitialExpirationValue()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_isExpired

          +
          @Test
          +@DisplayName("is expired")
          +public void test_isExpired()
          +                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasNoETag

          +
          @Test
          +@DisplayName("has no eTag")
          +public void test_hasNoETag()
          +                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          test_hasNoContentType

          +
          @Test
          +@DisplayName("has no content-type")
          +public void test_hasNoContentType()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverIT.Application.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverIT.Application.html new file mode 100644 index 00000000..a9cf28c7 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverIT.Application.html @@ -0,0 +1,326 @@ + + + + + +HttpResourceProtocolResolverIT.Application (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceProtocolResolverIT.Application

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceProtocolResolverIT.Application
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      org.springframework.web.servlet.config.annotation.WebMvcConfigurer
      +
      +
      +
      Enclosing class:
      +
      HttpResourceProtocolResolverIT
      +
      +
      +
      @SpringBootApplication
      +public static class HttpResourceProtocolResolverIT.Application
      +extends Object
      +implements org.springframework.web.servlet.config.annotation.WebMvcConfigurer
      +
    • +
    +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Summary

        + + + + + + + + + + +
        Constructors 
        ConstructorDescription
        Application() 
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethodDescription
        voidaddResourceHandlers​(org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry registry) 
        + +
          +
        • + + +

          Methods inherited from interface org.springframework.web.servlet.config.annotation.WebMvcConfigurer

          +addArgumentResolvers, addCorsMappings, addFormatters, addInterceptors, addReturnValueHandlers, addViewControllers, configureAsyncSupport, configureContentNegotiation, configureDefaultServletHandling, configureHandlerExceptionResolvers, configureMessageConverters, configurePathMatch, configureViewResolvers, extendHandlerExceptionResolvers, extendMessageConverters, getMessageCodesResolver, getValidator
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Application

          +
          public Application()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          addResourceHandlers

          +
          public void addResourceHandlers​(org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry registry)
          +
          +
          Specified by:
          +
          addResourceHandlers in interface org.springframework.web.servlet.config.annotation.WebMvcConfigurer
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverIT.html new file mode 100644 index 00000000..60c0c7d6 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverIT.html @@ -0,0 +1,502 @@ + + + + + +HttpResourceProtocolResolverIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceProtocolResolverIT

    +
    +
    + +
    +
      +
    • +
      +
      @SpringBootTest({"juplo.http-resources.protocol-resolver.enabled=true","juplo.http-resources.resolver.enabled=false","juplo.http-resources.resolver.exclusion-patterns=**.txt"})
      +public class HttpResourceProtocolResolverIT
      +extends IntegrationTestBase
      +
      Mostly identically with HttpResourceResolverIT. + Differences:Test explicit lookup with full address through context and has + no exclusion/inclusion.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceProtocolResolverIT

          +
          public HttpResourceProtocolResolverIT()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
        • +
        + + + +
          +
        • +

          testResourceHandling

          +
          @Test
          +public void testResourceHandling()
          +                          throws Exception
          +
          Olthough the is not enabled in this test-scenario, + this works nearly, identically to the same test there, because all lookups + for resources in the resource-chain for static http-resources are executed + through the application-context, where the + HttpResourceProtocolResolver is registerd. + Only exclusion is not working, since this is only implemented in the + .
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testFetchExistent

          +
          @Test
          +public void testFetchExistent()
          +                       throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testCachingOfExisting

          +
          @Test
          +public void testCachingOfExisting()
          +                           throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testFetchNonExistent

          +
          @Test
          +public void testFetchNonExistent()
          +                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testCachingOfNonExistent

          +
          @Test
          +public void testCachingOfNonExistent()
          +                              throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testModifiedResource

          +
          @Test
          +public void testModifiedResource()
          +                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverTest.html new file mode 100644 index 00000000..429a6a96 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourceProtocolResolverTest.html @@ -0,0 +1,355 @@ + + + + + +HttpResourceProtocolResolverTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourceProtocolResolverTest

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.HttpResourceProtocolResolverTest
      • +
      +
    • +
    +
    +
      +
    • +
      +
      public class HttpResourceProtocolResolverTest
      +extends Object
      +
      +
      Author:
      +
      kai
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourceProtocolResolverTest

          +
          public HttpResourceProtocolResolverTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          public void setUp()
          +
        • +
        + + + +
          +
        • +

          testHttpResource

          +
          public void testHttpResource​(org.springframework.core.io.ResourceLoader loader,
          +                             HttpResource resource)
          +
        • +
        + + + +
          +
        • +

          testHttpsResource

          +
          public void testHttpsResource​(org.springframework.core.io.ResourceLoader loader,
          +                              HttpResource resource)
          +
        • +
        + + + +
          +
        • +

          testClasspathResource

          +
          public void testClasspathResource​(org.springframework.core.io.ResourceLoader loader)
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourcesIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourcesIT.html new file mode 100644 index 00000000..b5f51215 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourcesIT.html @@ -0,0 +1,497 @@ + + + + + +HttpResourcesIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourcesIT

    +
    +
    + +
    +
      +
    • +
      +
      @SpringBootTest
      +public class HttpResourcesIT
      +extends IntegrationTestBase
      +
      +
      Author:
      +
      Kai Moritz
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourcesIT

          +
          public HttpResourcesIT()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          clearCache

          +
          @BeforeEach
          +public void clearCache()
          +
        • +
        + + + +
          +
        • +

          testFetchExistent

          +
          @Test
          +public void testFetchExistent()
          +                       throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testFetchNonExistent

          +
          @Test
          +public void testFetchNonExistent()
          +                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testFetchServerResponse500

          +
          @Test
          +public void testFetchServerResponse500()
          +                                throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testCaching

          +
          @Test
          +public void testCaching()
          +                 throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testFetchEncoded

          +
          @Test
          +public void testFetchEncoded()
          +                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testModifiedResource

          +
          @Test
          +public void testModifiedResource()
          +                          throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testModifiedResourceAccessOnly

          +
          @Test
          +public void testModifiedResourceAccessOnly()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourcesTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourcesTest.html new file mode 100644 index 00000000..65b7d39b --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/HttpResourcesTest.html @@ -0,0 +1,445 @@ + + + + + +HttpResourcesTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class HttpResourcesTest

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HttpResourcesTest

          +
          public HttpResourcesTest()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          testGetResource

          +
          @Test
          +public void testGetResource()
          +
        • +
        + + + +
          +
        • +

          testCreateRelative

          +
          @Test
          +@DisplayName("createRelative()")
          +public void testCreateRelative​(HttpResourceFetcher fetcher)
          +                        throws Exception
          +
          This test only checks the integration of the used methods + Detailed tests for URI-handling are implemented in + HttpResourcesUriHandlingTest.
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testConvertValid

          +
          public void testConvertValid()
          +                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testConvertInvalid

          +
          public void testConvertInvalid()
          +                        throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testResolveValid

          +
          public void testResolveValid()
          +                      throws IOException
          +
          Checks the resolving of normal examples, with enabled enforcment of a + relative path.
          +
          +
          Throws:
          +
          IOException
          +
          +
        • +
        + + + +
          +
        • +

          testResolveInvalid

          +
          public void testResolveInvalid()
          +                        throws IOException
          +
          Checks the resolving of normal examples, with enabled enforcment of a + relative path.
          +
          +
          Throws:
          +
          IOException
          +
          +
        • +
        + + + +
          +
        • +

          testHostWithoutTrailingSlash

          +
          public void testHostWithoutTrailingSlash()
          +                                  throws IOException
          +
          +
          Throws:
          +
          IOException
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.Callback.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.Callback.html new file mode 100644 index 00000000..4b650490 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.Callback.html @@ -0,0 +1,348 @@ + + + + + +IntegrationTestBase.Callback (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class IntegrationTestBase.Callback

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.IntegrationTestBase.Callback
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      org.mockserver.mock.action.ExpectationCallback<org.mockserver.model.HttpRequest>, org.mockserver.mock.action.ExpectationForwardAndResponseCallback, org.mockserver.mock.action.ExpectationForwardCallback
      +
      +
      +
      Enclosing class:
      +
      IntegrationTestBase
      +
      +
      +
      public static class IntegrationTestBase.Callback
      +extends Object
      +implements org.mockserver.mock.action.ExpectationForwardAndResponseCallback
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Callback

          +
          public Callback()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          handle

          +
          public org.mockserver.model.HttpRequest handle​(org.mockserver.model.HttpRequest request)
          +                                        throws Exception
          +
          +
          Specified by:
          +
          handle in interface org.mockserver.mock.action.ExpectationCallback<org.mockserver.model.HttpRequest>
          +
          Specified by:
          +
          handle in interface org.mockserver.mock.action.ExpectationForwardAndResponseCallback
          +
          Specified by:
          +
          handle in interface org.mockserver.mock.action.ExpectationForwardCallback
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          handle

          +
          public org.mockserver.model.HttpResponse handle​(org.mockserver.model.HttpRequest request,
          +                                                org.mockserver.model.HttpResponse response)
          +                                         throws Exception
          +
          +
          Specified by:
          +
          handle in interface org.mockserver.mock.action.ExpectationForwardAndResponseCallback
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.ClockStub.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.ClockStub.html new file mode 100644 index 00000000..84764c9f --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.ClockStub.html @@ -0,0 +1,445 @@ + + + + + +IntegrationTestBase.ClockStub (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class IntegrationTestBase.ClockStub

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
      + +
      + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ClockStub

          +
          public ClockStub()
          +
        • +
        +
      • +
      +
      + +
      + +
      +
    • +
    +
    +
    +
    + + + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.IntegrationTestConfiguration.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.IntegrationTestConfiguration.html new file mode 100644 index 00000000..bfe5eecf --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.IntegrationTestConfiguration.html @@ -0,0 +1,356 @@ + + + + + +IntegrationTestBase.IntegrationTestConfiguration (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class IntegrationTestBase.IntegrationTestConfiguration

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      IntegrationTestBase
      +
      +
      +
      @Configuration
      +public static class IntegrationTestBase.IntegrationTestConfiguration
      +extends Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          IntegrationTestConfiguration

          +
          public IntegrationTestConfiguration()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          server

          +
          @Bean(destroyMethod="stop")
          +public org.mockserver.integration.ClientAndServer server()
          +
        • +
        + + + +
          +
        • +

          fetcher

          +
          @Bean
          +public HttpResourceFetcher fetcher​(org.springframework.cache.Cache cache)
          +
        • +
        + + + +
          +
        • +

          cache

          +
          @Bean
          +public org.springframework.cache.Cache cache()
          +
        • +
        + + + + +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.html new file mode 100644 index 00000000..c6685b95 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/IntegrationTestBase.html @@ -0,0 +1,632 @@ + + + + + +IntegrationTestBase (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class IntegrationTestBase

    +
    +
    + +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      HttpResourceChainAwareResourceLoaderIT, HttpResourceProtocolResolverIT, HttpResourcesIT, ThymeleafWithHttpResourceProtocolResolverIT, VersionedResourcesIT
      +
      +
      +
      public abstract class IntegrationTestBase
      +extends Object
      +
      This class starts a + {@link https://www.testcontainers.org/modules/nginx/ NginX-Webserver} + via a {@link https://www.testcontainers.org/ Testcontainer} and a + standalone {@link http://www.mock-server.com/#what-is-mockserver MockServer}, + that can be used to intercept requests for assertions / verifications. +

      + We use the {@link + https://www.testcontainers.org/test_framework_integration/manual_lifecycle_control/#singleton-containers + Singleton Pattern} to start the NginX-Testcontainer and start the MockServer + programmatically via the {@link + http://www.mock-server.com/mock_server/running_mock_server.html#client_api + Client-API}.

      +
      +
      Author:
      +
      Kai Moritz
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Field Detail

        + + + + + + + + + + + +
          +
        • +

          NGINX

          +
          public static final org.testcontainers.containers.NginxContainer NGINX
          +
        • +
        + + + +
          +
        • +

          server

          +
          @Autowired
          +public org.mockserver.integration.ClientAndServer server
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          IntegrationTestBase

          +
          public IntegrationTestBase()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          NGINIX_IP

          +
          public static String NGINIX_IP()
          +
        • +
        + + + +
          +
        • +

          NGINX_PORT

          +
          public static int NGINX_PORT()
          +
        • +
        + + + +
          +
        • +

          NGINX_URI

          +
          public static String NGINX_URI()
          +
        • +
        + + + +
          +
        • +

          FETCH

          +
          public static org.mockserver.model.HttpRequest FETCH​(String path)
          +
        • +
        + + + +
          +
        • +

          RESPONSE

          +
          public static org.mockserver.model.HttpResponse RESPONSE()
          +
        • +
        + + + +
          +
        • +

          NGINX

          +
          public static org.mockserver.model.HttpOverrideForwardedRequest NGINX()
          +
        • +
        + + + +
          +
        • +

          NGINX

          +
          public static org.mockserver.model.HttpOverrideForwardedRequest NGINX​(String path)
          +
        • +
        + + + +
          +
        • +

          NOT_FOUND

          +
          public static org.mockserver.model.HttpResponse NOT_FOUND()
          +
        • +
        + + + +
          +
        • +

          INTERNAL_SERVER_ERROR

          +
          public static org.mockserver.model.HttpResponse INTERNAL_SERVER_ERROR()
          +
        • +
        + + + +
          +
        • +

          prepareMockServer

          +
          @BeforeEach
          +public void prepareMockServer()
          +
          Prepares the mock-server to forward any request to the NginX-server, + for which no more specific expectation was specified.
          +
        • +
        + + + +
          +
        • +

          clearMockServer

          +
          @AfterEach
          +public void clearMockServer()
          +
        • +
        + + + +
          +
        • +

          getMockServerPort

          +
          public int getMockServerPort()
          +
        • +
        + + + +
          +
        • +

          getMockServerUri

          +
          public String getMockServerUri()
          +
        • +
        + + + + +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/TestUtil.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/TestUtil.html new file mode 100644 index 00000000..47ad1b6d --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/TestUtil.html @@ -0,0 +1,271 @@ + + + + + +TestUtil (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class TestUtil

    +
    +
    + +
    +
      +
    • +
      +
      public class TestUtil
      +extends Object
      +
      +
      Author:
      +
      Kai Moritz
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          TestUtil

          +
          public TestUtil()
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.Application.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.Application.html new file mode 100644 index 00000000..d5f85585 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.Application.html @@ -0,0 +1,364 @@ + + + + + +ThymeleafWithHttpResourceProtocolResolverIT.Application (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class ThymeleafWithHttpResourceProtocolResolverIT.Application

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.Application
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      org.springframework.web.servlet.config.annotation.WebMvcConfigurer
      +
      +
      +
      Enclosing class:
      +
      ThymeleafWithHttpResourceProtocolResolverIT
      +
      +
      +
      @SpringBootApplication
      +public static class ThymeleafWithHttpResourceProtocolResolverIT.Application
      +extends Object
      +implements org.springframework.web.servlet.config.annotation.WebMvcConfigurer
      +
    • +
    +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Summary

        + + + + + + + + + + +
        Constructors 
        ConstructorDescription
        Application() 
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethodDescription
        voidaddResourceHandlers​(org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry registry) 
        org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolverdefaultTemplateResolver​(org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties properties, + org.springframework.context.ApplicationContext applicationContext, + org.mockserver.integration.ClientAndServer server) +
        This mimics the autoconfiguration of Thymeleaf in Spring-Boot.
        +
        ThymeleafWithHttpResourceProtocolResolverIT.TestControllertestController() 
        + +
          +
        • + + +

          Methods inherited from interface org.springframework.web.servlet.config.annotation.WebMvcConfigurer

          +addArgumentResolvers, addCorsMappings, addFormatters, addInterceptors, addReturnValueHandlers, addViewControllers, configureAsyncSupport, configureContentNegotiation, configureDefaultServletHandling, configureHandlerExceptionResolvers, configureMessageConverters, configurePathMatch, configureViewResolvers, extendHandlerExceptionResolvers, extendMessageConverters, getMessageCodesResolver, getValidator
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Application

          +
          public Application()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          defaultTemplateResolver

          +
          @Bean
          +public org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver defaultTemplateResolver​(org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties properties,
          +                                                                                                     org.springframework.context.ApplicationContext applicationContext,
          +                                                                                                     org.mockserver.integration.ClientAndServer server)
          +
          This mimics the autoconfiguration of Thymeleaf in Spring-Boot. + Reason: Found no other way to inject the property spring.thymeleaf.prefix dynamically
          +
        • +
        + + + + + + + +
          +
        • +

          addResourceHandlers

          +
          public void addResourceHandlers​(org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry registry)
          +
          +
          Specified by:
          +
          addResourceHandlers in interface org.springframework.web.servlet.config.annotation.WebMvcConfigurer
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.TestController.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.TestController.html new file mode 100644 index 00000000..aefd605d --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.TestController.html @@ -0,0 +1,314 @@ + + + + + +ThymeleafWithHttpResourceProtocolResolverIT.TestController (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class ThymeleafWithHttpResourceProtocolResolverIT.TestController

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.TestController
      • +
      +
    • +
    +
    + +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          TestController

          +
          public TestController()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          controller

          +
          @RequestMapping("/controller.html")
          +public String controller​(@RequestParam
          +                         String template,
          +                         org.springframework.ui.Model model)
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.html new file mode 100644 index 00000000..471fc703 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.html @@ -0,0 +1,463 @@ + + + + + +ThymeleafWithHttpResourceProtocolResolverIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class ThymeleafWithHttpResourceProtocolResolverIT

    +
    +
    + +
    +
      +
    • +
      +
      @SpringBootTest({"juplo.http-resources.protocol-resolver.enabled=true","spring.thymeleaf.cache=true"})
      +public class ThymeleafWithHttpResourceProtocolResolverIT
      +extends IntegrationTestBase
      +
      This test-case showcases the usage of the HttpResourceProtocolResolver + with Thymeleaf. + + Since Thymeleaf does not use the Resource-Chain mechanism, that Spring introduced + for the handling of static resources, the HttpResourceProtocolResolver has + to be used and the protocol has to be hardwired into the configuration as + spring.thymeleaf.prefix. + The downside of this approach is, that the templates are only resolved against + the configured remote-URI and do not take part in the fallback-mechanism, that + can be configured through spring.resources.static-locations. + + The test-case was addapted accordingly, to show the changed behaviour.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ThymeleafWithHttpResourceProtocolResolverIT

          +
          public ThymeleafWithHttpResourceProtocolResolverIT()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
        • +
        + + + +
          +
        • +

          testRenderLocalTemplate

          +
          @Test
          +public void testRenderLocalTemplate()
          +                             throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testRenderRemoteTemplate

          +
          @Test
          +public void testRenderRemoteTemplate()
          +                              throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testRenderCachedRemoteTemplate

          +
          @Test
          +public void testRenderCachedRemoteTemplate()
          +                                    throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        + + + +
          +
        • +

          testRenderModifiedRemoteTemplate

          +
          @Test
          +public void testRenderModifiedRemoteTemplate()
          +                                      throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/VersionedResourcesIT.Application.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/VersionedResourcesIT.Application.html new file mode 100644 index 00000000..e8d292cd --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/VersionedResourcesIT.Application.html @@ -0,0 +1,356 @@ + + + + + +VersionedResourcesIT.Application (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class VersionedResourcesIT.Application

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • de.juplo.httpresources.VersionedResourcesIT.Application
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      org.springframework.web.servlet.config.annotation.WebMvcConfigurer
      +
      +
      +
      Enclosing class:
      +
      VersionedResourcesIT
      +
      +
      +
      @SpringBootApplication
      +public static class VersionedResourcesIT.Application
      +extends Object
      +implements org.springframework.web.servlet.config.annotation.WebMvcConfigurer
      +
    • +
    +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Summary

        + + + + + + + + + + +
        Constructors 
        ConstructorDescription
        Application() 
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethodDescription
        voidaddResourceHandlers​(org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry registry) 
        Clockclock() 
        org.springframework.web.servlet.resource.VersionResourceResolverversionResourceResolver() 
        + +
          +
        • + + +

          Methods inherited from interface org.springframework.web.servlet.config.annotation.WebMvcConfigurer

          +addArgumentResolvers, addCorsMappings, addFormatters, addInterceptors, addReturnValueHandlers, addViewControllers, configureAsyncSupport, configureContentNegotiation, configureDefaultServletHandling, configureHandlerExceptionResolvers, configureMessageConverters, configurePathMatch, configureViewResolvers, extendHandlerExceptionResolvers, extendMessageConverters, getMessageCodesResolver, getValidator
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Application

          +
          public Application()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          clock

          +
          @Bean
          +public Clock clock()
          +
        • +
        + + + +
          +
        • +

          versionResourceResolver

          +
          @Bean
          +public org.springframework.web.servlet.resource.VersionResourceResolver versionResourceResolver()
          +
        • +
        + + + +
          +
        • +

          addResourceHandlers

          +
          public void addResourceHandlers​(org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry registry)
          +
          +
          Specified by:
          +
          addResourceHandlers in interface org.springframework.web.servlet.config.annotation.WebMvcConfigurer
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/VersionedResourcesIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/VersionedResourcesIT.html new file mode 100644 index 00000000..1cb4d179 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/VersionedResourcesIT.html @@ -0,0 +1,386 @@ + + + + + +VersionedResourcesIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +

    Class VersionedResourcesIT

    +
    +
    + +
    +
      +
    • +
      +
      @SpringBootTest("juplo.http-resources.protocol-resolver.enabled=true")
      +public class VersionedResourcesIT
      +extends IntegrationTestBase
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
      +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          VersionedResourcesIT

          +
          public VersionedResourcesIT()
          +
        • +
        +
      • +
      +
      + +
      +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setUp

          +
          @BeforeEach
          +public void setUp()
          +
        • +
        + + + +
          +
        • +

          testTransformation

          +
          @Test
          +public void testTransformation()
          +                        throws Exception
          +
          +
          Throws:
          +
          Exception
          +
          +
        • +
        +
      • +
      +
      +
    • +
    +
    +
    +
    + + + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ConfigurableNginxContainer.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ConfigurableNginxContainer.html new file mode 100644 index 00000000..64aec97c --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ConfigurableNginxContainer.html @@ -0,0 +1,184 @@ + + + + + +Uses of Class de.juplo.httpresources.ConfigurableNginxContainer (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.ConfigurableNginxContainer

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoaderIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoaderIT.html new file mode 100644 index 00000000..c8b5b44c --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoaderIT.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT

    +
    +
    No usage of de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoaderTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoaderTest.html new file mode 100644 index 00000000..a790b986 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceChainAwareResourceLoaderTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchModifiedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchModifiedTest.html new file mode 100644 index 00000000..868c8ff5 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchModifiedTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchNotFoundTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchNotFoundTest.html new file mode 100644 index 00000000..9fae41c3 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchNotFoundTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchServerErrorTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchServerErrorTest.html new file mode 100644 index 00000000..00b910a7 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchServerErrorTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchUnmodifiedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchUnmodifiedTest.html new file mode 100644 index 00000000..b9da3213 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredFetchUnmodifiedTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredTest.html new file mode 100644 index 00000000..9f674695 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceExpiredTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceExpiredTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceExpiredTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceExpiredTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceFetcherTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceFetcherTest.html new file mode 100644 index 00000000..090b4cf8 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceFetcherTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceFetcherTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceFetcherTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceFetcherTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchModifiedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchModifiedTest.html new file mode 100644 index 00000000..a8d2c2fd --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchModifiedTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchNotFoundTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchNotFoundTest.html new file mode 100644 index 00000000..beb9ce4e --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchNotFoundTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchServerErrorTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchServerErrorTest.html new file mode 100644 index 00000000..eb848722 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchServerErrorTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchUnmodifiedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchUnmodifiedTest.html new file mode 100644 index 00000000..86fc026b --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredFetchUnmodifiedTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotExpiredFetchUnmodifiedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotExpiredFetchUnmodifiedTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotExpiredFetchUnmodifiedTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredTest.html new file mode 100644 index 00000000..1c809860 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotExpiredTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotExpiredTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotExpiredTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotExpiredTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchNotFoundTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchNotFoundTest.html new file mode 100644 index 00000000..8e3ef01e --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchNotFoundTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchServerErrorTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchServerErrorTest.html new file mode 100644 index 00000000..25e43fa4 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchServerErrorTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchSuccessfulTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchSuccessfulTest.html new file mode 100644 index 00000000..0895592f --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedFirstFetchSuccessfulTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedTest.html new file mode 100644 index 00000000..39d4797b --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceNotFetchedTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceNotFetchedTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceNotFetchedTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceNotFetchedTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverIT.Application.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverIT.Application.html new file mode 100644 index 00000000..ac93d890 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverIT.Application.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceProtocolResolverIT.Application (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceProtocolResolverIT.Application

    +
    +
    No usage of de.juplo.httpresources.HttpResourceProtocolResolverIT.Application
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverIT.html new file mode 100644 index 00000000..2c3d02ad --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverIT.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceProtocolResolverIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceProtocolResolverIT

    +
    +
    No usage of de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverTest.html new file mode 100644 index 00000000..be4c9eae --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourceProtocolResolverTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourceProtocolResolverTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourceProtocolResolverTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourceProtocolResolverTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourcesIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourcesIT.html new file mode 100644 index 00000000..153d9aad --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourcesIT.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourcesIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourcesIT

    +
    +
    No usage of de.juplo.httpresources.HttpResourcesIT
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourcesTest.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourcesTest.html new file mode 100644 index 00000000..bc209335 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/HttpResourcesTest.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.HttpResourcesTest (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.HttpResourcesTest

    +
    +
    No usage of de.juplo.httpresources.HttpResourcesTest
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.Callback.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.Callback.html new file mode 100644 index 00000000..2079c360 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.Callback.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.IntegrationTestBase.Callback (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.IntegrationTestBase.Callback

    +
    +
    No usage of de.juplo.httpresources.IntegrationTestBase.Callback
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.ClockStub.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.ClockStub.html new file mode 100644 index 00000000..bb64265f --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.ClockStub.html @@ -0,0 +1,176 @@ + + + + + +Uses of Class de.juplo.httpresources.IntegrationTestBase.ClockStub (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.IntegrationTestBase.ClockStub

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.IntegrationTestConfiguration.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.IntegrationTestConfiguration.html new file mode 100644 index 00000000..65d7ec04 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.IntegrationTestConfiguration.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration

    +
    +
    No usage of de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.html new file mode 100644 index 00000000..ec0e97cb --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/IntegrationTestBase.html @@ -0,0 +1,201 @@ + + + + + +Uses of Class de.juplo.httpresources.IntegrationTestBase (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.IntegrationTestBase

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/TestUtil.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/TestUtil.html new file mode 100644 index 00000000..7c8f172e --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/TestUtil.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.TestUtil (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.TestUtil

    +
    +
    No usage of de.juplo.httpresources.TestUtil
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.Application.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.Application.html new file mode 100644 index 00000000..2e37c8f6 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.Application.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.Application (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.Application

    +
    +
    No usage of de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.Application
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.TestController.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.TestController.html new file mode 100644 index 00000000..8462a3e2 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.TestController.html @@ -0,0 +1,176 @@ + + + + + +Uses of Class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.TestController (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.TestController

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.html new file mode 100644 index 00000000..c5c439b5 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/ThymeleafWithHttpResourceProtocolResolverIT.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT

    +
    +
    No usage of de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/VersionedResourcesIT.Application.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/VersionedResourcesIT.Application.html new file mode 100644 index 00000000..534d7672 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/VersionedResourcesIT.Application.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.VersionedResourcesIT.Application (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.VersionedResourcesIT.Application

    +
    +
    No usage of de.juplo.httpresources.VersionedResourcesIT.Application
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/VersionedResourcesIT.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/VersionedResourcesIT.html new file mode 100644 index 00000000..f0907328 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/class-use/VersionedResourcesIT.html @@ -0,0 +1,147 @@ + + + + + +Uses of Class de.juplo.httpresources.VersionedResourcesIT (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Class
    de.juplo.httpresources.VersionedResourcesIT

    +
    +
    No usage of de.juplo.httpresources.VersionedResourcesIT
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-summary.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-summary.html new file mode 100644 index 00000000..b8c41375 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-summary.html @@ -0,0 +1,311 @@ + + + + + +de.juplo.httpresources (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Package de.juplo.httpresources

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-tree.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-tree.html new file mode 100644 index 00000000..4b8f2ead --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-tree.html @@ -0,0 +1,209 @@ + + + + + +de.juplo.httpresources Class Hierarchy (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Hierarchy For Package de.juplo.httpresources

    +
    +
    +
    +

    Class Hierarchy

    + +
    +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-use.html b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-use.html new file mode 100644 index 00000000..91140f8d --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/de/juplo/httpresources/package-use.html @@ -0,0 +1,187 @@ + + + + + +Uses of Package de.juplo.httpresources (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Uses of Package
    de.juplo.httpresources

    +
    +
    + +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/deprecated-list.html b/dist/http-resources/2.0.0/testapidocs/deprecated-list.html new file mode 100644 index 00000000..67103e0a --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/deprecated-list.html @@ -0,0 +1,147 @@ + + + + + +Deprecated List (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    Deprecated API

    +

    Contents

    +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/element-list b/dist/http-resources/2.0.0/testapidocs/element-list new file mode 100644 index 00000000..aee14e26 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/element-list @@ -0,0 +1 @@ +de.juplo.httpresources diff --git a/dist/http-resources/2.0.0/testapidocs/help-doc.html b/dist/http-resources/2.0.0/testapidocs/help-doc.html new file mode 100644 index 00000000..e1efeb25 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/help-doc.html @@ -0,0 +1,273 @@ + + + + + +API Help (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    +

    How This API Document Is Organized

    +
    This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
    +
    +
    +
      +
    • +
      +

      Package

      +

      Each package has a page that contains a list of its classes and interfaces, with a summary for each. These pages may contain six categories:

      +
        +
      • Interfaces
      • +
      • Classes
      • +
      • Enums
      • +
      • Exceptions
      • +
      • Errors
      • +
      • Annotation Types
      • +
      +
      +
    • +
    • +
      +

      Class or Interface

      +

      Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

      +
        +
      • Class Inheritance Diagram
      • +
      • Direct Subclasses
      • +
      • All Known Subinterfaces
      • +
      • All Known Implementing Classes
      • +
      • Class or Interface Declaration
      • +
      • Class or Interface Description
      • +
      +
      +
        +
      • Nested Class Summary
      • +
      • Field Summary
      • +
      • Property Summary
      • +
      • Constructor Summary
      • +
      • Method Summary
      • +
      +
      +
        +
      • Field Detail
      • +
      • Property Detail
      • +
      • Constructor Detail
      • +
      • Method Detail
      • +
      +

      Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.

      +
      +
    • +
    • +
      +

      Annotation Type

      +

      Each annotation type has its own separate page with the following sections:

      +
        +
      • Annotation Type Declaration
      • +
      • Annotation Type Description
      • +
      • Required Element Summary
      • +
      • Optional Element Summary
      • +
      • Element Detail
      • +
      +
      +
    • +
    • +
      +

      Enum

      +

      Each enum has its own separate page with the following sections:

      +
        +
      • Enum Declaration
      • +
      • Enum Description
      • +
      • Enum Constant Summary
      • +
      • Enum Constant Detail
      • +
      +
      +
    • +
    • +
      +

      Use

      +

      Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its "Use" page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.

      +
      +
    • +
    • +
      +

      Tree (Class Hierarchy)

      +

      There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. Classes are organized by inheritance structure starting with java.lang.Object. Interfaces do not inherit from java.lang.Object.

      +
        +
      • When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
      • +
      • When viewing a particular package, class or interface page, clicking on "Tree" displays the hierarchy for only that package.
      • +
      +
      +
    • +
    • +
      +

      Deprecated API

      +

      The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.

      +
      +
    • +
    • +
      +

      Index

      +

      The Index contains an alphabetic index of all classes, interfaces, constructors, methods, and fields, as well as lists of all packages and all classes.

      +
      +
    • +
    • +
      +

      All Classes

      +

      The All Classes link shows all classes and interfaces except non-static nested types.

      +
      +
    • +
    • +
      +

      Serialized Form

      +

      Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.

      +
      +
    • +
    • +
      +

      Constant Field Values

      +

      The Constant Field Values page lists the static final fields and their values.

      +
      +
    • +
    • +
      +

      Search

      +

      You can search for definitions of modules, packages, types, fields, methods and other terms defined in the API, using some or all of the name. "Camel-case" abbreviations are supported: for example, "InpStr" will find "InputStream" and "InputStreamReader".

      +
      +
    • +
    +
    +This help file applies to API documentation generated by the standard doclet.
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/index-all.html b/dist/http-resources/2.0.0/testapidocs/index-all.html new file mode 100644 index 00000000..6ae568df --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/index-all.html @@ -0,0 +1,1096 @@ + + + + + +Index (HttpResources 2.0.0 Test API) + + + + + + + + + + + + + + +
    + +
    +
    +
    A C D F G H I N P R S T V W 
    All Classes All Packages + + +

    A

    +
    +
    addResourceHandlers(ResourceHandlerRegistry) - Method in class de.juplo.httpresources.HttpResourceProtocolResolverIT.Application
    +
     
    +
    addResourceHandlers(ResourceHandlerRegistry) - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.Application
    +
     
    +
    addResourceHandlers(ResourceHandlerRegistry) - Method in class de.juplo.httpresources.VersionedResourcesIT.Application
    +
     
    +
    address(String) - Method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    Application() - Constructor for class de.juplo.httpresources.HttpResourceProtocolResolverIT.Application
    +
     
    +
    Application() - Constructor for class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.Application
    +
     
    +
    Application() - Constructor for class de.juplo.httpresources.VersionedResourcesIT.Application
    +
     
    +
    + + + +

    C

    +
    +
    cache() - Method in class de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration
    +
     
    +
    Callback() - Constructor for class de.juplo.httpresources.IntegrationTestBase.Callback
    +
     
    +
    clearCache() - Method in class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    clearMockServer() - Method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    clock() - Method in class de.juplo.httpresources.VersionedResourcesIT.Application
    +
     
    +
    CLOCK - Static variable in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    ClockStub() - Constructor for class de.juplo.httpresources.IntegrationTestBase.ClockStub
    +
     
    +
    ConfigurableNginxContainer - Class in de.juplo.httpresources
    +
    +
    A configurable subclass of the NginxContainer.
    +
    +
    ConfigurableNginxContainer() - Constructor for class de.juplo.httpresources.ConfigurableNginxContainer
    +
    +
    Creates an instance with a default-configuration, that matches the + static configuration of the base-class NginxContainer
    +
    +
    configure() - Method in class de.juplo.httpresources.ConfigurableNginxContainer
    +
     
    +
    controller(String, Model) - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.TestController
    +
     
    +
    + + + +

    D

    +
    +
    de.juplo.httpresources - package de.juplo.httpresources
    +
     
    +
    DEFAULT_NGINX_PORT - Static variable in class de.juplo.httpresources.ConfigurableNginxContainer
    +
     
    +
    DEFAULT_TICK - Static variable in class de.juplo.httpresources.IntegrationTestBase.ClockStub
    +
     
    +
    defaultTemplateResolver(ThymeleafProperties, ApplicationContext, ClientAndServer) - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.Application
    +
    +
    This mimics the autoconfiguration of Thymeleaf in Spring-Boot.
    +
    +
    + + + +

    F

    +
    +
    FETCH(String) - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    fetcher(Cache) - Method in class de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration
    +
     
    +
    formatter - Static variable in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    + + + +

    G

    +
    +
    getGlobalDirectives() - Method in class de.juplo.httpresources.ConfigurableNginxContainer
    +
     
    +
    getMockServerPort() - Method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    getMockServerUri() - Method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    getZone() - Method in class de.juplo.httpresources.IntegrationTestBase.ClockStub
    +
     
    +
    + + + +

    H

    +
    +
    handle(HttpRequest) - Method in class de.juplo.httpresources.IntegrationTestBase.Callback
    +
     
    +
    handle(HttpRequest, HttpResponse) - Method in class de.juplo.httpresources.IntegrationTestBase.Callback
    +
     
    +
    HttpResourceChainAwareResourceLoaderIT - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceChainAwareResourceLoaderIT() - Constructor for class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    HttpResourceChainAwareResourceLoaderTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceChainAwareResourceLoaderTest() - Constructor for class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
    +
     
    +
    HttpResourceExpiredFetchModifiedTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceExpiredFetchModifiedTest() - Constructor for class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    HttpResourceExpiredFetchNotFoundTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceExpiredFetchNotFoundTest() - Constructor for class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    HttpResourceExpiredFetchServerErrorTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceExpiredFetchServerErrorTest() - Constructor for class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    HttpResourceExpiredFetchUnmodifiedTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceExpiredFetchUnmodifiedTest() - Constructor for class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
     
    +
    HttpResourceExpiredTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceExpiredTest() - Constructor for class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    HttpResourceFetcherTest - Class in de.juplo.httpresources
    +
    +
    Tests the inner class HttpResourceFetcher.
    +
    +
    HttpResourceFetcherTest() - Constructor for class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    HttpResourceNotExpiredFetchModifiedTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotExpiredFetchModifiedTest() - Constructor for class de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest
    +
     
    +
    HttpResourceNotExpiredFetchNotFoundTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotExpiredFetchNotFoundTest() - Constructor for class de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest
    +
     
    +
    HttpResourceNotExpiredFetchServerErrorTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotExpiredFetchServerErrorTest() - Constructor for class de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest
    +
     
    +
    HttpResourceNotExpiredFetchUnmodifiedTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotExpiredFetchUnmodifiedTest() - Constructor for class de.juplo.httpresources.HttpResourceNotExpiredFetchUnmodifiedTest
    +
     
    +
    HttpResourceNotExpiredTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotExpiredTest() - Constructor for class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    HttpResourceNotFetchedFirstFetchNotFoundTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotFetchedFirstFetchNotFoundTest() - Constructor for class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    HttpResourceNotFetchedFirstFetchServerErrorTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotFetchedFirstFetchServerErrorTest() - Constructor for class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    HttpResourceNotFetchedFirstFetchSuccessfulTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotFetchedFirstFetchSuccessfulTest() - Constructor for class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    HttpResourceNotFetchedTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceNotFetchedTest() - Constructor for class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    HttpResourceProtocolResolverIT - Class in de.juplo.httpresources
    +
    +
    Mostly identically with HttpResourceResolverIT.
    +
    +
    HttpResourceProtocolResolverIT() - Constructor for class de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
     
    +
    HttpResourceProtocolResolverIT.Application - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceProtocolResolverTest - Class in de.juplo.httpresources
    +
     
    +
    HttpResourceProtocolResolverTest() - Constructor for class de.juplo.httpresources.HttpResourceProtocolResolverTest
    +
     
    +
    httpResources(HttpResourceFetcher) - Method in class de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration
    +
     
    +
    HttpResourcesIT - Class in de.juplo.httpresources
    +
     
    +
    HttpResourcesIT() - Constructor for class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    HttpResourcesTest - Class in de.juplo.httpresources
    +
    + +
    +
    HttpResourcesTest() - Constructor for class de.juplo.httpresources.HttpResourcesTest
    +
     
    +
    + + + +

    I

    +
    +
    instant() - Method in class de.juplo.httpresources.IntegrationTestBase.ClockStub
    +
     
    +
    IntegrationTestBase - Class in de.juplo.httpresources
    +
    +
    This class starts a + {@link https://www.testcontainers.org/modules/nginx/ NginX-Webserver} + via a {@link https://www.testcontainers.org/ Testcontainer} and a + standalone {@link http://www.mock-server.com/#what-is-mockserver MockServer}, + that can be used to intercept requests for assertions / verifications.
    +
    +
    IntegrationTestBase() - Constructor for class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    IntegrationTestBase.Callback - Class in de.juplo.httpresources
    +
     
    +
    IntegrationTestBase.ClockStub - Class in de.juplo.httpresources
    +
     
    +
    IntegrationTestBase.IntegrationTestConfiguration - Class in de.juplo.httpresources
    +
     
    +
    IntegrationTestConfiguration() - Constructor for class de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration
    +
     
    +
    INTERNAL_SERVER_ERROR() - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    + + + +

    N

    +
    +
    NGINIX_IP() - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    NGINX - Static variable in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    NGINX() - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    NGINX(String) - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    NGINX_PORT() - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    NGINX_URI() - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    NOT_FOUND() - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    now - Variable in class de.juplo.httpresources.IntegrationTestBase.ClockStub
    +
     
    +
    + + + +

    P

    +
    +
    prepareMockServer() - Method in class de.juplo.httpresources.IntegrationTestBase
    +
    +
    Prepares the mock-server to forward any request to the NginX-server, + for which no more specific expectation was specified.
    +
    +
    + + + +

    R

    +
    +
    RESPONSE() - Static method in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    + + + +

    S

    +
    +
    server - Variable in class de.juplo.httpresources.IntegrationTestBase
    +
     
    +
    server() - Method in class de.juplo.httpresources.IntegrationTestBase.IntegrationTestConfiguration
    +
     
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchUnmodifiedTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
    +
    SETUP
    +
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
     
    +
    setUp() - Method in class de.juplo.httpresources.HttpResourceProtocolResolverTest
    +
     
    +
    setUp() - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT
    +
     
    +
    setUp() - Method in class de.juplo.httpresources.VersionedResourcesIT
    +
     
    +
    + + + +

    T

    +
    +
    test_contentLength_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_contentLength_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_contentLength_ReturnsExpectedLength() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_contentLength_ThrowsFileNotFoundException() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_contentLength_ThrowsFileNotFoundException() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_contentLength_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_contentLength_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_contentLength_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_contentLength_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_contentType_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_contentType_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_contentType_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_eTag_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_eTag_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_eTag_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_exists_IsFalse() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_exists_IsFalse() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_exists_IsTrue() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    test_exists_IsTrue() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
     
    +
    test_exists_IsTrue() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_exists_IsTrue() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_exists_ReportsFalse() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    test_exists_ReportsFalse() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    test_exists_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_exists_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_exists_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    test_exists_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    test_exists_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    test_exists_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
     
    +
    test_exists_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_exists_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_exists_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_expires_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_expires_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_expires_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_Fetch_200_HTTP10() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP10_InvalidExpires() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP11() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP11_DateMissing_() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP11_Encoding() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP11_MaxAge0() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP11_MinTTL() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP11_MustRevalidate() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP11_NoCache() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_HTTP11_NoCacheQualified() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_Mixed() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_Mixed_ExpiresOverwritten() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_NoHeaders() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_200_NoHeaders_NoBody() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_404_HTTP11() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_404_HTTP11_Cacheable() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_500_HTTP11() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_Cached_Expired() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_Cached_NotFound() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_Cached_ServerError() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Fetch_Cached_Valid() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_fetch_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
    +
    Results for calls, that did trigger a fetch
    +
    +
    test_fetch_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
    +
    Results for calls, that did trigger a fetch
    +
    +
    test_fetch_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
    +
    Results for calls, that did trigger a fetch
    +
    +
    test_fetch_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
    +
    Results for calls, that trigger a fetch
    +
    +
    test_fetch_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
    +
    Results for calls, that trigger a fetch
    +
    +
    test_fetch_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
    +
    Results for calls, that trigger a fetch
    +
    +
    test_fetch_ReportsNoModifications() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
    +
    Results for calls, that did trigger a fetch
    +
    +
    test_fetch_ReturnsFalseIfFetcherReturnedFalse() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchUnmodifiedTest
    +
    +
    Results for calls, that does trigger a fetch
    +
    +
    test_fetch_ReturnsTrueIfFetcherReturnedFalse() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest
    +
    +
    Results for calls, that does trigger a fetch
    +
    +
    test_fetch_ReturnsTrueIfFetcherReturnedFalse() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest
    +
    +
    Results for calls, that does trigger a fetch
    +
    +
    test_fetch_ReturnsTrueIfFetcherReturnedFalse() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest
    +
    +
    Results for calls, that does trigger a fetch
    +
    +
    test_Fetch_ServerDown() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_fetch_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
    +
    Calls, that trigger a fetch
    +
    +
    test_fetch_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest
    +
    +
    Calls, that trigger a fetch
    +
    +
    test_fetch_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest
    +
    +
    Calls, that trigger a fetch
    +
    +
    test_fetch_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest
    +
    +
    Calls, that trigger a fetch
    +
    +
    test_fetch_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
    +
    Calls, that trigger a fetch
    +
    +
    test_fetch_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
    +
    Calls, that trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
    +
    Expected state after calls, that did trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
    +
    Expected state after calls, that did trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
    +
    Expected state after calls, that did trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
    +
    Expected state after calls, that did trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchModifiedTest
    +
    +
    Expected state after calls that trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchNotFoundTest
    +
    +
    Expected state after calls that trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchServerErrorTest
    +
    +
    Expected state after calls that trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotExpiredFetchUnmodifiedTest
    +
    +
    Expected state after calls that trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
    +
    Expected state after calls that trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
    +
    Expected state after calls that trigger a fetch
    +
    +
    test_fetch_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
    +
    Expected state after calls that trigger a fetch
    +
    +
    test_fetched_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
    +
    Calls, that do not trigger a fetch
    +
    +
    test_fetched_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
    +
    Calls, that do not trigger a fetch
    +
    +
    test_fetched_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
    +
    Calls, that do not trigger a fetch
    +
    +
    test_getInputStream_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_getInputStream_ThrowsFileNotFoundException() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_getInputStream_ThrowsFileNotFoundException() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_getInputStream_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_getInputStream_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_getInputStream_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_getInputStream_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    test_getInputStream_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    test_getInputStream_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    test_getInputStream_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
     
    +
    test_getInputStream_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_getInputStream_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_getInputStream_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_hasExpectedContent() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    test_hasExpectedContent() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_hasExpectedContentLength() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_hasExpectedContentLength() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_hasExpectedContentType() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_hasExpectedContentType() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_hasExpectedETag() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_hasExpectedETag() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_hasExpectedLastModification() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_hasExpectedLastModification() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_hasInitialExpirationValue() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_hasInitialExpirationValue() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_hasInitialExpirationValue() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_HasNoContent() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    test_HasNoContent() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    test_hasNoContentType() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_hasNoETag() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_isExpired() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_isExpired_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_isExpired_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_isExpired_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_isModified_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_isModified_IsTrue() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_isModified_IsTrue() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_isModified_IsTrue() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_isModified_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    test_isModified_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    test_isModified_ReportsModifications() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    test_isModified_ReportsNoModifications() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
     
    +
    test_isModified_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_isModified_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_isModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    test_isModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    test_isModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    test_isModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
     
    +
    test_isModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_isModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_isModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_isNotExpired() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_isNotExpired() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_isNotFetched() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
    +
    Results for calls, that does never trigger a fetch
    +
    +
    test_isNotFetched() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
    +
    Results for calls, that does never trigger a fetch
    +
    +
    test_isNotFetched() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
    +
    Initial results for calls, that does not trigger a fetch
    +
    +
    test_isNotModified() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_isNotModified() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_isReadable_IsFalse() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_isReadable_IsFalse() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_isReadable_IsTrue() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    test_isReadable_IsTrue() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
     
    +
    test_isReadable_IsTrue() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_isReadable_IsTrue() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_isReadable_ReportsFalse() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    test_isReadable_ReportsFalse() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    test_isReadable_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_isReadable_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_isReadable_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchModifiedTest
    +
     
    +
    test_isReadable_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchNotFoundTest
    +
     
    +
    test_isReadable_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchServerErrorTest
    +
     
    +
    test_isReadable_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceExpiredFetchUnmodifiedTest
    +
     
    +
    test_isReadable_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_isReadable_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_isReadable_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_lastModified_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceExpiredTest
    +
     
    +
    test_lastModified_DoesNotTriggerFetch() - Method in class de.juplo.httpresources.HttpResourceNotExpiredTest
    +
     
    +
    test_lastModified_ReturnsExpectedTime() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_lastModified_ReturnsExpectedTime() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_lastModified_ReturnsExpectedTime() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_lastModified_TriggersFetch() - Method in class de.juplo.httpresources.HttpResourceNotFetchedTest
    +
     
    +
    test_lastModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchNotFoundTest
    +
     
    +
    test_lastModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchServerErrorTest
    +
     
    +
    test_lastModified_UpdatesData() - Method in class de.juplo.httpresources.HttpResourceNotFetchedFirstFetchSuccessfulTest
    +
     
    +
    test_Update_200() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_304() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_404() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_404_ServeStale() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_500() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_500_MustRevalidate_ServeStale() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_Cached_Expired_RequestIsExecuted() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_Cached_Same_RequestIsExecuted() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_Cached_Valid() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_MustRevalidate_304() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_MustRevalidate_500() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    test_Update_ServerDown() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    testCaching() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    testCaching() - Method in class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    testCachingOfExisting() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    testCachingOfExisting() - Method in class de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
     
    +
    testCachingOfModified() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    testCachingOfNonExistent() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    testCachingOfNonExistent() - Method in class de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
     
    +
    testClasspathResource(ResourceLoader) - Method in class de.juplo.httpresources.HttpResourceProtocolResolverTest
    +
     
    +
    testController() - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.Application
    +
     
    +
    TestController() - Constructor for class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT.TestController
    +
     
    +
    testConvertInvalid() - Method in class de.juplo.httpresources.HttpResourcesTest
    +
     
    +
    testConvertValid() - Method in class de.juplo.httpresources.HttpResourcesTest
    +
     
    +
    testCreateRelative(HttpResourceFetcher) - Method in class de.juplo.httpresources.HttpResourcesTest
    +
    +
    This test only checks the integration of the used methods + Detailed tests for URI-handling are implemented in + HttpResourcesUriHandlingTest.
    +
    +
    testFetchEncoded() - Method in class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    testFetchExistent() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    testFetchExistent() - Method in class de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
     
    +
    testFetchExistent() - Method in class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    testFetchNonExistent() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    testFetchNonExistent() - Method in class de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
     
    +
    testFetchNonExistent() - Method in class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    testFetchServerResponse500() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
     
    +
    testFetchServerResponse500() - Method in class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    testGetResource() - Method in class de.juplo.httpresources.HttpResourcesTest
    +
     
    +
    testHandlingOfLeadingSlashesInResourceNames(WebApplicationContext, Resource, Resource) - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
    +
     
    +
    testHandlingOfTrailingSlashesInResourceLocations(WebApplicationContext, Resource, Resource) - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
    +
     
    +
    testHostWithoutTrailingSlash() - Method in class de.juplo.httpresources.HttpResourcesTest
    +
     
    +
    testHttpResource(ResourceLoader, HttpResource) - Method in class de.juplo.httpresources.HttpResourceProtocolResolverTest
    +
     
    +
    testHttpsResource(ResourceLoader, HttpResource) - Method in class de.juplo.httpresources.HttpResourceProtocolResolverTest
    +
     
    +
    testModifiedResource() - Method in class de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
     
    +
    testModifiedResource() - Method in class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    testModifiedResourceAccessOnly() - Method in class de.juplo.httpresources.HttpResourcesIT
    +
     
    +
    testRenderCachedRemoteTemplate() - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT
    +
     
    +
    testRenderLocalTemplate() - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT
    +
     
    +
    testRenderModifiedRemoteTemplate() - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT
    +
     
    +
    testRenderRemoteTemplate() - Method in class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT
    +
     
    +
    testResolveInvalid() - Method in class de.juplo.httpresources.HttpResourcesTest
    +
    +
    Checks the resolving of normal examples, with enabled enforcment of a + relative path.
    +
    +
    testResolveValid() - Method in class de.juplo.httpresources.HttpResourcesTest
    +
    +
    Checks the resolving of normal examples, with enabled enforcment of a + relative path.
    +
    +
    testResourceDoesNotExist(WebApplicationContext, Resource, Resource) - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
    +
     
    +
    testResourceExistsForaLocation(WebApplicationContext, Resource, Resource) - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
    +
     
    +
    testResourceExistsForSecondLocation(WebApplicationContext, Resource, Resource) - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
    +
     
    +
    testResourceExistsForThirdLocation(WebApplicationContext, Resource, Resource) - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderTest
    +
     
    +
    testResourceHandling() - Method in class de.juplo.httpresources.HttpResourceChainAwareResourceLoaderIT
    +
    +
    In contrast to HttpResourceResolverIT and + HttpResourceProtocolResolverIT it does not + make sense to test through the web-layer here, + because the HttpResourceChainAwareResourceLoader + is intended to mimic the look-upp through the source, + that are configured for resource-chain for static + http-resources for the look-up of local resources.
    +
    +
    testResourceHandling() - Method in class de.juplo.httpresources.HttpResourceProtocolResolverIT
    +
    +
    Olthough the is not enabled in this test-scenario, + this works nearly, identically to the same test there, because all lookups + for resources in the resource-chain for static http-resources are executed + through the application-context, where the + HttpResourceProtocolResolver is registerd.
    +
    +
    testTransformation() - Method in class de.juplo.httpresources.VersionedResourcesIT
    +
     
    +
    TestUtil - Class in de.juplo.httpresources
    +
     
    +
    TestUtil() - Constructor for class de.juplo.httpresources.TestUtil
    +
     
    +
    ThymeleafWithHttpResourceProtocolResolverIT - Class in de.juplo.httpresources
    +
    +
    This test-case showcases the usage of the HttpResourceProtocolResolver + with Thymeleaf.
    +
    +
    ThymeleafWithHttpResourceProtocolResolverIT() - Constructor for class de.juplo.httpresources.ThymeleafWithHttpResourceProtocolResolverIT
    +
     
    +
    ThymeleafWithHttpResourceProtocolResolverIT.Application - Class in de.juplo.httpresources
    +
     
    +
    ThymeleafWithHttpResourceProtocolResolverIT.TestController - Class in de.juplo.httpresources
    +
     
    +
    tick() - Method in class de.juplo.httpresources.IntegrationTestBase.ClockStub
    +
     
    +
    timetravel(Duration) - Method in class de.juplo.httpresources.IntegrationTestBase.ClockStub
    +
     
    +
    + + + +

    V

    +
    +
    VersionedResourcesIT - Class in de.juplo.httpresources
    +
     
    +
    VersionedResourcesIT() - Constructor for class de.juplo.httpresources.VersionedResourcesIT
    +
     
    +
    VersionedResourcesIT.Application - Class in de.juplo.httpresources
    +
     
    +
    versionResourceResolver() - Method in class de.juplo.httpresources.VersionedResourcesIT.Application
    +
     
    +
    + + + +

    W

    +
    +
    withConfiguration(String) - Method in class de.juplo.httpresources.ConfigurableNginxContainer
    +
     
    +
    withGlobalDirective(String, String) - Method in class de.juplo.httpresources.ConfigurableNginxContainer
    +
    +
    Adds a global directive to the configuration-map.
    +
    +
    withServeStaleFalse() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    withServeStaleFalseAndMinTTL() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    withServeStaleTrue() - Method in class de.juplo.httpresources.HttpResourceFetcherTest
    +
     
    +
    withZone(ZoneId) - Method in class de.juplo.httpresources.IntegrationTestBase.ClockStub
    +
     
    +
    +A C D F G H I N P R S T V W 
    All Classes All Packages
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/index.html b/dist/http-resources/2.0.0/testapidocs/index.html new file mode 100644 index 00000000..aba72a9d --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/index.html @@ -0,0 +1,23 @@ + + + + + +HttpResources 2.0.0 Test API + + + + + + + +
    + +

    de/juplo/httpresources/package-summary.html

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/jquery/external/jquery/jquery.js b/dist/http-resources/2.0.0/testapidocs/jquery/external/jquery/jquery.js new file mode 100644 index 00000000..50937333 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/jquery/external/jquery/jquery.js @@ -0,0 +1,10872 @@ +/*! + * jQuery JavaScript Library v3.5.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2020-05-04T22:49Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + return typeof obj === "function" && typeof obj.nodeType !== "number"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.5.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.5 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2020-03-14 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem.namespaceURI, + docElem = ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "\r\n"; + +// inject VBScript +document.write(IEBinaryToArray_ByteStr_Script); + +global.JSZipUtils._getBinaryFromXHR = function (xhr) { + var binary = xhr.responseBody; + var byteMapping = {}; + for ( var i = 0; i < 256; i++ ) { + for ( var j = 0; j < 256; j++ ) { + byteMapping[ String.fromCharCode( i + (j << 8) ) ] = + String.fromCharCode(i) + String.fromCharCode(j); + } + } + var rawBytes = IEBinaryToArray_ByteStr(binary); + var lastChr = IEBinaryToArray_ByteStr_Last(binary); + return rawBytes.replace(/[\s\S]/g, function( match ) { + return byteMapping[match]; + }) + lastChr; +}; + +// enforcing Stuk's coding style +// vim: set shiftwidth=4 softtabstop=4: + +},{}]},{},[1]) +; diff --git a/dist/http-resources/2.0.0/testapidocs/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/dist/http-resources/2.0.0/testapidocs/jquery/jszip-utils/dist/jszip-utils-ie.min.js new file mode 100644 index 00000000..93d8bc8e --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/jquery/jszip-utils/dist/jszip-utils-ie.min.js @@ -0,0 +1,10 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/dist/http-resources/2.0.0/testapidocs/jquery/jszip-utils/dist/jszip-utils.js b/dist/http-resources/2.0.0/testapidocs/jquery/jszip-utils/dist/jszip-utils.js new file mode 100644 index 00000000..775895ec --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/jquery/jszip-utils/dist/jszip-utils.js @@ -0,0 +1,118 @@ +/*! + +JSZipUtils - A collection of cross-browser utilities to go along with JSZip. + + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o + +(c) 2014 Stuart Knightley, David Duponchel +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. + +*/ +!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ + +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; + enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; + + output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); + + } + + return output.join(""); +}; + +// public method for decoding +exports.decode = function(input) { + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0, resultIndex = 0; + + var dataUrlPrefix = "data:"; + + if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { + // This is a common error: people give a data url + // (data:image/png;base64,iVBOR...) with a {base64: true} and + // wonders why things don't work. + // We can detect that the string input looks like a data url but we + // *can't* be sure it is one: removing everything up to the comma would + // be too dangerous. + throw new Error("Invalid base64 input, it looks like a data url."); + } + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + var totalLength = input.length * 3 / 4; + if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { + totalLength--; + } + if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { + totalLength--; + } + if (totalLength % 1 !== 0) { + // totalLength is not an integer, the length does not match a valid + // base64 content. That can happen if: + // - the input is not a base64 content + // - the input is *almost* a base64 content, with a extra chars at the + // beginning or at the end + // - the input uses a base64 variant (base64url for example) + throw new Error("Invalid base64 input, bad content length."); + } + var output; + if (support.uint8array) { + output = new Uint8Array(totalLength|0); + } else { + output = new Array(totalLength|0); + } + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output[resultIndex++] = chr1; + + if (enc3 !== 64) { + output[resultIndex++] = chr2; + } + if (enc4 !== 64) { + output[resultIndex++] = chr3; + } + + } + + return output; +}; + +},{"./support":30,"./utils":32}],2:[function(require,module,exports){ +'use strict'; + +var external = require("./external"); +var DataWorker = require('./stream/DataWorker'); +var DataLengthProbe = require('./stream/DataLengthProbe'); +var Crc32Probe = require('./stream/Crc32Probe'); +var DataLengthProbe = require('./stream/DataLengthProbe'); + +/** + * Represent a compressed object, with everything needed to decompress it. + * @constructor + * @param {number} compressedSize the size of the data compressed. + * @param {number} uncompressedSize the size of the data after decompression. + * @param {number} crc32 the crc32 of the decompressed file. + * @param {object} compression the type of compression, see lib/compressions.js. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. + */ +function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { + this.compressedSize = compressedSize; + this.uncompressedSize = uncompressedSize; + this.crc32 = crc32; + this.compression = compression; + this.compressedContent = data; +} + +CompressedObject.prototype = { + /** + * Create a worker to get the uncompressed content. + * @return {GenericWorker} the worker. + */ + getContentWorker : function () { + var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) + .pipe(this.compression.uncompressWorker()) + .pipe(new DataLengthProbe("data_length")); + + var that = this; + worker.on("end", function () { + if(this.streamInfo['data_length'] !== that.uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + }); + return worker; + }, + /** + * Create a worker to get the compressed content. + * @return {GenericWorker} the worker. + */ + getCompressedWorker : function () { + return new DataWorker(external.Promise.resolve(this.compressedContent)) + .withStreamInfo("compressedSize", this.compressedSize) + .withStreamInfo("uncompressedSize", this.uncompressedSize) + .withStreamInfo("crc32", this.crc32) + .withStreamInfo("compression", this.compression) + ; + } +}; + +/** + * Chain the given worker with other workers to compress the content with the + * given compresion. + * @param {GenericWorker} uncompressedWorker the worker to pipe. + * @param {Object} compression the compression object. + * @param {Object} compressionOptions the options to use when compressing. + * @return {GenericWorker} the new worker compressing the content. + */ +CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { + return uncompressedWorker + .pipe(new Crc32Probe()) + .pipe(new DataLengthProbe("uncompressedSize")) + .pipe(compression.compressWorker(compressionOptions)) + .pipe(new DataLengthProbe("compressedSize")) + .withStreamInfo("compression", compression); +}; + +module.exports = CompressedObject; + +},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require("./stream/GenericWorker"); + +exports.STORE = { + magic: "\x00\x00", + compressWorker : function (compressionOptions) { + return new GenericWorker("STORE compression"); + }, + uncompressWorker : function () { + return new GenericWorker("STORE decompression"); + } +}; +exports.DEFLATE = require('./flate'); + +},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); + +/** + * The following functions come from pako, from pako/lib/zlib/crc32.js + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +// That's all for the pako functions. + +/** + * Compute the crc32 of a string. + * This is almost the same as the function crc32, but for strings. Using the + * same function for the two use cases leads to horrible performances. + * @param {Number} crc the starting value of the crc. + * @param {String} str the string to use. + * @param {Number} len the length of the string. + * @param {Number} pos the starting position for the crc32 computation. + * @return {Number} the computed crc32. + */ +function crc32str(crc, str, len, pos) { + var t = crcTable, end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + +module.exports = function crc32wrapper(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if(isArray) { + return crc32(crc|0, input, input.length, 0); + } else { + return crc32str(crc|0, input, input.length, 0); + } +}; + +},{"./utils":32}],5:[function(require,module,exports){ +'use strict'; +exports.base64 = false; +exports.binary = false; +exports.dir = false; +exports.createFolders = true; +exports.date = null; +exports.compression = null; +exports.compressionOptions = null; +exports.comment = null; +exports.unixPermissions = null; +exports.dosPermissions = null; + +},{}],6:[function(require,module,exports){ +/* global Promise */ +'use strict'; + +// load the global object first: +// - it should be better integrated in the system (unhandledRejection in node) +// - the environment may have a custom Promise implementation (see zone.js) +var ES6Promise = null; +if (typeof Promise !== "undefined") { + ES6Promise = Promise; +} else { + ES6Promise = require("lie"); +} + +/** + * Let the user use/change some implementations. + */ +module.exports = { + Promise: ES6Promise +}; + +},{"lie":37}],7:[function(require,module,exports){ +'use strict'; +var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + +var pako = require("pako"); +var utils = require("./utils"); +var GenericWorker = require("./stream/GenericWorker"); + +var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; + +exports.magic = "\x08\x00"; + +/** + * Create a worker that uses pako to inflate/deflate. + * @constructor + * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". + * @param {Object} options the options to use when (de)compressing. + */ +function FlateWorker(action, options) { + GenericWorker.call(this, "FlateWorker/" + action); + + this._pako = null; + this._pakoAction = action; + this._pakoOptions = options; + // the `meta` object from the last chunk received + // this allow this worker to pass around metadata + this.meta = {}; +} + +utils.inherits(FlateWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +FlateWorker.prototype.processChunk = function (chunk) { + this.meta = chunk.meta; + if (this._pako === null) { + this._createPako(); + } + this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); +}; + +/** + * @see GenericWorker.flush + */ +FlateWorker.prototype.flush = function () { + GenericWorker.prototype.flush.call(this); + if (this._pako === null) { + this._createPako(); + } + this._pako.push([], true); +}; +/** + * @see GenericWorker.cleanUp + */ +FlateWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this._pako = null; +}; + +/** + * Create the _pako object. + * TODO: lazy-loading this object isn't the best solution but it's the + * quickest. The best solution is to lazy-load the worker list. See also the + * issue #446. + */ +FlateWorker.prototype._createPako = function () { + this._pako = new pako[this._pakoAction]({ + raw: true, + level: this._pakoOptions.level || -1 // default compression + }); + var self = this; + this._pako.onData = function(data) { + self.push({ + data : data, + meta : self.meta + }); + }; +}; + +exports.compressWorker = function (compressionOptions) { + return new FlateWorker("Deflate", compressionOptions); +}; +exports.uncompressWorker = function () { + return new FlateWorker("Inflate", {}); +}; + +},{"./stream/GenericWorker":28,"./utils":32,"pako":38}],8:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); +var utf8 = require('../utf8'); +var crc32 = require('../crc32'); +var signature = require('../signature'); + +/** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ +var decToHex = function(dec, bytes) { + var hex = "", i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; +}; + +/** + * Generate the UNIX part of the external file attributes. + * @param {Object} unixPermissions the unix permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : + * + * TTTTsstrwxrwxrwx0000000000ADVSHR + * ^^^^____________________________ file type, see zipinfo.c (UNX_*) + * ^^^_________________________ setuid, setgid, sticky + * ^^^^^^^^^________________ permissions + * ^^^^^^^^^^______ not used ? + * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only + */ +var generateUnixExternalFileAttr = function (unixPermissions, isDir) { + + var result = unixPermissions; + if (!unixPermissions) { + // I can't use octal values in strict mode, hence the hexa. + // 040775 => 0x41fd + // 0100664 => 0x81b4 + result = isDir ? 0x41fd : 0x81b4; + } + return (result & 0xFFFF) << 16; +}; + +/** + * Generate the DOS part of the external file attributes. + * @param {Object} dosPermissions the dos permissions or null. + * @param {Boolean} isDir true if the entry is a directory, false otherwise. + * @return {Number} a 32 bit integer. + * + * Bit 0 Read-Only + * Bit 1 Hidden + * Bit 2 System + * Bit 3 Volume Label + * Bit 4 Directory + * Bit 5 Archive + */ +var generateDosExternalFileAttr = function (dosPermissions, isDir) { + + // the dir flag is already set for compatibility + return (dosPermissions || 0) & 0x3F; +}; + +/** + * Generate the various parts used in the construction of the final zip file. + * @param {Object} streamInfo the hash with informations about the compressed file. + * @param {Boolean} streamedContent is the content streamed ? + * @param {Boolean} streamingEnded is the stream finished ? + * @param {number} offset the current offset from the start of the zip file. + * @param {String} platform let's pretend we are this platform (change platform dependents fields) + * @param {Function} encodeFileName the function to encode the file name / comment. + * @return {Object} the zip parts. + */ +var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { + var file = streamInfo['file'], + compression = streamInfo['compression'], + useCustomEncoding = encodeFileName !== utf8.utf8encode, + encodedFileName = utils.transformTo("string", encodeFileName(file.name)), + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment, + encodedComment = utils.transformTo("string", encodeFileName(comment)), + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir = file.dir, + date = file.date; + + + var dataInfo = { + crc32 : 0, + compressedSize : 0, + uncompressedSize : 0 + }; + + // if the content is streamed, the sizes/crc32 are only available AFTER + // the end of the stream. + if (!streamedContent || streamingEnded) { + dataInfo.crc32 = streamInfo['crc32']; + dataInfo.compressedSize = streamInfo['compressedSize']; + dataInfo.uncompressedSize = streamInfo['uncompressedSize']; + } + + var bitflag = 0; + if (streamedContent) { + // Bit 3: the sizes/crc32 are set to zero in the local header. + // The correct values are put in the data descriptor immediately + // following the compressed data. + bitflag |= 0x0008; + } + if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { + // Bit 11: Language encoding flag (EFS). + bitflag |= 0x0800; + } + + + var extFileAttr = 0; + var versionMadeBy = 0; + if (dir) { + // dos or unix, we set the dos dir flag + extFileAttr |= 0x00010; + } + if(platform === "UNIX") { + versionMadeBy = 0x031E; // UNIX, version 3.0 + extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); + } else { // DOS or other, fallback to DOS + versionMadeBy = 0x0014; // DOS, version 2.0 + extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); + } + + // date + // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html + // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html + + dosTime = date.getUTCHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getUTCMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getUTCSeconds() / 2; + + dosDate = date.getUTCFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getUTCMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getUTCDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(encodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(crc32(encodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + header += decToHex(bitflag, 2); + // compression method + header += compression.magic; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(dataInfo.crc32, 4); + // compressed size + header += decToHex(dataInfo.compressedSize, 4); + // uncompressed size + header += decToHex(dataInfo.uncompressedSize, 4); + // file name length + header += decToHex(encodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + decToHex(versionMadeBy, 2) + + // file header (common to file and central directory) + header + + // file comment length + decToHex(encodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + decToHex(extFileAttr, 4) + + // relative offset of local header + decToHex(offset, 4) + + // file name + encodedFileName + + // extra field + extraFields + + // file comment + encodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord + }; +}; + +/** + * Generate the EOCD record. + * @param {Number} entriesCount the number of entries in the zip file. + * @param {Number} centralDirLength the length (in bytes) of the central dir. + * @param {Number} localDirLength the length (in bytes) of the local dir. + * @param {String} comment the zip file comment as a binary string. + * @param {Function} encodeFileName the function to encode the comment. + * @return {String} the EOCD record. + */ +var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { + var dirEnd = ""; + var encodedComment = utils.transformTo("string", encodeFileName(comment)); + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(entriesCount, 2) + + // total number of entries in the central directory + decToHex(entriesCount, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(encodedComment.length, 2) + + // .ZIP file comment + encodedComment; + + return dirEnd; +}; + +/** + * Generate data descriptors for a file entry. + * @param {Object} streamInfo the hash generated by a worker, containing informations + * on the file entry. + * @return {String} the data descriptors. + */ +var generateDataDescriptors = function (streamInfo) { + var descriptor = ""; + descriptor = signature.DATA_DESCRIPTOR + + // crc-32 4 bytes + decToHex(streamInfo['crc32'], 4) + + // compressed size 4 bytes + decToHex(streamInfo['compressedSize'], 4) + + // uncompressed size 4 bytes + decToHex(streamInfo['uncompressedSize'], 4); + + return descriptor; +}; + + +/** + * A worker to concatenate other workers to create a zip file. + * @param {Boolean} streamFiles `true` to stream the content of the files, + * `false` to accumulate it. + * @param {String} comment the comment to use. + * @param {String} platform the platform to use, "UNIX" or "DOS". + * @param {Function} encodeFileName the function to encode file names and comments. + */ +function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { + GenericWorker.call(this, "ZipFileWorker"); + // The number of bytes written so far. This doesn't count accumulated chunks. + this.bytesWritten = 0; + // The comment of the zip file + this.zipComment = comment; + // The platform "generating" the zip file. + this.zipPlatform = platform; + // the function to encode file names and comments. + this.encodeFileName = encodeFileName; + // Should we stream the content of the files ? + this.streamFiles = streamFiles; + // If `streamFiles` is false, we will need to accumulate the content of the + // files to calculate sizes / crc32 (and write them *before* the content). + // This boolean indicates if we are accumulating chunks (it will change a lot + // during the lifetime of this worker). + this.accumulate = false; + // The buffer receiving chunks when accumulating content. + this.contentBuffer = []; + // The list of generated directory records. + this.dirRecords = []; + // The offset (in bytes) from the beginning of the zip file for the current source. + this.currentSourceOffset = 0; + // The total number of entries in this zip file. + this.entriesCount = 0; + // the name of the file currently being added, null when handling the end of the zip file. + // Used for the emited metadata. + this.currentFile = null; + + + + this._sources = []; +} +utils.inherits(ZipFileWorker, GenericWorker); + +/** + * @see GenericWorker.push + */ +ZipFileWorker.prototype.push = function (chunk) { + + var currentFilePercent = chunk.meta.percent || 0; + var entriesCount = this.entriesCount; + var remainingFiles = this._sources.length; + + if(this.accumulate) { + this.contentBuffer.push(chunk); + } else { + this.bytesWritten += chunk.data.length; + + GenericWorker.prototype.push.call(this, { + data : chunk.data, + meta : { + currentFile : this.currentFile, + percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 + } + }); + } +}; + +/** + * The worker started a new source (an other worker). + * @param {Object} streamInfo the streamInfo object from the new source. + */ +ZipFileWorker.prototype.openedSource = function (streamInfo) { + this.currentSourceOffset = this.bytesWritten; + this.currentFile = streamInfo['file'].name; + + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + + // don't stream folders (because they don't have any content) + if(streamedContent) { + var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + } else { + // we need to wait for the whole file before pushing anything + this.accumulate = true; + } +}; + +/** + * The worker finished a source (an other worker). + * @param {Object} streamInfo the streamInfo object from the finished source. + */ +ZipFileWorker.prototype.closedSource = function (streamInfo) { + this.accumulate = false; + var streamedContent = this.streamFiles && !streamInfo['file'].dir; + var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); + + this.dirRecords.push(record.dirRecord); + if(streamedContent) { + // after the streamed file, we put data descriptors + this.push({ + data : generateDataDescriptors(streamInfo), + meta : {percent:100} + }); + } else { + // the content wasn't streamed, we need to push everything now + // first the file record, then the content + this.push({ + data : record.fileRecord, + meta : {percent:0} + }); + while(this.contentBuffer.length) { + this.push(this.contentBuffer.shift()); + } + } + this.currentFile = null; +}; + +/** + * @see GenericWorker.flush + */ +ZipFileWorker.prototype.flush = function () { + + var localDirLength = this.bytesWritten; + for(var i = 0; i < this.dirRecords.length; i++) { + this.push({ + data : this.dirRecords[i], + meta : {percent:100} + }); + } + var centralDirLength = this.bytesWritten - localDirLength; + + var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); + + this.push({ + data : dirEnd, + meta : {percent:100} + }); +}; + +/** + * Prepare the next source to be read. + */ +ZipFileWorker.prototype.prepareNextSource = function () { + this.previous = this._sources.shift(); + this.openedSource(this.previous.streamInfo); + if (this.isPaused) { + this.previous.pause(); + } else { + this.previous.resume(); + } +}; + +/** + * @see GenericWorker.registerPrevious + */ +ZipFileWorker.prototype.registerPrevious = function (previous) { + this._sources.push(previous); + var self = this; + + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.closedSource(self.previous.streamInfo); + if(self._sources.length) { + self.prepareNextSource(); + } else { + self.end(); + } + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; +}; + +/** + * @see GenericWorker.resume + */ +ZipFileWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this.previous && this._sources.length) { + this.prepareNextSource(); + return true; + } + if (!this.previous && !this._sources.length && !this.generatedError) { + this.end(); + return true; + } +}; + +/** + * @see GenericWorker.error + */ +ZipFileWorker.prototype.error = function (e) { + var sources = this._sources; + if(!GenericWorker.prototype.error.call(this, e)) { + return false; + } + for(var i = 0; i < sources.length; i++) { + try { + sources[i].error(e); + } catch(e) { + // the `error` exploded, nothing to do + } + } + return true; +}; + +/** + * @see GenericWorker.lock + */ +ZipFileWorker.prototype.lock = function () { + GenericWorker.prototype.lock.call(this); + var sources = this._sources; + for(var i = 0; i < sources.length; i++) { + sources[i].lock(); + } +}; + +module.exports = ZipFileWorker; + +},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ +'use strict'; + +var compressions = require('../compressions'); +var ZipFileWorker = require('./ZipFileWorker'); + +/** + * Find the compression to use. + * @param {String} fileCompression the compression defined at the file level, if any. + * @param {String} zipCompression the compression defined at the load() level. + * @return {Object} the compression object to use. + */ +var getCompression = function (fileCompression, zipCompression) { + + var compressionName = fileCompression || zipCompression; + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + return compression; +}; + +/** + * Create a worker to generate a zip file. + * @param {JSZip} zip the JSZip instance at the right root level. + * @param {Object} options to generate the zip file. + * @param {String} comment the comment to use. + */ +exports.generateWorker = function (zip, options, comment) { + + var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); + var entriesCount = 0; + try { + + zip.forEach(function (relativePath, file) { + entriesCount++; + var compression = getCompression(file.options.compression, options.compression); + var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; + var dir = file.dir, date = file.date; + + file._compressWorker(compression, compressionOptions) + .withStreamInfo("file", { + name : relativePath, + dir : dir, + date : date, + comment : file.comment || "", + unixPermissions : file.unixPermissions, + dosPermissions : file.dosPermissions + }) + .pipe(zipFileWorker); + }); + zipFileWorker.entriesCount = entriesCount; + } catch (e) { + zipFileWorker.error(e); + } + + return zipFileWorker; +}; + +},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ +'use strict'; + +/** + * Representation a of zip file in js + * @constructor + */ +function JSZip() { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZip)) { + return new JSZip(); + } + + if(arguments.length) { + throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); + } + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + this.clone = function() { + var newObj = new JSZip(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; +} +JSZip.prototype = require('./object'); +JSZip.prototype.loadAsync = require('./load'); +JSZip.support = require('./support'); +JSZip.defaults = require('./defaults'); + +// TODO find a better way to handle this version, +// a require('package.json').version doesn't work with webpack, see #327 +JSZip.version = "3.2.0"; + +JSZip.loadAsync = function (content, options) { + return new JSZip().loadAsync(content, options); +}; + +JSZip.external = require("./external"); +module.exports = JSZip; + +},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ +'use strict'; +var utils = require('./utils'); +var external = require("./external"); +var utf8 = require('./utf8'); +var utils = require('./utils'); +var ZipEntries = require('./zipEntries'); +var Crc32Probe = require('./stream/Crc32Probe'); +var nodejsUtils = require("./nodejsUtils"); + +/** + * Check the CRC32 of an entry. + * @param {ZipEntry} zipEntry the zip entry to check. + * @return {Promise} the result. + */ +function checkEntryCRC32(zipEntry) { + return new external.Promise(function (resolve, reject) { + var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); + worker.on("error", function (e) { + reject(e); + }) + .on("end", function () { + if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { + reject(new Error("Corrupted zip : CRC32 mismatch")); + } else { + resolve(); + } + }) + .resume(); + }); +} + +module.exports = function(data, options) { + var zip = this; + options = utils.extend(options || {}, { + base64: false, + checkCRC32: false, + optimizedBinaryString: false, + createFolders: false, + decodeFileName: utf8.utf8decode + }); + + if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); + } + + return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) + .then(function(data) { + var zipEntries = new ZipEntries(options); + zipEntries.load(data); + return zipEntries; + }).then(function checkCRC32(zipEntries) { + var promises = [external.Promise.resolve(zipEntries)]; + var files = zipEntries.files; + if (options.checkCRC32) { + for (var i = 0; i < files.length; i++) { + promises.push(checkEntryCRC32(files[i])); + } + } + return external.Promise.all(promises); + }).then(function addFiles(results) { + var zipEntries = results.shift(); + var files = zipEntries.files; + for (var i = 0; i < files.length; i++) { + var input = files[i]; + zip.file(input.fileNameStr, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileCommentStr.length ? input.fileCommentStr : null, + unixPermissions : input.unixPermissions, + dosPermissions : input.dosPermissions, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + zip.comment = zipEntries.zipComment; + } + + return zip; + }); +}; + +},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ +"use strict"; + +var utils = require('../utils'); +var GenericWorker = require('../stream/GenericWorker'); + +/** + * A worker that use a nodejs stream as source. + * @constructor + * @param {String} filename the name of the file entry for this stream. + * @param {Readable} stream the nodejs stream. + */ +function NodejsStreamInputAdapter(filename, stream) { + GenericWorker.call(this, "Nodejs stream input adapter for " + filename); + this._upstreamEnded = false; + this._bindStream(stream); +} + +utils.inherits(NodejsStreamInputAdapter, GenericWorker); + +/** + * Prepare the stream and bind the callbacks on it. + * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. + * @param {Stream} stream the nodejs stream to use. + */ +NodejsStreamInputAdapter.prototype._bindStream = function (stream) { + var self = this; + this._stream = stream; + stream.pause(); + stream + .on("data", function (chunk) { + self.push({ + data: chunk, + meta : { + percent : 0 + } + }); + }) + .on("error", function (e) { + if(self.isPaused) { + this.generatedError = e; + } else { + self.error(e); + } + }) + .on("end", function () { + if(self.isPaused) { + self._upstreamEnded = true; + } else { + self.end(); + } + }); +}; +NodejsStreamInputAdapter.prototype.pause = function () { + if(!GenericWorker.prototype.pause.call(this)) { + return false; + } + this._stream.pause(); + return true; +}; +NodejsStreamInputAdapter.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if(this._upstreamEnded) { + this.end(); + } else { + this._stream.resume(); + } + + return true; +}; + +module.exports = NodejsStreamInputAdapter; + +},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ +'use strict'; + +var Readable = require('readable-stream').Readable; + +var utils = require('../utils'); +utils.inherits(NodejsStreamOutputAdapter, Readable); + +/** +* A nodejs stream using a worker as source. +* @see the SourceWrapper in http://nodejs.org/api/stream.html +* @constructor +* @param {StreamHelper} helper the helper wrapping the worker +* @param {Object} options the nodejs stream options +* @param {Function} updateCb the update callback. +*/ +function NodejsStreamOutputAdapter(helper, options, updateCb) { + Readable.call(this, options); + this._helper = helper; + + var self = this; + helper.on("data", function (data, meta) { + if (!self.push(data)) { + self._helper.pause(); + } + if(updateCb) { + updateCb(meta); + } + }) + .on("error", function(e) { + self.emit('error', e); + }) + .on("end", function () { + self.push(null); + }); +} + + +NodejsStreamOutputAdapter.prototype._read = function() { + this._helper.resume(); +}; + +module.exports = NodejsStreamOutputAdapter; + +},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ +'use strict'; + +module.exports = { + /** + * True if this is running in Nodejs, will be undefined in a browser. + * In a browser, browserify won't include this file and the whole module + * will be resolved an empty object. + */ + isNode : typeof Buffer !== "undefined", + /** + * Create a new nodejs Buffer from an existing content. + * @param {Object} data the data to pass to the constructor. + * @param {String} encoding the encoding to use. + * @return {Buffer} a new Buffer. + */ + newBufferFrom: function(data, encoding) { + if (Buffer.from && Buffer.from !== Uint8Array.from) { + return Buffer.from(data, encoding); + } else { + if (typeof data === "number") { + // Safeguard for old Node.js versions. On newer versions, + // Buffer.from(number) / Buffer(number, encoding) already throw. + throw new Error("The \"data\" argument must not be a number"); + } + return new Buffer(data, encoding); + } + }, + /** + * Create a new nodejs Buffer with the specified size. + * @param {Integer} size the size of the buffer. + * @return {Buffer} a new Buffer. + */ + allocBuffer: function (size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + var buf = new Buffer(size); + buf.fill(0); + return buf; + } + }, + /** + * Find out if an object is a Buffer. + * @param {Object} b the object to test. + * @return {Boolean} true if the object is a Buffer, false otherwise. + */ + isBuffer : function(b){ + return Buffer.isBuffer(b); + }, + + isStream : function (obj) { + return obj && + typeof obj.on === "function" && + typeof obj.pause === "function" && + typeof obj.resume === "function"; + } +}; + +},{}],15:[function(require,module,exports){ +'use strict'; +var utf8 = require('./utf8'); +var utils = require('./utils'); +var GenericWorker = require('./stream/GenericWorker'); +var StreamHelper = require('./stream/StreamHelper'); +var defaults = require('./defaults'); +var CompressedObject = require('./compressedObject'); +var ZipObject = require('./zipObject'); +var generate = require("./generate"); +var nodejsUtils = require("./nodejsUtils"); +var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); + + +/** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} originalOptions the options of the file + * @return {Object} the new file. + */ +var fileAdd = function(name, data, originalOptions) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + + /* + * Correct options. + */ + + var o = utils.extend(originalOptions || {}, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) { + o.compression = o.compression.toUpperCase(); + } + + if (typeof o.unixPermissions === "string") { + o.unixPermissions = parseInt(o.unixPermissions, 8); + } + + // UNX_IFDIR 0040000 see zipinfo.c + if (o.unixPermissions && (o.unixPermissions & 0x4000)) { + o.dir = true; + } + // Bit 4 Directory + if (o.dosPermissions && (o.dosPermissions & 0x0010)) { + o.dir = true; + } + + if (o.dir) { + name = forceTrailingSlash(name); + } + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; + if (!originalOptions || typeof originalOptions.binary === "undefined") { + o.binary = !isUnicodeString; + } + + + var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; + + if (isCompressedEmpty || o.dir || !data || data.length === 0) { + o.base64 = false; + o.binary = true; + data = ""; + o.compression = "STORE"; + dataType = "string"; + } + + /* + * Convert content to fit. + */ + + var zipObjectContent = null; + if (data instanceof CompressedObject || data instanceof GenericWorker) { + zipObjectContent = data; + } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { + zipObjectContent = new NodejsStreamInputAdapter(name, data); + } else { + zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); + } + + var object = new ZipObject(name, zipObjectContent, o); + this.files[name] = object; + /* + TODO: we can't throw an exception because we have async promises + (we can have a promise of a Date() for example) but returning a + promise is useless because file(name, data) returns the JSZip + object for chaining. Should we break that to allow the user + to catch the error ? + + return external.Promise.resolve(zipObjectContent) + .then(function () { + return object; + }); + */ +}; + +/** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ +var parentFolder = function (path) { + if (path.slice(-1) === '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; +}; + +/** + * Returns the path with a slash at the end. + * @private + * @param {String} path the path to check. + * @return {String} the path with a trailing slash. + */ +var forceTrailingSlash = function(path) { + // Check the name ends with a / + if (path.slice(-1) !== "/") { + path += "/"; // IE doesn't like substr(-1) + } + return path; +}; + +/** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ +var folderAdd = function(name, createFolders) { + createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; + + name = forceTrailingSlash(name); + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; +}; + +/** +* Cross-window, cross-Node-context regular expression detection +* @param {Object} object Anything +* @return {Boolean} true if the object is a regular expression, +* false otherwise +*/ +function isRegExp(object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; +} + +// return the actual prototype of JSZip +var out = { + /** + * @see loadAsync + */ + load: function() { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + + /** + * Call a callback function for each entry at this folder level. + * @param {Function} cb the callback function: + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + */ + forEach: function(cb) { + var filename, relativePath, file; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + relativePath = filename.slice(this.root.length, filename.length); + if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root + cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... + } + } + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = []; + this.forEach(function (relativePath, entry) { + if (search(relativePath, entry)) { // the file matches the function + result.push(entry); + } + + }); + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + var obj = this.files[this.root + name]; + if (obj && !obj.dir) { + return obj; + } else { + return null; + } + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) !== "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); + }, + + /** + * Generate the complete zip file as an internal stream. + * @param {Object} options the options to generate the zip file : + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {StreamHelper} the streamed zip file. + */ + generateInternalStream: function(options) { + var worker, opts = {}; + try { + opts = utils.extend(options || {}, { + streamFiles: false, + compression: "STORE", + compressionOptions : null, + type: "", + platform: "DOS", + comment: null, + mimeType: 'application/zip', + encodeFileName: utf8.utf8encode + }); + + opts.type = opts.type.toLowerCase(); + opts.compression = opts.compression.toUpperCase(); + + // "binarystring" is prefered but the internals use "string". + if(opts.type === "binarystring") { + opts.type = "string"; + } + + if (!opts.type) { + throw new Error("No output type specified."); + } + + utils.checkSupport(opts.type); + + // accept nodejs `process.platform` + if( + opts.platform === 'darwin' || + opts.platform === 'freebsd' || + opts.platform === 'linux' || + opts.platform === 'sunos' + ) { + opts.platform = "UNIX"; + } + if (opts.platform === 'win32') { + opts.platform = "DOS"; + } + + var comment = opts.comment || this.comment || ""; + worker = generate.generateWorker(this, opts, comment); + } catch (e) { + worker = new GenericWorker("error"); + worker.error(e); + } + return new StreamHelper(worker, opts.type || "string", opts.mimeType); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateAsync: function(options, onUpdate) { + return this.generateInternalStream(options).accumulate(onUpdate); + }, + /** + * Generate the complete zip file asynchronously. + * @see generateInternalStream + */ + generateNodeStream: function(options, onUpdate) { + options = options || {}; + if (!options.type) { + options.type = "nodebuffer"; + } + return this.generateInternalStream(options).toNodejsStream(onUpdate); + } +}; +module.exports = out; + +},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ +/* + * This file is used by module bundlers (browserify/webpack/etc) when + * including a stream implementation. We use "readable-stream" to get a + * consistent behavior between nodejs versions but bundlers often have a shim + * for "stream". Using this shim greatly improve the compatibility and greatly + * reduce the final size of the bundle (only one stream implementation, not + * two). + */ +module.exports = require("stream"); + +},{"stream":undefined}],17:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function ArrayReader(data) { + DataReader.call(this, data); + for(var i = 0; i < this.data.length; i++) { + data[i] = data[i] & 0xFF; + } +} +utils.inherits(ArrayReader, DataReader); +/** + * @see DataReader.byteAt + */ +ArrayReader.prototype.byteAt = function(i) { + return this.data[this.zero + i]; +}; +/** + * @see DataReader.lastIndexOfSignature + */ +ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i - this.zero; + } + } + + return -1; +}; +/** + * @see DataReader.readAndCheckSignature + */ +ArrayReader.prototype.readAndCheckSignature = function (sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3), + data = this.readData(4); + return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; +}; +/** + * @see DataReader.readData + */ +ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + return []; + } + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = ArrayReader; + +},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ +'use strict'; +var utils = require('../utils'); + +function DataReader(data) { + this.data = data; // type : see implementation + this.length = data.length; + this.index = 0; + this.zero = 0; +} +DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specified index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < this.zero + newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Read the signature (4 bytes) at the current position and compare it with sig. + * @param {string} sig the expected signature + * @return {boolean} true if the signature matches, false otherwise. + */ + readAndCheckSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date(Date.UTC( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1)); // second + } +}; +module.exports = DataReader; + +},{"../utils":32}],19:[function(require,module,exports){ +'use strict'; +var Uint8ArrayReader = require('./Uint8ArrayReader'); +var utils = require('../utils'); + +function NodeBufferReader(data) { + Uint8ArrayReader.call(this, data); +} +utils.inherits(NodeBufferReader, Uint8ArrayReader); + +/** + * @see DataReader.readData + */ +NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = NodeBufferReader; + +},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ +'use strict'; +var DataReader = require('./DataReader'); +var utils = require('../utils'); + +function StringReader(data) { + DataReader.call(this, data); +} +utils.inherits(StringReader, DataReader); +/** + * @see DataReader.byteAt + */ +StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(this.zero + i); +}; +/** + * @see DataReader.lastIndexOfSignature + */ +StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig) - this.zero; +}; +/** + * @see DataReader.readAndCheckSignature + */ +StringReader.prototype.readAndCheckSignature = function (sig) { + var data = this.readData(4); + return sig === data; +}; +/** + * @see DataReader.readData + */ +StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = StringReader; + +},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ +'use strict'; +var ArrayReader = require('./ArrayReader'); +var utils = require('../utils'); + +function Uint8ArrayReader(data) { + ArrayReader.call(this, data); +} +utils.inherits(Uint8ArrayReader, ArrayReader); +/** + * @see DataReader.readData + */ +Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); + this.index += size; + return result; +}; +module.exports = Uint8ArrayReader; + +},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var support = require('../support'); +var ArrayReader = require('./ArrayReader'); +var StringReader = require('./StringReader'); +var NodeBufferReader = require('./NodeBufferReader'); +var Uint8ArrayReader = require('./Uint8ArrayReader'); + +/** + * Create a reader adapted to the data. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. + * @return {DataReader} the data reader. + */ +module.exports = function (data) { + var type = utils.getTypeOf(data); + utils.checkSupport(type); + if (type === "string" && !support.uint8array) { + return new StringReader(data); + } + if (type === "nodebuffer") { + return new NodeBufferReader(data); + } + if (support.uint8array) { + return new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + return new ArrayReader(utils.transformTo("array", data)); +}; + +},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ +'use strict'; +exports.LOCAL_FILE_HEADER = "PK\x03\x04"; +exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; +exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; +exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; +exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; +exports.DATA_DESCRIPTOR = "PK\x07\x08"; + +},{}],24:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var utils = require('../utils'); + +/** + * A worker which convert chunks to a specified type. + * @constructor + * @param {String} destType the destination type. + */ +function ConvertWorker(destType) { + GenericWorker.call(this, "ConvertWorker to " + destType); + this.destType = destType; +} +utils.inherits(ConvertWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +ConvertWorker.prototype.processChunk = function (chunk) { + this.push({ + data : utils.transformTo(this.destType, chunk.data), + meta : chunk.meta + }); +}; +module.exports = ConvertWorker; + +},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ +'use strict'; + +var GenericWorker = require('./GenericWorker'); +var crc32 = require('../crc32'); +var utils = require('../utils'); + +/** + * A worker which calculate the crc32 of the data flowing through. + * @constructor + */ +function Crc32Probe() { + GenericWorker.call(this, "Crc32Probe"); + this.withStreamInfo("crc32", 0); +} +utils.inherits(Crc32Probe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Crc32Probe.prototype.processChunk = function (chunk) { + this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); + this.push(chunk); +}; +module.exports = Crc32Probe; + +},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +/** + * A worker which calculate the total length of the data flowing through. + * @constructor + * @param {String} propName the name used to expose the length + */ +function DataLengthProbe(propName) { + GenericWorker.call(this, "DataLengthProbe for " + propName); + this.propName = propName; + this.withStreamInfo(propName, 0); +} +utils.inherits(DataLengthProbe, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +DataLengthProbe.prototype.processChunk = function (chunk) { + if(chunk) { + var length = this.streamInfo[this.propName] || 0; + this.streamInfo[this.propName] = length + chunk.data.length; + } + GenericWorker.prototype.processChunk.call(this, chunk); +}; +module.exports = DataLengthProbe; + + +},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var GenericWorker = require('./GenericWorker'); + +// the size of the generated chunks +// TODO expose this as a public variable +var DEFAULT_BLOCK_SIZE = 16 * 1024; + +/** + * A worker that reads a content and emits chunks. + * @constructor + * @param {Promise} dataP the promise of the data to split + */ +function DataWorker(dataP) { + GenericWorker.call(this, "DataWorker"); + var self = this; + this.dataIsReady = false; + this.index = 0; + this.max = 0; + this.data = null; + this.type = ""; + + this._tickScheduled = false; + + dataP.then(function (data) { + self.dataIsReady = true; + self.data = data; + self.max = data && data.length || 0; + self.type = utils.getTypeOf(data); + if(!self.isPaused) { + self._tickAndRepeat(); + } + }, function (e) { + self.error(e); + }); +} + +utils.inherits(DataWorker, GenericWorker); + +/** + * @see GenericWorker.cleanUp + */ +DataWorker.prototype.cleanUp = function () { + GenericWorker.prototype.cleanUp.call(this); + this.data = null; +}; + +/** + * @see GenericWorker.resume + */ +DataWorker.prototype.resume = function () { + if(!GenericWorker.prototype.resume.call(this)) { + return false; + } + + if (!this._tickScheduled && this.dataIsReady) { + this._tickScheduled = true; + utils.delay(this._tickAndRepeat, [], this); + } + return true; +}; + +/** + * Trigger a tick a schedule an other call to this function. + */ +DataWorker.prototype._tickAndRepeat = function() { + this._tickScheduled = false; + if(this.isPaused || this.isFinished) { + return; + } + this._tick(); + if(!this.isFinished) { + utils.delay(this._tickAndRepeat, [], this); + this._tickScheduled = true; + } +}; + +/** + * Read and push a chunk. + */ +DataWorker.prototype._tick = function() { + + if(this.isPaused || this.isFinished) { + return false; + } + + var size = DEFAULT_BLOCK_SIZE; + var data = null, nextIndex = Math.min(this.max, this.index + size); + if (this.index >= this.max) { + // EOF + return this.end(); + } else { + switch(this.type) { + case "string": + data = this.data.substring(this.index, nextIndex); + break; + case "uint8array": + data = this.data.subarray(this.index, nextIndex); + break; + case "array": + case "nodebuffer": + data = this.data.slice(this.index, nextIndex); + break; + } + this.index = nextIndex; + return this.push({ + data : data, + meta : { + percent : this.max ? this.index / this.max * 100 : 0 + } + }); + } +}; + +module.exports = DataWorker; + +},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ +'use strict'; + +/** + * A worker that does nothing but passing chunks to the next one. This is like + * a nodejs stream but with some differences. On the good side : + * - it works on IE 6-9 without any issue / polyfill + * - it weights less than the full dependencies bundled with browserify + * - it forwards errors (no need to declare an error handler EVERYWHERE) + * + * A chunk is an object with 2 attributes : `meta` and `data`. The former is an + * object containing anything (`percent` for example), see each worker for more + * details. The latter is the real data (String, Uint8Array, etc). + * + * @constructor + * @param {String} name the name of the stream (mainly used for debugging purposes) + */ +function GenericWorker(name) { + // the name of the worker + this.name = name || "default"; + // an object containing metadata about the workers chain + this.streamInfo = {}; + // an error which happened when the worker was paused + this.generatedError = null; + // an object containing metadata to be merged by this worker into the general metadata + this.extraStreamInfo = {}; + // true if the stream is paused (and should not do anything), false otherwise + this.isPaused = true; + // true if the stream is finished (and should not do anything), false otherwise + this.isFinished = false; + // true if the stream is locked to prevent further structure updates (pipe), false otherwise + this.isLocked = false; + // the event listeners + this._listeners = { + 'data':[], + 'end':[], + 'error':[] + }; + // the previous worker, if any + this.previous = null; +} + +GenericWorker.prototype = { + /** + * Push a chunk to the next workers. + * @param {Object} chunk the chunk to push + */ + push : function (chunk) { + this.emit("data", chunk); + }, + /** + * End the stream. + * @return {Boolean} true if this call ended the worker, false otherwise. + */ + end : function () { + if (this.isFinished) { + return false; + } + + this.flush(); + try { + this.emit("end"); + this.cleanUp(); + this.isFinished = true; + } catch (e) { + this.emit("error", e); + } + return true; + }, + /** + * End the stream with an error. + * @param {Error} e the error which caused the premature end. + * @return {Boolean} true if this call ended the worker with an error, false otherwise. + */ + error : function (e) { + if (this.isFinished) { + return false; + } + + if(this.isPaused) { + this.generatedError = e; + } else { + this.isFinished = true; + + this.emit("error", e); + + // in the workers chain exploded in the middle of the chain, + // the error event will go downward but we also need to notify + // workers upward that there has been an error. + if(this.previous) { + this.previous.error(e); + } + + this.cleanUp(); + } + return true; + }, + /** + * Add a callback on an event. + * @param {String} name the name of the event (data, end, error) + * @param {Function} listener the function to call when the event is triggered + * @return {GenericWorker} the current object for chainability + */ + on : function (name, listener) { + this._listeners[name].push(listener); + return this; + }, + /** + * Clean any references when a worker is ending. + */ + cleanUp : function () { + this.streamInfo = this.generatedError = this.extraStreamInfo = null; + this._listeners = []; + }, + /** + * Trigger an event. This will call registered callback with the provided arg. + * @param {String} name the name of the event (data, end, error) + * @param {Object} arg the argument to call the callback with. + */ + emit : function (name, arg) { + if (this._listeners[name]) { + for(var i = 0; i < this._listeners[name].length; i++) { + this._listeners[name][i].call(this, arg); + } + } + }, + /** + * Chain a worker with an other. + * @param {Worker} next the worker receiving events from the current one. + * @return {worker} the next worker for chainability + */ + pipe : function (next) { + return next.registerPrevious(this); + }, + /** + * Same as `pipe` in the other direction. + * Using an API with `pipe(next)` is very easy. + * Implementing the API with the point of view of the next one registering + * a source is easier, see the ZipFileWorker. + * @param {Worker} previous the previous worker, sending events to this one + * @return {Worker} the current worker for chainability + */ + registerPrevious : function (previous) { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + + // sharing the streamInfo... + this.streamInfo = previous.streamInfo; + // ... and adding our own bits + this.mergeStreamInfo(); + this.previous = previous; + var self = this; + previous.on('data', function (chunk) { + self.processChunk(chunk); + }); + previous.on('end', function () { + self.end(); + }); + previous.on('error', function (e) { + self.error(e); + }); + return this; + }, + /** + * Pause the stream so it doesn't send events anymore. + * @return {Boolean} true if this call paused the worker, false otherwise. + */ + pause : function () { + if(this.isPaused || this.isFinished) { + return false; + } + this.isPaused = true; + + if(this.previous) { + this.previous.pause(); + } + return true; + }, + /** + * Resume a paused stream. + * @return {Boolean} true if this call resumed the worker, false otherwise. + */ + resume : function () { + if(!this.isPaused || this.isFinished) { + return false; + } + this.isPaused = false; + + // if true, the worker tried to resume but failed + var withError = false; + if(this.generatedError) { + this.error(this.generatedError); + withError = true; + } + if(this.previous) { + this.previous.resume(); + } + + return !withError; + }, + /** + * Flush any remaining bytes as the stream is ending. + */ + flush : function () {}, + /** + * Process a chunk. This is usually the method overridden. + * @param {Object} chunk the chunk to process. + */ + processChunk : function(chunk) { + this.push(chunk); + }, + /** + * Add a key/value to be added in the workers chain streamInfo once activated. + * @param {String} key the key to use + * @param {Object} value the associated value + * @return {Worker} the current worker for chainability + */ + withStreamInfo : function (key, value) { + this.extraStreamInfo[key] = value; + this.mergeStreamInfo(); + return this; + }, + /** + * Merge this worker's streamInfo into the chain's streamInfo. + */ + mergeStreamInfo : function () { + for(var key in this.extraStreamInfo) { + if (!this.extraStreamInfo.hasOwnProperty(key)) { + continue; + } + this.streamInfo[key] = this.extraStreamInfo[key]; + } + }, + + /** + * Lock the stream to prevent further updates on the workers chain. + * After calling this method, all calls to pipe will fail. + */ + lock: function () { + if (this.isLocked) { + throw new Error("The stream '" + this + "' has already been used."); + } + this.isLocked = true; + if (this.previous) { + this.previous.lock(); + } + }, + + /** + * + * Pretty print the workers chain. + */ + toString : function () { + var me = "Worker " + this.name; + if (this.previous) { + return this.previous + " -> " + me; + } else { + return me; + } + } +}; + +module.exports = GenericWorker; + +},{}],29:[function(require,module,exports){ +'use strict'; + +var utils = require('../utils'); +var ConvertWorker = require('./ConvertWorker'); +var GenericWorker = require('./GenericWorker'); +var base64 = require('../base64'); +var support = require("../support"); +var external = require("../external"); + +var NodejsStreamOutputAdapter = null; +if (support.nodestream) { + try { + NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); + } catch(e) {} +} + +/** + * Apply the final transformation of the data. If the user wants a Blob for + * example, it's easier to work with an U8intArray and finally do the + * ArrayBuffer/Blob conversion. + * @param {String} type the name of the final type + * @param {String|Uint8Array|Buffer} content the content to transform + * @param {String} mimeType the mime type of the content, if applicable. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. + */ +function transformZipOutput(type, content, mimeType) { + switch(type) { + case "blob" : + return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); + case "base64" : + return base64.encode(content); + default : + return utils.transformTo(type, content); + } +} + +/** + * Concatenate an array of data of the given type. + * @param {String} type the type of the data in the given array. + * @param {Array} dataArray the array containing the data chunks to concatenate + * @return {String|Uint8Array|Buffer} the concatenated data + * @throws Error if the asked type is unsupported + */ +function concat (type, dataArray) { + var i, index = 0, res = null, totalLength = 0; + for(i = 0; i < dataArray.length; i++) { + totalLength += dataArray[i].length; + } + switch(type) { + case "string": + return dataArray.join(""); + case "array": + return Array.prototype.concat.apply([], dataArray); + case "uint8array": + res = new Uint8Array(totalLength); + for(i = 0; i < dataArray.length; i++) { + res.set(dataArray[i], index); + index += dataArray[i].length; + } + return res; + case "nodebuffer": + return Buffer.concat(dataArray); + default: + throw new Error("concat : unsupported type '" + type + "'"); + } +} + +/** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {StreamHelper} helper the helper to use. + * @param {Function} updateCallback a callback called on each update. Called + * with one arg : + * - the metadata linked to the update received. + * @return Promise the promise for the accumulation. + */ +function accumulate(helper, updateCallback) { + return new external.Promise(function (resolve, reject){ + var dataArray = []; + var chunkType = helper._internalType, + resultType = helper._outputType, + mimeType = helper._mimeType; + helper + .on('data', function (data, meta) { + dataArray.push(data); + if(updateCallback) { + updateCallback(meta); + } + }) + .on('error', function(err) { + dataArray = []; + reject(err); + }) + .on('end', function (){ + try { + var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); + resolve(result); + } catch (e) { + reject(e); + } + dataArray = []; + }) + .resume(); + }); +} + +/** + * An helper to easily use workers outside of JSZip. + * @constructor + * @param {Worker} worker the worker to wrap + * @param {String} outputType the type of data expected by the use + * @param {String} mimeType the mime type of the content, if applicable. + */ +function StreamHelper(worker, outputType, mimeType) { + var internalType = outputType; + switch(outputType) { + case "blob": + case "arraybuffer": + internalType = "uint8array"; + break; + case "base64": + internalType = "string"; + break; + } + + try { + // the type used internally + this._internalType = internalType; + // the type used to output results + this._outputType = outputType; + // the mime type + this._mimeType = mimeType; + utils.checkSupport(internalType); + this._worker = worker.pipe(new ConvertWorker(internalType)); + // the last workers can be rewired without issues but we need to + // prevent any updates on previous workers. + worker.lock(); + } catch(e) { + this._worker = new GenericWorker("error"); + this._worker.error(e); + } +} + +StreamHelper.prototype = { + /** + * Listen a StreamHelper, accumulate its content and concatenate it into a + * complete block. + * @param {Function} updateCb the update callback. + * @return Promise the promise for the accumulation. + */ + accumulate : function (updateCb) { + return accumulate(this, updateCb); + }, + /** + * Add a listener on an event triggered on a stream. + * @param {String} evt the name of the event + * @param {Function} fn the listener + * @return {StreamHelper} the current helper. + */ + on : function (evt, fn) { + var self = this; + + if(evt === "data") { + this._worker.on(evt, function (chunk) { + fn.call(self, chunk.data, chunk.meta); + }); + } else { + this._worker.on(evt, function () { + utils.delay(fn, arguments, self); + }); + } + return this; + }, + /** + * Resume the flow of chunks. + * @return {StreamHelper} the current helper. + */ + resume : function () { + utils.delay(this._worker.resume, [], this._worker); + return this; + }, + /** + * Pause the flow of chunks. + * @return {StreamHelper} the current helper. + */ + pause : function () { + this._worker.pause(); + return this; + }, + /** + * Return a nodejs stream for this helper. + * @param {Function} updateCb the update callback. + * @return {NodejsStreamOutputAdapter} the nodejs stream. + */ + toNodejsStream : function (updateCb) { + utils.checkSupport("nodestream"); + if (this._outputType !== "nodebuffer") { + // an object stream containing blob/arraybuffer/uint8array/string + // is strange and I don't know if it would be useful. + // I you find this comment and have a good usecase, please open a + // bug report ! + throw new Error(this._outputType + " is not supported by this method"); + } + + return new NodejsStreamOutputAdapter(this, { + objectMode : this._outputType !== "nodebuffer" + }, updateCb); + } +}; + + +module.exports = StreamHelper; + +},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ +'use strict'; + +exports.base64 = true; +exports.array = true; +exports.string = true; +exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. +exports.uint8array = typeof Uint8Array !== "undefined"; + +if (typeof ArrayBuffer === "undefined") { + exports.blob = false; +} +else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } +} + +try { + exports.nodestream = !!require('readable-stream').Readable; +} catch(e) { + exports.nodestream = false; +} + +},{"readable-stream":16}],31:[function(require,module,exports){ +'use strict'; + +var utils = require('./utils'); +var support = require('./support'); +var nodejsUtils = require('./nodejsUtils'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new Array(256); +for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); +} +_utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) +var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + +// convert array to string +var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); +}; + + +// That's all for the pako functions. + + +/** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ +exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodejsUtils.newBufferFrom(str, "utf-8"); + } + + return string2buf(str); +}; + + +/** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ +exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + return buf2string(buf); +}; + +/** + * A worker to decode utf8 encoded binary chunks into string chunks. + * @constructor + */ +function Utf8DecodeWorker() { + GenericWorker.call(this, "utf-8 decode"); + // the last bytes if a chunk didn't end with a complete codepoint. + this.leftOver = null; +} +utils.inherits(Utf8DecodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8DecodeWorker.prototype.processChunk = function (chunk) { + + var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); + + // 1st step, re-use what's left of the previous chunk + if (this.leftOver && this.leftOver.length) { + if(support.uint8array) { + var previousData = data; + data = new Uint8Array(previousData.length + this.leftOver.length); + data.set(this.leftOver, 0); + data.set(previousData, this.leftOver.length); + } else { + data = this.leftOver.concat(data); + } + this.leftOver = null; + } + + var nextBoundary = utf8border(data); + var usableData = data; + if (nextBoundary !== data.length) { + if (support.uint8array) { + usableData = data.subarray(0, nextBoundary); + this.leftOver = data.subarray(nextBoundary, data.length); + } else { + usableData = data.slice(0, nextBoundary); + this.leftOver = data.slice(nextBoundary, data.length); + } + } + + this.push({ + data : exports.utf8decode(usableData), + meta : chunk.meta + }); +}; + +/** + * @see GenericWorker.flush + */ +Utf8DecodeWorker.prototype.flush = function () { + if(this.leftOver && this.leftOver.length) { + this.push({ + data : exports.utf8decode(this.leftOver), + meta : {} + }); + this.leftOver = null; + } +}; +exports.Utf8DecodeWorker = Utf8DecodeWorker; + +/** + * A worker to endcode string chunks into utf8 encoded binary chunks. + * @constructor + */ +function Utf8EncodeWorker() { + GenericWorker.call(this, "utf-8 encode"); +} +utils.inherits(Utf8EncodeWorker, GenericWorker); + +/** + * @see GenericWorker.processChunk + */ +Utf8EncodeWorker.prototype.processChunk = function (chunk) { + this.push({ + data : exports.utf8encode(chunk.data), + meta : chunk.meta + }); +}; +exports.Utf8EncodeWorker = Utf8EncodeWorker; + +},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ +'use strict'; + +var support = require('./support'); +var base64 = require('./base64'); +var nodejsUtils = require('./nodejsUtils'); +var setImmediate = require('set-immediate-shim'); +var external = require("./external"); + + +/** + * Convert a string that pass as a "binary string": it should represent a byte + * array but may have > 255 char codes. Be sure to take only the first byte + * and returns the byte array. + * @param {String} str the string to transform. + * @return {Array|Uint8Array} the string in a binary format. + */ +function string2binary(str) { + var result = null; + if (support.uint8array) { + result = new Uint8Array(str.length); + } else { + result = new Array(str.length); + } + return stringToArrayLike(str, result); +} + +/** + * Create a new blob with the given content and the given type. + * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use + * an Uint8Array because the stock browser of android 4 won't accept it (it + * will be silently converted to a string, "[object Uint8Array]"). + * + * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: + * when a large amount of Array is used to create the Blob, the amount of + * memory consumed is nearly 100 times the original data amount. + * + * @param {String} type the mime type of the blob. + * @return {Blob} the created blob. + */ +exports.newBlob = function(part, type) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([part], { + type: type + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder(); + builder.append(part); + return builder.getBlob(type); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + +}; +/** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ +function identity(input) { + return input; +} + +/** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ +function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; +} + +/** + * An helper for the function arrayLikeToString. + * This contains static informations and functions that + * can be optimized by the browser JIT compiler. + */ +var arrayToStringHelper = { + /** + * Transform an array of int into a string, chunk by chunk. + * See the performances notes on arrayLikeToString. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @param {String} type the type of the array. + * @param {Integer} chunk the chunk size. + * @return {String} the resulting string. + * @throws Error if the chunk is too big for the stack. + */ + stringifyByChunk: function(array, type, chunk) { + var result = [], k = 0, len = array.length; + // shortcut + if (len <= chunk) { + return String.fromCharCode.apply(null, array); + } + while (k < len) { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + return result.join(""); + }, + /** + * Call String.fromCharCode on every item in the array. + * This is the naive implementation, which generate A LOT of intermediate string. + * This should be used when everything else fail. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + stringifyByChar: function(array){ + var resultStr = ""; + for(var i = 0; i < array.length; i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + }, + applyCanBeUsed : { + /** + * true if the browser accepts to use String.fromCharCode on Uint8Array + */ + uint8array : (function () { + try { + return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; + } catch (e) { + return false; + } + })(), + /** + * true if the browser accepts to use String.fromCharCode on nodejs Buffer. + */ + nodebuffer : (function () { + try { + return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; + } catch (e) { + return false; + } + })() + } +}; + +/** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ +function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + // TODO : we now have workers that split the work. Do we still need that ? + var chunk = 65536, + type = exports.getTypeOf(array), + canUseApply = true; + if (type === "uint8array") { + canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; + } else if (type === "nodebuffer") { + canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; + } + + if (canUseApply) { + while (chunk > 1) { + try { + return arrayToStringHelper.stringifyByChunk(array, type, chunk); + } catch (e) { + chunk = Math.floor(chunk / 2); + } + } + } + + // no apply or chunk error : slow and painful algorithm + // default browser on android 4.* + return arrayToStringHelper.stringifyByChar(array); +} + +exports.applyFromCharCode = arrayLikeToString; + + +/** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ +function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; +} + +// a matrix containing functions to transform everything into everything. +var transform = {}; + +// string to ? +transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); + } +}; + +// array to ? +transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// arraybuffer to ? +transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(new Uint8Array(input)); + } +}; + +// uint8array to ? +transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodejsUtils.newBufferFrom(input); + } +}; + +// nodebuffer to ? +transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity +}; + +/** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ +exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; +}; + +/** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ +exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodejsUtils.isBuffer(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } +}; + +/** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ +exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this platform"); + } +}; + +exports.MAX_VALUE_16BITS = 65535; +exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + +/** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ +exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; +}; + +/** + * Defer the call of a function. + * @param {Function} callback the function to call asynchronously. + * @param {Array} args the arguments to give to the callback. + */ +exports.delay = function(callback, args, self) { + setImmediate(function () { + callback.apply(self || null, args || []); + }); +}; + +/** + * Extends a prototype with an other, without calling a constructor with + * side effects. Inspired by nodejs' `utils.inherits` + * @param {Function} ctor the constructor to augment + * @param {Function} superCtor the parent constructor to use + */ +exports.inherits = function (ctor, superCtor) { + var Obj = function() {}; + Obj.prototype = superCtor.prototype; + ctor.prototype = new Obj(); +}; + +/** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ +exports.extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; +}; + +/** + * Transform arbitrary content into a Promise. + * @param {String} name a name for the content being processed. + * @param {Object} inputData the content to process. + * @param {Boolean} isBinary true if the content is not an unicode string + * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. + * @param {Boolean} isBase64 true if the string content is encoded with base64. + * @return {Promise} a promise in a format usable by JSZip. + */ +exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { + + // if inputData is already a promise, this flatten it. + var promise = external.Promise.resolve(inputData).then(function(data) { + + + var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); + + if (isBlob && typeof FileReader !== "undefined") { + return new external.Promise(function (resolve, reject) { + var reader = new FileReader(); + + reader.onload = function(e) { + resolve(e.target.result); + }; + reader.onerror = function(e) { + reject(e.target.error); + }; + reader.readAsArrayBuffer(data); + }); + } else { + return data; + } + }); + + return promise.then(function(data) { + var dataType = exports.getTypeOf(data); + + if (!dataType) { + return external.Promise.reject( + new Error("Can't read the data of '" + name + "'. Is it " + + "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") + ); + } + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = exports.transformTo("uint8array", data); + } else if (dataType === "string") { + if (isBase64) { + data = base64.decode(data); + } + else if (isBinary) { + // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask + if (isOptimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = string2binary(data); + } + } + } + return data; + }); +}; + +},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"set-immediate-shim":54}],33:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var sig = require('./signature'); +var ZipEntry = require('./zipEntry'); +var utf8 = require('./utf8'); +var support = require('./support'); +// class ZipEntries {{{ +/** + * All the entries in the zip file. + * @constructor + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntries(loadOptions) { + this.files = []; + this.loadOptions = loadOptions; +} +ZipEntries.prototype = { + /** + * Check that the reader is on the specified signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + if (!this.reader.readAndCheckSignature(expectedSignature)) { + this.reader.index -= 4; + var signature = this.reader.readString(4); + throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Check if the given signature is at the given index. + * @param {number} askedIndex the index to check. + * @param {string} expectedSignature the signature to expect. + * @return {boolean} true if the signature is here, false otherwise. + */ + isSignature: function(askedIndex, expectedSignature) { + var currentIndex = this.reader.index; + this.reader.setIndex(askedIndex); + var signature = this.reader.readString(4); + var result = signature === expectedSignature; + this.reader.setIndex(currentIndex); + return result; + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + var zipComment = this.reader.readData(this.zipCommentLength); + var decodeParamType = support.uint8array ? "uint8array" : "array"; + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded unless specified otherwise. + var decodeContent = utils.transformTo(decodeParamType, zipComment); + this.zipComment = this.loadOptions.decodeFileName(decodeContent); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.reader.skip(4); + // this.versionMadeBy = this.reader.readString(2); + // this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readData(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + file.processAttributes(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + + if (this.centralDirRecords !== this.files.length) { + if (this.centralDirRecords !== 0 && this.files.length === 0) { + // We expected some records but couldn't find ANY. + // This is really suspicious, as if something went wrong. + throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); + } else { + // We found some records but not all. + // Something is wrong but we got something for the user: no error here. + // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); + } + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset < 0) { + // Check if the content is a truncated zip or complete garbage. + // A "LOCAL_FILE_HEADER" is not required at the beginning (auto + // extractible zip for example) but it can give a good hint. + // If an ajax request was used without responseType, we will also + // get unreadable data. + var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); + + if (isGarbage) { + throw new Error("Can't find end of central directory : is this a zip file ? " + + "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); + } else { + throw new Error("Corrupted zip: can't find end of central directory"); + } + + } + this.reader.setIndex(offset); + var endOfCentralDirOffset = offset; + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { + // console.warn("ZIP64 end of central directory not where expected."); + this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + if (this.relativeOffsetEndOfZip64CentralDir < 0) { + throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); + } + } + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + + var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; + if (this.zip64) { + expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator + expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; + } + + var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; + + if (extraBytes > 0) { + // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); + if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { + // The offsets seem wrong, but we have something at the specified offset. + // So… we keep it. + } else { + // the offset is wrong, update the "zero" of the reader + // this happens if data has been prepended (crx files for example) + this.reader.zero = extraBytes; + } + } else if (extraBytes < 0) { + throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); + } + }, + prepareReader: function(data) { + this.reader = readerFor(data); + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } +}; +// }}} end of ZipEntries +module.exports = ZipEntries; + +},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ +'use strict'; +var readerFor = require('./reader/readerFor'); +var utils = require('./utils'); +var CompressedObject = require('./compressedObject'); +var crc32fn = require('./crc32'); +var utf8 = require('./utf8'); +var compressions = require('./compressions'); +var support = require('./support'); + +var MADE_BY_DOS = 0x00; +var MADE_BY_UNIX = 0x03; + +/** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ +var findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; +}; + +// class ZipEntry {{{ +/** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ +function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; +} +ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. + this.fileName = reader.readData(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize === -1 || this.uncompressedSize === -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); + } + + compression = findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); + } + this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readInt(2); + reader.skip(2); + // this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + var fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + // will be read in the local part, see the comments there + reader.skip(fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readData(this.fileCommentLength); + }, + + /** + * Parse the external file attributes and get the unix/dos permissions. + */ + processAttributes: function () { + this.unixPermissions = null; + this.dosPermissions = null; + var madeBy = this.versionMadeBy >> 8; + + // Check if we have the DOS directory flag set. + // We look for it in the DOS and UNIX permissions + // but some unknown platform could set it as a compatibility flag. + this.dir = this.externalFileAttributes & 0x0010 ? true : false; + + if(madeBy === MADE_BY_DOS) { + // first 6 bits (0 to 5) + this.dosPermissions = this.externalFileAttributes & 0x3F; + } + + if(madeBy === MADE_BY_UNIX) { + this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; + // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); + } + + // fail safe : if the name ends with a / it probably means a folder + if (!this.dir && this.fileNameStr.slice(-1) === '/') { + this.dir = true; + } + }, + + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = readerFor(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var end = reader.index + this.extraFieldsLength, + extraFieldId, + extraFieldLength, + extraFieldValue; + + if (!this.extraFields) { + this.extraFields = {}; + } + + while (reader.index < end) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readData(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + var decodeParamType = support.uint8array ? "uint8array" : "array"; + if (this.useUTF8()) { + this.fileNameStr = utf8.utf8decode(this.fileName); + this.fileCommentStr = utf8.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileNameStr = upath; + } else { + // ASCII text or unsupported code page + var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); + this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); + } + + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileCommentStr = ucomment; + } else { + // ASCII text or unsupported code page + var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); + this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = readerFor(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (crc32fn(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = readerFor(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); + } + return null; + } +}; +module.exports = ZipEntry; + +},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ +'use strict'; + +var StreamHelper = require('./stream/StreamHelper'); +var DataWorker = require('./stream/DataWorker'); +var utf8 = require('./utf8'); +var CompressedObject = require('./compressedObject'); +var GenericWorker = require('./stream/GenericWorker'); + +/** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ +var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + this.unixPermissions = options.unixPermissions; + this.dosPermissions = options.dosPermissions; + + this._data = data; + this._dataBinary = options.binary; + // keep only the compression + this.options = { + compression : options.compression, + compressionOptions : options.compressionOptions + }; +}; + +ZipObject.prototype = { + /** + * Create an internal stream for the content of this object. + * @param {String} type the type of each chunk. + * @return StreamHelper the stream. + */ + internalStream: function (type) { + var result = null, outputType = "string"; + try { + if (!type) { + throw new Error("No output type specified."); + } + outputType = type.toLowerCase(); + var askUnicodeString = outputType === "string" || outputType === "text"; + if (outputType === "binarystring" || outputType === "text") { + outputType = "string"; + } + result = this._decompressWorker(); + + var isUnicodeString = !this._dataBinary; + + if (isUnicodeString && !askUnicodeString) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + if (!isUnicodeString && askUnicodeString) { + result = result.pipe(new utf8.Utf8DecodeWorker()); + } + } catch (e) { + result = new GenericWorker("error"); + result.error(e); + } + + return new StreamHelper(result, outputType, ""); + }, + + /** + * Prepare the content in the asked type. + * @param {String} type the type of the result. + * @param {Function} onUpdate a function to call on each internal update. + * @return Promise the promise of the result. + */ + async: function (type, onUpdate) { + return this.internalStream(type).accumulate(onUpdate); + }, + + /** + * Prepare the content as a nodejs stream. + * @param {String} type the type of each chunk. + * @param {Function} onUpdate a function to call on each internal update. + * @return Stream the stream. + */ + nodeStream: function (type, onUpdate) { + return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); + }, + + /** + * Return a worker for the compressed content. + * @private + * @param {Object} compression the compression object to use. + * @param {Object} compressionOptions the options to use when compressing. + * @return Worker the worker. + */ + _compressWorker: function (compression, compressionOptions) { + if ( + this._data instanceof CompressedObject && + this._data.compression.magic === compression.magic + ) { + return this._data.getCompressedWorker(); + } else { + var result = this._decompressWorker(); + if(!this._dataBinary) { + result = result.pipe(new utf8.Utf8EncodeWorker()); + } + return CompressedObject.createWorkerFrom(result, compression, compressionOptions); + } + }, + /** + * Return a worker for the decompressed content. + * @private + * @return Worker the worker. + */ + _decompressWorker : function () { + if (this._data instanceof CompressedObject) { + return this._data.getContentWorker(); + } else if (this._data instanceof GenericWorker) { + return this._data; + } else { + return new DataWorker(this._data); + } + } +}; + +var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; +var removedFn = function () { + throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); +}; + +for(var i = 0; i < removedMethods.length; i++) { + ZipObject.prototype[removedMethods[i]] = removedFn; +} +module.exports = ZipObject; + +},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ +(function (global){ +'use strict'; +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a + + + + + + + + + +
    + +
    +
    +
    +

    Hierarchy For All Packages

    +Package Hierarchies: + +
    +
    +
    +

    Class Hierarchy

    + +
    +
    +
    +
    + +

    Copyright © 2020–2021 juplo. All rights reserved.

    +
    + + diff --git a/dist/http-resources/2.0.0/testapidocs/package-search-index.js b/dist/http-resources/2.0.0/testapidocs/package-search-index.js new file mode 100644 index 00000000..b3220c85 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/package-search-index.js @@ -0,0 +1 @@ +packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"de.juplo.httpresources"}] \ No newline at end of file diff --git a/dist/http-resources/2.0.0/testapidocs/package-search-index.zip b/dist/http-resources/2.0.0/testapidocs/package-search-index.zip new file mode 100644 index 00000000..e72d48a0 Binary files /dev/null and b/dist/http-resources/2.0.0/testapidocs/package-search-index.zip differ diff --git a/dist/http-resources/2.0.0/testapidocs/resources/glass.png b/dist/http-resources/2.0.0/testapidocs/resources/glass.png new file mode 100644 index 00000000..a7f591f4 Binary files /dev/null and b/dist/http-resources/2.0.0/testapidocs/resources/glass.png differ diff --git a/dist/http-resources/2.0.0/testapidocs/resources/x.png b/dist/http-resources/2.0.0/testapidocs/resources/x.png new file mode 100644 index 00000000..30548a75 Binary files /dev/null and b/dist/http-resources/2.0.0/testapidocs/resources/x.png differ diff --git a/dist/http-resources/2.0.0/testapidocs/script.js b/dist/http-resources/2.0.0/testapidocs/script.js new file mode 100644 index 00000000..7dc93c48 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/script.js @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var moduleSearchIndex; +var packageSearchIndex; +var typeSearchIndex; +var memberSearchIndex; +var tagSearchIndex; +function loadScripts(doc, tag) { + createElem(doc, tag, 'jquery/jszip/dist/jszip.js'); + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils.js'); + if (window.navigator.userAgent.indexOf('MSIE ') > 0 || window.navigator.userAgent.indexOf('Trident/') > 0 || + window.navigator.userAgent.indexOf('Edge/') > 0) { + createElem(doc, tag, 'jquery/jszip-utils/dist/jszip-utils-ie.js'); + } + createElem(doc, tag, 'search.js'); + + $.get(pathtoroot + "module-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "module-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("module-search-index.json").async("text").then(function(content){ + moduleSearchIndex = JSON.parse(content); + }); + }); + }); + }); + $.get(pathtoroot + "package-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "package-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("package-search-index.json").async("text").then(function(content){ + packageSearchIndex = JSON.parse(content); + }); + }); + }); + }); + $.get(pathtoroot + "type-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "type-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("type-search-index.json").async("text").then(function(content){ + typeSearchIndex = JSON.parse(content); + }); + }); + }); + }); + $.get(pathtoroot + "member-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "member-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("member-search-index.json").async("text").then(function(content){ + memberSearchIndex = JSON.parse(content); + }); + }); + }); + }); + $.get(pathtoroot + "tag-search-index.zip") + .done(function() { + JSZipUtils.getBinaryContent(pathtoroot + "tag-search-index.zip", function(e, data) { + JSZip.loadAsync(data).then(function(zip){ + zip.file("tag-search-index.json").async("text").then(function(content){ + tagSearchIndex = JSON.parse(content); + }); + }); + }); + }); + if (!moduleSearchIndex) { + createElem(doc, tag, 'module-search-index.js'); + } + if (!packageSearchIndex) { + createElem(doc, tag, 'package-search-index.js'); + } + if (!typeSearchIndex) { + createElem(doc, tag, 'type-search-index.js'); + } + if (!memberSearchIndex) { + createElem(doc, tag, 'member-search-index.js'); + } + if (!tagSearchIndex) { + createElem(doc, tag, 'tag-search-index.js'); + } + $(window).resize(function() { + $('.navPadding').css('padding-top', $('.fixedNav').css("height")); + }); +} + +function createElem(doc, tag, path) { + var script = doc.createElement(tag); + var scriptElement = doc.getElementsByTagName(tag)[0]; + script.src = pathtoroot + path; + scriptElement.parentNode.insertBefore(script, scriptElement); +} + +function show(type) { + count = 0; + for (var key in data) { + var row = document.getElementById(key); + if ((data[key] & type) !== 0) { + row.style.display = ''; + row.className = (count++ % 2) ? rowColor : altColor; + } + else + row.style.display = 'none'; + } + updateTabs(type); +} + +function updateTabs(type) { + for (var value in tabs) { + var sNode = document.getElementById(tabs[value][0]); + var spanNode = sNode.firstChild; + if (value == type) { + sNode.className = activeTableTab; + spanNode.innerHTML = tabs[value][1]; + } + else { + sNode.className = tableTab; + spanNode.innerHTML = "" + tabs[value][1] + ""; + } + } +} + +function updateModuleFrame(pFrame, cFrame) { + top.packageFrame.location = pFrame; + top.classFrame.location = cFrame; +} diff --git a/dist/http-resources/2.0.0/testapidocs/search.js b/dist/http-resources/2.0.0/testapidocs/search.js new file mode 100644 index 00000000..b773531b --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/search.js @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +var noResult = {l: "No results found"}; +var catModules = "Modules"; +var catPackages = "Packages"; +var catTypes = "Types"; +var catMembers = "Members"; +var catSearchTags = "SearchTags"; +var highlight = "$&"; +var camelCaseRegexp = ""; +var secondaryMatcher = ""; +function getHighlightedText(item) { + var ccMatcher = new RegExp(camelCaseRegexp); + var label = item.replace(ccMatcher, highlight); + if (label === item) { + label = item.replace(secondaryMatcher, highlight); + } + return label; +} +function getURLPrefix(ui) { + var urlPrefix=""; + if (useModuleDirectories) { + var slash = "/"; + if (ui.item.category === catModules) { + return ui.item.l + slash; + } else if (ui.item.category === catPackages && ui.item.m) { + return ui.item.m + slash; + } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { + $.each(packageSearchIndex, function(index, item) { + if (ui.item.p == item.l) { + urlPrefix = item.m + slash; + } + }); + return urlPrefix; + } else { + return urlPrefix; + } + } + return urlPrefix; +} +var watermark = 'Search'; +$(function() { + $("#search").val(''); + $("#search").prop("disabled", false); + $("#reset").prop("disabled", false); + $("#search").val(watermark).addClass('watermark'); + $("#search").blur(function() { + if ($(this).val().length == 0) { + $(this).val(watermark).addClass('watermark'); + } + }); + $("#search").on('click keydown', function() { + if ($(this).val() == watermark) { + $(this).val('').removeClass('watermark'); + } + }); + $("#reset").click(function() { + $("#search").val(''); + $("#search").focus(); + }); + $("#search").focus(); + $("#search")[0].setSelectionRange(0, 0); +}); +$.widget("custom.catcomplete", $.ui.autocomplete, { + _create: function() { + this._super(); + this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); + }, + _renderMenu: function(ul, items) { + var rMenu = this, + currentCategory = ""; + rMenu.menu.bindings = $(); + $.each(items, function(index, item) { + var li; + if (item.l !== noResult.l && item.category !== currentCategory) { + ul.append("
  • " + item.category + "
  • "); + currentCategory = item.category; + } + li = rMenu._renderItemData(ul, item); + if (item.category) { + li.attr("aria-label", item.category + " : " + item.l); + li.attr("class", "resultItem"); + } else { + li.attr("aria-label", item.l); + li.attr("class", "resultItem"); + } + }); + }, + _renderItem: function(ul, item) { + var label = ""; + if (item.category === catModules) { + label = getHighlightedText(item.l); + } else if (item.category === catPackages) { + label = (item.m) + ? getHighlightedText(item.m + "/" + item.l) + : getHighlightedText(item.l); + } else if (item.category === catTypes) { + label = (item.p) + ? getHighlightedText(item.p + "." + item.l) + : getHighlightedText(item.l); + } else if (item.category === catMembers) { + label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); + } else if (item.category === catSearchTags) { + label = getHighlightedText(item.l); + } else { + label = item.l; + } + var li = $("
  • ").appendTo(ul); + var div = $("
    ").appendTo(li); + if (item.category === catSearchTags) { + if (item.d) { + div.html(label + " (" + item.h + ")
    " + + item.d + "
    "); + } else { + div.html(label + " (" + item.h + ")"); + } + } else { + div.html(label); + } + return li; + } +}); +$(function() { + $("#search").catcomplete({ + minLength: 1, + delay: 100, + source: function(request, response) { + var result = new Array(); + var presult = new Array(); + var tresult = new Array(); + var mresult = new Array(); + var tgresult = new Array(); + var secondaryresult = new Array(); + var displayCount = 0; + var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); + camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); + var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); + secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); + + // Return the nested innermost name from the specified object + function nestedName(e) { + return e.l.substring(e.l.lastIndexOf(".") + 1); + } + + function concatResults(a1, a2) { + a1 = a1.concat(a2); + a2.length = 0; + return a1; + } + + if (moduleSearchIndex) { + var mdleCount = 0; + $.each(moduleSearchIndex, function(index, item) { + item.category = catModules; + if (exactMatcher.test(item.l)) { + result.push(item); + mdleCount++; + } else if (camelCaseMatcher.test(item.l)) { + result.push(item); + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + displayCount = mdleCount; + result = concatResults(result, secondaryresult); + } + if (packageSearchIndex) { + var pCount = 0; + var pkg = ""; + $.each(packageSearchIndex, function(index, item) { + item.category = catPackages; + pkg = (item.m) + ? (item.m + "/" + item.l) + : item.l; + if (exactMatcher.test(item.l)) { + presult.push(item); + pCount++; + } else if (camelCaseMatcher.test(pkg)) { + presult.push(item); + } else if (secondaryMatcher.test(pkg)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(presult, secondaryresult)); + displayCount = (pCount > displayCount) ? pCount : displayCount; + } + if (typeSearchIndex) { + var tCount = 0; + $.each(typeSearchIndex, function(index, item) { + item.category = catTypes; + var s = nestedName(item); + if (exactMatcher.test(s)) { + tresult.push(item); + tCount++; + } else if (camelCaseMatcher.test(s)) { + tresult.push(item); + } else if (secondaryMatcher.test(item.p + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tresult, secondaryresult)); + displayCount = (tCount > displayCount) ? tCount : displayCount; + } + if (memberSearchIndex) { + var mCount = 0; + $.each(memberSearchIndex, function(index, item) { + item.category = catMembers; + var s = nestedName(item); + if (exactMatcher.test(s)) { + mresult.push(item); + mCount++; + } else if (camelCaseMatcher.test(s)) { + mresult.push(item); + } else if (secondaryMatcher.test(item.c + "." + item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(mresult, secondaryresult)); + displayCount = (mCount > displayCount) ? mCount : displayCount; + } + if (tagSearchIndex) { + var tgCount = 0; + $.each(tagSearchIndex, function(index, item) { + item.category = catSearchTags; + if (exactMatcher.test(item.l)) { + tgresult.push(item); + tgCount++; + } else if (secondaryMatcher.test(item.l)) { + secondaryresult.push(item); + } + }); + result = result.concat(concatResults(tgresult, secondaryresult)); + displayCount = (tgCount > displayCount) ? tgCount : displayCount; + } + displayCount = (displayCount > 500) ? displayCount : 500; + var counter = function() { + var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; + var f = function(item) { + count[item.category] += 1; + return (count[item.category] <= displayCount); + }; + return f; + }(); + response(result.filter(counter)); + }, + response: function(event, ui) { + if (!ui.content.length) { + ui.content.push(noResult); + } else { + $("#search").empty(); + } + }, + autoFocus: true, + position: { + collision: "flip" + }, + select: function(event, ui) { + if (ui.item.l !== noResult.l) { + var url = getURLPrefix(ui); + if (ui.item.category === catModules) { + if (useModuleDirectories) { + url += "module-summary.html"; + } else { + url = ui.item.l + "-summary.html"; + } + } else if (ui.item.category === catPackages) { + if (ui.item.url) { + url = ui.item.url; + } else { + url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; + } + } else if (ui.item.category === catTypes) { + if (ui.item.url) { + url = ui.item.url; + } else if (ui.item.p === "") { + url += ui.item.l + ".html"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; + } + } else if (ui.item.category === catMembers) { + if (ui.item.p === "") { + url += ui.item.c + ".html" + "#"; + } else { + url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; + } + if (ui.item.url) { + url += ui.item.url; + } else { + url += ui.item.l; + } + } else if (ui.item.category === catSearchTags) { + url += ui.item.u; + } + if (top !== window) { + parent.classFrame.location = pathtoroot + url; + } else { + window.location.href = pathtoroot + url; + } + $("#search").focus(); + } + } + }); +}); diff --git a/dist/http-resources/2.0.0/testapidocs/stylesheet.css b/dist/http-resources/2.0.0/testapidocs/stylesheet.css new file mode 100644 index 00000000..fa246765 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/stylesheet.css @@ -0,0 +1,906 @@ +/* + * Javadoc style sheet + */ + +@import url('resources/fonts/dejavu.css'); + +/* + * Styles for individual HTML elements. + * + * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular + * HTML element throughout the page. + */ + +body { + background-color:#ffffff; + color:#353833; + font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; + font-size:14px; + margin:0; + padding:0; + height:100%; + width:100%; +} +iframe { + margin:0; + padding:0; + height:100%; + width:100%; + overflow-y:scroll; + border:none; +} +a:link, a:visited { + text-decoration:none; + color:#4A6782; +} +a[href]:hover, a[href]:focus { + text-decoration:none; + color:#bb7a2a; +} +a[name] { + color:#353833; +} +a[name]:before, a[name]:target, a[id]:before, a[id]:target { + content:""; + display:inline-block; + position:relative; + padding-top:129px; + margin-top:-129px; +} +pre { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; +} +h1 { + font-size:20px; +} +h2 { + font-size:18px; +} +h3 { + font-size:16px; + font-style:italic; +} +h4 { + font-size:13px; +} +h5 { + font-size:12px; +} +h6 { + font-size:11px; +} +ul { + list-style-type:disc; +} +code, tt { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; + margin-top:8px; + line-height:1.4em; +} +dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; +} +table tr td dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + vertical-align:top; + padding-top:4px; +} +sup { + font-size:8px; +} + +/* + * Styles for HTML generated by javadoc. + * + * These are style classes that are used by the standard doclet to generate HTML documentation. + */ + +/* + * Styles for document title and copyright. + */ +.clear { + clear:both; + height:0px; + overflow:hidden; +} +.aboutLanguage { + float:right; + padding:0px 21px; + font-size:11px; + z-index:200; + margin-top:-9px; +} +.legalCopy { + margin-left:.5em; +} +.bar a, .bar a:link, .bar a:visited, .bar a:active { + color:#FFFFFF; + text-decoration:none; +} +.bar a:hover, .bar a:focus { + color:#bb7a2a; +} +.tab { + background-color:#0066FF; + color:#ffffff; + padding:8px; + width:5em; + font-weight:bold; +} +/* + * Styles for navigation bar. + */ +.bar { + background-color:#4D7A97; + color:#FFFFFF; + padding:.8em .5em .4em .8em; + height:auto;/*height:1.8em;*/ + font-size:11px; + margin:0; +} +.navPadding { + padding-top: 107px; +} +.fixedNav { + position:fixed; + width:100%; + z-index:999; + background-color:#ffffff; +} +.topNav { + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.bottomNav { + margin-top:10px; + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.subNav { + background-color:#dee3e9; + float:left; + width:100%; + overflow:hidden; + font-size:12px; +} +.subNav div { + clear:left; + float:left; + padding:0 0 5px 6px; + text-transform:uppercase; +} +ul.navList, ul.subNavList { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.navList li{ + list-style:none; + float:left; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch { + float:right; + margin:0 0 0 0; + padding:0; +} +ul.navListSearch li { + list-style:none; + float:right; + padding: 5px 6px; + text-transform:uppercase; +} +ul.navListSearch li label { + position:relative; + right:-16px; +} +ul.subNavList li { + list-style:none; + float:left; +} +.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { + color:#FFFFFF; + text-decoration:none; + text-transform:uppercase; +} +.topNav a:hover, .bottomNav a:hover { + text-decoration:none; + color:#bb7a2a; + text-transform:uppercase; +} +.navBarCell1Rev { + background-color:#F8981D; + color:#253441; + margin: auto 5px; +} +.skipNav { + position:absolute; + top:auto; + left:-9999px; + overflow:hidden; +} +/* + * Styles for page header and footer. + */ +.header, .footer { + clear:both; + margin:0 20px; + padding:5px 0 0 0; +} +.indexNav { + position:relative; + font-size:12px; + background-color:#dee3e9; +} +.indexNav ul { + margin-top:0; + padding:5px; +} +.indexNav ul li { + display:inline; + list-style-type:none; + padding-right:10px; + text-transform:uppercase; +} +.indexNav h1 { + font-size:13px; +} +.title { + color:#2c4557; + margin:10px 0; +} +.subTitle { + margin:5px 0 0 0; +} +.header ul { + margin:0 0 15px 0; + padding:0; +} +.footer ul { + margin:20px 0 5px 0; +} +.header ul li, .footer ul li { + list-style:none; + font-size:13px; +} +/* + * Styles for headings. + */ +div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList li.blockList h3 { + padding:0; + margin:15px 0; +} +ul.blockList li.blockList h2 { + padding:0px 0 20px 0; +} +/* + * Styles for page layout containers. + */ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, +.allClassesContainer, .allPackagesContainer { + clear:both; + padding:10px 20px; + position:relative; +} +.indexContainer { + margin:10px; + position:relative; + font-size:12px; +} +.indexContainer h2 { + font-size:13px; + padding:0 0 3px 0; +} +.indexContainer ul { + margin:0; + padding:0; +} +.indexContainer ul li { + list-style:none; + padding-top:2px; +} +.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { + font-size:12px; + font-weight:bold; + margin:10px 0 0 0; + color:#4E4E4E; +} +.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { + margin:5px 0 10px 0px; + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; +} +.serializedFormContainer dl.nameValue dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +.serializedFormContainer dl.nameValue dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* + * Styles for lists. + */ +li.circle { + list-style:circle; +} +ul.horizontal li { + display:inline; + font-size:0.9em; +} +ul.inheritance { + margin:0; + padding:0; +} +ul.inheritance li { + display:inline; + list-style:none; +} +ul.inheritance li ul.inheritance { + margin-left:15px; + padding-left:15px; + padding-top:1px; +} +ul.blockList, ul.blockListLast { + margin:10px 0 10px 0; + padding:0; +} +ul.blockList li.blockList, ul.blockListLast li.blockList { + list-style:none; + margin-bottom:15px; + line-height:1.4; +} +ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { + padding:0px 20px 5px 10px; + border:1px solid #ededed; + background-color:#f8f8f8; +} +ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { + padding:0 0 5px 8px; + background-color:#ffffff; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { + margin-left:0; + padding-left:0; + padding-bottom:15px; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { + list-style:none; + border-bottom:none; + padding-bottom:0; +} +table tr td dl, table tr td dl dt, table tr td dl dd { + margin-top:0; + margin-bottom:1px; +} +/* + * Styles for tables. + */ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, +.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { + width:100%; + border-spacing:0; + border-left:1px solid #EEE; + border-right:1px solid #EEE; + border-bottom:1px solid #EEE; +} +.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { + padding:0px; +} +.overviewSummary caption, .memberSummary caption, .typeSummary caption, +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, +.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:#253441; + font-weight:bold; + clear:none; + overflow:hidden; + padding:0px; + padding-top:10px; + padding-left:1px; + margin:0px; + white-space:pre; +} +.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, +.constantsSummary caption a:link, .deprecatedSummary caption a:link, +.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, +.usesSummary caption a:link, +.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, +.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, +.usesSummary caption a:hover, +.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, +.constantsSummary caption a:active, .deprecatedSummary caption a:active, +.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, +.usesSummary caption a:active, +.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, +.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, +.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, +.usesSummary caption a:visited { + color:#FFFFFF; +} +.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, +.useSummary caption a:visited { + color:#1f389c; +} +.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, +.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, +.usesSummary caption span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + padding-bottom:7px; + display:inline-block; + float:left; + background-color:#F8981D; + border: none; + height:16px; +} +.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, +.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#F8981D; + height:16px; +} +.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, +.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#4D7A97; + height:16px; +} +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, +.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, +.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, +.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { + padding-top:0px; + padding-left:0px; + padding-right:0px; + background-image:none; + float:none; + display:inline; +} +.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, +.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { + display:none; + width:5px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, +.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, +.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + background-color:#4D7A97; + float:left; +} +.rowColor th, .altColor th { + font-weight:normal; +} +.overviewSummary td, .memberSummary td, .typeSummary td, +.useSummary td, .constantsSummary td, .deprecatedSummary td, +.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { + text-align:left; + padding:0px 0px 12px 10px; +} +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, +.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, +.constantsSummary td { + vertical-align:top; + padding-right:0px; + padding-top:8px; + padding-bottom:3px; +} +th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, +.packagesSummary th { + background:#dee3e9; + text-align:left; + padding:8px 3px 3px 7px; +} +td.colFirst, th.colFirst { + font-size:13px; +} +td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { + font-size:13px; +} +.constantsSummary th, .packagesSummary th { + font-size:13px; +} +.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, +.providesSummary td.colLast { + white-space:normal; + font-size:13px; +} +.overviewSummary td.colFirst, .overviewSummary th.colFirst, +.requiresSummary td.colFirst, .requiresSummary th.colFirst, +.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, +.usesSummary td.colFirst, .usesSummary th.colFirst, +.providesSummary td.colFirst, .providesSummary th.colFirst, +.memberSummary td.colFirst, .memberSummary th.colFirst, +.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, +.typeSummary td.colFirst, .typeSummary th.colFirst { + vertical-align:top; +} +.packagesSummary th.colLast, .packagesSummary td.colLast { + white-space:normal; +} +td.colFirst a:link, td.colFirst a:visited, +td.colSecond a:link, td.colSecond a:visited, +th.colFirst a:link, th.colFirst a:visited, +th.colSecond a:link, th.colSecond a:visited, +th.colConstructorName a:link, th.colConstructorName a:visited, +th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, +.constantValuesContainer td a:link, .constantValuesContainer td a:visited, +.allClassesContainer td a:link, .allClassesContainer td a:visited, +.allPackagesContainer td a:link, .allPackagesContainer td a:visited { + font-weight:bold; +} +.tableSubHeadingColor { + background-color:#EEEEFF; +} +.altColor, .altColor th { + background-color:#FFFFFF; +} +.rowColor, .rowColor th { + background-color:#EEEEEF; +} +/* + * Styles for contents. + */ +.description pre { + margin-top:0; +} +.deprecatedContent { + margin:0; + padding:10px 0; +} +.docSummary { + padding:0; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + font-style:normal; +} +div.block { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; +} +td.colLast div { + padding-top:0px; +} +td.colLast a { + padding-bottom:3px; +} +/* + * Styles for formatting effect. + */ +.sourceLineNo { + color:green; + padding:0 30px 0 0; +} +h1.hidden { + visibility:hidden; + overflow:hidden; + font-size:10px; +} +.block { + display:block; + margin:3px 10px 2px 0px; + color:#474747; +} +.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, +.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, +.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, +.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { + font-weight:bold; +} +.deprecationComment, .emphasizedPhrase, .interfaceName { + font-style:italic; +} +.deprecationBlock { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + border-style:solid; + border-width:thin; + border-radius:10px; + padding:10px; + margin-bottom:10px; + margin-right:10px; + display:inline-block; +} +div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, +div.block div.block span.interfaceName { + font-style:normal; +} +div.contentContainer ul.blockList li.blockList h2 { + padding-bottom:0px; +} +/* + * Styles for IFRAME. + */ +.mainContainer { + margin:0 auto; + padding:0; + height:100%; + width:100%; + position:fixed; + top:0; + left:0; +} +.leftContainer { + height:100%; + position:fixed; + width:320px; +} +.leftTop { + position:relative; + float:left; + width:315px; + top:0; + left:0; + height:30%; + border-right:6px solid #ccc; + border-bottom:6px solid #ccc; +} +.leftBottom { + position:relative; + float:left; + width:315px; + bottom:0; + left:0; + height:70%; + border-right:6px solid #ccc; + border-top:1px solid #000; +} +.rightContainer { + position:absolute; + left:320px; + top:0; + bottom:0; + height:100%; + right:0; + border-left:1px solid #000; +} +.rightIframe { + margin:0; + padding:0; + height:100%; + right:30px; + width:100%; + overflow:visible; + margin-bottom:30px; +} +/* + * Styles specific to HTML5 elements. + */ +main, nav, header, footer, section { + display:block; +} +/* + * Styles for javadoc search. + */ +.ui-autocomplete-category { + font-weight:bold; + font-size:15px; + padding:7px 0 7px 3px; + background-color:#4D7A97; + color:#FFFFFF; +} +.resultItem { + font-size:13px; +} +.ui-autocomplete { + max-height:85%; + max-width:65%; + overflow-y:scroll; + overflow-x:scroll; + white-space:nowrap; + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); +} +ul.ui-autocomplete { + position:fixed; + z-index:999999; +} +ul.ui-autocomplete li { + float:left; + clear:both; + width:100%; +} +.resultHighlight { + font-weight:bold; +} +#search { + background-image:url('resources/glass.png'); + background-size:13px; + background-repeat:no-repeat; + background-position:2px 3px; + padding-left:20px; + position:relative; + right:-18px; +} +#reset { + background-color: rgb(255,255,255); + background-image:url('resources/x.png'); + background-position:center; + background-repeat:no-repeat; + background-size:12px; + border:0 none; + width:16px; + height:17px; + position:relative; + left:-4px; + top:-4px; + font-size:0px; +} +.watermark { + color:#545454; +} +.searchTagDescResult { + font-style:italic; + font-size:11px; +} +.searchTagHolderResult { + font-style:italic; + font-size:12px; +} +.searchTagResult:before, .searchTagResult:target { + color:red; +} +.moduleGraph span { + display:none; + position:absolute; +} +.moduleGraph:hover span { + display:block; + margin: -100px 0 0 100px; + z-index: 1; +} +.methodSignature { + white-space:normal; +} + +/* + * Styles for user-provided tables. + * + * borderless: + * No borders, vertical margins, styled caption. + * This style is provided for use with existing doc comments. + * In general, borderless tables should not be used for layout purposes. + * + * plain: + * Plain borders around table and cells, vertical margins, styled caption. + * Best for small tables or for complex tables for tables with cells that span + * rows and columns, when the "striped" style does not work well. + * + * striped: + * Borders around the table and vertical borders between cells, striped rows, + * vertical margins, styled caption. + * Best for tables that have a header row, and a body containing a series of simple rows. + */ + +table.borderless, +table.plain, +table.striped { + margin-top: 10px; + margin-bottom: 10px; +} +table.borderless > caption, +table.plain > caption, +table.striped > caption { + font-weight: bold; + font-size: smaller; +} +table.borderless th, table.borderless td, +table.plain th, table.plain td, +table.striped th, table.striped td { + padding: 2px 5px; +} +table.borderless, +table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, +table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { + border: none; +} +table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { + background-color: transparent; +} +table.plain { + border-collapse: collapse; + border: 1px solid black; +} +table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { + background-color: transparent; +} +table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, +table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { + border: 1px solid black; +} +table.striped { + border-collapse: collapse; + border: 1px solid black; +} +table.striped > thead { + background-color: #E3E3E3; +} +table.striped > thead > tr > th, table.striped > thead > tr > td { + border: 1px solid black; +} +table.striped > tbody > tr:nth-child(even) { + background-color: #EEE +} +table.striped > tbody > tr:nth-child(odd) { + background-color: #FFF +} +table.striped > tbody > tr > th, table.striped > tbody > tr > td { + border-left: 1px solid black; + border-right: 1px solid black; +} +table.striped > tbody > tr > th { + font-weight: normal; +} diff --git a/dist/http-resources/2.0.0/testapidocs/type-search-index.js b/dist/http-resources/2.0.0/testapidocs/type-search-index.js new file mode 100644 index 00000000..d6629e68 --- /dev/null +++ b/dist/http-resources/2.0.0/testapidocs/type-search-index.js @@ -0,0 +1 @@ +typeSearchIndex = [{"l":"All Classes","url":"allclasses-index.html"},{"p":"de.juplo.httpresources","l":"HttpResourceProtocolResolverIT.Application"},{"p":"de.juplo.httpresources","l":"ThymeleafWithHttpResourceProtocolResolverIT.Application"},{"p":"de.juplo.httpresources","l":"VersionedResourcesIT.Application"},{"p":"de.juplo.httpresources","l":"IntegrationTestBase.Callback"},{"p":"de.juplo.httpresources","l":"IntegrationTestBase.ClockStub"},{"p":"de.juplo.httpresources","l":"ConfigurableNginxContainer"},{"p":"de.juplo.httpresources","l":"HttpResourceChainAwareResourceLoaderIT"},{"p":"de.juplo.httpresources","l":"HttpResourceChainAwareResourceLoaderTest"},{"p":"de.juplo.httpresources","l":"HttpResourceExpiredFetchModifiedTest"},{"p":"de.juplo.httpresources","l":"HttpResourceExpiredFetchNotFoundTest"},{"p":"de.juplo.httpresources","l":"HttpResourceExpiredFetchServerErrorTest"},{"p":"de.juplo.httpresources","l":"HttpResourceExpiredFetchUnmodifiedTest"},{"p":"de.juplo.httpresources","l":"HttpResourceExpiredTest"},{"p":"de.juplo.httpresources","l":"HttpResourceFetcherTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotExpiredFetchModifiedTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotExpiredFetchNotFoundTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotExpiredFetchServerErrorTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotExpiredFetchUnmodifiedTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotExpiredTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotFetchedFirstFetchNotFoundTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotFetchedFirstFetchServerErrorTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotFetchedFirstFetchSuccessfulTest"},{"p":"de.juplo.httpresources","l":"HttpResourceNotFetchedTest"},{"p":"de.juplo.httpresources","l":"HttpResourceProtocolResolverIT"},{"p":"de.juplo.httpresources","l":"HttpResourceProtocolResolverTest"},{"p":"de.juplo.httpresources","l":"HttpResourcesIT"},{"p":"de.juplo.httpresources","l":"HttpResourcesTest"},{"p":"de.juplo.httpresources","l":"IntegrationTestBase"},{"p":"de.juplo.httpresources","l":"IntegrationTestBase.IntegrationTestConfiguration"},{"p":"de.juplo.httpresources","l":"ThymeleafWithHttpResourceProtocolResolverIT.TestController"},{"p":"de.juplo.httpresources","l":"TestUtil"},{"p":"de.juplo.httpresources","l":"ThymeleafWithHttpResourceProtocolResolverIT"},{"p":"de.juplo.httpresources","l":"VersionedResourcesIT"}] \ No newline at end of file diff --git a/dist/http-resources/2.0.0/testapidocs/type-search-index.zip b/dist/http-resources/2.0.0/testapidocs/type-search-index.zip new file mode 100644 index 00000000..5a6c4e66 Binary files /dev/null and b/dist/http-resources/2.0.0/testapidocs/type-search-index.zip differ diff --git a/dist/http-resources/2.0.0/xref-test/allclasses-frame.html b/dist/http-resources/2.0.0/xref-test/allclasses-frame.html new file mode 100644 index 00000000..4957c9cb --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/allclasses-frame.html @@ -0,0 +1,28 @@ + + + + + + + All Classes + + + +

    All Classes

    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/ConfigurableNginxContainer.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/ConfigurableNginxContainer.html new file mode 100644 index 00000000..e5303135 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/ConfigurableNginxContainer.html @@ -0,0 +1,120 @@ + + + +ConfigurableNginxContainer xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import java.nio.file.Files;
    +5   import java.nio.file.Path;
    +6   import java.nio.file.Paths;
    +7   import java.util.LinkedHashMap;
    +8   import java.util.LinkedList;
    +9   import java.util.List;
    +10  import java.util.Map;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.testcontainers.containers.BindMode;
    +14  import org.testcontainers.containers.NginxContainer;
    +15  
    +16  
    +17  /**
    +18   * A configurable subclass of the {@link NginxContainer}.
    +19   * @author Kai Moritz
    +20   */
    +21  public class ConfigurableNginxContainer extends NginxContainer
    +22  {
    +23    private final static Logger LOG =
    +24        LoggerFactory.getLogger(ConfigurableNginxContainer.class);
    +25  
    +26  
    +27    public final static int DEFAULT_NGINX_PORT = 80;
    +28  
    +29    private final Map<String, String> directives;
    +30  
    +31  
    +32    /**
    +33     * Creates an instance with a default-configuration, that matches the
    +34     * static configuration of the base-class {@link NginxContainer}
    +35     */
    +36    public ConfigurableNginxContainer()
    +37    {
    +38      directives = new LinkedHashMap<>();
    +39      directives.put("daemon", "off");
    +40    }
    +41  
    +42  
    +43    /**
    +44     * Adds a global directive to the configuration-map.
    +45     * <p>
    +46     * This method can only be used to add <em>global</em> directives.
    +47     * Global directives are all directives, that are marked with the context
    +48     * <code>Main</code> in the {@link http://nginx.org/en/docs/ngx_core_module.html
    +49     * Nginx-documentation}, for example <code>daemon</code>, <code>user</code>
    +50     * and <code>env</code>.
    +51     * <p>
    +52     * If you need to modify contexts, like <code>server</code> or
    +53     * <code>http</code>, you have to
    +54     * {@link #withConfiguration(String) pass in a complete configuration}.
    +55     * @param key The key of the directive
    +56     * @param value The value of the directive (the <code>;</code> is added automatically)
    +57     * @return <code>this</code> instance, to enable a fluid API.
    +58     */
    +59    public ConfigurableNginxContainer withGlobalDirective(String key, String value)
    +60    {
    +61      directives.put(key, value);
    +62      return this;
    +63    }
    +64  
    +65    public Map<String, String> getGlobalDirectives()
    +66    {
    +67      return directives;
    +68    }
    +69  
    +70    public ConfigurableNginxContainer withConfiguration(String path)
    +71    {
    +72      Path config = Paths.get(path);
    +73  
    +74      if (Files.isRegularFile(config))
    +75      {
    +76        LOG.info("Binding file {} as /etc/nginx/nginx.conf", config.toAbsolutePath());
    +77        addFileSystemBind(path, "/etc/nginx/nginx.conf", BindMode.READ_ONLY);
    +78        return this;
    +79      }
    +80  
    +81      if (Files.isDirectory(config))
    +82      {
    +83        LOG.info("Binding directory {} as /etc/nginx/", config.toAbsolutePath());
    +84        addFileSystemBind(path, "/etc/nginx/nginx.conf", BindMode.READ_ONLY);
    +85        return this;
    +86      }
    +87  
    +88      throw new IllegalArgumentException(
    +89            config.toAbsolutePath() +
    +90            " has to represent either a directory, or a regular file!");
    +91    }
    +92  
    +93    @Override
    +94    protected void configure()
    +95    {
    +96      addExposedPort(DEFAULT_NGINX_PORT);
    +97      List<String> commands = new LinkedList<>();
    +98      commands.add("nginx");
    +99      directives.entrySet().forEach((directive) ->
    +100     {
    +101       commands.add("-g");
    +102       commands.add(directive.getKey() + " " + directive.getValue() + ";");
    +103     });
    +104     LOG.info("CMD: {}", commands);
    +105     setCommand(commands.toArray(new String[commands.size()]));
    +106   }
    +107 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderIT.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderIT.html new file mode 100644 index 00000000..a6116f35 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderIT.html @@ -0,0 +1,374 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderIT.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import org.junit.jupiter.api.BeforeEach;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.mockserver.integration.ClientAndServer;
    +7   import org.slf4j.Logger;
    +8   import org.slf4j.LoggerFactory;
    +9   import org.springframework.beans.factory.annotation.Autowired;
    +10  import org.springframework.beans.factory.annotation.Value;
    +11  import org.springframework.boot.autoconfigure.SpringBootApplication;
    +12  import org.springframework.boot.test.context.SpringBootTest;
    +13  import org.springframework.cache.Cache;
    +14  import org.springframework.context.ApplicationContext;
    +15  import org.springframework.context.annotation.Bean;
    +16  import org.springframework.core.io.Resource;
    +17  import org.springframework.util.MimeType;
    +18  
    +19  import java.time.Duration;
    +20  
    +21  import static org.assertj.core.api.Assertions.assertThat;
    +22  import static org.junit.jupiter.api.Assertions.*;
    +23  import static org.mockserver.model.HttpRequest.request;
    +24  import static org.mockserver.verify.VerificationTimes.exactly;
    +25  
    +26  
    +27  /**
    +28   *
    +29   * @author Kai Moritz
    +30   */
    +31  @SpringBootTest({
    +32      "juplo.http-resources.protocol-resolver.enabled=true",
    +33      "juplo.http-resources.resolver.enabled=false",
    +34      "juplo.http-resources.resolver.exclusion-patterns=**.txt"
    +35      })
    +36  public class HttpResourceChainAwareResourceLoaderIT extends IntegrationTestBase
    +37  {
    +38    private final static Logger LOG =
    +39        LoggerFactory.getLogger(HttpResourceChainAwareResourceLoaderIT.class);
    +40  
    +41  
    +42    @Autowired
    +43    HttpResourceChainAwareResourceLoader loader;
    +44    @Autowired
    +45    Cache cache;
    +46    @Autowired
    +47    HttpResources resources;
    +48  
    +49    @Value("classpath:static/foo")
    +50    Resource foo;
    +51    @Value("classpath:public/bar")
    +52    Resource bar;
    +53    @Value("classpath:remote/hello")
    +54    Resource hello;
    +55    @Value("classpath:remote/remote.html")
    +56    Resource remote;
    +57    @Value("classpath:remote/modified.html")
    +58    Resource modified;
    +59    @Value("classpath:fallback/foobar")
    +60    Resource foobar;
    +61    @Value("classpath:remote/hallo.txt")
    +62    Resource hallo;
    +63  
    +64  
    +65    @BeforeEach
    +66    public void setUp()
    +67    {
    +68      cache.clear();
    +69    }
    +70  
    +71  
    +72    /**
    +73     * In contrast to {@link HttpResourceResolverIT} and
    +74     * {@link HttpResourceProtocolResolverIT} it does not
    +75     * make sense to test through the web-layer here,
    +76     * because the {@link HttpResourceChainAwareResourceLoader}
    +77     * is intended to mimic the look-upp through the source,
    +78     * that are configured for resource-chain for static
    +79     * http-resources for the look-up of local resources.
    +80     */
    +81    @Test
    +82    public void testResourceHandling() throws Exception
    +83    {
    +84      LOG.info("<-- start of test-case");
    +85  
    +86      Resource resource;
    +87  
    +88      resource = loader.getResource("foo");
    +89      assertThat(resource.exists());
    +90      assertThat(resource.getInputStream()).hasSameContentAs(foo.getInputStream());
    +91  
    +92      resource = loader.getResource("bar");
    +93      assertThat(resource.exists());
    +94      assertThat(resource.getInputStream()).hasSameContentAs(bar.getInputStream());
    +95  
    +96      resource = loader.getResource("hello");
    +97      assertThat(resource.exists());
    +98      assertThat(resource).isInstanceOf(HttpResource.class);
    +99      assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("application/octet-stream"));
    +100     assertThat(resource.getInputStream()).hasSameContentAs(hello.getInputStream());
    +101 
    +102     resource = loader.getResource("remote.html");
    +103     assertThat(resource.exists());
    +104     assertThat(resource).isInstanceOf(HttpResource.class);
    +105     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +106     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +107 
    +108     resource = loader.getResource("foobar");
    +109     assertThat(resource.exists());
    +110     assertThat(resource.getInputStream()).hasSameContentAs(foobar.getInputStream());
    +111 
    +112     resource = loader.getResource("/hello");
    +113     assertThat(resource.exists());
    +114     assertThat(resource).isInstanceOf(HttpResource.class);
    +115     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("application/octet-stream"));
    +116     assertThat(resource.getInputStream()).hasSameContentAs(hello.getInputStream());
    +117 
    +118     resource = loader.getResource("hello");
    +119     assertThat(resource.exists());
    +120     assertThat(resource).isInstanceOf(HttpResource.class);
    +121     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("application/octet-stream"));
    +122     assertThat(resource.getInputStream()).hasSameContentAs(hello.getInputStream());
    +123 
    +124     resource = loader.getResource("/hello");
    +125     assertThat(resource.exists());
    +126     assertThat(resource).isInstanceOf(HttpResource.class);
    +127     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("application/octet-stream"));
    +128     assertThat(resource.getInputStream()).hasSameContentAs(hello.getInputStream());
    +129 
    +130     resource = loader.getResource("hallo.txt");
    +131     assertThat(resource.exists());
    +132     assertThat(resource).isInstanceOf(HttpResource.class);
    +133     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/plain"));
    +134     assertThat(resource.getInputStream()).hasSameContentAs(hallo.getInputStream());
    +135 
    +136     server.verify(FETCH("/foo"), exactly(0));
    +137     server.verify(FETCH("/bar"), exactly(0));
    +138     server.verify(FETCH("/hello"), exactly(1));
    +139     server.verify(FETCH("/hallo.txt"), exactly(1));
    +140     server.verify(FETCH("/remote.html"), exactly(1));
    +141     server.verify(FETCH("/foobar"), exactly(2));
    +142   }
    +143 
    +144   @Test
    +145   public void testFetchExistent() throws Exception
    +146   {
    +147     LOG.info("<-- Start of test-case");
    +148 
    +149     getRemoteHtml();
    +150 
    +151     server.verify(FETCH("/remote.html"), exactly(1));
    +152   }
    +153 
    +154   @Test
    +155   public void testCachingOfExisting() throws Exception
    +156   {
    +157     LOG.info("<-- Start of test-case");
    +158 
    +159     getRemoteHtml();
    +160     getRemoteHtml();
    +161     getRemoteHtml();
    +162     getRemoteHtml();
    +163     getRemoteHtml();
    +164     getRemoteHtml();
    +165     getRemoteHtml();
    +166     getRemoteHtml();
    +167 
    +168     server.verify(FETCH("/remote.html"), exactly(1));
    +169   }
    +170 
    +171   private void getRemoteHtml() throws Exception
    +172   {
    +173     Resource resource = loader.getResource("/remote.html");
    +174     assertNotNull(resource);
    +175     assertTrue(resource.exists());
    +176     assertThat(resource).isInstanceOf(HttpResource.class);
    +177     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +178     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +179   }
    +180 
    +181   @Test
    +182   public void testCachingOfModified() throws Exception
    +183   {
    +184     LOG.info("<-- Start of test-case");
    +185 
    +186     Resource resource;
    +187 
    +188     resource = loader.getResource("/remote.html");
    +189     assertNotNull(resource);
    +190     assertTrue(resource.exists());
    +191     assertThat(resource).isInstanceOf(HttpResource.class);
    +192     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +193     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +194 
    +195     CLOCK.timetravel(Duration.ofSeconds(10));
    +196     server.when(FETCH("/remote.html")).forward(NGINX("/modified.html"));
    +197 
    +198     resource = loader.getResource("/remote.html");
    +199     assertNotNull(resource);
    +200     assertTrue(resource.exists());
    +201     assertThat(resource).isInstanceOf(HttpResource.class);
    +202     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +203     assertThat(resource.getInputStream()).hasSameContentAs(modified.getInputStream());
    +204 
    +205     server.verify(FETCH("/remote.html"), exactly(2));
    +206     server.verify(
    +207         request()
    +208             .withPath("/remote.html")
    +209             .withHeader("If-Modified-Since")
    +210             .withHeader("If-None-Match"),
    +211         exactly(1));
    +212   }
    +213 
    +214   @Test
    +215   public void testFetchNonExistent() throws Exception
    +216   {
    +217     LOG.info("<-- Start of test-case");
    +218 
    +219     getNonExistingHtml();
    +220 
    +221     server.verify(FETCH("/peter.html"), exactly(2));
    +222   }
    +223 
    +224   @Test
    +225   public void testCachingOfNonExistent() throws Exception
    +226   {
    +227     LOG.info("<-- Start of test-case");
    +228 
    +229     getNonExistingHtml();
    +230     getNonExistingHtml();
    +231     getNonExistingHtml();
    +232     getNonExistingHtml();
    +233     getNonExistingHtml();
    +234     getNonExistingHtml();
    +235     getNonExistingHtml();
    +236 
    +237     // Remote-requests answered with 404 are repeated
    +238     server.verify(FETCH("/peter.html"), exactly(14));
    +239   }
    +240 
    +241   private void getNonExistingHtml() throws Exception
    +242   {
    +243     Resource resource = loader.getResource("/peter.html");
    +244     assertNotNull(resource);
    +245     assertFalse(resource.exists());
    +246   }
    +247 
    +248   @Test
    +249   public void testFetchServerResponse500() throws Exception
    +250   {
    +251     LOG.info("<-- Start of test-case");
    +252 
    +253     server.when(FETCH("/peter.html")).respond(INTERNAL_SERVER_ERROR());
    +254 
    +255     Resource resource = loader.getResource(address("/peter.html"));
    +256 
    +257     assertThat(resource.exists()).isFalse();
    +258     server.verify(FETCH("/peter.html"), exactly(2));
    +259   }
    +260 
    +261   @Test
    +262   public void testCaching() throws Exception
    +263   {
    +264     LOG.info("<-- Start of test-case");
    +265 
    +266     Resource resource;
    +267 
    +268     LOG.debug("First access /remote.html");
    +269     resource= loader.getResource("/remote.html");
    +270     assertThat(resource.exists()).isTrue();
    +271     assertThat(resource).isInstanceOf(HttpResource.class);
    +272     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +273     assertThat(((HttpResource)resource).isModified()).isFalse();
    +274     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +275 
    +276     LOG.debug("Second access to /remote.html");
    +277     resource= loader.getResource("/remote.html");
    +278     assertThat(resource.exists()).isTrue();
    +279     assertThat(resource).isInstanceOf(HttpResource.class);
    +280     assertThat(((HttpResource)resource).isModified()).isFalse();
    +281     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +282     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +283 
    +284     LOG.debug("Third access /remote.html");
    +285     resource= loader.getResource("/remote.html");
    +286     assertThat(resource.exists()).isTrue();
    +287     assertThat(resource).isInstanceOf(HttpResource.class);
    +288     assertThat(((HttpResource)resource).isModified()).isFalse();
    +289     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +290     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +291 
    +292     LOG.debug("First access to remote.html");
    +293     resource= loader.getResource("remote.html");
    +294     assertThat(resource.exists()).isTrue();
    +295     assertThat(resource).isInstanceOf(HttpResource.class);
    +296     assertThat(((HttpResource)resource).isModified()).isFalse();
    +297     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +298     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +299 
    +300     LOG.debug("Fourth access to /remote.html after a pause of 10 seconds -- resource should be expired");
    +301     CLOCK.timetravel(Duration.ofSeconds(10));
    +302     assertThat(resource.exists()).isTrue();
    +303     assertThat(resource).isInstanceOf(HttpResource.class);
    +304     assertThat(((HttpResource)resource).isModified()).isFalse();
    +305     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +306     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +307 
    +308     LOG.debug("Fifth access /remote.html");
    +309     resource= loader.getResource("/remote.html");
    +310     assertThat(resource.exists()).isTrue();
    +311     assertThat(resource).isInstanceOf(HttpResource.class);
    +312     assertThat(((HttpResource)resource).isModified()).isFalse();
    +313     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +314     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +315 
    +316     LOG.debug("Sixth access /remote.html");
    +317     resource= loader.getResource("/remote.html");
    +318     assertThat(resource.exists()).isTrue();
    +319     assertThat(resource).isInstanceOf(HttpResource.class);
    +320     assertThat(((HttpResource)resource).isModified()).isFalse();
    +321     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +322     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +323 
    +324     LOG.debug("Second access /remote.html");
    +325     resource= loader.getResource("remote.html");
    +326     assertThat(resource.exists()).isTrue();
    +327     assertThat(resource).isInstanceOf(HttpResource.class);
    +328     assertThat(((HttpResource)resource).isModified()).isFalse();
    +329     assertThat(((HttpResource)resource).contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +330     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +331 
    +332     server.verify(FETCH("/remote.html"), exactly(2));
    +333     server.verify(
    +334         request()
    +335             .withPath("/remote.html")
    +336             .withHeader("If-Modified-Since")
    +337             .withHeader("If-None-Match"),
    +338         exactly(1));
    +339   }
    +340 
    +341 
    +342   @SpringBootApplication
    +343   static class Application
    +344   {
    +345     @Bean
    +346     public HttpResourceChainAwareResourceLoader httpResourceChainAwareResourceLoader(
    +347         ClientAndServer server,
    +348         ApplicationContext context)
    +349     {
    +350       return new HttpResourceChainAwareResourceLoader(
    +351           context,
    +352           new String[]
    +353           {
    +354               "classpath:/static/",
    +355               "classpath:/public/",
    +356               "http://localhost:" + server.getLocalPort(),
    +357               "classpath:/fallback/"
    +358           });
    +359     }
    +360   }
    +361 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderTest.html new file mode 100644 index 00000000..c9869b11 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderTest.html @@ -0,0 +1,190 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceChainAwareResourceLoaderTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.Test;
    +4   import org.junit.jupiter.api.extension.ExtendWith;
    +5   import org.mockito.Mock;
    +6   import org.mockito.junit.jupiter.MockitoExtension;
    +7   import org.mockito.junit.jupiter.MockitoSettings;
    +8   import org.mockito.quality.Strictness;
    +9   import org.slf4j.Logger;
    +10  import org.slf4j.LoggerFactory;
    +11  import org.springframework.core.io.Resource;
    +12  import org.springframework.web.context.WebApplicationContext;
    +13  
    +14  import static org.assertj.core.api.Assertions.assertThat;
    +15  import static org.mockito.ArgumentMatchers.eq;
    +16  import static org.mockito.Mockito.*;
    +17  
    +18  
    +19  @ExtendWith({ MockitoExtension.class })
    +20  @MockitoSettings(strictness = Strictness.LENIENT)
    +21  public class HttpResourceChainAwareResourceLoaderTest
    +22  {
    +23    private static final Logger LOG =
    +24        LoggerFactory.getLogger(HttpResourceChainAwareResourceLoaderTest.class);
    +25  
    +26  
    +27    @Test
    +28    public void testResourceExistsForaLocation(
    +29        @Mock WebApplicationContext context,
    +30        @Mock Resource existing,
    +31        @Mock Resource nonExisting)
    +32    {
    +33      LOG.info("<-- start of test-case");
    +34  
    +35      HttpResourceChainAwareResourceLoader loader =
    +36          new HttpResourceChainAwareResourceLoader(context, new String[] { "A/", "B/", "C/" });
    +37  
    +38      when(context.getResource(eq("A/PATH"))).thenReturn(existing);
    +39      when(context.getResource(eq("B/PATH"))).thenReturn(nonExisting);
    +40      when(context.getResource(eq("C/PATH"))).thenReturn(nonExisting);
    +41      when(context.getResource(eq("PATH"))).thenReturn(nonExisting);
    +42      when(existing.exists()).thenReturn(true);
    +43      when(nonExisting.exists()).thenReturn(false);
    +44  
    +45      assertThat(loader.getResource("PATH")).isSameAs(existing);
    +46  
    +47      verify(context, times(1)).getResource(eq("A/PATH"));
    +48      verify(context, never()).getResource(eq("B/PATH"));
    +49      verify(context, never()).getResource(eq("C/PATH"));
    +50      verify(context, never()).getResource(eq("PATH"));
    +51    }
    +52  
    +53    @Test
    +54    public void testResourceExistsForSecondLocation(
    +55        @Mock WebApplicationContext context,
    +56        @Mock Resource existing,
    +57        @Mock Resource nonExisting)
    +58    {
    +59      LOG.info("<-- start of test-case");
    +60  
    +61      HttpResourceChainAwareResourceLoader loader =
    +62          new HttpResourceChainAwareResourceLoader(context, new String[] { "A/", "B/", "C/" });
    +63  
    +64      when(context.getResource(eq("A/PATH"))).thenReturn(nonExisting);
    +65      when(context.getResource(eq("B/PATH"))).thenReturn(existing);
    +66      when(context.getResource(eq("C/PATH"))).thenReturn(nonExisting);
    +67      when(context.getResource(eq("PATH"))).thenReturn(nonExisting);
    +68      when(existing.exists()).thenReturn(true);
    +69      when(nonExisting.exists()).thenReturn(false);
    +70  
    +71      assertThat(loader.getResource("PATH")).isSameAs(existing);
    +72  
    +73      verify(context, times(1)).getResource(eq("A/PATH"));
    +74      verify(context, times(1)).getResource(eq("B/PATH"));
    +75      verify(context, never()).getResource(eq("C/PATH"));
    +76      verify(context, never()).getResource(eq("PATH"));
    +77    }
    +78  
    +79    @Test
    +80    public void testResourceExistsForThirdLocation(
    +81        @Mock WebApplicationContext context,
    +82        @Mock Resource existing,
    +83        @Mock Resource nonExisting)
    +84    {
    +85      LOG.info("<-- start of test-case");
    +86  
    +87      HttpResourceChainAwareResourceLoader loader =
    +88          new HttpResourceChainAwareResourceLoader(context, new String[] { "A/", "B/", "C/" });
    +89  
    +90      when(context.getResource(eq("A/PATH"))).thenReturn(nonExisting);
    +91      when(context.getResource(eq("B/PATH"))).thenReturn(nonExisting);
    +92      when(context.getResource(eq("C/PATH"))).thenReturn(existing);
    +93      when(context.getResource(eq("PATH"))).thenReturn(nonExisting);
    +94      when(existing.exists()).thenReturn(true);
    +95      when(nonExisting.exists()).thenReturn(false);
    +96  
    +97      assertThat(loader.getResource("PATH")).isSameAs(existing);
    +98  
    +99      verify(context, times(1)).getResource(eq("A/PATH"));
    +100     verify(context, times(1)).getResource(eq("B/PATH"));
    +101     verify(context, times(1)).getResource(eq("C/PATH"));
    +102     verify(context, never()).getResource(eq("PATH"));
    +103   }
    +104 
    +105   @Test
    +106   public void testResourceDoesNotExist(
    +107       @Mock WebApplicationContext context,
    +108       @Mock Resource nonExisting,
    +109       @Mock Resource other)
    +110   {
    +111     LOG.info("<-- start of test-case");
    +112 
    +113     HttpResourceChainAwareResourceLoader loader =
    +114         new HttpResourceChainAwareResourceLoader(context, new String[] { "A/", "B/", "C/" });
    +115 
    +116     when(context.getResource(eq("A/PATH"))).thenReturn(nonExisting);
    +117     when(context.getResource(eq("B/PATH"))).thenReturn(nonExisting);
    +118     when(context.getResource(eq("C/PATH"))).thenReturn(nonExisting);
    +119     when(context.getResource(eq("PATH"))).thenReturn(other);
    +120     when(nonExisting.exists()).thenReturn(false);
    +121 
    +122     assertThat(loader.getResource("PATH")).isSameAs(other);
    +123 
    +124     verify(context, times(1)).getResource(eq("A/PATH"));
    +125     verify(context, times(1)).getResource(eq("B/PATH"));
    +126     verify(context, times(1)).getResource(eq("C/PATH"));
    +127     verify(context, times(1)).getResource(eq("PATH"));
    +128   }
    +129 
    +130   @Test
    +131   public void testHandlingOfLeadingSlashesInResourceNames(
    +132       @Mock WebApplicationContext context,
    +133       @Mock Resource nonExisting,
    +134       @Mock Resource other)
    +135   {
    +136     LOG.info("<-- start of test-case");
    +137 
    +138     HttpResourceChainAwareResourceLoader loader =
    +139         new HttpResourceChainAwareResourceLoader(context, new String[] { "A/", "B/" });
    +140 
    +141     when(context.getResource(startsWith("A"))).thenReturn(nonExisting);
    +142     when(context.getResource(startsWith("B"))).thenReturn(nonExisting);
    +143     when(context.getResource(eq("/PATH/WITH/LEADING/SLASH"))).thenReturn(other);
    +144     when(nonExisting.exists()).thenReturn(false);
    +145 
    +146     assertThat(loader.getResource("/PATH/WITH/LEADING/SLASH")).isSameAs(other);
    +147 
    +148     verify(context, times(1)).getResource(eq("A/PATH/WITH/LEADING/SLASH"));
    +149     verify(context, times(1)).getResource(eq("B/PATH/WITH/LEADING/SLASH"));
    +150     verify(context, times(1)).getResource(eq("/PATH/WITH/LEADING/SLASH"));
    +151   }
    +152 
    +153   @Test
    +154   public void testHandlingOfTrailingSlashesInResourceLocations(
    +155       @Mock WebApplicationContext context,
    +156       @Mock Resource nonExisting,
    +157       @Mock Resource other)
    +158   {
    +159     LOG.info("<-- start of test-case");
    +160 
    +161     HttpResourceChainAwareResourceLoader loader =
    +162         new HttpResourceChainAwareResourceLoader(context, new String[] { "A/", "B", "C//" });
    +163 
    +164     when(context.getResource(startsWith("A"))).thenReturn(nonExisting);
    +165     when(context.getResource(startsWith("B"))).thenReturn(nonExisting);
    +166     when(context.getResource(startsWith("C"))).thenReturn(nonExisting);
    +167     when(context.getResource(eq("/PATH/WITH/LEADING/SLASH"))).thenReturn(other);
    +168     when(nonExisting.exists()).thenReturn(false);
    +169 
    +170     assertThat(loader.getResource("/PATH/WITH/LEADING/SLASH")).isSameAs(other);
    +171 
    +172     verify(context, times(1)).getResource(eq("A/PATH/WITH/LEADING/SLASH"));
    +173     verify(context, times(1)).getResource(eq("B/PATH/WITH/LEADING/SLASH"));
    +174     verify(context, times(1)).getResource(eq("C//PATH/WITH/LEADING/SLASH"));
    +175     verify(context, times(1)).getResource(eq("/PATH/WITH/LEADING/SLASH"));
    +176   }
    +177 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchModifiedTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchModifiedTest.html new file mode 100644 index 00000000..ed5f64b3 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchModifiedTest.html @@ -0,0 +1,184 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceExpiredFetchModifiedTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.beans.factory.annotation.Autowired;
    +14  import org.springframework.cache.Cache;
    +15  import org.springframework.cache.support.NoOpCache;
    +16  import org.springframework.http.HttpHeaders;
    +17  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +18  
    +19  import java.net.URI;
    +20  import java.time.Clock;
    +21  import java.time.ZoneId;
    +22  
    +23  import static de.juplo.httpresources.TestUtil.*;
    +24  import static org.assertj.core.api.Assertions.assertThat;
    +25  import static org.mockito.ArgumentMatchers.any;
    +26  import static org.mockito.Mockito.when;
    +27  
    +28  
    +29  @DisplayName(("HttpResource - Expired - Fetch: Modified"))
    +30  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +31  @MockitoSettings(strictness = Strictness.LENIENT)
    +32  public class HttpResourceExpiredFetchModifiedTest
    +33  {
    +34    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceExpiredFetchModifiedTest.class);
    +35  
    +36    @Mock
    +37    HttpResourceFetcher fetcher;
    +38  
    +39    HttpResources resources;
    +40    URI uri;
    +41    HttpResource resource;
    +42  
    +43  
    +44    /************** SETUP */
    +45  
    +46    @BeforeEach
    +47    public void setUp()
    +48    {
    +49      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +50      resources = new HttpResources(fetcher, clock);
    +51      uri = URI.create("http://foo/bar");
    +52      resource = new HttpResource(resources, fetcher, clock, uri);
    +53      resource.data = DATA_EXPIRED;
    +54  
    +55      // Everything is possible, nothing is necessary: Only defines behavior!
    +56  
    +57      HttpHeaders headers = new HttpHeaders();
    +58      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +59  
    +60      when(fetcher.fetch(any(), any())).thenReturn(DATA_UPDATED);
    +61    }
    +62  
    +63  
    +64    /*************** For calls, that do not trigger a fetch see: HttpResourceNotExpiredTest */
    +65  
    +66  
    +67    /*************** Results for calls, that did trigger a fetch */
    +68  
    +69    @Test
    +70    @DisplayName(("fetch() reports modifications"))
    +71    public void test_fetch_ReportsModifications()
    +72    {
    +73      LOG.info("<-- start of test-case");
    +74  
    +75      assertThat(resource.fetch()).isTrue();
    +76    }
    +77  
    +78    @Test
    +79    @DisplayName(("exists() is true"))
    +80    public void test_exists_IsTrue()
    +81    {
    +82      LOG.info("<-- start of test-case");
    +83  
    +84      assertThat(resource.exists()).isTrue();
    +85    }
    +86  
    +87    @Test
    +88    @DisplayName(("readable() is true"))
    +89    public void test_isReadable_IsTrue()
    +90    {
    +91      LOG.info("<-- start of test-case");
    +92  
    +93      assertThat(resource.isReadable()).isTrue();
    +94    }
    +95  
    +96    @Test
    +97    @DisplayName(("isModified() reports modifications"))
    +98    public void test_isModified_ReportsModifications()
    +99    {
    +100     LOG.info("<-- start of test-case");
    +101 
    +102     assertThat(resource.isModified()).isTrue();
    +103   }
    +104 
    +105   @Test
    +106   @DisplayName(("getInputStream() returns expected content"))
    +107   public void test_hasExpectedContent() throws Exception
    +108   {
    +109     LOG.info("<-- start of test-case");
    +110 
    +111     assertThat(resource.getInputStream()).hasContent(STR_CONTENT_MODIFIED);
    +112   }
    +113 
    +114 
    +115   /*************** Expected state after calls, that did trigger a fetch */
    +116 
    +117   @Test
    +118   @DisplayName(("fetch() updates data"))
    +119   public void test_fetch_UpdatesData()
    +120   {
    +121     LOG.info("<-- start of test-case");
    +122 
    +123     resource.fetch();
    +124 
    +125     assertThat(resource.data).isSameAs(DATA_UPDATED);
    +126   }
    +127 
    +128   @Test
    +129   @DisplayName(("exists() updates data"))
    +130   public void test_exists_UpdatesData()
    +131   {
    +132     LOG.info("<-- start of test-case");
    +133 
    +134     resource.exists();
    +135 
    +136     assertThat(resource.data).isSameAs(DATA_UPDATED);
    +137   }
    +138 
    +139   @Test
    +140   @DisplayName(("isReadable() updates data"))
    +141   public void test_isReadable_UpdatesData()
    +142   {
    +143     LOG.info("<-- start of test-case");
    +144 
    +145     resource.isReadable();
    +146 
    +147     assertThat(resource.data).isSameAs(DATA_UPDATED);
    +148   }
    +149 
    +150   @Test
    +151   @DisplayName(("isModified() updates data"))
    +152   public void test_isModified_UpdatesData()
    +153   {
    +154     LOG.info("<-- start of test-case");
    +155 
    +156     resource.isModified();
    +157 
    +158     assertThat(resource.data).isSameAs(DATA_UPDATED);
    +159   }
    +160 
    +161   @Test
    +162   @DisplayName(("getInputStream() updates data"))
    +163   public void test_getInputStream_UpdatesData() throws Exception
    +164   {
    +165     LOG.info("<-- start of test-case");
    +166 
    +167     resource.getInputStream();
    +168 
    +169     assertThat(resource.data).isSameAs(DATA_UPDATED);
    +170   }
    +171 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchNotFoundTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchNotFoundTest.html new file mode 100644 index 00000000..7fff14c1 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchNotFoundTest.html @@ -0,0 +1,188 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceExpiredFetchNotFoundTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.io.FileNotFoundException;
    +18  import java.net.URI;
    +19  import java.time.Clock;
    +20  import java.time.ZoneId;
    +21  
    +22  import static de.juplo.httpresources.TestUtil.*;
    +23  import static org.assertj.core.api.Assertions.assertThat;
    +24  import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
    +25  import static org.mockito.ArgumentMatchers.any;
    +26  import static org.mockito.Mockito.when;
    +27  
    +28  
    +29  @DisplayName(("HttpResource - Expired - Fetch: Not Found"))
    +30  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +31  @MockitoSettings(strictness = Strictness.LENIENT)
    +32  public class HttpResourceExpiredFetchNotFoundTest
    +33  {
    +34    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceExpiredFetchNotFoundTest.class);
    +35  
    +36    @Mock
    +37    HttpResourceFetcher fetcher;
    +38  
    +39    HttpResources resources;
    +40    URI uri;
    +41    HttpResource resource;
    +42  
    +43  
    +44    /************** SETUP */
    +45  
    +46    @BeforeEach
    +47    public void setUp()
    +48    {
    +49      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +50      resources = new HttpResources(fetcher, clock);
    +51      uri = URI.create("http://foo/bar");
    +52      resource = new HttpResource(resources, fetcher, clock, uri);
    +53      resource.data = DATA_EXPIRED;
    +54  
    +55      // Everything is possible, nothing is necessary: Only defines behavior!
    +56  
    +57      HttpHeaders headers = new HttpHeaders();
    +58      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +59  
    +60      when(fetcher.fetch(any(), any())).thenReturn(DATA_NOT_FOUND);
    +61    }
    +62  
    +63  
    +64    /*************** For calls, that do not trigger a fetch see: HttpResourceNotExpiredTest */
    +65  
    +66  
    +67    /*************** Results for calls, that did trigger a fetch */
    +68  
    +69    @Test
    +70    @DisplayName(("fetch() reports modifications"))
    +71    public void test_fetch_ReportsModifications()
    +72    {
    +73      LOG.info("<-- start of test-case");
    +74  
    +75      assertThat(resource.fetch()).isTrue();
    +76    }
    +77  
    +78    @Test
    +79    @DisplayName(("exists() is false"))
    +80    public void test_exists_ReportsFalse()
    +81    {
    +82      LOG.info("<-- start of test-case");
    +83  
    +84      assertThat(resource.exists()).isFalse();
    +85    }
    +86  
    +87    @Test
    +88    @DisplayName(("isReadable() is false"))
    +89    public void test_isReadable_ReportsFalse()
    +90    {
    +91      LOG.info("<-- start of test-case");
    +92  
    +93      assertThat(resource.isReadable()).isFalse();
    +94    }
    +95  
    +96    @Test
    +97    @DisplayName(("isModified() reports modifications"))
    +98    public void test_isModified_ReportsModifications()
    +99    {
    +100     LOG.info("<-- start of test-case");
    +101 
    +102     assertThat(resource.isModified()).isTrue();
    +103   }
    +104 
    +105   @Test
    +106   @DisplayName(("getInputStream() throws FileNotFoundException"))
    +107   public void test_HasNoContent()
    +108   {
    +109     LOG.info("<-- start of test-case");
    +110 
    +111     assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> resource.getInputStream());
    +112   }
    +113 
    +114 
    +115   /*************** Expected state after calls, that did trigger a fetch */
    +116 
    +117   @Test
    +118   @DisplayName(("fetch() updates data"))
    +119   public void test_fetch_UpdatesData()
    +120   {
    +121     LOG.info("<-- start of test-case");
    +122 
    +123     resource.fetch();
    +124 
    +125     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +126   }
    +127 
    +128   @Test
    +129   @DisplayName(("exists() updates data"))
    +130   public void test_exists_UpdatesData()
    +131   {
    +132     LOG.info("<-- start of test-case");
    +133 
    +134     resource.exists();
    +135 
    +136     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +137   }
    +138 
    +139   @Test
    +140   @DisplayName(("isReadable() updates data"))
    +141   public void test_isReadable_UpdatesData()
    +142   {
    +143     LOG.info("<-- start of test-case");
    +144 
    +145     resource.isReadable();
    +146 
    +147     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +148   }
    +149 
    +150   @Test
    +151   @DisplayName(("isModified() updates data"))
    +152   public void test_isModified_UpdatesData()
    +153   {
    +154     LOG.info("<-- start of test-case");
    +155 
    +156     resource.isModified();
    +157 
    +158     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +159   }
    +160 
    +161   @Test
    +162   @DisplayName(("getInputStream() updates data"))
    +163   public void test_getInputStream_UpdatesData()
    +164   {
    +165     LOG.info("<-- start of test-case");
    +166 
    +167     try
    +168     {
    +169       resource.getInputStream();
    +170     }
    +171     catch(Exception e) {}
    +172 
    +173     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +174   }
    +175 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchServerErrorTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchServerErrorTest.html new file mode 100644 index 00000000..5b9a6d6a --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchServerErrorTest.html @@ -0,0 +1,186 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceExpiredFetchServerErrorTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.io.FileNotFoundException;
    +18  import java.net.URI;
    +19  import java.time.Clock;
    +20  import java.time.ZoneId;
    +21  
    +22  import static de.juplo.httpresources.HttpData.SERVER_ERROR;
    +23  import static de.juplo.httpresources.TestUtil.*;
    +24  import static org.assertj.core.api.Assertions.assertThat;
    +25  import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
    +26  import static org.mockito.ArgumentMatchers.any;
    +27  import static org.mockito.Mockito.when;
    +28  
    +29  
    +30  @DisplayName(("HttpResource - Expired - Fetch: Server Error"))
    +31  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +32  @MockitoSettings(strictness = Strictness.LENIENT)
    +33  public class HttpResourceExpiredFetchServerErrorTest
    +34  {
    +35    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceExpiredFetchServerErrorTest.class);
    +36  
    +37    @Mock
    +38    HttpResourceFetcher fetcher;
    +39  
    +40    HttpResources resources;
    +41    URI uri;
    +42    HttpResource resource;
    +43  
    +44  
    +45    /************** SETUP */
    +46  
    +47    @BeforeEach
    +48    public void setUp()
    +49    {
    +50      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +51      resources = new HttpResources(fetcher, clock);
    +52      uri = URI.create("http://foo/bar");
    +53      resource = new HttpResource(resources, fetcher, clock, uri);
    +54      resource.data = DATA_EXPIRED;
    +55  
    +56      // Everything is possible, nothing is necessary: Only defines behavior!
    +57  
    +58      HttpHeaders headers = new HttpHeaders();
    +59      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +60  
    +61      when(fetcher.fetch(any(), any())).thenReturn(SERVER_ERROR);
    +62    }
    +63  
    +64  
    +65    /*************** Results for calls, that did trigger a fetch */
    +66  
    +67    @Test
    +68    @DisplayName(("fetch() reports modifications"))
    +69    public void test_fetch_ReportsModifications()
    +70    {
    +71      LOG.info("<-- start of test-case");
    +72  
    +73      assertThat(resource.fetch()).isTrue();
    +74    }
    +75  
    +76    @Test
    +77    @DisplayName(("exists() is false"))
    +78    public void test_exists_ReportsFalse()
    +79    {
    +80      LOG.info("<-- start of test-case");
    +81  
    +82      assertThat(resource.exists()).isFalse();
    +83    }
    +84  
    +85    @Test
    +86    @DisplayName(("isReadable() is false"))
    +87    public void test_isReadable_ReportsFalse()
    +88    {
    +89      LOG.info("<-- start of test-case");
    +90  
    +91      assertThat(resource.isReadable()).isFalse();
    +92    }
    +93  
    +94    @Test
    +95    @DisplayName(("isModified() reports modifications"))
    +96    public void test_isModified_ReportsModifications()
    +97    {
    +98      LOG.info("<-- start of test-case");
    +99  
    +100     assertThat(resource.isModified()).isTrue();
    +101   }
    +102 
    +103   @Test
    +104   @DisplayName(("getInputStream() throws FileNotFoundException"))
    +105   public void test_HasNoContent()
    +106   {
    +107     LOG.info("<-- start of test-case");
    +108 
    +109     assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> resource.getInputStream());
    +110   }
    +111 
    +112 
    +113   /*************** Expected state after calls, that did trigger a fetch */
    +114 
    +115   @Test
    +116   @DisplayName(("fetch() updates data"))
    +117   public void test_fetch_UpdatesData()
    +118   {
    +119     LOG.info("<-- start of test-case");
    +120 
    +121     resource.fetch();
    +122 
    +123     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +124   }
    +125 
    +126   @Test
    +127   @DisplayName(("exists() updates data"))
    +128   public void test_exists_UpdatesData()
    +129   {
    +130     LOG.info("<-- start of test-case");
    +131 
    +132     resource.exists();
    +133 
    +134     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +135   }
    +136 
    +137   @Test
    +138   @DisplayName(("isReadable() updates data"))
    +139   public void test_isReadable_UpdatesData()
    +140   {
    +141     LOG.info("<-- start of test-case");
    +142 
    +143     resource.isReadable();
    +144 
    +145     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +146   }
    +147 
    +148   @Test
    +149   @DisplayName(("isModified() updates data"))
    +150   public void test_isModified_UpdatesData()
    +151   {
    +152     LOG.info("<-- start of test-case");
    +153 
    +154     resource.isModified();
    +155 
    +156     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +157   }
    +158 
    +159   @Test
    +160   @DisplayName(("getInputStream() updates data"))
    +161   public void test_getInputStream_UpdatesData()
    +162   {
    +163     LOG.info("<-- start of test-case");
    +164 
    +165     try
    +166     {
    +167       resource.getInputStream();
    +168     }
    +169     catch(Exception e) {}
    +170 
    +171     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +172   }
    +173 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchUnmodifiedTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchUnmodifiedTest.html new file mode 100644 index 00000000..816b11e6 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredFetchUnmodifiedTest.html @@ -0,0 +1,170 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceExpiredFetchUnmodifiedTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.TestUtil.*;
    +22  import static org.assertj.core.api.Assertions.assertThat;
    +23  import static org.mockito.ArgumentMatchers.any;
    +24  import static org.mockito.Mockito.*;
    +25  
    +26  
    +27  @DisplayName(("HttpResource - Expired - Fetch: Unmodified"))
    +28  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +29  @MockitoSettings(strictness = Strictness.LENIENT)
    +30  public class HttpResourceExpiredFetchUnmodifiedTest
    +31  {
    +32    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceExpiredFetchUnmodifiedTest.class);
    +33  
    +34    @Mock
    +35    HttpResourceFetcher fetcher;
    +36  
    +37    HttpResources resources;
    +38    URI uri;
    +39    HttpResource resource;
    +40  
    +41  
    +42    /************** SETUP */
    +43  
    +44    @BeforeEach
    +45    public void setUp()
    +46    {
    +47      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +48      resources = new HttpResources(fetcher, clock);
    +49      uri = URI.create("http://foo/bar");
    +50      resource = new HttpResource(resources, fetcher, clock, uri);
    +51      resource.data = DATA_EXPIRED;
    +52  
    +53      // Everything is possible, nothing is necessary: Only defines behavior!
    +54  
    +55      HttpHeaders headers = new HttpHeaders();
    +56      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +57  
    +58      when(fetcher.fetch(any(), any())).thenReturn(DATA_EXPIRED_DUMMY);
    +59    }
    +60  
    +61  
    +62    /*************** Results for calls, that did trigger a fetch */
    +63  
    +64    @Test
    +65    @DisplayName(("fetch() reports no modification"))
    +66    public void test_fetch_ReportsNoModifications()
    +67    {
    +68      LOG.info("<-- start of test-case");
    +69  
    +70      assertThat(resource.fetch()).isFalse();
    +71    }
    +72  
    +73    @Test
    +74    @DisplayName(("exists() is true"))
    +75    public void test_exists_IsTrue()
    +76    {
    +77      LOG.info("<-- start of test-case");
    +78  
    +79      assertThat(resource.exists()).isTrue();
    +80    }
    +81  
    +82    @Test
    +83    @DisplayName(("readable() is true"))
    +84    public void test_isReadable_IsTrue()
    +85    {
    +86      LOG.info("<-- start of test-case");
    +87  
    +88      assertThat(resource.isReadable()).isTrue();
    +89    }
    +90  
    +91    @Test
    +92    @DisplayName(("isModified() reports no modification"))
    +93    public void test_isModified_ReportsNoModifications()
    +94    {
    +95      LOG.info("<-- start of test-case");
    +96  
    +97      assertThat(resource.isModified()).isFalse();
    +98    }
    +99  
    +100 
    +101   /*************** Expected state after calls, that did trigger a fetch */
    +102 
    +103   @Test
    +104   @DisplayName(("fetch() updates data"))
    +105   public void test_fetch_UpdatesData()
    +106   {
    +107     LOG.info("<-- start of test-case");
    +108 
    +109     resource.fetch();
    +110 
    +111     assertThat(resource.data).isSameAs(DATA_EXPIRED_DUMMY);
    +112   }
    +113 
    +114   @Test
    +115   @DisplayName(("exists() updates data"))
    +116   public void test_exists_UpdatesData()
    +117   {
    +118     LOG.info("<-- start of test-case");
    +119 
    +120     resource.exists();
    +121 
    +122     assertThat(resource.data).isSameAs(DATA_EXPIRED_DUMMY);
    +123   }
    +124 
    +125   @Test
    +126   @DisplayName(("isReadable() updates data"))
    +127   public void test_isReadable_UpdatesData()
    +128   {
    +129     LOG.info("<-- start of test-case");
    +130 
    +131     resource.isReadable();
    +132 
    +133     assertThat(resource.data).isSameAs(DATA_EXPIRED_DUMMY);
    +134   }
    +135 
    +136   @Test
    +137   @DisplayName(("isModified() updates data"))
    +138   public void test_isModified_UpdatesData()
    +139   {
    +140     LOG.info("<-- start of test-case");
    +141 
    +142     resource.isModified();
    +143 
    +144     assertThat(resource.data).isSameAs(DATA_EXPIRED_DUMMY);
    +145   }
    +146 
    +147   @Test
    +148   @DisplayName(("getInputStream() updates data"))
    +149   public void test_getInputStream_UpdatesData() throws Exception
    +150   {
    +151     LOG.info("<-- start of test-case");
    +152 
    +153     resource.getInputStream();
    +154 
    +155     assertThat(resource.data).isSameAs(DATA_EXPIRED_DUMMY);
    +156   }
    +157 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredTest.html new file mode 100644 index 00000000..dc090554 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceExpiredTest.html @@ -0,0 +1,306 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceExpiredTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.TestUtil.*;
    +22  import static org.assertj.core.api.Assertions.assertThat;
    +23  import static org.mockito.ArgumentMatchers.any;
    +24  import static org.mockito.ArgumentMatchers.eq;
    +25  import static org.mockito.Mockito.*;
    +26  
    +27  
    +28  @DisplayName(("HttpResource - Expired"))
    +29  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +30  @MockitoSettings(strictness = Strictness.LENIENT)
    +31  public class HttpResourceExpiredTest
    +32  {
    +33    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceExpiredTest.class);
    +34  
    +35    @Mock
    +36    HttpResourceFetcher fetcher;
    +37  
    +38    HttpResources resources;
    +39    URI uri;
    +40    HttpResource resource;
    +41  
    +42  
    +43    /************** SETUP */
    +44  
    +45    @BeforeEach
    +46    public void setUp()
    +47    {
    +48      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +49      resources = new HttpResources(fetcher, clock);
    +50      uri = URI.create("http://foo/bar");
    +51      resource = new HttpResource(resources, fetcher, clock, uri);
    +52      resource.data = DATA_EXPIRED;
    +53  
    +54      // Everything is possible, nothing is necessary: Only defines behavior!
    +55  
    +56      HttpHeaders headers = new HttpHeaders();
    +57      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +58  
    +59      when(fetcher.fetch(any(), any())).thenReturn(DATA_EXPIRED_DUMMY);
    +60    }
    +61  
    +62  
    +63    /*************** Calls, that trigger a fetch */
    +64  
    +65    @Test
    +66    @DisplayName(("call to fetch() triggers fetch"))
    +67    public void test_fetch_TriggersFetch()
    +68    {
    +69      LOG.info("<-- start of test-case");
    +70  
    +71      resource.fetch();
    +72  
    +73      // Do not verify implementation: Only verify necessary outcome!
    +74      verify(fetcher).fetch(eq(uri), any());
    +75    }
    +76  
    +77    @Test
    +78    @DisplayName(("call to exists() triggers fetch"))
    +79    public void test_exists_TriggersFetch()
    +80    {
    +81      LOG.info("<-- start of test-case");
    +82  
    +83      resource.exists();
    +84  
    +85      // Do not verify implementation: Only verify necessary outcome!
    +86      verify(fetcher).fetch(eq(uri), any());
    +87    }
    +88  
    +89    @Test
    +90    @DisplayName(("call to isReadable() triggers fetch"))
    +91    public void test_isReadable_TriggersFetch()
    +92    {
    +93      LOG.info("<-- start of test-case");
    +94  
    +95      resource.isReadable();
    +96  
    +97      // Do not verify implementation: Only verify necessary outcome!
    +98      verify(fetcher).fetch(eq(uri), any());
    +99    }
    +100 
    +101   @Test
    +102   @DisplayName(("call to isModified() triggers fetch"))
    +103   public void test_isModified_TriggersFetch()
    +104   {
    +105     LOG.info("<-- start of test-case");
    +106 
    +107     resource.isModified();
    +108 
    +109     // Do not verify implementation: Only verify necessary outcome!
    +110     verify(fetcher).fetch(eq(uri), any());
    +111   }
    +112 
    +113   @Test
    +114   @DisplayName(("call to getInputStream() triggers fetch"))
    +115   public void test_getInputStream_TriggersFetch() throws Exception
    +116   {
    +117     LOG.info("<-- start of test-case");
    +118 
    +119     resource.getInputStream();
    +120 
    +121     // Do not verify implementation: Only verify necessary outcome!
    +122     verify(fetcher).fetch(eq(uri), any());
    +123   }
    +124 
    +125   /*************** Calls, that do not trigger a fetch */
    +126 
    +127   @Test
    +128   @DisplayName(("call to fetched() does not trigger fetch"))
    +129   public void test_fetched_DoesNotTriggerFetch() throws Exception
    +130   {
    +131     LOG.info("<-- start of test-case");
    +132 
    +133     resource.fetched();
    +134 
    +135     // Do not verify implementation: Only verify necessary outcome!
    +136     verify(fetcher, never()).fetch(eq(uri), any());
    +137   }
    +138 
    +139   @Test
    +140   @DisplayName(("call to lastModified() does not trigger fetch"))
    +141   public void test_lastModified_DoesNotTriggerFetch() throws Exception
    +142   {
    +143     LOG.info("<-- start of test-case");
    +144 
    +145     resource.lastModified();
    +146 
    +147     // Do not verify implementation: Only verify necessary outcome!
    +148     verify(fetcher, never()).fetch(eq(uri), any());
    +149   }
    +150 
    +151   @Test
    +152   @DisplayName(("call to contentLength() does not trigger fetch"))
    +153   public void test_contentLength_DoesNotTriggerFetch() throws Exception
    +154   {
    +155     LOG.info("<-- start of test-case");
    +156 
    +157     resource.contentLength();
    +158 
    +159     // Do not verify implementation: Only verify necessary outcome!
    +160     verify(fetcher, never()).fetch(eq(uri), any());
    +161   }
    +162 
    +163   @Test
    +164   @DisplayName(("call to expires() does not trigger fetch"))
    +165   public void test_expires_DoesNotTriggerFetch() throws Exception
    +166   {
    +167     LOG.info("<-- start of test-case");
    +168 
    +169     resource.expires();
    +170 
    +171     // Do not verify implementation: Only verify necessary outcome!
    +172     verify(fetcher, never()).fetch(eq(uri), any());
    +173   }
    +174 
    +175   @Test
    +176   @DisplayName(("call to isExpired() does not trigger fetch"))
    +177   public void test_isExpired_DoesNotTriggerFetch() throws Exception
    +178   {
    +179     LOG.info("<-- start of test-case");
    +180 
    +181     resource.isExpired();
    +182 
    +183     // Do not verify implementation: Only verify necessary outcome!
    +184     verify(fetcher, never()).fetch(eq(uri), any());
    +185   }
    +186 
    +187   @Test
    +188   @DisplayName(("call to eTag() does not trigger fetch"))
    +189   public void test_eTag_DoesNotTriggerFetch() throws Exception
    +190   {
    +191     LOG.info("<-- start of test-case");
    +192 
    +193     resource.eTag();
    +194 
    +195     // Do not verify implementation: Only verify necessary outcome!
    +196     verify(fetcher, never()).fetch(eq(uri), any());
    +197   }
    +198 
    +199   @Test
    +200   @DisplayName(("call to contentType() does not trigger fetch"))
    +201   public void test_contentType_DoesNotTriggerFetch() throws Exception
    +202   {
    +203     LOG.info("<-- start of test-case");
    +204 
    +205     resource.contentType();
    +206 
    +207     // Do not verify implementation: Only verify necessary outcome!
    +208     verify(fetcher, never()).fetch(eq(uri), any());
    +209   }
    +210 
    +211 
    +212   /*************** Results for calls, that does never trigger a fetch */
    +213 
    +214   @Test
    +215   @DisplayName(("is fetched"))
    +216   public void test_isNotFetched() throws Exception
    +217   {
    +218     LOG.info("<-- start of test-case");
    +219 
    +220     assertThat(resource.fetched()).isTrue();
    +221   }
    +222 
    +223   @Test
    +224   @DisplayName(("has expected value for last modification"))
    +225   public void test_hasExpectedLastModification() throws Exception
    +226   {
    +227     LOG.info("<-- start of test-case");
    +228 
    +229     assertThat(resource.lastModified()).isEqualTo(LONG_THEN   );
    +230   }
    +231 
    +232   @Test
    +233   @DisplayName(("is not modified"))
    +234   public void test_isNotModified()
    +235   {
    +236     LOG.info("<-- start of test-case");
    +237 
    +238     assertThat(resource.isModified()).isFalse();
    +239   }
    +240 
    +241   @Test
    +242   @DisplayName(("has expected content-length"))
    +243   public void test_hasExpectedContentLength() throws Exception
    +244   {
    +245     LOG.info("<-- start of test-case");
    +246 
    +247     assertThat(resource.contentLength()).isEqualTo(STR_CONTENT.getBytes().length);
    +248   }
    +249 
    +250   @Test
    +251   @DisplayName(("has expected expiration value"))
    +252   public void test_hasInitialExpirationValue() throws Exception
    +253   {
    +254     LOG.info("<-- start of test-case");
    +255 
    +256     assertThat(resource.expires()).isEqualTo(LONG_EXPIRED);
    +257   }
    +258 
    +259   @Test
    +260   @DisplayName(("is expired"))
    +261   public void test_isNotExpired() throws Exception
    +262   {
    +263     LOG.info("<-- start of test-case");
    +264 
    +265     assertThat(resource.isExpired()).isTrue();
    +266   }
    +267 
    +268   @Test
    +269   @DisplayName(("has expected eTag"))
    +270   public void test_hasExpectedETag() throws Exception
    +271   {
    +272     LOG.info("<-- start of test-case");
    +273 
    +274     assertThat(resource.eTag()).isEqualTo(STR_ETAG);
    +275   }
    +276 
    +277   @Test
    +278   @DisplayName(("has expected content-type"))
    +279   public void test_hasExpectedContentType() throws Exception
    +280   {
    +281     LOG.info("<-- start of test-case");
    +282 
    +283     assertThat(resource.contentType()).isEqualTo(MIME_TYPE_CONTENT_TYPE_HTML);
    +284   }
    +285 
    +286 
    +287   /*************** For results for calls, that does trigger a fetch, see:
    +288    *************** - HttpResourceExpiredFetchUnodifiedTest
    +289    *************** - HttpResourceExpiredFetchModifiedTest
    +290    *************** - HttpResourceExpiredFetchVanishedTest
    +291    *************** - HttpResourceExpiredFetchServerErrorTest
    +292    ***************/
    +293 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceFetcherTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceFetcherTest.html new file mode 100644 index 00000000..6748a5d1 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceFetcherTest.html @@ -0,0 +1,1269 @@ + + + +HttpResourceFetcherTest xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import mockit.Expectations;
    +5   import mockit.Injectable;
    +6   import mockit.Verifications;
    +7   import org.apache.http.Header;
    +8   import org.apache.http.HttpHeaders;
    +9   import org.apache.http.client.methods.CloseableHttpResponse;
    +10  import org.apache.http.client.methods.HttpUriRequest;
    +11  import org.apache.http.conn.HttpHostConnectException;
    +12  import org.apache.http.impl.client.CloseableHttpClient;
    +13  import org.apache.http.protocol.HttpContext;
    +14  import org.junit.jupiter.api.DisplayName;
    +15  import org.junit.jupiter.api.Test;
    +16  import org.slf4j.Logger;
    +17  import org.slf4j.LoggerFactory;
    +18  import org.springframework.cache.Cache;
    +19  import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
    +20  
    +21  import java.net.InetAddress;
    +22  import java.net.URI;
    +23  import java.time.Clock;
    +24  import java.time.ZoneId;
    +25  
    +26  import static de.juplo.httpresources.HttpData.NOT_FETCHED;
    +27  import static de.juplo.httpresources.HttpResourceFetcher.DEFAULT_TTL;
    +28  import static de.juplo.httpresources.TestUtil.*;
    +29  import static org.junit.Assert.*;
    +30  
    +31  
    +32  /**
    +33   * Tests the inner class {@link HttpResourceFetcher}.
    +34   * @author Kai Moritz
    +35   */
    +36  public class HttpResourceFetcherTest
    +37  {
    +38    private final static Logger LOG =
    +39        LoggerFactory.getLogger(HttpResourceFetcherTest.class);
    +40  
    +41    final static String ADDRESS = "http://foo/bar";
    +42    final static URI ADDRESS_URI = URI.create(ADDRESS);
    +43  
    +44    final static HttpData WHATEVER = DATA_EXPIRED_DUMMY;
    +45    final static HttpData SAME_AS_CACHED = DATA_NOT_EXPIRED_DUMMY;
    +46  
    +47    @Injectable
    +48    CloseableHttpClient client;
    +49    @Injectable
    +50    CloseableHttpResponse response;
    +51    @Injectable
    +52    Cache cache;
    +53  
    +54    Clock clock;
    +55    HttpResourceFetcher fetcher;
    +56    HttpResources resources;
    +57  
    +58    public void withServeStaleFalse()
    +59    {
    +60      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +61      fetcher = new HttpResourceFetcher(
    +62          new HttpComponentsClientHttpRequestFactory(client),
    +63          cache,
    +64          clock,
    +65          DEFAULT_TTL,
    +66          0,
    +67          false);
    +68      resources = new HttpResources(
    +69          fetcher,
    +70          clock);
    +71    }
    +72  
    +73    public void withServeStaleFalseAndMinTTL()
    +74    { 
    +75      clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +76      fetcher = new HttpResourceFetcher(
    +77          new HttpComponentsClientHttpRequestFactory(client),
    +78          cache,
    +79          clock,
    +80          DEFAULT_TTL,
    +81          MIN_TTL,
    +82          false);
    +83      resources = new HttpResources(
    +84          fetcher,
    +85          clock);
    +86    }
    +87  
    +88    public void withServeStaleTrue()
    +89    {
    +90      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +91      fetcher = new HttpResourceFetcher(
    +92          new HttpComponentsClientHttpRequestFactory(client),
    +93          cache,
    +94          clock);
    +95      resources = new HttpResources(
    +96          fetcher,
    +97          clock);
    +98    }
    +99  
    +100 
    +101   @Test
    +102   @DisplayName("first request -- cached - valid")
    +103   public void test_Fetch_Cached_Valid() throws Exception
    +104   {
    +105     LOG.info("<-- start of test-case");
    +106     withServeStaleFalse();
    +107     new Expectations()
    +108     {{
    +109       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = DATA_NOT_EXPIRED;
    +110       // Should not be called...
    +111       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +112       response.getStatusLine(); result = OK; minTimes = 0;
    +113       response.getAllHeaders(); result = new Header[0]; minTimes = 0;
    +114       response.getEntity(); result = null; minTimes = 0;
    +115       response.close(); minTimes = 0;
    +116     }};
    +117 
    +118     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +119 
    +120     new Verifications()
    +121     {{
    +122       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); times = 0;
    +123     }};
    +124 
    +125     assertEquals(data, DATA_NOT_EXPIRED);
    +126   }
    +127 
    +128 
    +129   @Test
    +130   @DisplayName("first request -- cached - expired")
    +131   public void test_Fetch_Cached_Expired() throws Exception
    +132   {
    +133     LOG.info("<-- start of test-case");
    +134     withServeStaleFalse();
    +135     new Expectations()
    +136     {{
    +137       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = DATA_EXPIRED;
    +138       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +139       response.getStatusLine(); result = OK;
    +140       response.getAllHeaders(); result = new Header[0];
    +141       response.getEntity(); result = null;
    +142       response.close();
    +143     }};
    +144 
    +145     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +146 
    +147     new Verifications()
    +148     {{
    +149       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); times = 1;
    +150       cache.put(ADDRESS_URI, data);
    +151     }};
    +152 
    +153     assertNull(data.headers.getContentType());
    +154     assertNotNull(data.content);
    +155     assertEquals("", new String(data.content, UTF8));
    +156     assertEquals(LONG_NOW + DEFAULT_TTL, data.expires);
    +157     assertFalse(data.revalidate);
    +158     assertNull(data.eTag);
    +159     assertEquals(0l, data.lastModified);
    +160   }
    +161 
    +162 
    +163   @Test
    +164   @DisplayName("first request -- cached - not found")
    +165   public void test_Fetch_Cached_NotFound() throws Exception
    +166   {
    +167     LOG.info("<-- start of test-case");
    +168     withServeStaleFalse();
    +169     new Expectations()
    +170     {{
    +171       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = HttpData.NOT_FOUND;
    +172       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +173       response.getStatusLine(); result = OK;
    +174       response.getAllHeaders(); result = new Header[0];
    +175       response.getEntity(); result = null;
    +176       response.close();
    +177     }};
    +178 
    +179     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +180 
    +181     new Verifications()
    +182     {{
    +183       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); times = 1;
    +184       cache.put(ADDRESS_URI, data);
    +185     }};
    +186 
    +187     assertNull(data.headers.getContentType());
    +188     assertNotNull(data.content);
    +189     assertEquals("", new String(data.content, UTF8));
    +190     assertEquals(LONG_NOW + DEFAULT_TTL, data.expires);
    +191     assertFalse(data.revalidate);
    +192     assertNull(data.eTag);
    +193     assertEquals(0l, data.lastModified);
    +194   }
    +195 
    +196 
    +197   @Test
    +198   @DisplayName("first request -- cached - server error")
    +199   public void test_Fetch_Cached_ServerError() throws Exception
    +200   {
    +201     LOG.info("<-- start of test-case");
    +202     withServeStaleFalse();
    +203     new Expectations()
    +204     {{
    +205       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = HttpData.SERVER_ERROR;
    +206       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +207       response.getStatusLine(); result = OK;
    +208       response.getAllHeaders(); result = new Header[0];
    +209       response.getEntity(); result = null;
    +210       response.close();
    +211     }};
    +212 
    +213     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +214 
    +215     new Verifications()
    +216     {{
    +217       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); times = 1;
    +218       cache.put(ADDRESS_URI, data);
    +219     }};
    +220 
    +221     assertNull(data.headers.getContentType());
    +222     assertNotNull(data.content);
    +223     assertEquals("", new String(data.content, UTF8));
    +224     assertEquals(LONG_NOW + DEFAULT_TTL, data.expires);
    +225     assertFalse(data.revalidate);
    +226     assertNull(data.eTag);
    +227     assertEquals(0l, data.lastModified);
    +228   }
    +229 
    +230 
    +231   @Test
    +232   @DisplayName("first request -- 200 - no headers / no body")
    +233   public void test_Fetch_200_NoHeaders_NoBody() throws Exception
    +234   {
    +235     LOG.info("<-- start of test-case");
    +236     withServeStaleFalse();
    +237     new Expectations()
    +238     {{
    +239       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +240       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +241       response.getStatusLine(); result = OK;
    +242       response.getAllHeaders(); result = new Header[0];
    +243       response.getEntity(); result = null;
    +244       response.close();
    +245     }};
    +246 
    +247     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +248 
    +249     new Verifications()
    +250     {{
    +251       HttpUriRequest request;
    +252       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +253       assertEquals(ADDRESS_URI, request.getURI());
    +254       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +255       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +256       cache.put(ADDRESS_URI, data);
    +257     }};
    +258 
    +259     assertNull(data.headers.getContentType());
    +260     assertNotNull(data.content);
    +261     assertEquals("", new String(data.content, UTF8));
    +262     assertEquals(LONG_NOW + DEFAULT_TTL, data.expires);
    +263     assertFalse(data.revalidate);
    +264     assertNull(data.eTag);
    +265     assertEquals(0l, data.lastModified);
    +266   }
    +267 
    +268 
    +269   @Test
    +270   @DisplayName("first request -- 200 - no headers")
    +271   public void test_Fetch_200_NoHeaders() throws Exception
    +272   {
    +273     LOG.info("<-- start of test-case");
    +274     withServeStaleFalse();
    +275     new Expectations()
    +276     {{
    +277       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +278       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +279       response.getStatusLine(); result = OK;
    +280       response.getAllHeaders(); result = new Header[0];
    +281       response.getEntity(); result = BODY;
    +282       response.close();
    +283     }};
    +284 
    +285     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +286 
    +287     new Verifications()
    +288     {{
    +289       HttpUriRequest request;
    +290       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +291       assertEquals(ADDRESS_URI, request.getURI());
    +292       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +293       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +294       cache.put(ADDRESS_URI, data);
    +295     }};
    +296 
    +297     assertNull(data.headers.getContentType());
    +298     assertNotNull(data.content);
    +299     assertEquals(STR_CONTENT, new String(data.content, UTF8));
    +300     assertEquals(LONG_NOW + DEFAULT_TTL, data.expires);
    +301     assertFalse(data.revalidate);
    +302     assertNull(data.eTag);
    +303     assertEquals(0l, data.lastModified);
    +304   }
    +305 
    +306 
    +307   @Test
    +308   @DisplayName("first request -- 200 - HTTP/1.1")
    +309   public void test_Fetch_200_HTTP11() throws Exception
    +310   {
    +311     LOG.info("<-- start of test-case");
    +312     withServeStaleFalse();
    +313     new Expectations()
    +314     {{
    +315       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +316       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +317       response.getStatusLine(); result = OK;
    +318       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE };
    +319       response.getEntity(); result = BODY;
    +320       response.close();
    +321     }};
    +322 
    +323     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +324 
    +325     new Verifications()
    +326     {{
    +327       HttpUriRequest request;
    +328       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +329       assertEquals(ADDRESS_URI, request.getURI());
    +330       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +331       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +332       cache.put(ADDRESS_URI, data);
    +333     }};
    +334 
    +335     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +336     assertNotNull(data.content);
    +337     assertEquals(STR_CONTENT, new String(data.content, UTF8));
    +338     assertEquals(LONG_SEND + (MAX_AGE - 1) * 1000, data.expires);
    +339     assertFalse(data.revalidate);
    +340     assertEquals(STR_ETAG, data.eTag);
    +341     assertEquals(LONG_THEN, data.lastModified);
    +342   }
    +343 
    +344   @Test
    +345   @DisplayName("first request + min-TTL -- 200 - HTTP/1.1")
    +346   public void test_Fetch_200_HTTP11_MinTTL() throws Exception
    +347   {
    +348     LOG.info("<-- start of test-case");
    +349     withServeStaleFalseAndMinTTL();
    +350     new Expectations()
    +351     {{
    +352       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +353       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +354       response.getStatusLine(); result = OK;
    +355       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE };
    +356       response.getEntity(); result = BODY;
    +357       response.close();
    +358     }};
    +359 
    +360     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +361 
    +362     new Verifications()
    +363     {{
    +364       HttpUriRequest request;
    +365       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +366       assertEquals(ADDRESS_URI, request.getURI());
    +367       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +368       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +369       cache.put(ADDRESS_URI, data);
    +370     }};
    +371 
    +372     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +373     assertNotNull(data.content);
    +374     assertEquals(STR_CONTENT, new String(data.content, UTF8));
    +375     assertEquals(LONG_SEND + MIN_TTL - 1000, data.expires);
    +376     assertFalse(data.revalidate);
    +377     assertEquals(STR_ETAG, data.eTag);
    +378     assertEquals(LONG_THEN, data.lastModified);
    +379   }
    +380 
    +381 
    +382   @Test
    +383   @DisplayName("first request -- 200 - HTTP/1.1 / Date-Header is missing")
    +384   public void test_Fetch_200_HTTP11_DateMissing_() throws Exception
    +385   {
    +386     LOG.info("<-- start of test-case");
    +387     withServeStaleFalse();
    +388     new Expectations()
    +389     {{
    +390       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +391       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +392       response.getStatusLine(); result = OK;
    +393       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE };
    +394       response.getEntity(); result = BODY;
    +395       response.close();
    +396     }};
    +397 
    +398     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +399 
    +400     new Verifications()
    +401     {{
    +402       HttpUriRequest request;
    +403       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +404       assertEquals(ADDRESS_URI, request.getURI());
    +405       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +406       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +407       cache.put(ADDRESS_URI, data);
    +408     }};
    +409 
    +410     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +411     assertNotNull(data.content);
    +412     assertEquals(STR_CONTENT, new String(data.content, UTF8));
    +413     assertEquals(LONG_NOW + MAX_AGE * 1000, data.expires);
    +414     assertFalse(data.revalidate);
    +415     assertEquals(STR_ETAG, data.eTag);
    +416     assertEquals(LONG_THEN, data.lastModified);
    +417   }
    +418 
    +419 
    +420   @Test
    +421   @DisplayName("first request -- 200 - HTTP/1.1 / Cache-Control: public, max-age=0")
    +422   public void test_Fetch_200_HTTP11_MaxAge0() throws Exception
    +423   {
    +424     LOG.info("<-- start of test-case");
    +425     withServeStaleFalse();
    +426     new Expectations()
    +427     {{
    +428       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +429       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +430       response.getStatusLine(); result = OK;
    +431       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE_0 };
    +432       response.getEntity(); result = BODY;
    +433       response.close();
    +434     }};
    +435 
    +436     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +437 
    +438     new Verifications()
    +439     {{
    +440       HttpUriRequest request;
    +441       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +442       assertEquals(ADDRESS_URI, request.getURI());
    +443       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +444       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +445       cache.put(ADDRESS_URI, data);
    +446     }};
    +447 
    +448     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +449     assertNotNull(data.content);
    +450     assertEquals(LONG_SEND - 1000, data.expires);
    +451     assertFalse(data.revalidate);
    +452     assertEquals(STR_ETAG, data.eTag);
    +453     assertEquals(LONG_THEN, data.lastModified);
    +454   }
    +455   @Test
    +456   @DisplayName("first request -- 200 - HTTP/1.1 / Cache-Control: no-cache")
    +457   public void test_Fetch_200_HTTP11_NoCache() throws Exception
    +458   {
    +459     LOG.info("<-- start of test-case");
    +460     withServeStaleFalse();
    +461     new Expectations()
    +462     {{
    +463       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +464       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +465       response.getStatusLine(); result = OK;
    +466       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_NO_CACHE };
    +467       response.getEntity(); result = BODY;
    +468       response.close();
    +469     }};
    +470 
    +471     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +472 
    +473     new Verifications()
    +474     {{
    +475       HttpUriRequest request;
    +476       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +477       assertEquals(ADDRESS_URI, request.getURI());
    +478       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +479       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +480       cache.put(ADDRESS_URI, data);
    +481     }};
    +482 
    +483     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +484     assertNotNull(data.content);
    +485     assertEquals(LONG_SEND, data.expires);
    +486     assertFalse(data.revalidate);
    +487     assertEquals(STR_ETAG, data.eTag);
    +488     assertEquals(LONG_THEN, data.lastModified);
    +489   }
    +490 
    +491 
    +492   @Test
    +493   @DisplayName("first request -- 200 - HTTP/1.1 / Cache-Control: no-cache=\"Cookie\"")
    +494   public void test_Fetch_200_HTTP11_NoCacheQualified() throws Exception
    +495   {
    +496     LOG.info("<-- start of test-case");
    +497     withServeStaleFalse();
    +498     new Expectations()
    +499     {{
    +500       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +501       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +502       response.getStatusLine(); result = OK;
    +503       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_NO_CACHE_QUALIFIED };
    +504       response.getEntity(); result = BODY;
    +505       response.close();
    +506     }};
    +507 
    +508     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +509 
    +510     new Verifications()
    +511     {{
    +512       HttpUriRequest request;
    +513       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +514       assertEquals(ADDRESS_URI, request.getURI());
    +515       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +516       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +517       cache.put(ADDRESS_URI, data);
    +518     }};
    +519 
    +520     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +521     assertNotNull(data.content);
    +522     assertEquals(STR_CONTENT, new String(data.content, UTF8));
    +523     assertEquals(LONG_SEND + (MAX_AGE - 1) * 1000, data.expires);
    +524     assertFalse(data.revalidate);
    +525     assertEquals(STR_ETAG, data.eTag);
    +526     assertEquals(LONG_THEN, data.lastModified);
    +527   }
    +528 
    +529 
    +530   @Test
    +531   @DisplayName("first request -- 200 - HTTP/1.0")
    +532   public void test_Fetch_200_HTTP10() throws Exception
    +533   {
    +534     LOG.info("<-- start of test-case");
    +535     withServeStaleFalse();
    +536     new Expectations()
    +537     {{
    +538       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +539       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +540       response.getStatusLine(); result = OK;
    +541       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, EXPIRES_VALID };
    +542       response.getEntity(); result = BODY;
    +543       response.close();
    +544     }};
    +545 
    +546     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +547 
    +548     new Verifications()
    +549     {{
    +550       HttpUriRequest request;
    +551       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +552       assertEquals(ADDRESS_URI, request.getURI());
    +553       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +554       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +555       cache.put(ADDRESS_URI, data);
    +556     }};
    +557 
    +558     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +559     assertNotNull(data.content);
    +560     assertEquals(STR_CONTENT, new String(data.content, UTF8));
    +561     assertEquals(LONG_FEATURE, data.expires);
    +562     assertFalse(data.revalidate);
    +563     assertNull(data.eTag);
    +564     assertEquals(LONG_THEN, data.lastModified);
    +565   }
    +566 
    +567 
    +568   @Test
    +569   @DisplayName("first request -- 200 - HTTP/1.0 / invalid Expires-Header")
    +570   public void test_Fetch_200_HTTP10_InvalidExpires() throws Exception
    +571   {
    +572     LOG.info("<-- start of test-case");
    +573     withServeStaleFalse();
    +574     new Expectations()
    +575     {{
    +576       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +577       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +578       response.getStatusLine(); result = OK;
    +579       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, EXPIRES_INVALID };
    +580       response.getEntity(); result = BODY;
    +581       response.close();
    +582     }};
    +583 
    +584     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +585 
    +586     new Verifications()
    +587     {{
    +588       HttpUriRequest request;
    +589       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +590       assertEquals(ADDRESS_URI, request.getURI());
    +591       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +592       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +593       cache.put(ADDRESS_URI, data);
    +594     }};
    +595 
    +596     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +597     assertNotNull(data.content);
    +598     assertEquals(0l, data.expires);
    +599     assertFalse(data.revalidate);
    +600     assertNull(data.eTag);
    +601     assertEquals(LONG_THEN, data.lastModified);
    +602   }
    +603 
    +604 
    +605   @Test
    +606   @DisplayName("first request -- 200 - HTTP/mixed: Expires + Cache-Control: private")
    +607   public void test_Fetch_200_Mixed() throws Exception
    +608   {
    +609     LOG.info("<-- start of test-case");
    +610     withServeStaleFalse();
    +611     new Expectations()
    +612     {{
    +613       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +614       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +615       response.getStatusLine(); result = OK;
    +616       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, ETAG, EXPIRES_VALID, CACHE_CONTROL_PRIVATE };
    +617       response.getEntity(); result = BODY;
    +618       response.close();
    +619     }};
    +620 
    +621     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +622 
    +623     new Verifications()
    +624     {{
    +625       HttpUriRequest request;
    +626       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +627       assertEquals(ADDRESS_URI, request.getURI());
    +628       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +629       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +630       cache.put(ADDRESS_URI, data);
    +631     }};
    +632 
    +633     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +634     assertNotNull(data.content);
    +635     assertEquals(STR_CONTENT, new String(data.content, UTF8));
    +636     assertEquals(LONG_FEATURE, data.expires);
    +637     assertFalse(data.revalidate);
    +638     assertEquals(STR_ETAG, data.eTag);
    +639     assertEquals(LONG_THEN, data.lastModified);
    +640   }
    +641 
    +642 
    +643   @Test
    +644   @DisplayName("first request -- 200 - HTTP/mixed: Expires + Cache-Control: max-age")
    +645   public void test_Fetch_200_Mixed_ExpiresOverwritten() throws Exception
    +646   {
    +647     LOG.info("<-- start of test-case");
    +648     withServeStaleFalse();
    +649     new Expectations()
    +650     {{
    +651       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +652       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +653       response.getStatusLine(); result = OK;
    +654       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE };
    +655       response.getEntity(); result = BODY;
    +656       response.close();
    +657     }};
    +658 
    +659     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +660 
    +661     new Verifications()
    +662     {{
    +663       HttpUriRequest request;
    +664       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +665       assertEquals(ADDRESS_URI, request.getURI());
    +666       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +667       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +668       cache.put(ADDRESS_URI, data);
    +669     }};
    +670 
    +671     assertEquals(DATA_NOT_EXPIRED, data);
    +672   }
    +673 
    +674 
    +675   @Test
    +676   @DisplayName("first request -- 200 - HTTP/1.1 + Content-Encoding: gzip")
    +677   public void test_Fetch_200_HTTP11_Encoding() throws Exception
    +678   {
    +679     LOG.info("<-- start of test-case");
    +680     withServeStaleFalse();
    +681     new Expectations()
    +682     {{
    +683       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +684       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +685       response.getStatusLine(); result = OK;
    +686       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, CONTENT_ENCODING, DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE };
    +687       response.getEntity(); result = BODY_GZIPPED;
    +688       response.close();
    +689     }};
    +690 
    +691     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +692 
    +693     new Verifications()
    +694     {{
    +695       HttpUriRequest request;
    +696       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +697       assertEquals(ADDRESS_URI, request.getURI());
    +698       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +699       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +700       cache.put(ADDRESS_URI, data);
    +701     }};
    +702 
    +703     assertEquals(MIME_TYPE_CONTENT_TYPE_HTML, data.headers.getContentType());
    +704     assertNotNull(data.content);
    +705     assertEquals(new String(CONTENT_GZIPPED), new String(data.content, UTF8));
    +706     assertEquals(LONG_SEND + (MAX_AGE - 1) * 1000, data.expires);
    +707     assertFalse(data.revalidate);
    +708     assertEquals(STR_ETAG, data.eTag);
    +709     assertEquals(LONG_THEN, data.lastModified);
    +710   }
    +711 
    +712   @Test
    +713   @DisplayName("first request -- 200 - HTTP/1.1 + Cache-Control: must-revalidate")
    +714   public void test_Fetch_200_HTTP11_MustRevalidate() throws Exception
    +715   {
    +716     LOG.info("<-- start of test-case");
    +717     withServeStaleFalse();
    +718     new Expectations()
    +719     {{
    +720       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +721       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +722       response.getStatusLine(); result = OK;
    +723       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_REVALIDATE };
    +724       response.getEntity(); result = BODY;
    +725       response.close();
    +726     }};
    +727 
    +728     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +729 
    +730     new Verifications()
    +731     {{
    +732       HttpUriRequest request;
    +733       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +734       assertEquals(ADDRESS_URI, request.getURI());
    +735       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +736       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +737       cache.put(ADDRESS_URI, data);
    +738     }};
    +739 
    +740     assertEquals(DATA_NOT_EXPIRED_REVALIDATION_REQUIRED, data);
    +741   }
    +742 
    +743 
    +744   @Test
    +745   @DisplayName("first request -- 400 - HTTP/1.1")
    +746   public void test_Fetch_404_HTTP11() throws Exception
    +747   {
    +748     LOG.info("<-- start of test-case");
    +749     withServeStaleFalse();
    +750     new Expectations()
    +751     {{
    +752       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +753       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +754       response.getStatusLine(); result = NOT_FOUND;
    +755       response.getAllHeaders(); result = new Header[] { DATE };
    +756       response.close();
    +757     }};
    +758 
    +759     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +760 
    +761     new Verifications()
    +762     {{
    +763       HttpUriRequest request;
    +764       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +765       assertEquals(ADDRESS_URI, request.getURI());
    +766       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +767       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +768       cache.put(ADDRESS_URI, data);
    +769     }};
    +770 
    +771     assertNull(data.headers.getContentType());
    +772     assertNull(data.content);
    +773     assertEquals(LONG_SEND - 1000, data.expires);
    +774     assertFalse(data.revalidate);
    +775     assertNull(data.eTag);
    +776     assertEquals(0, data.lastModified);
    +777   }
    +778 
    +779 
    +780   @Test
    +781   @DisplayName("first request -- 404 - HTTP/1.1 + Cache-Control: max-age")
    +782   public void test_Fetch_404_HTTP11_Cacheable() throws Exception
    +783   {
    +784     LOG.info("<-- start of test-case");
    +785     withServeStaleFalse();
    +786     new Expectations()
    +787     {{
    +788       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +789       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response;
    +790       response.getStatusLine(); result = NOT_FOUND;
    +791       response.getAllHeaders(); result = new Header[] { DATE };
    +792       response.close();
    +793     }};
    +794 
    +795     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +796 
    +797     new Verifications()
    +798     {{
    +799       HttpUriRequest request;
    +800       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +801       assertEquals(ADDRESS_URI, request.getURI());
    +802       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +803       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +804       cache.put(ADDRESS_URI, data);
    +805     }};
    +806 
    +807     assertEquals(DATA_NOT_FOUND, data);
    +808   }
    +809 
    +810 
    +811   @Test
    +812   @DisplayName("first request -- 500 - HTTP/1.1")
    +813   public void test_Fetch_500_HTTP11() throws Exception
    +814   {
    +815     LOG.info("<-- start of test-case");
    +816     withServeStaleFalse();
    +817     new Expectations()
    +818     {{
    +819       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +820       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; times = 1;
    +821       response.getStatusLine(); result = SERVER_ERROR;
    +822       response.close();
    +823     }};
    +824 
    +825     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +826 
    +827     new Verifications()
    +828     {{
    +829       HttpUriRequest request;
    +830       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +831       assertEquals(ADDRESS_URI, request.getURI());
    +832       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +833       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +834       cache.put(ADDRESS_URI, data);
    +835     }};
    +836 
    +837     assertEquals(HttpData.SERVER_ERROR, data);
    +838   }
    +839 
    +840 
    +841   @Test
    +842   @DisplayName("first request -- server is down")
    +843   public void test_Fetch_ServerDown() throws Exception
    +844   {
    +845     LOG.info("<-- start of test-case");
    +846     withServeStaleFalse();
    +847     new Expectations()
    +848     {{
    +849       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +850       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = new HttpHostConnectException(null, null, (InetAddress)null);
    +851     }};
    +852 
    +853     HttpData data = fetcher.fetch(ADDRESS_URI, NOT_FETCHED);
    +854 
    +855     new Verifications()
    +856     {{
    +857       HttpUriRequest request;
    +858       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +859       assertEquals(ADDRESS_URI, request.getURI());
    +860       assertNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +861       assertNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +862       cache.put(ADDRESS_URI, data);
    +863     }};
    +864 
    +865     assertEquals(HttpData.SERVER_ERROR, data);
    +866   }
    +867 
    +868 
    +869   @Test
    +870   @DisplayName("update request -- cached - same -> request is executed")
    +871   public void test_Update_Cached_Same_RequestIsExecuted() throws Exception
    +872   {
    +873     LOG.info("<-- start of test-case");
    +874     withServeStaleFalse();
    +875     new Expectations()
    +876     {{
    +877       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = SAME_AS_CACHED;
    +878       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +879       response.getStatusLine(); result = NOT_MODIFIED; minTimes = 0;
    +880       response.getAllHeaders(); result = new Header[] { DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE }; minTimes = 0;
    +881       response.close(); minTimes = 0;
    +882     }};
    +883 
    +884     HttpData data = fetcher.fetch(ADDRESS_URI, SAME_AS_CACHED);
    +885 
    +886     new Verifications()
    +887     {{
    +888       HttpUriRequest request;
    +889       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +890       times = 1;
    +891       assertEquals(ADDRESS_URI, request.getURI());
    +892       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +893       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +894       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +895       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +896       cache.put(ADDRESS_URI, data);
    +897     }};
    +898 
    +899     assertEquals(DATA_NOT_EXPIRED, data);
    +900   }
    +901 
    +902 
    +903   @Test
    +904   @DisplayName("update request -- cached - valid")
    +905   public void test_Update_Cached_Valid() throws Exception
    +906   {
    +907     LOG.info("<-- start of test-case");
    +908     withServeStaleFalse();
    +909     new Expectations()
    +910     {{
    +911       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = DATA_NOT_EXPIRED;
    +912       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +913       response.getStatusLine(); result = NOT_MODIFIED; minTimes = 0;
    +914       response.getAllHeaders(); result = new Header[] { DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE }; minTimes = 0;
    +915       response.close(); minTimes = 0;
    +916     }};
    +917 
    +918     HttpData data = fetcher.fetch(ADDRESS_URI, WHATEVER);
    +919 
    +920     new Verifications()
    +921     {{
    +922       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); times = 0;
    +923     }};
    +924 
    +925     assertEquals(data, DATA_NOT_EXPIRED);
    +926   }
    +927 
    +928 
    +929   @Test
    +930   @DisplayName("update request -- cached - expired -> request is executed")
    +931   public void test_Update_Cached_Expired_RequestIsExecuted() throws Exception
    +932   {
    +933     LOG.info("<-- start of test-case");
    +934     withServeStaleFalse();
    +935     new Expectations()
    +936     {{
    +937       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = DATA_EXPIRED;
    +938       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +939       response.getStatusLine(); result = NOT_MODIFIED; minTimes = 0;
    +940       response.getAllHeaders(); result = new Header[] { DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE }; minTimes = 0;
    +941       response.close(); minTimes = 0;
    +942     }};
    +943 
    +944     HttpData data = fetcher.fetch(ADDRESS_URI, WHATEVER);
    +945 
    +946     new Verifications()
    +947     {{
    +948       HttpUriRequest request;
    +949       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +950       times = 1;
    +951       assertEquals(ADDRESS_URI, request.getURI());
    +952       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +953       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +954       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +955       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +956       cache.put(ADDRESS_URI, data);
    +957     }};
    +958 
    +959     assertEquals(DATA_NOT_EXPIRED, data);
    +960   }
    +961 
    +962 
    +963   @Test
    +964   @DisplayName("update request -- 304: not modified")
    +965   public void test_Update_304() throws Exception
    +966   {
    +967     LOG.info("<-- start of test-case");
    +968     withServeStaleFalse();
    +969     new Expectations()
    +970     {{
    +971       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +972       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +973       response.getStatusLine(); result = NOT_MODIFIED; minTimes = 0;
    +974       response.getAllHeaders(); result = new Header[] { DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE }; minTimes = 0;
    +975       response.close(); minTimes = 0;
    +976     }};
    +977 
    +978     HttpData data = fetcher.fetch(ADDRESS_URI, DATA_EXPIRED);
    +979 
    +980     new Verifications()
    +981     {{
    +982       HttpUriRequest request;
    +983       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +984       times = 1;
    +985       assertEquals(ADDRESS_URI, request.getURI());
    +986       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +987       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +988       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +989       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +990       cache.put(ADDRESS_URI, data);
    +991     }};
    +992 
    +993     assertEquals(DATA_NOT_EXPIRED, data);
    +994   }
    +995 
    +996 
    +997   @Test
    +998   @DisplayName("update request -- 200: modified")
    +999   public void test_Update_200() throws Exception
    +1000   {
    +1001     LOG.info("<-- start of test-case");
    +1002     withServeStaleFalse();
    +1003     new Expectations()
    +1004     {{
    +1005       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +1006       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +1007       response.getStatusLine(); result = OK; minTimes = 0;
    +1008       response.getAllHeaders(); result = new Header[] { CONTENT_TYPE_HTML, DATE_MODIFIED, LAST_MODIFIED_MODIFIED, ETAG_MODIFIED, CACHE_CONTROL_MAX_AGE }; minTimes = 0;
    +1009       response.getEntity(); result = BODY_MODIFIED; minTimes = 0;
    +1010       response.close(); minTimes = 0;
    +1011     }};
    +1012 
    +1013     HttpData data = fetcher.fetch(ADDRESS_URI, DATA_EXPIRED);
    +1014 
    +1015     new Verifications()
    +1016     {{
    +1017       HttpUriRequest request;
    +1018       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +1019       times = 1;
    +1020       assertEquals(ADDRESS_URI, request.getURI());
    +1021       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +1022       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +1023       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +1024       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +1025       cache.put(ADDRESS_URI, data);
    +1026     }};
    +1027 
    +1028     assertEquals(DATA_UPDATED, data);
    +1029   }
    +1030 
    +1031 
    +1032   @Test
    +1033   @DisplayName("update request -- 404: not found")
    +1034   public void test_Update_404() throws Exception
    +1035   {
    +1036     LOG.info("<-- start of test-case");
    +1037     withServeStaleFalse();
    +1038     new Expectations()
    +1039     {{
    +1040       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +1041       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +1042       response.getStatusLine(); result = NOT_FOUND; minTimes = 0;
    +1043       response.getAllHeaders(); result = new Header[] { DATE }; minTimes = 0;
    +1044       response.close(); minTimes = 0;
    +1045     }};
    +1046 
    +1047     HttpData data = fetcher.fetch(ADDRESS_URI, DATA_EXPIRED);
    +1048 
    +1049     new Verifications()
    +1050     {{
    +1051       HttpUriRequest request;
    +1052       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +1053       times = 1;
    +1054       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +1055       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +1056       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +1057       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +1058       cache.put(ADDRESS_URI, data);
    +1059     }};
    +1060 
    +1061     assertEquals(DATA_NOT_FOUND, data);
    +1062   }
    +1063 
    +1064 
    +1065   @Test
    +1066   @DisplayName("update request -- 500: server error")
    +1067   public void test_Update_500() throws Exception
    +1068   {
    +1069     LOG.info("<-- start of test-case");
    +1070     withServeStaleFalse();
    +1071     new Expectations()
    +1072     {{
    +1073       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +1074       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +1075       response.getStatusLine(); result = SERVER_ERROR; minTimes = 0;
    +1076       response.close(); minTimes = 0;
    +1077     }};
    +1078 
    +1079     HttpData data = fetcher.fetch(ADDRESS_URI, DATA_EXPIRED);
    +1080 
    +1081     new Verifications()
    +1082     {{
    +1083       HttpUriRequest request;
    +1084       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +1085       times = 1;
    +1086       assertEquals(ADDRESS_URI, request.getURI());
    +1087       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +1088       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +1089       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +1090       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +1091       cache.put(ADDRESS_URI, data);
    +1092     }};
    +1093 
    +1094     assertEquals(DATA_EXPIRED, data);
    +1095   }
    +1096 
    +1097 
    +1098   @Test
    +1099   @DisplayName("update request -- must revalidate / 304: not modified")
    +1100   public void test_Update_MustRevalidate_304() throws Exception
    +1101   {
    +1102     LOG.info("<-- start of test-case");
    +1103     withServeStaleFalse();
    +1104     new Expectations()
    +1105     {{
    +1106       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +1107       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +1108       response.getStatusLine(); result = NOT_MODIFIED; minTimes = 0;
    +1109       response.getAllHeaders(); result = new Header[] { DATE, LAST_MODIFIED, ETAG, CACHE_CONTROL_MAX_AGE }; minTimes = 0;
    +1110       response.close(); minTimes = 0;
    +1111     }};
    +1112 
    +1113     HttpResource resource = new HttpResource(resources, fetcher, clock, ADDRESS_URI);
    +1114     resource.data = DATA_NOT_EXPIRED_REVALIDATION_REQUIRED;
    +1115 
    +1116     HttpData data = fetcher.fetch(resource.uri, resource.data);
    +1117 
    +1118     new Verifications()
    +1119     {{
    +1120       HttpUriRequest request;
    +1121       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +1122       times = 1;
    +1123       assertEquals(ADDRESS_URI, request.getURI());
    +1124       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +1125       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +1126       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +1127       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +1128       cache.put(ADDRESS_URI, data);
    +1129     }};
    +1130 
    +1131     assertEquals(DATA_NOT_EXPIRED, data); // << Flag "revalidate" is cleared, because header ist not set
    +1132   }
    +1133 
    +1134 
    +1135   @Test
    +1136   @DisplayName("update request -- must-revalidate / 500: server error")
    +1137   public void test_Update_MustRevalidate_500() throws Exception
    +1138   {
    +1139     LOG.info("<-- start of test-case");
    +1140     withServeStaleFalse();
    +1141     new Expectations()
    +1142     {{
    +1143       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +1144       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +1145       response.getStatusLine(); result = SERVER_ERROR; minTimes = 0;
    +1146       response.close(); minTimes = 0;
    +1147     }};
    +1148 
    +1149     HttpData data = fetcher.fetch(ADDRESS_URI, DATA_NOT_EXPIRED_REVALIDATION_REQUIRED);
    +1150 
    +1151     new Verifications() {{
    +1152       HttpUriRequest request;
    +1153       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +1154       times = 1;
    +1155       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +1156       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +1157       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +1158       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +1159       cache.put(ADDRESS_URI, data);
    +1160     }};
    +1161 
    +1162     assertEquals(HttpData.SERVER_ERROR, data);
    +1163   }
    +1164 
    +1165 
    +1166   @Test
    +1167   @DisplayName("update request + serve-stale -- 404: not found")
    +1168   public void test_Update_404_ServeStale() throws Exception
    +1169   {
    +1170     LOG.info("<-- start of test-case");
    +1171     withServeStaleTrue();
    +1172     new Expectations()
    +1173     {{
    +1174       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +1175       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +1176       response.getStatusLine(); result = NOT_FOUND; minTimes = 0;
    +1177       response.close(); minTimes = 0;
    +1178     }};
    +1179 
    +1180     HttpData data = fetcher.fetch(ADDRESS_URI, DATA_EXPIRED);
    +1181 
    +1182     new Verifications()
    +1183     {{
    +1184       HttpUriRequest request;
    +1185       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +1186       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +1187       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +1188       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +1189       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +1190       cache.put(ADDRESS_URI, data);
    +1191     }};
    +1192 
    +1193     assertEquals(DATA_EXPIRED, data);
    +1194   }
    +1195 
    +1196 
    +1197   @Test
    +1198   @DisplayName("update request + serve-stale -- must-revalidate / 500: server error")
    +1199   public void test_Update_500_MustRevalidate_ServeStale() throws Exception
    +1200   {
    +1201     LOG.info("<-- start of test-case");
    +1202     withServeStaleTrue();
    +1203     new Expectations()
    +1204     {{
    +1205       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +1206       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = response; minTimes = 0;
    +1207       response.getStatusLine(); result = SERVER_ERROR; minTimes = 0;
    +1208       response.close(); minTimes = 0;
    +1209     }};
    +1210 
    +1211     HttpData data = fetcher.fetch(ADDRESS_URI, DATA_NOT_EXPIRED_REVALIDATION_REQUIRED);
    +1212 
    +1213     new Verifications()
    +1214     {{
    +1215       HttpUriRequest request;
    +1216       client.execute(request = withCapture(), withInstanceOf(HttpContext.class)); times = 1;
    +1217       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +1218       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +1219       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +1220       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +1221       cache.put(ADDRESS_URI, data);
    +1222     }};
    +1223 
    +1224     assertEquals(DATA_NOT_EXPIRED_REVALIDATION_REQUIRED, data);
    +1225   }
    +1226 
    +1227 
    +1228   @Test
    +1229   @DisplayName("update request -- server is down")
    +1230   public void test_Update_ServerDown() throws Exception
    +1231   {
    +1232     LOG.info("<-- start of test-case");
    +1233     withServeStaleFalse();
    +1234     new Expectations()
    +1235     {{
    +1236       cache.get(withInstanceOf(URI.class), withEqual(HttpData.class)); result = null;
    +1237       client.execute(withInstanceOf(HttpUriRequest.class), withInstanceOf(HttpContext.class)); result = new HttpHostConnectException(null, null, (InetAddress)null); minTimes = 0;
    +1238     }};
    +1239 
    +1240     HttpData data = fetcher.fetch(ADDRESS_URI, DATA_EXPIRED);
    +1241 
    +1242     new Verifications()
    +1243     {{
    +1244       HttpUriRequest request;
    +1245       client.execute(request = withCapture(), withInstanceOf(HttpContext.class));
    +1246       times = 1;
    +1247       assertNotNull(request.getLastHeader(HttpHeaders.IF_NONE_MATCH));
    +1248       assertEquals(STR_ETAG, request.getLastHeader(HttpHeaders.IF_NONE_MATCH).getValue());
    +1249       assertNotNull(request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE));
    +1250       assertEquals(STR_THEN, request.getLastHeader(HttpHeaders.IF_MODIFIED_SINCE).getValue());
    +1251       cache.put(ADDRESS_URI, data);
    +1252     }};
    +1253 
    +1254     assertEquals(DATA_EXPIRED, data);
    +1255   }
    +1256 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchModifiedTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchModifiedTest.html new file mode 100644 index 00000000..d01e785d --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchModifiedTest.html @@ -0,0 +1,118 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotExpiredFetchModifiedTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.TestUtil.*;
    +22  import static org.assertj.core.api.Assertions.assertThat;
    +23  import static org.mockito.ArgumentMatchers.any;
    +24  import static org.mockito.ArgumentMatchers.eq;
    +25  import static org.mockito.Mockito.*;
    +26  
    +27  
    +28  @DisplayName(("HttpResource - Fetched - Not Expired - Fetch: Modified"))
    +29  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +30  @MockitoSettings(strictness = Strictness.LENIENT)
    +31  public class HttpResourceNotExpiredFetchModifiedTest
    +32  {
    +33    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotExpiredFetchModifiedTest.class);
    +34  
    +35    @Mock
    +36    HttpResourceFetcher fetcher;
    +37  
    +38    HttpResources resources;
    +39    URI uri;
    +40    HttpResource resource;
    +41  
    +42  
    +43    /************** SETUP */
    +44  
    +45    @BeforeEach
    +46    public void setUp()
    +47    {
    +48      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +49      resources = new HttpResources(fetcher, clock);
    +50      uri = URI.create("http://foo/bar");
    +51      resource = new HttpResource(resources, fetcher, clock, uri);
    +52      resource.data = DATA_NOT_EXPIRED;
    +53  
    +54      // Everything is possible, nothing is necessary: Only defines behavior!
    +55  
    +56      HttpHeaders headers = new HttpHeaders();
    +57      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +58  
    +59      when(fetcher.fetch(any(), any())).thenReturn(DATA_UPDATED);
    +60    }
    +61  
    +62  
    +63    /*************** For calls, that do not trigger a fetch see: HttpResourceNotExpiredTest */
    +64  
    +65  
    +66    /*************** Calls, that trigger a fetch */
    +67  
    +68    @Test
    +69    @DisplayName(("call to fetch() triggers fetch"))
    +70    public void test_fetch_TriggersFetch()
    +71    {
    +72      LOG.info("<-- start of test-case");
    +73  
    +74      resource.fetch();
    +75  
    +76      // Do not verify implementation: Only verify necessary outcome!
    +77      verify(fetcher).fetch(eq(uri), any());
    +78    }
    +79  
    +80  
    +81    /*************** Results for calls, that does trigger a fetch */
    +82  
    +83    @Test
    +84    @DisplayName(("fetch() returns true, if fetcher returned true"))
    +85    public void test_fetch_ReturnsTrueIfFetcherReturnedFalse()
    +86    {
    +87      LOG.info("<-- start of test-case");
    +88  
    +89      assertThat(resource.fetch()).isTrue();
    +90    }
    +91  
    +92  
    +93    /*************** Expected state after calls that trigger a fetch */
    +94  
    +95    @Test
    +96    @DisplayName(("fetch() updates data"))
    +97    public void test_fetch_UpdatesData()
    +98    {
    +99      LOG.info("<-- start of test-case");
    +100 
    +101     resource.fetch();
    +102 
    +103     assertThat(resource.data).isSameAs(DATA_UPDATED);
    +104   }
    +105 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchNotFoundTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchNotFoundTest.html new file mode 100644 index 00000000..bbe29ca1 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchNotFoundTest.html @@ -0,0 +1,119 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotExpiredFetchNotFoundTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.TestUtil.*;
    +22  import static org.assertj.core.api.Assertions.assertThat;
    +23  import static org.mockito.ArgumentMatchers.any;
    +24  import static org.mockito.ArgumentMatchers.eq;
    +25  import static org.mockito.Mockito.verify;
    +26  import static org.mockito.Mockito.when;
    +27  
    +28  
    +29  @DisplayName(("HttpResource - Fetched - Not Expired - Fetch: NotFound"))
    +30  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +31  @MockitoSettings(strictness = Strictness.LENIENT)
    +32  public class HttpResourceNotExpiredFetchNotFoundTest
    +33  {
    +34    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotExpiredFetchNotFoundTest.class);
    +35  
    +36    @Mock
    +37    HttpResourceFetcher fetcher;
    +38  
    +39    HttpResources resources;
    +40    URI uri;
    +41    HttpResource resource;
    +42  
    +43  
    +44    /************** SETUP */
    +45  
    +46    @BeforeEach
    +47    public void setUp()
    +48    {
    +49      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +50      resources = new HttpResources(fetcher, clock);
    +51      uri = URI.create("http://foo/bar");
    +52      resource = new HttpResource(resources, fetcher, clock, uri);
    +53      resource.data = DATA_NOT_EXPIRED;
    +54  
    +55      // Everything is possible, nothing is necessary: Only defines behavior!
    +56  
    +57      HttpHeaders headers = new HttpHeaders();
    +58      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +59  
    +60      when(fetcher.fetch(any(), any())).thenReturn(DATA_NOT_FOUND);
    +61    }
    +62  
    +63  
    +64    /*************** For calls, that do not trigger a fetch see: HttpResourceNotExpiredTest */
    +65  
    +66  
    +67    /*************** Calls, that trigger a fetch */
    +68  
    +69    @Test
    +70    @DisplayName(("call to fetch() triggers fetch"))
    +71    public void test_fetch_TriggersFetch()
    +72    {
    +73      LOG.info("<-- start of test-case");
    +74  
    +75      resource.fetch();
    +76  
    +77      // Do not verify implementation: Only verify necessary outcome!
    +78      verify(fetcher).fetch(eq(uri), any());
    +79    }
    +80  
    +81  
    +82    /*************** Results for calls, that does trigger a fetch */
    +83  
    +84    @Test
    +85    @DisplayName(("fetch() returns true, if fetcher returned true"))
    +86    public void test_fetch_ReturnsTrueIfFetcherReturnedFalse()
    +87    {
    +88      LOG.info("<-- start of test-case");
    +89  
    +90      assertThat(resource.fetch()).isTrue();
    +91    }
    +92  
    +93  
    +94    /*************** Expected state after calls that trigger a fetch */
    +95  
    +96    @Test
    +97    @DisplayName(("fetch() updates data"))
    +98    public void test_fetch_UpdatesData()
    +99    {
    +100     LOG.info("<-- start of test-case");
    +101 
    +102     resource.fetch();
    +103 
    +104     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +105   }
    +106 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchServerErrorTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchServerErrorTest.html new file mode 100644 index 00000000..323785b0 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchServerErrorTest.html @@ -0,0 +1,120 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotExpiredFetchServerErrorTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.HttpData.SERVER_ERROR;
    +22  import static de.juplo.httpresources.TestUtil.*;
    +23  import static org.assertj.core.api.Assertions.assertThat;
    +24  import static org.mockito.ArgumentMatchers.any;
    +25  import static org.mockito.ArgumentMatchers.eq;
    +26  import static org.mockito.Mockito.verify;
    +27  import static org.mockito.Mockito.when;
    +28  
    +29  
    +30  @DisplayName(("HttpResource - Fetched - Not Expired - Fetch: Server Error"))
    +31  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +32  @MockitoSettings(strictness = Strictness.LENIENT)
    +33  public class HttpResourceNotExpiredFetchServerErrorTest
    +34  {
    +35    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotExpiredFetchServerErrorTest.class);
    +36  
    +37    @Mock
    +38    HttpResourceFetcher fetcher;
    +39  
    +40    HttpResources resources;
    +41    URI uri;
    +42    HttpResource resource;
    +43  
    +44  
    +45    /************** SETUP */
    +46  
    +47    @BeforeEach
    +48    public void setUp()
    +49    {
    +50      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +51      resources = new HttpResources(fetcher, clock);
    +52      uri = URI.create("http://foo/bar");
    +53      resource = new HttpResource(resources, fetcher, clock, uri);
    +54      resource.data = DATA_NOT_EXPIRED;
    +55  
    +56      // Everything is possible, nothing is necessary: Only defines behavior!
    +57  
    +58      HttpHeaders headers = new HttpHeaders();
    +59      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +60  
    +61      when(fetcher.fetch(any(), any())).thenReturn(SERVER_ERROR);
    +62    }
    +63  
    +64  
    +65    /*************** Calls, that trigger a fetch */
    +66  
    +67    @Test
    +68    @DisplayName(("call to fetch() triggers fetch"))
    +69    public void test_fetch_TriggersFetch()
    +70    {
    +71      LOG.info("<-- start of test-case");
    +72  
    +73      resource.fetch();
    +74  
    +75      // Do not verify implementation: Only verify necessary outcome!
    +76      verify(fetcher).fetch(eq(uri), any());
    +77    }
    +78  
    +79  
    +80    /*************** For calls, that do not trigger a fetch see: HttpResourceNotExpiredTest */
    +81  
    +82  
    +83    /*************** Results for calls, that does trigger a fetch */
    +84  
    +85    @Test
    +86    @DisplayName(("fetch() returns true, if fetcher returned true"))
    +87    public void test_fetch_ReturnsTrueIfFetcherReturnedFalse()
    +88    {
    +89      LOG.info("<-- start of test-case");
    +90  
    +91      assertThat(resource.fetch()).isTrue();
    +92    }
    +93  
    +94  
    +95    /*************** Expected state after calls that trigger a fetch */
    +96  
    +97    @Test
    +98    @DisplayName(("fetch() updates data"))
    +99    public void test_fetch_UpdatesData()
    +100   {
    +101     LOG.info("<-- start of test-case");
    +102 
    +103     resource.fetch();
    +104 
    +105     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +106   }
    +107 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchUnmodifiedTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchUnmodifiedTest.html new file mode 100644 index 00000000..f99a4f4f --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredFetchUnmodifiedTest.html @@ -0,0 +1,102 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotExpiredFetchUnmodifiedTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.TestUtil.*;
    +22  import static org.assertj.core.api.Assertions.assertThat;
    +23  import static org.mockito.ArgumentMatchers.any;
    +24  import static org.mockito.Mockito.*;
    +25  
    +26  
    +27  @DisplayName(("HttpResource - Fetched - Not Expired - Fetch: Unmodified"))
    +28  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +29  @MockitoSettings(strictness = Strictness.LENIENT)
    +30  public class HttpResourceNotExpiredFetchUnmodifiedTest
    +31  {
    +32    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotExpiredFetchUnmodifiedTest.class);
    +33  
    +34    @Mock
    +35    HttpResourceFetcher fetcher;
    +36  
    +37    HttpResources resources;
    +38    URI uri;
    +39    HttpResource resource;
    +40  
    +41  
    +42    /************** SETUP */
    +43  
    +44    @BeforeEach
    +45    public void setUp()
    +46    {
    +47      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +48      resources = new HttpResources(fetcher, clock);
    +49      uri = URI.create("http://foo/bar");
    +50      resource = new HttpResource(resources, fetcher, clock, uri);
    +51      resource.data = DATA_NOT_EXPIRED;
    +52  
    +53      // Everything is possible, nothing is necessary: Only defines behavior!
    +54  
    +55      HttpHeaders headers = new HttpHeaders();
    +56      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +57  
    +58      when(fetcher.fetch(any(), any())).thenReturn(DATA_NOT_EXPIRED_DUMMY);
    +59    }
    +60  
    +61  
    +62    /*************** For calls, that do not trigger a fetch see: HttpResourceNotExpiredTest */
    +63  
    +64  
    +65    /*************** Results for calls, that does trigger a fetch */
    +66  
    +67    @Test
    +68    @DisplayName(("fetch() returns false, if fetcher returned false"))
    +69    public void test_fetch_ReturnsFalseIfFetcherReturnedFalse()
    +70    {
    +71      LOG.info("<-- start of test-case");
    +72  
    +73      assertThat(resource.fetch()).isFalse();
    +74    }
    +75  
    +76  
    +77    /*************** Expected state after calls that trigger a fetch */
    +78  
    +79    @Test
    +80    @DisplayName(("fetch() updates data"))
    +81    public void test_fetch_UpdatesData()
    +82    {
    +83      LOG.info("<-- start of test-case");
    +84  
    +85      resource.fetch();
    +86  
    +87      assertThat(resource.data).isSameAs(DATA_NOT_EXPIRED_DUMMY);
    +88    }
    +89  }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredTest.html new file mode 100644 index 00000000..ae4ea218 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotExpiredTest.html @@ -0,0 +1,310 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotExpiredTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.TestUtil.*;
    +22  import static org.assertj.core.api.Assertions.assertThat;
    +23  import static org.mockito.ArgumentMatchers.any;
    +24  import static org.mockito.ArgumentMatchers.eq;
    +25  import static org.mockito.Mockito.*;
    +26  
    +27  
    +28  @DisplayName(("HttpResource - Not Expired"))
    +29  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +30  @MockitoSettings(strictness = Strictness.LENIENT)
    +31  public class HttpResourceNotExpiredTest
    +32  {
    +33    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotExpiredTest.class);
    +34  
    +35    @Mock
    +36    HttpResourceFetcher fetcher;
    +37  
    +38    HttpResources resources;
    +39    URI uri;
    +40    HttpResource resource;
    +41  
    +42  
    +43    /************** SETUP */
    +44  
    +45    @BeforeEach
    +46    public void setUp()
    +47    {
    +48      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +49      resources = new HttpResources(fetcher, clock);
    +50      uri = URI.create("http://foo/bar");
    +51      resource = new HttpResource(resources, fetcher, clock, uri);
    +52      resource.data = DATA_NOT_EXPIRED;
    +53  
    +54      // Everything is possible, nothing is necessary: Only defines behavior!
    +55  
    +56      HttpHeaders headers = new HttpHeaders();
    +57      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +58  
    +59      when(fetcher.fetch(any(), any())).thenReturn(DATA_NOT_EXPIRED_DUMMY);
    +60    }
    +61  
    +62  
    +63    /*************** Calls, that trigger a fetch */
    +64  
    +65    @Test
    +66    @DisplayName(("call to fetch() triggers fetch"))
    +67    public void test_fetch_TriggersFetch()
    +68    {
    +69      LOG.info("<-- start of test-case");
    +70  
    +71      resource.fetch();
    +72  
    +73      // Do not verify implementation: Only verify necessary outcome!
    +74      verify(fetcher).fetch(eq(uri), any());
    +75    }
    +76  
    +77  
    +78    /*************** Calls, that do not trigger a fetch */
    +79  
    +80    @Test
    +81    @DisplayName(("call to fetched() does not trigger fetch"))
    +82    public void test_fetched_DoesNotTriggerFetch() throws Exception
    +83    {
    +84      LOG.info("<-- start of test-case");
    +85  
    +86      resource.fetched();
    +87  
    +88      // Do not verify implementation: Only verify necessary outcome!
    +89      verify(fetcher, never()).fetch(eq(uri), any());
    +90    }
    +91  
    +92    @Test
    +93    @DisplayName(("call to lastModified() does not trigger fetch"))
    +94    public void test_lastModified_DoesNotTriggerFetch() throws Exception
    +95    {
    +96      LOG.info("<-- start of test-case");
    +97  
    +98      resource.lastModified();
    +99  
    +100     // Do not verify implementation: Only verify necessary outcome!
    +101     verify(fetcher, never()).fetch(eq(uri), any());
    +102   }
    +103 
    +104   @Test
    +105   @DisplayName(("call to isModified() does not trigger fetch"))
    +106   public void test_isModified_DoesNotTriggerFetch() throws Exception
    +107   {
    +108     LOG.info("<-- start of test-case");
    +109 
    +110     resource.isModified();
    +111 
    +112     // Do not verify implementation: Only verify necessary outcome!
    +113     verify(fetcher, never()).fetch(eq(uri), any());
    +114   }
    +115 
    +116   @Test
    +117   @DisplayName(("call to getInputStream() does not trigger fetch"))
    +118   public void test_getInputStream_DoesNotTriggerFetch() throws Exception
    +119   {
    +120     LOG.info("<-- start of test-case");
    +121 
    +122     resource.getInputStream();
    +123 
    +124     // Do not verify implementation: Only verify necessary outcome!
    +125     verify(fetcher, never()).fetch(eq(uri), any());
    +126   }
    +127 
    +128   @Test
    +129   @DisplayName(("call to contentLength() does not trigger fetch"))
    +130   public void test_contentLength_DoesNotTriggerFetch() throws Exception
    +131   {
    +132     LOG.info("<-- start of test-case");
    +133 
    +134     resource.contentLength();
    +135 
    +136     // Do not verify implementation: Only verify necessary outcome!
    +137     verify(fetcher, never()).fetch(eq(uri), any());
    +138   }
    +139 
    +140   @Test
    +141   @DisplayName(("call to expires() does not trigger fetch"))
    +142   public void test_expires_DoesNotTriggerFetch() throws Exception
    +143   {
    +144     LOG.info("<-- start of test-case");
    +145 
    +146     resource.expires();
    +147 
    +148     // Do not verify implementation: Only verify necessary outcome!
    +149     verify(fetcher, never()).fetch(eq(uri), any());
    +150   }
    +151 
    +152   @Test
    +153   @DisplayName(("call to isExpired() does not trigger fetch"))
    +154   public void test_isExpired_DoesNotTriggerFetch() throws Exception
    +155   {
    +156     LOG.info("<-- start of test-case");
    +157 
    +158     resource.isExpired();
    +159 
    +160     // Do not verify implementation: Only verify necessary outcome!
    +161     verify(fetcher, never()).fetch(eq(uri), any());
    +162   }
    +163 
    +164   @Test
    +165   @DisplayName(("call to eTag() does not trigger fetch"))
    +166   public void test_eTag_DoesNotTriggerFetch() throws Exception
    +167   {
    +168     LOG.info("<-- start of test-case");
    +169 
    +170     resource.eTag();
    +171 
    +172     // Do not verify implementation: Only verify necessary outcome!
    +173     verify(fetcher, never()).fetch(eq(uri), any());
    +174   }
    +175 
    +176   @Test
    +177   @DisplayName(("call to contentType() does not trigger fetch"))
    +178   public void test_contentType_DoesNotTriggerFetch() throws Exception
    +179   {
    +180     LOG.info("<-- start of test-case");
    +181 
    +182     resource.contentType();
    +183 
    +184     // Do not verify implementation: Only verify necessary outcome!
    +185     verify(fetcher, never()).fetch(eq(uri), any());
    +186   }
    +187 
    +188 
    +189   /*************** Results for calls, that does never trigger a fetch */
    +190 
    +191   @Test
    +192   @DisplayName(("is fetched"))
    +193   public void test_isNotFetched() throws Exception
    +194   {
    +195     LOG.info("<-- start of test-case");
    +196 
    +197     assertThat(resource.fetched()).isTrue();
    +198   }
    +199 
    +200   @Test
    +201   @DisplayName(("exists"))
    +202   public void test_exists_IsTrue()
    +203   {
    +204     LOG.info("<-- start of test-case");
    +205 
    +206     assertThat(resource.exists()).isTrue();
    +207   }
    +208 
    +209   @Test
    +210   @DisplayName(("is readable"))
    +211   public void test_isReadable_IsTrue()
    +212   {
    +213     LOG.info("<-- start of test-case");
    +214 
    +215     assertThat(resource.isReadable()).isTrue();
    +216   }
    +217 
    +218   @Test
    +219   @DisplayName(("has expected value for last modification"))
    +220   public void test_hasExpectedLastModification() throws Exception
    +221   {
    +222     LOG.info("<-- start of test-case");
    +223 
    +224     assertThat(resource.lastModified()).isEqualTo(LONG_THEN   );
    +225   }
    +226 
    +227   @Test
    +228   @DisplayName(("is not modified"))
    +229   public void test_isNotModified()
    +230   {
    +231     LOG.info("<-- start of test-case");
    +232 
    +233     assertThat(resource.isModified()).isFalse();
    +234   }
    +235 
    +236   @Test
    +237   @DisplayName(("has expected content"))
    +238   public void test_hasExpectedContent() throws Exception
    +239   {
    +240     LOG.info("<-- start of test-case");
    +241 
    +242     assertThat(resource.getInputStream()).hasContent(STR_CONTENT);
    +243   }
    +244 
    +245   @Test
    +246   @DisplayName(("has expected content-length"))
    +247   public void test_hasExpectedContentLength() throws Exception
    +248   {
    +249     LOG.info("<-- start of test-case");
    +250 
    +251     assertThat(resource.contentLength()).isEqualTo(STR_CONTENT.getBytes().length);
    +252   }
    +253 
    +254   @Test
    +255   @DisplayName(("has expected expiration value"))
    +256   public void test_hasInitialExpirationValue() throws Exception
    +257   {
    +258     LOG.info("<-- start of test-case");
    +259 
    +260     assertThat(resource.expires()).isEqualTo(DATA_NOT_EXPIRED.expires);
    +261   }
    +262 
    +263   @Test
    +264   @DisplayName(("is not expired"))
    +265   public void test_isNotExpired() throws Exception
    +266   {
    +267     LOG.info("<-- start of test-case");
    +268 
    +269     assertThat(resource.isExpired()).isFalse();
    +270   }
    +271 
    +272   @Test
    +273   @DisplayName(("has expected eTag"))
    +274   public void test_hasExpectedETag() throws Exception
    +275   {
    +276     LOG.info("<-- start of test-case");
    +277 
    +278     assertThat(resource.eTag()).isEqualTo(STR_ETAG);
    +279   }
    +280 
    +281   @Test
    +282   @DisplayName(("has expected content-type"))
    +283   public void test_hasExpectedContentType() throws Exception
    +284   {
    +285     LOG.info("<-- start of test-case");
    +286 
    +287     assertThat(resource.contentType()).isEqualTo(MIME_TYPE_CONTENT_TYPE_HTML);
    +288   }
    +289 
    +290 
    +291   /*************** For results for calls, that does trigger a fetch, see
    +292    *************** - HttpResourceNotExpiredFetchUnodifiedTest
    +293    *************** - HttpResourceNotExpiredFetchModifiedTest
    +294    *************** - HttpResourceNotExpiredFetchVanishedTest
    +295    *************** - HttpResourceNotExpiredFetchServerErrorTest
    +296    ***************/
    +297 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchNotFoundTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchNotFoundTest.html new file mode 100644 index 00000000..662db79e --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchNotFoundTest.html @@ -0,0 +1,232 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchNotFoundTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.io.FileNotFoundException;
    +18  import java.net.URI;
    +19  import java.time.Clock;
    +20  import java.time.ZoneId;
    +21  
    +22  import static de.juplo.httpresources.TestUtil.*;
    +23  import static org.assertj.core.api.Assertions.assertThat;
    +24  import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
    +25  import static org.mockito.ArgumentMatchers.any;
    +26  import static org.mockito.Mockito.when;
    +27  
    +28  
    +29  @DisplayName(("HttpResource - Not Fetched - First Fetch: Not Found"))
    +30  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +31  @MockitoSettings(strictness = Strictness.LENIENT)
    +32  public class HttpResourceNotFetchedFirstFetchNotFoundTest
    +33  {
    +34    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotFetchedFirstFetchNotFoundTest.class);
    +35  
    +36    @Mock
    +37    HttpResourceFetcher fetcher;
    +38  
    +39    HttpResources resources;
    +40    URI uri;
    +41    HttpResource resource;
    +42  
    +43  
    +44    /************** SETUP */
    +45  
    +46    @BeforeEach
    +47    public void setUp()
    +48    {
    +49      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +50      resources = new HttpResources(fetcher, clock);
    +51      uri = URI.create("http://foo/bar");
    +52      resource = new HttpResource(resources, fetcher, clock, uri);
    +53  
    +54      // Everything is possible, nothing is necessary: Only defines behavior!
    +55  
    +56      HttpHeaders headers = new HttpHeaders();
    +57      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +58  
    +59      when(fetcher.fetch(any(), any())).thenReturn(DATA_NOT_FOUND);
    +60    }
    +61  
    +62  
    +63    /*************** Results for calls, that trigger a fetch */
    +64  
    +65    @Test
    +66    @DisplayName(("fetch() reports modifications"))
    +67    public void test_fetch_ReportsModifications()
    +68    {
    +69      LOG.info("<-- start of test-case");
    +70  
    +71      assertThat(resource.fetch()).isTrue();
    +72    }
    +73  
    +74    @Test
    +75    @DisplayName(("exists() is false"))
    +76    public void test_exists_IsFalse()
    +77    {
    +78      LOG.info("<-- start of test-case");
    +79  
    +80      assertThat(resource.exists()).isFalse();
    +81    }
    +82  
    +83    @Test
    +84    @DisplayName(("isReadable() is false"))
    +85    public void test_isReadable_IsFalse()
    +86    {
    +87      LOG.info("<-- start of test-case");
    +88  
    +89      assertThat(resource.isReadable()).isFalse();
    +90    }
    +91  
    +92    @Test
    +93    @DisplayName(("lastModified() returns the expected time"))
    +94    public void test_lastModified_ReturnsExpectedTime() throws Exception
    +95    {
    +96      LOG.info("<-- start of test-case");
    +97  
    +98      assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> resource.lastModified());
    +99    }
    +100 
    +101   @Test
    +102   @DisplayName(("isModified() if true"))
    +103   public void test_isModified_IsTrue()
    +104   {
    +105     LOG.info("<-- start of test-case");
    +106 
    +107     assertThat(resource.isModified()).isTrue();
    +108   }
    +109 
    +110   @Test
    +111   @DisplayName(("getInputStream() throws FileNotFoundException"))
    +112   public void test_getInputStream_ThrowsFileNotFoundException() throws Exception
    +113   {
    +114     LOG.info("<-- start of test-case");
    +115 
    +116     assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> resource.getInputStream());
    +117   }
    +118 
    +119   @Test
    +120   @DisplayName(("contentLength() throws FileNotFoundException"))
    +121   public void test_contentLength_ThrowsFileNotFoundException() throws Exception
    +122   {
    +123     LOG.info("<-- start of test-case");
    +124 
    +125     assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> resource.contentLength());
    +126   }
    +127 
    +128 
    +129   /*************** Expected state after calls that trigger a fetch */
    +130 
    +131   @Test
    +132   @DisplayName(("call to fetch() updates data"))
    +133   public void test_fetch_UpdatesData()
    +134   {
    +135     LOG.info("<-- start of test-case");
    +136 
    +137     resource.fetch();
    +138 
    +139     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +140   }
    +141 
    +142   @Test
    +143   @DisplayName(("call to exists() updates data"))
    +144   public void test_exists_UpdatesData()
    +145   {
    +146     LOG.info("<-- start of test-case");
    +147 
    +148     resource.exists();
    +149 
    +150     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +151   }
    +152 
    +153   @Test
    +154   @DisplayName(("call to isReadable() updates data"))
    +155   public void test_isReadable_UpdatesData()
    +156   {
    +157     LOG.info("<-- start of test-case");
    +158 
    +159     resource.isReadable();
    +160 
    +161     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +162   }
    +163 
    +164   @Test
    +165   @DisplayName(("call to lastModified() updates data"))
    +166   public void test_lastModified_UpdatesData() throws Exception
    +167   {
    +168     LOG.info("<-- start of test-case");
    +169 
    +170     try
    +171     {
    +172       resource.lastModified();
    +173     }
    +174     catch (FileNotFoundException e) {}
    +175 
    +176     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +177   }
    +178 
    +179   @Test
    +180   @DisplayName(("call to isModified() updates data"))
    +181   public void test_isModified_UpdatesData()
    +182   {
    +183     LOG.info("<-- start of test-case");
    +184 
    +185     resource.isModified();
    +186 
    +187     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +188   }
    +189 
    +190   @Test
    +191   @DisplayName(("call to getInputStream() updates data"))
    +192   public void test_getInputStream_UpdatesData() throws Exception
    +193   {
    +194     LOG.info("<-- start of test-case");
    +195 
    +196     try
    +197     {
    +198       resource.getInputStream();
    +199     }
    +200     catch (FileNotFoundException e) {}
    +201 
    +202     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +203   }
    +204 
    +205   @Test
    +206   @DisplayName(("call to contentLength() updates data"))
    +207   public void test_contentLength_UpdatesData() throws Exception
    +208   {
    +209     LOG.info("<-- start of test-case");
    +210 
    +211     try
    +212     {
    +213       resource.contentLength();
    +214     }
    +215     catch (FileNotFoundException e) {}
    +216 
    +217     assertThat(resource.data).isSameAs(DATA_NOT_FOUND);
    +218   }
    +219 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchServerErrorTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchServerErrorTest.html new file mode 100644 index 00000000..25af806f --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchServerErrorTest.html @@ -0,0 +1,233 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchServerErrorTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.io.FileNotFoundException;
    +18  import java.net.URI;
    +19  import java.time.Clock;
    +20  import java.time.ZoneId;
    +21  
    +22  import static de.juplo.httpresources.HttpData.SERVER_ERROR;
    +23  import static de.juplo.httpresources.TestUtil.*;
    +24  import static org.assertj.core.api.Assertions.assertThat;
    +25  import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
    +26  import static org.mockito.ArgumentMatchers.any;
    +27  import static org.mockito.Mockito.when;
    +28  
    +29  
    +30  @DisplayName(("HttpResource - Not Fetched - First Fetch: Server Error"))
    +31  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +32  @MockitoSettings(strictness = Strictness.LENIENT)
    +33  public class HttpResourceNotFetchedFirstFetchServerErrorTest
    +34  {
    +35    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotFetchedFirstFetchServerErrorTest.class);
    +36  
    +37    @Mock
    +38    HttpResourceFetcher fetcher;
    +39  
    +40    HttpResources resources;
    +41    URI uri;
    +42    HttpResource resource;
    +43  
    +44  
    +45    /************** SETUP */
    +46  
    +47    @BeforeEach
    +48    public void setUp()
    +49    {
    +50      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +51      resources = new HttpResources(fetcher, clock);
    +52      uri = URI.create("http://foo/bar");
    +53      resource = new HttpResource(resources, fetcher, clock, uri);
    +54  
    +55      // Everything is possible, nothing is necessary: Only defines behavior!
    +56  
    +57      HttpHeaders headers = new HttpHeaders();
    +58      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +59  
    +60      when(fetcher.fetch(any(), any())).thenReturn(SERVER_ERROR);
    +61    }
    +62  
    +63  
    +64    /*************** Results for calls, that trigger a fetch */
    +65  
    +66    @Test
    +67    @DisplayName(("fetch() reports modifications"))
    +68    public void test_fetch_ReportsModifications()
    +69    {
    +70      LOG.info("<-- start of test-case");
    +71  
    +72      assertThat(resource.fetch()).isTrue();
    +73    }
    +74  
    +75    @Test
    +76    @DisplayName(("exists() is false"))
    +77    public void test_exists_IsFalse()
    +78    {
    +79      LOG.info("<-- start of test-case");
    +80  
    +81      assertThat(resource.exists()).isFalse();
    +82    }
    +83  
    +84    @Test
    +85    @DisplayName(("isReadable() is false"))
    +86    public void test_isReadable_IsFalse()
    +87    {
    +88      LOG.info("<-- start of test-case");
    +89  
    +90      assertThat(resource.isReadable()).isFalse();
    +91    }
    +92  
    +93    @Test
    +94    @DisplayName(("lastModified() returns the expected time"))
    +95    public void test_lastModified_ReturnsExpectedTime() throws Exception
    +96    {
    +97      LOG.info("<-- start of test-case");
    +98  
    +99      assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> resource.lastModified());
    +100   }
    +101 
    +102   @Test
    +103   @DisplayName(("isModified() if true"))
    +104   public void test_isModified_IsTrue()
    +105   {
    +106     LOG.info("<-- start of test-case");
    +107 
    +108     assertThat(resource.isModified()).isTrue();
    +109   }
    +110 
    +111   @Test
    +112   @DisplayName(("getInputStream() throws FileNotFoundException"))
    +113   public void test_getInputStream_ThrowsFileNotFoundException() throws Exception
    +114   {
    +115     LOG.info("<-- start of test-case");
    +116 
    +117     assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> resource.getInputStream());
    +118   }
    +119 
    +120   @Test
    +121   @DisplayName(("contentLength() throws FileNotFoundException"))
    +122   public void test_contentLength_ThrowsFileNotFoundException() throws Exception
    +123   {
    +124     LOG.info("<-- start of test-case");
    +125 
    +126     assertThatExceptionOfType(FileNotFoundException.class).isThrownBy(() -> resource.contentLength());
    +127   }
    +128 
    +129 
    +130   /*************** Expected state after calls that trigger a fetch */
    +131 
    +132   @Test
    +133   @DisplayName(("call to fetch() updates data"))
    +134   public void test_fetch_UpdatesData()
    +135   {
    +136     LOG.info("<-- start of test-case");
    +137 
    +138     resource.fetch();
    +139 
    +140     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +141   }
    +142 
    +143   @Test
    +144   @DisplayName(("call to exists() updates data"))
    +145   public void test_exists_UpdatesData()
    +146   {
    +147     LOG.info("<-- start of test-case");
    +148 
    +149     resource.exists();
    +150 
    +151     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +152   }
    +153 
    +154   @Test
    +155   @DisplayName(("call to isReadable() updates data"))
    +156   public void test_isReadable_UpdatesData()
    +157   {
    +158     LOG.info("<-- start of test-case");
    +159 
    +160     resource.isReadable();
    +161 
    +162     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +163   }
    +164 
    +165   @Test
    +166   @DisplayName(("call to lastModified() updates data"))
    +167   public void test_lastModified_UpdatesData() throws Exception
    +168   {
    +169     LOG.info("<-- start of test-case");
    +170 
    +171     try
    +172     {
    +173       resource.lastModified();
    +174     }
    +175     catch (FileNotFoundException e) {}
    +176 
    +177     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +178   }
    +179 
    +180   @Test
    +181   @DisplayName(("call to isModified() updates data"))
    +182   public void test_isModified_UpdatesData()
    +183   {
    +184     LOG.info("<-- start of test-case");
    +185 
    +186     resource.isModified();
    +187 
    +188     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +189   }
    +190 
    +191   @Test
    +192   @DisplayName(("call to getInputStream() updates data"))
    +193   public void test_getInputStream_UpdatesData() throws Exception
    +194   {
    +195     LOG.info("<-- start of test-case");
    +196 
    +197     try
    +198     {
    +199       resource.getInputStream();
    +200     }
    +201     catch (FileNotFoundException e) {}
    +202 
    +203     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +204   }
    +205 
    +206   @Test
    +207   @DisplayName(("call to contentLength() updates data"))
    +208   public void test_contentLength_UpdatesData() throws Exception
    +209   {
    +210     LOG.info("<-- start of test-case");
    +211 
    +212     try
    +213     {
    +214       resource.contentLength();
    +215     }
    +216     catch (FileNotFoundException e) {}
    +217 
    +218     assertThat(resource.data).isSameAs(SERVER_ERROR);
    +219   }
    +220 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchSuccessfulTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchSuccessfulTest.html new file mode 100644 index 00000000..c184b374 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchSuccessfulTest.html @@ -0,0 +1,218 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotFetchedFirstFetchSuccessfulTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.TestUtil.*;
    +22  import static org.assertj.core.api.Assertions.assertThat;
    +23  import static org.mockito.ArgumentMatchers.any;
    +24  import static org.mockito.Mockito.*;
    +25  
    +26  
    +27  @DisplayName(("HttpResource - Not Fetched - First Fetch: Successfull"))
    +28  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +29  @MockitoSettings(strictness = Strictness.LENIENT)
    +30  public class HttpResourceNotFetchedFirstFetchSuccessfulTest
    +31  {
    +32    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotFetchedFirstFetchSuccessfulTest.class);
    +33  
    +34    @Mock
    +35    HttpResourceFetcher fetcher;
    +36  
    +37    HttpResources resources;
    +38    URI uri;
    +39    HttpResource resource;
    +40  
    +41  
    +42    /************** SETUP */
    +43  
    +44    @BeforeEach
    +45    public void setUp()
    +46    {
    +47      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +48      resources = new HttpResources(fetcher, clock);
    +49      uri = URI.create("http://foo/bar");
    +50      resource = new HttpResource(resources, fetcher, clock, uri);
    +51  
    +52      // Everything is possible, nothing is necessary: Only defines behavior!
    +53  
    +54      HttpHeaders headers = new HttpHeaders();
    +55      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +56  
    +57      when(fetcher.fetch(any(), any())).thenReturn(DATA_NOT_EXPIRED);
    +58    }
    +59  
    +60  
    +61    /*************** Results for calls, that trigger a fetch */
    +62  
    +63    @Test
    +64    @DisplayName(("fetch() reports modifications"))
    +65    public void test_fetch_ReportsModifications()
    +66    {
    +67      LOG.info("<-- start of test-case");
    +68  
    +69      assertThat(resource.fetch()).isTrue();
    +70    }
    +71  
    +72    @Test
    +73    @DisplayName(("exists() is true"))
    +74    public void test_exists_IsTrue()
    +75    {
    +76      LOG.info("<-- start of test-case");
    +77  
    +78      assertThat(resource.exists()).isTrue();
    +79    }
    +80  
    +81    @Test
    +82    @DisplayName(("isReadable() is true"))
    +83    public void test_isReadable_IsTrue()
    +84    {
    +85      LOG.info("<-- start of test-case");
    +86  
    +87      assertThat(resource.isReadable()).isTrue();
    +88    }
    +89  
    +90    @Test
    +91    @DisplayName(("lastModified() returns the expected time"))
    +92    public void test_lastModified_ReturnsExpectedTime() throws Exception
    +93    {
    +94      LOG.info("<-- start of test-case");
    +95  
    +96      assertThat(resource.lastModified()).isEqualTo(DATA_NOT_EXPIRED.lastModified);
    +97    }
    +98  
    +99    @Test
    +100   @DisplayName(("isModified() is true"))
    +101   public void test_isModified_IsTrue()
    +102   {
    +103     LOG.info("<-- start of test-case");
    +104 
    +105     assertThat(resource.isModified()).isTrue();
    +106  }
    +107 
    +108   @Test
    +109   @DisplayName(("getInputStream() returns expected content"))
    +110   public void test_getInputStream_TriggersFetch() throws Exception
    +111   {
    +112     LOG.info("<-- start of test-case");
    +113 
    +114     assertThat(resource.getInputStream()).hasContent(STR_CONTENT);
    +115   }
    +116 
    +117   @Test
    +118   @DisplayName(("contentLength() returns expected content-length"))
    +119   public void test_contentLength_ReturnsExpectedLength() throws Exception
    +120   {
    +121     LOG.info("<-- start of test-case");
    +122 
    +123     assertThat(resource.contentLength()).isSameAs((long)STR_CONTENT.getBytes().length);
    +124   }
    +125 
    +126 
    +127   /*************** Expected state after calls that trigger a fetch */
    +128 
    +129   @Test
    +130   @DisplayName(("call to fetch() updates data"))
    +131   public void test_fetch_UpdatesData()
    +132   {
    +133     LOG.info("<-- start of test-case");
    +134 
    +135     resource.fetch();
    +136 
    +137     assertThat(resource.data).isSameAs(DATA_NOT_EXPIRED);
    +138   }
    +139 
    +140   @Test
    +141   @DisplayName(("call to exists() updates data"))
    +142   public void test_exists_UpdatesData()
    +143   {
    +144     LOG.info("<-- start of test-case");
    +145 
    +146     resource.exists();
    +147 
    +148     assertThat(resource.data).isSameAs(DATA_NOT_EXPIRED);
    +149   }
    +150 
    +151   @Test
    +152   @DisplayName(("call to isReadable() updates data"))
    +153   public void test_isReadable_UpdatesData()
    +154   {
    +155     LOG.info("<-- start of test-case");
    +156 
    +157     resource.isReadable();
    +158 
    +159     assertThat(resource.data).isSameAs(DATA_NOT_EXPIRED);
    +160   }
    +161 
    +162   @Test
    +163   @DisplayName(("call to lastModified() updates data"))
    +164   public void test_lastModified_UpdatesData() throws Exception
    +165   {
    +166     LOG.info("<-- start of test-case");
    +167 
    +168     resource.lastModified();
    +169 
    +170     assertThat(resource.data).isSameAs(DATA_NOT_EXPIRED);
    +171   }
    +172 
    +173   @Test
    +174   @DisplayName(("call to isModified() updates data"))
    +175   public void test_isModified_UpdatesData()
    +176   {
    +177     LOG.info("<-- start of test-case");
    +178 
    +179     resource.isModified();
    +180 
    +181     assertThat(resource.data).isSameAs(DATA_NOT_EXPIRED);
    +182   }
    +183 
    +184   @Test
    +185   @DisplayName(("call to getInputStream() updates data"))
    +186   public void test_getInputStream_UpdatesData() throws Exception
    +187   {
    +188     LOG.info("<-- start of test-case");
    +189 
    +190     resource.getInputStream();
    +191 
    +192     assertThat(resource.data).isSameAs(DATA_NOT_EXPIRED);
    +193   }
    +194 
    +195   @Test
    +196   @DisplayName(("call to contentLength() updates data"))
    +197   public void test_contentLength_UpdatesData() throws Exception
    +198   {
    +199     LOG.info("<-- start of test-case");
    +200 
    +201     resource.contentLength();
    +202 
    +203     assertThat(resource.data).isSameAs(DATA_NOT_EXPIRED);
    +204   }
    +205 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedTest.html new file mode 100644 index 00000000..497af827 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceNotFetchedTest.html @@ -0,0 +1,279 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceNotFetchedTest.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.DisplayName;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.junit.jupiter.api.extension.ExtendWith;
    +7   import org.mockito.Mock;
    +8   import org.mockito.junit.jupiter.MockitoExtension;
    +9   import org.mockito.junit.jupiter.MockitoSettings;
    +10  import org.mockito.quality.Strictness;
    +11  import org.slf4j.Logger;
    +12  import org.slf4j.LoggerFactory;
    +13  import org.springframework.cache.support.NoOpCache;
    +14  import org.springframework.http.HttpHeaders;
    +15  import org.springframework.test.context.junit.jupiter.SpringExtension;
    +16  
    +17  import java.net.URI;
    +18  import java.time.Clock;
    +19  import java.time.ZoneId;
    +20  
    +21  import static de.juplo.httpresources.TestUtil.*;
    +22  import static org.assertj.core.api.Assertions.assertThat;
    +23  import static org.junit.jupiter.api.Assertions.assertNull;
    +24  import static org.mockito.ArgumentMatchers.any;
    +25  import static org.mockito.ArgumentMatchers.eq;
    +26  import static org.mockito.Mockito.*;
    +27  
    +28  
    +29  @DisplayName(("HttpResource - Not Fetched"))
    +30  @ExtendWith({ SpringExtension.class, MockitoExtension.class })
    +31  @MockitoSettings(strictness = Strictness.LENIENT)
    +32  public class HttpResourceNotFetchedTest
    +33  {
    +34    private final static Logger LOG = LoggerFactory.getLogger(HttpResourceNotFetchedTest.class);
    +35  
    +36    @Mock
    +37    HttpResourceFetcher fetcher;
    +38  
    +39    HttpResources resources;
    +40    URI uri;
    +41    HttpResource resource;
    +42  
    +43  
    +44    /************** SETUP */
    +45  
    +46    @BeforeEach
    +47    public void setUp()
    +48    {
    +49      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +50      resources = new HttpResources(fetcher, clock);
    +51      uri = URI.create("http://foo/bar");
    +52      resource = new HttpResource(resources, fetcher, clock, uri);
    +53  
    +54      // Everything is possible, nothing is necessary: Only defines behavior!
    +55  
    +56      HttpHeaders headers = new HttpHeaders();
    +57      headers.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +58  
    +59      when(fetcher.fetch(any(), any())).thenReturn(DATA_NOT_EXPIRED);
    +60    }
    +61  
    +62  
    +63    /*************** Calls, that trigger a fetch */
    +64  
    +65    @Test
    +66    @DisplayName(("call to fetch() triggers fetch"))
    +67    public void test_fetch_TriggersFetch()
    +68    {
    +69      LOG.info("<-- start of test-case");
    +70  
    +71      resource.fetch();
    +72  
    +73      // Do not verify implementation: Only verify necessary outcome!
    +74      verify(fetcher).fetch(eq(uri), any());
    +75    }
    +76  
    +77    @Test
    +78    @DisplayName(("call to exists() triggers fetch"))
    +79    public void test_exists_TriggersFetch()
    +80    {
    +81      LOG.info("<-- start of test-case");
    +82  
    +83      resource.exists();
    +84  
    +85      // Do not verify implementation: Only verify necessary outcome!
    +86      verify(fetcher).fetch(eq(uri), any());
    +87    }
    +88  
    +89    @Test
    +90    @DisplayName(("call to isReadable() triggers fetch"))
    +91    public void test_isReadable_TriggersFetch()
    +92    {
    +93      LOG.info("<-- start of test-case");
    +94  
    +95      resource.isReadable();
    +96  
    +97      // Do not verify implementation: Only verify necessary outcome!
    +98      verify(fetcher).fetch(eq(uri), any());
    +99    }
    +100 
    +101   @Test
    +102   @DisplayName(("call to lastModified() triggers fetch"))
    +103   public void test_lastModified_TriggersFetch() throws Exception
    +104   {
    +105     LOG.info("<-- start of test-case");
    +106 
    +107     resource.lastModified();
    +108 
    +109     // Do not verify implementation: Only verify necessary outcome!
    +110     verify(fetcher).fetch(eq(uri), any());
    +111   }
    +112 
    +113   @Test
    +114   @DisplayName(("call to isModified() triggers fetch"))
    +115   public void test_isModified_TriggersFetch()
    +116   {
    +117     LOG.info("<-- start of test-case");
    +118 
    +119     resource.isModified();
    +120 
    +121     // Do not verify implementation: Only verify necessary outcome!
    +122     verify(fetcher).fetch(eq(uri), any());
    +123   }
    +124 
    +125   @Test
    +126   @DisplayName(("call to getInputStream() triggers fetch"))
    +127   public void test_getInputStream_TriggersFetch() throws Exception
    +128   {
    +129     LOG.info("<-- start of test-case");
    +130 
    +131     resource.getInputStream();
    +132 
    +133     // Do not verify implementation: Only verify necessary outcome!
    +134     verify(fetcher).fetch(eq(uri), any());
    +135   }
    +136 
    +137   @Test
    +138   @DisplayName(("call to contentLength() does trigger fetch"))
    +139   public void test_contentLength_TriggersFetch() throws Exception
    +140   {
    +141     LOG.info("<-- start of test-case");
    +142 
    +143     resource.contentLength();
    +144 
    +145     // Do not verify implementation: Only verify necessary outcome!
    +146     verify(fetcher).fetch(eq(uri), any());
    +147   }
    +148 
    +149 
    +150   /*************** Calls, that do not trigger a fetch */
    +151 
    +152   @Test
    +153   @DisplayName(("call to fetched() does not trigger fetch"))
    +154   public void test_fetched_DoesNotTriggerFetch() throws Exception
    +155   {
    +156     LOG.info("<-- start of test-case");
    +157 
    +158     resource.fetched();
    +159 
    +160     // Do not verify implementation: Only verify necessary outcome!
    +161     verify(fetcher, never()).fetch(eq(uri), any());
    +162   }
    +163 
    +164   @Test
    +165   @DisplayName(("call to expires() does not trigger fetch"))
    +166   public void test_expires_DoesNotTriggerFetch() throws Exception
    +167   {
    +168     LOG.info("<-- start of test-case");
    +169 
    +170     resource.expires();
    +171 
    +172     // Do not verify implementation: Only verify necessary outcome!
    +173     verify(fetcher, never()).fetch(eq(uri), any());
    +174   }
    +175 
    +176   @Test
    +177   @DisplayName(("call to isExpired() does not trigger fetch"))
    +178   public void test_isExpired_DoesNotTriggerFetch() throws Exception
    +179   {
    +180     LOG.info("<-- start of test-case");
    +181 
    +182     resource.isExpired();
    +183 
    +184     // Do not verify implementation: Only verify necessary outcome!
    +185     verify(fetcher, never()).fetch(eq(uri), any());
    +186   }
    +187 
    +188   @Test
    +189   @DisplayName(("call to eTag() does not trigger fetch"))
    +190   public void test_eTag_DoesNotTriggerFetch() throws Exception
    +191   {
    +192     LOG.info("<-- start of test-case");
    +193 
    +194     resource.eTag();
    +195 
    +196     // Do not verify implementation: Only verify necessary outcome!
    +197     verify(fetcher, never()).fetch(eq(uri), any());
    +198   }
    +199 
    +200   @Test
    +201   @DisplayName(("call to contentType() does not trigger fetch"))
    +202   public void test_contentType_DoesNotTriggerFetch() throws Exception
    +203   {
    +204     LOG.info("<-- start of test-case");
    +205 
    +206     resource.contentType();
    +207 
    +208     // Do not verify implementation: Only verify necessary outcome!
    +209     verify(fetcher, never()).fetch(eq(uri), any());
    +210   }
    +211 
    +212 
    +213   /*************** Initial results for calls, that does not trigger a fetch */
    +214 
    +215   @Test
    +216   @DisplayName(("is not fetched"))
    +217   public void test_isNotFetched() throws Exception
    +218   {
    +219     LOG.info("<-- start of test-case");
    +220 
    +221     assertThat(resource.fetched()).isFalse();
    +222   }
    +223 
    +224   @Test
    +225   @DisplayName(("has Long.MIN_VALUE as initial expiration value"))
    +226   public void test_hasInitialExpirationValue() throws Exception
    +227   {
    +228     LOG.info("<-- start of test-case");
    +229 
    +230     assertThat(resource.expires()).isEqualTo(Long.MIN_VALUE);
    +231   }
    +232 
    +233   @Test
    +234   @DisplayName(("is expired"))
    +235   public void test_isExpired() throws Exception
    +236   {
    +237     LOG.info("<-- start of test-case");
    +238 
    +239     assertThat(resource.isExpired()).isTrue();
    +240   }
    +241 
    +242   @Test
    +243   @DisplayName(("has no eTag"))
    +244   public void test_hasNoETag() throws Exception
    +245   {
    +246     LOG.info("<-- start of test-case");
    +247 
    +248     assertThat(resource.eTag()).isNull();
    +249   }
    +250 
    +251   @Test
    +252   @DisplayName(("has no content-type"))
    +253   public void test_hasNoContentType() throws Exception
    +254   {
    +255     LOG.info("<-- start of test-case");
    +256 
    +257     assertThat(resource.contentType()).isNull();
    +258   }
    +259 
    +260 
    +261   /*************** For results for calls, that does trigger a fetch, see
    +262    *************** - HttpResourceNotFetchedFirstFetchSuccessfullTest
    +263    *************** - HttpResourceNotFetchedFirstFetchNotFoundTest
    +264    *************** - HttpResourceNotFetchedFirstFetchServerErrorTest
    +265    ***************/
    +266 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceProtocolResolverIT.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceProtocolResolverIT.html new file mode 100644 index 00000000..2fe598cf --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceProtocolResolverIT.html @@ -0,0 +1,281 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/HttpResourceProtocolResolverIT.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.Test;
    +5   import org.mockserver.integration.ClientAndServer;
    +6   import org.slf4j.Logger;
    +7   import org.slf4j.LoggerFactory;
    +8   import org.springframework.beans.factory.annotation.Autowired;
    +9   import org.springframework.beans.factory.annotation.Value;
    +10  import org.springframework.boot.autoconfigure.SpringBootApplication;
    +11  import org.springframework.boot.test.context.SpringBootTest;
    +12  import org.springframework.cache.Cache;
    +13  import org.springframework.core.io.Resource;
    +14  import org.springframework.test.web.servlet.MockMvc;
    +15  import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    +16  import org.springframework.util.StreamUtils;
    +17  import org.springframework.web.context.WebApplicationContext;
    +18  import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    +19  import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    +20  
    +21  import java.net.URI;
    +22  import java.nio.charset.Charset;
    +23  import java.time.Duration;
    +24  
    +25  import static de.juplo.httpresources.TestUtil.CONTENT;
    +26  import static de.juplo.httpresources.TestUtil.read;
    +27  import static org.junit.jupiter.api.Assertions.*;
    +28  import static org.mockserver.model.HttpRequest.request;
    +29  import static org.mockserver.verify.VerificationTimes.exactly;
    +30  import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    +31  import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
    +32  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    +33  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    +34  
    +35  /**
    +36   * Mostly identically with {@link HttpResourceResolverIT}.
    +37   * Differences:Test explicit lookup with full address through context and has
    +38   * no exclusion/inclusion.
    +39   */
    +40  @SpringBootTest({
    +41      "juplo.http-resources.protocol-resolver.enabled=true",
    +42      "juplo.http-resources.resolver.enabled=false",
    +43      "juplo.http-resources.resolver.exclusion-patterns=**.txt" // << Not used here!
    +44      })
    +45  public class HttpResourceProtocolResolverIT extends IntegrationTestBase
    +46  {
    +47    private final static Logger LOG =
    +48        LoggerFactory.getLogger(HttpResourceProtocolResolverIT.class);
    +49  
    +50  
    +51    @Autowired
    +52    HttpResources resources;
    +53    @Autowired
    +54    Cache cache;
    +55    @Autowired
    +56    WebApplicationContext context;
    +57  
    +58    @Value("classpath:remote/remote.html")
    +59    Resource remote;
    +60    @Value("classpath:remote/modified.html")
    +61    Resource modified;
    +62  
    +63    MockMvc mvc;
    +64  
    +65  
    +66    @BeforeEach
    +67    public void setUp()
    +68    {
    +69      cache.clear();
    +70      mvc = MockMvcBuilders
    +71              .webAppContextSetup(context)
    +72              .alwaysDo(print())
    +73              .build();
    +74    }
    +75  
    +76  
    +77    /**
    +78     * Olthough the {@HttpResourceResolver} is not enabled in this test-scenario,
    +79     * this works nearly, identically to the same test there, because all lookups
    +80     * for resources in the resource-chain for static http-resources are executed
    +81     * through the application-context, where the
    +82     * {@link HttpResourceProtocolResolver} is registerd.
    +83     * Only exclusion is not working, since this is only implemented in the
    +84     * {@HttpResourceResolver}.
    +85     */
    +86    @Test
    +87    public void testResourceHandling() throws Exception
    +88    {
    +89      LOG.info("<-- start of test-case");
    +90  
    +91      mvc
    +92          .perform(get(URI.create("http://test/foo")))
    +93          .andExpect(status().isOk())
    +94          .andExpect(content().contentType("application/octet-stream"))
    +95          .andExpect(content().string("FOO\n"));
    +96      mvc
    +97          .perform(get(URI.create("http://test/bar")))
    +98          .andExpect(status().isOk())
    +99          .andExpect(content().contentType("application/octet-stream"))
    +100         .andExpect(content().string("BAR\n"));
    +101     mvc
    +102         .perform(get(URI.create("http://test/hello")))
    +103         .andExpect(status().isOk())
    +104         .andExpect(content().contentType("application/octet-stream"))
    +105         .andExpect(content().bytes(CONTENT));
    +106     mvc
    +107         .perform(get(URI.create("http://test/remote.html")))
    +108         .andExpect(status().isOk())
    +109         .andExpect(content().contentType("text/html"))
    +110         .andExpect(content().bytes(StreamUtils.copyToByteArray(remote.getInputStream())));
    +111     mvc
    +112         .perform(get(URI.create("http://test/foobar")))
    +113         .andExpect(status().isOk())
    +114         .andExpect(content().contentType("application/octet-stream"))
    +115         .andExpect(content().string("FOOBAR\n"));
    +116     mvc
    +117         .perform(get(URI.create("http://test/hello")))
    +118         .andExpect(status().isOk())
    +119         .andExpect(content().contentType("application/octet-stream"))
    +120         .andExpect(content().bytes(CONTENT));
    +121     mvc
    +122         .perform(get(URI.create("http://test/hello")))
    +123         .andExpect(status().isOk())
    +124         .andExpect(content().contentType("application/octet-stream"))
    +125         .andExpect(content().bytes(CONTENT));
    +126     mvc
    +127         .perform(get(URI.create("http://test/hello")))
    +128         .andExpect(status().isOk())
    +129         .andExpect(content().contentType("application/octet-stream"))
    +130         .andExpect(content().bytes(CONTENT));
    +131     mvc
    +132         .perform(get(URI.create("http://test/hallo.txt")))
    +133         .andExpect(status().isOk())
    +134         .andExpect(content().contentType("text/plain"))
    +135         .andExpect(content().string("welt\n"));
    +136 
    +137     server.verify(FETCH("/foo"), exactly(0));
    +138     server.verify(FETCH("/bar"), exactly(0));
    +139     server.verify(FETCH("/hello"), exactly(1));
    +140     server.verify(FETCH("/hallo.txt"), exactly(1));
    +141     server.verify(FETCH("/remote.html"), exactly(1));
    +142     server.verify(FETCH("/foobar"), exactly(2));
    +143   }
    +144 
    +145   @Test
    +146   public void testFetchExistent() throws Exception
    +147   {
    +148     LOG.info("<-- Start of test-case");
    +149 
    +150     getRemoteHtml();
    +151 
    +152     server.verify(FETCH("/remote.html"), exactly(1));
    +153   }
    +154 
    +155   @Test
    +156   public void testCachingOfExisting() throws Exception
    +157   {
    +158     LOG.info("<-- Start of test-case");
    +159 
    +160     getRemoteHtml();
    +161     getRemoteHtml();
    +162     getRemoteHtml();
    +163     getRemoteHtml();
    +164     getRemoteHtml();
    +165     getRemoteHtml();
    +166     getRemoteHtml();
    +167     getRemoteHtml();
    +168 
    +169     server.verify(FETCH("/remote.html"), exactly(1));
    +170   }
    +171 
    +172   private void getRemoteHtml() throws Exception
    +173   {
    +174     Resource resource = context.getResource(address("/remote.html"));
    +175     assertNotNull(resource);
    +176     assertTrue(resource.exists());
    +177     String expected = StreamUtils.copyToString(remote.getInputStream(), Charset.forName("UTF-8"));
    +178     String content = StreamUtils.copyToString(resource.getInputStream(), Charset.forName("UTF-8"));
    +179     assertEquals(expected, content);
    +180   }
    +181 
    +182   @Test
    +183   public void testFetchNonExistent() throws Exception
    +184   {
    +185     LOG.info("<-- Start of test-case");
    +186 
    +187     getNonExistingHtml();
    +188 
    +189     server.verify(FETCH("/peter.html"), exactly(2));
    +190   }
    +191 
    +192   @Test
    +193   public void testCachingOfNonExistent() throws Exception
    +194   {
    +195     LOG.info("<-- Start of test-case");
    +196 
    +197     getNonExistingHtml();
    +198     getNonExistingHtml();
    +199     getNonExistingHtml();
    +200     getNonExistingHtml();
    +201     getNonExistingHtml();
    +202     getNonExistingHtml();
    +203     getNonExistingHtml();
    +204 
    +205     // Remote-requests answered with 404 are repeated
    +206     server.verify(FETCH("/peter.html"), exactly(14));
    +207   }
    +208 
    +209   private void getNonExistingHtml() throws Exception
    +210   {
    +211     Resource resource = context.getResource(address("/peter.html"));
    +212     assertNotNull(resource);
    +213     assertFalse(resource.exists());
    +214   }
    +215 
    +216   @Test
    +217   public void testModifiedResource() throws Exception
    +218   {
    +219     LOG.info("<-- Start of test-case");
    +220 
    +221     mvc
    +222         .perform(get(URI.create("http://test/remote.html")))
    +223         .andExpect(status().isOk())
    +224         .andExpect(content().string(read(remote)));
    +225 
    +226     CLOCK.timetravel(Duration.ofSeconds(10));
    +227     server.when(FETCH("/remote.html")).forward(NGINX("/modified.html"));
    +228 
    +229     mvc
    +230         .perform(get(URI.create("http://test/remote.html")))
    +231             .andExpect(status().isOk())
    +232             .andExpect(content().string(read(modified)));
    +233 
    +234     server.verify(FETCH("/remote.html"), exactly(2));
    +235     server.verify(
    +236         request()
    +237             .withPath("/remote.html")
    +238             .withHeader("If-Modified-Since")
    +239             .withHeader("If-None-Match"),
    +240         exactly(1));
    +241   }
    +242 
    +243 
    +244   @SpringBootApplication
    +245   public static class Application implements WebMvcConfigurer
    +246   {
    +247     @Autowired
    +248     ClientAndServer server;
    +249 
    +250     @Override
    +251     public void addResourceHandlers(ResourceHandlerRegistry registry)
    +252     {
    +253       LOG.info(
    +254           "{} resource-handler for static location {}",
    +255           registry.hasMappingForPattern("/**") ? "Overwriting" : "Setting",
    +256           "/**"
    +257           );
    +258       registry
    +259           .addResourceHandler("/**")
    +260           .addResourceLocations(
    +261               "classpath:/static/",
    +262               "classpath:/public/",
    +263               "http://localhost:" + server.getLocalPort(),
    +264               "classpath:/fallback/")
    +265           .resourceChain(false);
    +266     }
    +267   }
    +268 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceProtocolResolverTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceProtocolResolverTest.html new file mode 100644 index 00000000..b848e940 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourceProtocolResolverTest.html @@ -0,0 +1,98 @@ + + + +HttpResourceProtocolResolverTest xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import mockit.Expectations;
    +4   import mockit.Injectable;
    +5   import mockit.Mocked;
    +6   import mockit.Verifications;
    +7   import static org.junit.Assert.assertEquals;
    +8   import static org.junit.Assert.assertNull;
    +9   import org.junit.Before;
    +10  import org.junit.Test;
    +11  import org.springframework.core.io.Resource;
    +12  import org.springframework.core.io.ResourceLoader;
    +13  
    +14  
    +15  /**
    +16   *
    +17   * @author kai
    +18   */
    +19  public class HttpResourceProtocolResolverTest
    +20  {
    +21    @Injectable
    +22    HttpResources resources;
    +23  
    +24    HttpResourceProtocolResolver reslover;
    +25  
    +26    @Before
    +27    public void setUp()
    +28    {
    +29      reslover = new HttpResourceProtocolResolver(resources);
    +30    }
    +31  
    +32  
    +33    @Test
    +34    public void testHttpResource(
    +35        @Mocked ResourceLoader loader,
    +36        @Mocked HttpResource resource
    +37        )
    +38    {
    +39      String location = "http://remote/";
    +40  
    +41      new Expectations() {{
    +42        resources.getResource(location); result = resource;
    +43      }};
    +44  
    +45      Resource result = reslover.resolve(location, loader);
    +46  
    +47      assertEquals(resource, result);
    +48      new Verifications() {{
    +49        resources.getResource(location); times = 1;
    +50      }};
    +51    }
    +52  
    +53    @Test
    +54    public void testHttpsResource(
    +55        @Mocked ResourceLoader loader,
    +56        @Mocked HttpResource resource
    +57        )
    +58    {
    +59      String location = "https://remote/";
    +60  
    +61      new Expectations() {{
    +62        resources.getResource(location); result = resource;
    +63      }};
    +64  
    +65      Resource result = reslover.resolve(location, loader);
    +66  
    +67      assertEquals(resource, result);
    +68      new Verifications() {{
    +69        resources.getResource(location); times = 1;
    +70      }};
    +71    }
    +72  
    +73    @Test
    +74    public void testClasspathResource(@Mocked ResourceLoader loader)
    +75    {
    +76      String location = "classpath:/static/";
    +77  
    +78      Resource result = reslover.resolve(location, loader);
    +79  
    +80      assertNull(result);
    +81      new Verifications() {{
    +82        resources.getResource(location); times = 0;
    +83      }};
    +84    }
    +85  }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourcesIT.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourcesIT.html new file mode 100644 index 00000000..d3f093df --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourcesIT.html @@ -0,0 +1,243 @@ + + + +HttpResourcesIT xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import static org.assertj.core.api.Assertions.*;
    +5   import static org.mockserver.verify.VerificationTimes.exactly;
    +6   
    +7   import static org.mockserver.model.HttpRequest.request;
    +8   import org.junit.jupiter.api.BeforeEach;
    +9   import org.junit.jupiter.api.Test;
    +10  import org.slf4j.Logger;
    +11  import org.slf4j.LoggerFactory;
    +12  import org.springframework.beans.factory.annotation.Autowired;
    +13  import org.springframework.beans.factory.annotation.Value;
    +14  import org.springframework.boot.autoconfigure.SpringBootApplication;
    +15  import org.springframework.boot.test.context.SpringBootTest;
    +16  import org.springframework.cache.Cache;
    +17  import org.springframework.core.io.Resource;
    +18  import org.springframework.util.MimeType;
    +19  
    +20  import java.time.*;
    +21  
    +22  
    +23  /**
    +24   *
    +25   * @author Kai Moritz
    +26   */
    +27  @SpringBootTest
    +28  public class HttpResourcesIT extends IntegrationTestBase
    +29  {
    +30    private final static Logger LOG =
    +31        LoggerFactory.getLogger(HttpResourcesIT.class);
    +32  
    +33  
    +34    @Autowired
    +35    HttpResources resources;
    +36    @Autowired
    +37    Cache cache;
    +38  
    +39    @Value("classpath:remote/remote.html")
    +40    Resource remote;
    +41    @Value("classpath:remote/modified.html")
    +42    Resource modified;
    +43  
    +44  
    +45    @BeforeEach
    +46    public void clearCache()
    +47    {
    +48      cache.clear();
    +49    }
    +50  
    +51  
    +52    @Test
    +53    public void testFetchExistent() throws Exception
    +54    {
    +55      LOG.info("<-- Start of test-case");
    +56  
    +57      HttpResource resource = resources.getResource(address("/remote.html"));
    +58  
    +59      assertThat(resource.exists()).isTrue();
    +60      assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +61      assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +62      server.verify(FETCH("/remote.html"), exactly(1));
    +63    }
    +64  
    +65    @Test
    +66    public void testFetchNonExistent() throws Exception
    +67    {
    +68      LOG.info("<-- Start of test-case");
    +69  
    +70      HttpResource resource = resources.getResource(address("/peter.html"));
    +71  
    +72      assertThat(resource.exists()).isFalse();
    +73      server.verify(FETCH("/peter.html"), exactly(2));
    +74    }
    +75  
    +76    @Test
    +77    public void testFetchServerResponse500() throws Exception
    +78    {
    +79      LOG.info("<-- Start of test-case");
    +80  
    +81      server.when(FETCH("/peter.html")).respond(INTERNAL_SERVER_ERROR());
    +82  
    +83      HttpResource resource = resources.getResource(address("/peter.html"));
    +84  
    +85      assertThat(resource.exists()).isFalse();
    +86      server.verify(FETCH("/peter.html"), exactly(2));
    +87    }
    +88  
    +89    @Test
    +90    public void testCaching() throws Exception
    +91    {
    +92      LOG.info("<-- Start of test-case");
    +93  
    +94      String uri = address("/remote.html");
    +95  
    +96      HttpResource resource;
    +97  
    +98      LOG.debug("First access to {}", uri);
    +99      resource= resources.getResource(uri);
    +100     assertThat(resource.exists()).isTrue();
    +101     assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +102     assertThat(resource.isModified()).isFalse();
    +103     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +104 
    +105     LOG.debug("Second access to {}", uri);
    +106     resource= resources.getResource(uri);
    +107     assertThat(resource.exists()).isTrue();
    +108     assertThat(resource.isModified()).isFalse();
    +109     assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +110     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +111 
    +112     LOG.debug("Third access to {}", uri);
    +113     resource= resources.getResource(uri);
    +114     assertThat(resource.exists()).isTrue();
    +115     assertThat(resource.isModified()).isFalse();
    +116     assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +117     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +118 
    +119     LOG.debug("Fourth access to {} after a pause of 10 seconds -- resource should be expired", uri);
    +120     CLOCK.timetravel(Duration.ofSeconds(10));
    +121     assertThat(resource.exists()).isTrue();
    +122     assertThat(resource.isModified()).isFalse();
    +123     assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +124     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +125 
    +126     LOG.debug("Fifth access to {}", uri);
    +127     resource= resources.getResource(uri);
    +128     assertThat(resource.exists()).isTrue();
    +129     assertThat(resource.isModified()).isFalse();
    +130     assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +131     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +132 
    +133     LOG.debug("Sixth access to {}", uri);
    +134     resource= resources.getResource(uri);
    +135     assertThat(resource.exists()).isTrue();
    +136     assertThat(resource.isModified()).isFalse();
    +137     assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +138     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +139 
    +140     server.verify(FETCH("/remote.html"), exactly(2));
    +141     server.verify(
    +142         request()
    +143             .withPath("/remote.html")
    +144             .withHeader("If-Modified-Since")
    +145             .withHeader("If-None-Match"),
    +146         exactly(1));
    +147   }
    +148 
    +149   @Test
    +150   public void testFetchEncoded() throws Exception
    +151   {
    +152     LOG.info("<-- Start of test-case");
    +153 
    +154     // To test an encoded response, we have to contact Nginx directly
    +155     String uri = NGINX_URI() + "/remote.html";
    +156 
    +157     HttpResource resource = resources.getResource(uri);
    +158 
    +159     assertThat(resource.exists()).isTrue();
    +160     assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
    +161     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +162   }
    +163 
    +164   @Test
    +165   public void testModifiedResource() throws Exception
    +166   {
    +167     LOG.info("<-- Start of test-case");
    +168 
    +169     String uri = address("/remote.html");
    +170 
    +171     HttpResource resource;
    +172 
    +173     resource= resources.getResource(uri);
    +174 
    +175     LOG.debug("Initial access to resource {}", uri);
    +176     assertThat(resource.isModified()).isFalse();
    +177     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +178 
    +179     CLOCK.timetravel(Duration.ofSeconds(10));
    +180     server.when(FETCH("/remote.html")).forward(NGINX("/modified.html"));
    +181 
    +182     LOG.debug("Access to modified resource {} after expiration", uri);
    +183     assertThat(resource.isModified()).isTrue();
    +184     assertThat(resource.getInputStream()).hasSameContentAs(modified.getInputStream());
    +185     assertThat(resource.isModified()).isFalse();
    +186 
    +187     server.verify(FETCH("/remote.html"), exactly(2));
    +188     server.verify(
    +189         request()
    +190             .withPath("/remote.html")
    +191             .withHeader("If-Modified-Since")
    +192             .withHeader("If-None-Match"),
    +193         exactly(1));
    +194   }
    +195 
    +196   @Test
    +197   public void testModifiedResourceAccessOnly() throws Exception
    +198   {
    +199     LOG.info("<-- Start of test-case");
    +200 
    +201     String uri = address("/remote.html");
    +202 
    +203     HttpResource resource;
    +204 
    +205     resource= resources.getResource(uri);
    +206 
    +207     LOG.debug("Initial access to resource {}", uri);
    +208     assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
    +209 
    +210     CLOCK.timetravel(Duration.ofSeconds(10));
    +211     server.when(FETCH("/remote.html")).forward(NGINX("/modified.html"));
    +212 
    +213     LOG.debug("Access to modified resource {} after expiration", uri);
    +214     assertThat(resource.getInputStream()).hasSameContentAs(modified.getInputStream());
    +215 
    +216     server.verify(FETCH("/remote.html"), exactly(2));
    +217     server.verify(
    +218         request()
    +219             .withPath("/remote.html")
    +220             .withHeader("If-Modified-Since")
    +221             .withHeader("If-None-Match"),
    +222         exactly(1));
    +223   }
    +224 
    +225 
    +226   @SpringBootApplication
    +227   static class Application
    +228   {
    +229   }
    +230 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourcesTest.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourcesTest.html new file mode 100644 index 00000000..b6812307 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/HttpResourcesTest.html @@ -0,0 +1,317 @@ + + + +HttpResourcesTest xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import java.io.IOException;
    +5   import java.net.URI;
    +6   import java.time.Clock;
    +7   import java.time.ZoneId;
    +8   
    +9   import mockit.Mocked;
    +10  import org.junit.jupiter.api.DisplayName;
    +11  import org.junit.jupiter.api.Test;
    +12  import org.slf4j.Logger;
    +13  import org.slf4j.LoggerFactory;
    +14  
    +15  import static de.juplo.httpresources.TestUtil.*;
    +16  import static org.assertj.core.api.Assertions.fail;
    +17  import static org.junit.Assert.assertEquals;
    +18  import static org.junit.Assert.assertNotNull;
    +19  import static org.mockito.ArgumentMatchers.*;
    +20  import static org.mockito.Mockito.*;
    +21  
    +22  import org.springframework.cache.support.NoOpCache;
    +23  
    +24  
    +25  /**
    +26   * Tests for the methods {@link HttpResources#getResource(java.net.URI)}
    +27   * and {@link HttpResources#convert(java.lang.String)}
    +28   * @author Kai Moritz
    +29   */
    +30  public class HttpResourcesTest
    +31  {
    +32    private final static Logger LOG =
    +33        LoggerFactory.getLogger(HttpResourcesTest.class);
    +34  
    +35    String base = "http://a/b/c/d;p?q";
    +36  
    +37  
    +38    @Test
    +39    public void testGetResource()
    +40    {
    +41      LOG.info("<-- start of test-case");
    +42  
    +43      HttpResourceFetcher fetcher = mock(HttpResourceFetcher.class);
    +44      Clock clock = mock(Clock.class);
    +45  
    +46      HttpResources httpResources = new HttpResources(fetcher, clock);
    +47      URI uri = URI.create("http://foo/bar");
    +48  
    +49      // Everything is possible, nothing is necessary: Only defines behavior!
    +50      when(fetcher.fetch(any(), any())).thenReturn(DATA_NOT_EXPIRED);
    +51  
    +52      HttpResource resource = httpResources.getResource(uri);
    +53  
    +54      assertNotNull(resource);
    +55      assertEquals(HttpResource.class, resource.getClass());
    +56      assertEquals(uri, resource.getURI());
    +57      assertEquals(clock, resource.clock);
    +58      assertEquals(DATA_NOT_EXPIRED, resource.data);
    +59  
    +60      verify(fetcher).fetch(eq(uri), eq(HttpData.NOT_FETCHED));
    +61    }
    +62  
    +63    /**
    +64     * This test only checks the integration of the used methods
    +65     * Detailed tests for {@link URI}-handling are implemented in
    +66     * {@link HttpResourcesUriHandlingTest}.
    +67     */
    +68    @Test
    +69    @DisplayName("createRelative()")
    +70    public void testCreateRelative(@Mocked HttpResourceFetcher fetcher) throws Exception
    +71    {
    +72      Clock clock = Clock.fixed(NOW.toInstant(), ZoneId.of("GMT"));
    +73      HttpResources resources = new HttpResources(fetcher, clock);
    +74      HttpResource base = new HttpResource(resources, fetcher, clock, HttpResources.convert("http://a/b/c/d;p?q"));
    +75      HttpResource relative;
    +76  
    +77      relative = base.createRelative("g;x?y#s");
    +78      assertEquals(URI.create("http://a/b/c/g;x?y#s"), relative.getURI());
    +79      relative = base.createRelative("/g");
    +80      assertEquals(URI.create("http://a/b/c/g"), relative.getURI());
    +81      relative = base.createRelative("//g;x?y#s");
    +82      assertEquals(URI.create("http://a/b/c/?y#s"), relative.getURI());
    +83      relative = base.createRelative("../../g");
    +84      assertEquals(URI.create("http://a/b/c/g"), relative.getURI());
    +85    }
    +86  
    +87    @org.junit.Test
    +88    public void testConvertValid() throws Exception
    +89    {
    +90      // These examples are derived from RFC 2396 (page 29)
    +91      checkConvertValid("g", "g");
    +92      checkConvertValid("g", "./g");
    +93      checkConvertValid("g/", "g/");
    +94      checkConvertValid("/g", "/g");
    +95      checkConvertValid("//g/", "//g");
    +96      checkConvertValid("?y", "?y");
    +97      checkConvertValid("//g/?y", "//g?y"); // The extra slash needed in our use-case
    +98      checkConvertValid("//g/h?y", "//g/h?y");
    +99      checkConvertValid("g?y", "g?y");
    +100     checkConvertValid("//g/h?y", "//g/h?y");
    +101     checkConvertValid("#s", "#s");
    +102     checkConvertValid("g#s", "g#s");
    +103     checkConvertValid("g?y#s", "g?y#s");
    +104     checkConvertValid(";x", ";x");
    +105     checkConvertValid("g;x", "g;x");
    +106     checkConvertValid("g;x?y#s", "g;x?y#s");
    +107     checkConvertValid("", ".");
    +108     checkConvertValid("", "./");
    +109     checkConvertValid("..", "..");
    +110     checkConvertValid("../", "../");
    +111     checkConvertValid("../g", "../g");
    +112     checkConvertValid("../..", "../..");
    +113     checkConvertValid("../../", "../../");
    +114     checkConvertValid("../../g", "../../g");
    +115     checkConvertValid("http://g/", "http://g");
    +116     checkConvertValid("http://g/h", "http://g/h");
    +117     checkConvertValid("https://g/", "https://g");
    +118     checkConvertValid("https://g/h", "https://g/h");
    +119 
    +120     // Additionally examples for lower-case conversions
    +121     checkConvertValid("//g/", "//G");
    +122     checkConvertValid("//g/H/i/J", "//G/H/i/J");
    +123     checkConvertValid("http://g/", "HTtP://G");
    +124     checkConvertValid("http://g/H", "hTTP://G/H");
    +125     checkConvertValid("http://g.com/H", "hTTP://G.cOM/H");
    +126     checkConvertValid("https://g/", "HTTPs://G");
    +127     checkConvertValid("https://g/H", "HTTPs://G/H");
    +128     checkConvertValid("https://g.com/H/i/J", "HTTPs://g.COM/H/i/J");
    +129   }
    +130 
    +131   @org.junit.Test
    +132   public void testConvertInvalid() throws Exception
    +133   {
    +134     // Examples for invalid urls
    +135     checkConvertInvalid("http:/foo/bar");
    +136   }
    +137 
    +138   /**
    +139    * Checks the resolving of normal examples, with enabled enforcment of a
    +140    * relative path.
    +141    * @see https://www.ietf.org/rfc/rfc2396.txt
    +142    * @throws IOException
    +143    */
    +144   @org.junit.Test
    +145   public void testResolveValid() throws IOException
    +146   {
    +147     // These examples are taken from RFC 2396 (page 29), but the outcome is
    +148     // different, because the resolved path is forcefully turned into a
    +149     // relative URL.
    +150     //            "https:h","https:h"  << Not accepted, because opaque
    +151     checkResolveValid("http://a/b/c/g","g");
    +152     checkResolveValid("http://a/b/c/g","./g");
    +153     checkResolveValid("http://a/b/c/g/","g/");
    +154     checkResolveValid("http://a/b/c/g","/g");
    +155     checkResolveValid("http://a/b/c/g;x?y#s","/g;x?y#s");
    +156     checkResolveValid("http://a/b/c/?y","?y");
    +157     checkResolveValid("http://a/b/c/g?y","g?y");
    +158     checkResolveValid("http://a/b/c/d;p?q#s","#s");
    +159     checkResolveValid("http://a/b/c/g#s","g#s");
    +160     checkResolveValid("http://a/b/c/g?y#s","g?y#s");
    +161     checkResolveValid("http://a/b/c/;x",";x");
    +162     checkResolveValid("http://a/b/c/g;x","g;x");
    +163     checkResolveValid("http://a/b/c/g;x?y#s","g;x?y#s");
    +164     checkResolveValid("http://a/b/c/",".");
    +165     checkResolveValid("http://a/b/c/","./");
    +166     checkResolveValid("http://a/b/c/","..");
    +167     checkResolveValid("http://a/b/c/","../");
    +168     checkResolveValid("http://a/b/c/g","../g");
    +169     checkResolveValid("http://a/b/c/","../..");
    +170     checkResolveValid("http://a/b/c/","../../");
    +171     checkResolveValid("http://a/b/c/g","../../g");
    +172 
    +173     // Additionally examples for lower-case conversions
    +174     checkResolveValid("http://a/b/c/G","G");
    +175   }
    +176 
    +177   /**
    +178    * Checks the resolving of normal examples, with enabled enforcment of a
    +179    * relative path.
    +180    * @see https://www.ietf.org/rfc/rfc2396.txt
    +181    * @throws IOException
    +182    */
    +183   @org.junit.Test
    +184   public void testResolveInvalid() throws IOException
    +185   {
    +186     // These examples are taken from RFC 2396 (page 29), but the outcome is
    +187     // different, because the resolved path is forcefully turned into a
    +188     // relative URL.
    +189     //            "https:h","https:h"  << Not accepted, because opaque
    +190     checkResolveInvalid("http://a/b/c/","//g");
    +191     checkResolveInvalid("http://a/b/c/?y#s","//g;x?y#s"); // << g;x actually is an authority, because ';' is an allowed character! See RFC 2396 Chapter 3.2
    +192     checkResolveInvalid("http://a/b/c/?y#s","//g/;x?y#s");
    +193 
    +194     // Additionally examples for lower-case conversions
    +195     checkResolveInvalid("http://a/b/c/","//G");
    +196     checkResolveInvalid("http://a/b/c/","HTTPS://G");
    +197     checkResolveInvalid("http://a/b/c/H","HTTPS://G/H");
    +198 
    +199     // Additionally examples for absolute URI's
    +200     checkResolveInvalid("http://a/b/c/","https://g");
    +201     checkResolveInvalid("http://a/b/c/","https://g/.");
    +202     checkResolveInvalid("http://a/b/c/","https://g/./");
    +203     checkResolveInvalid("http://a/b/c/h","https://g/./h");
    +204     checkResolveInvalid("http://a/b/c/h/","https://g/./h/.");
    +205     checkResolveInvalid("http://a/b/c/h/","https://g/./h/./");
    +206     checkResolveInvalid("http://a/b/c/","https://g/./h/..");
    +207     checkResolveInvalid("http://a/b/c/","https://g/./h/../");
    +208     checkResolveInvalid("http://a/b/c/h","https://g/../h");
    +209     checkResolveInvalid("http://a/b/c/h/","https://g/../h/.");
    +210     checkResolveInvalid("http://a/b/c/h/","https://g/../h/./");
    +211     checkResolveInvalid("http://a/b/c/","https://g/../h/..");
    +212     checkResolveInvalid("http://a/b/c/","https://g/../h/../");
    +213     checkResolveInvalid("http://a/b/c/","http://h@g");
    +214     checkResolveInvalid("http://a/b/c/","http://g:1");
    +215     checkResolveInvalid("http://a/b/c/","http://h@g:1");
    +216     checkResolveInvalid("http://a/b/c/i","http://h@g:1/i");
    +217 
    +218     // Additionally examples for relative URI's with authority
    +219     checkResolveInvalid("http://a/b/c/","//g");
    +220     checkResolveInvalid("http://a/b/c/","//g/.");
    +221     checkResolveInvalid("http://a/b/c/","//g/./");
    +222     checkResolveInvalid("http://a/b/c/h","//g/./h");
    +223     checkResolveInvalid("http://a/b/c/h/","//g/./h/.");
    +224     checkResolveInvalid("http://a/b/c/h/","//g/./h/./");
    +225     checkResolveInvalid("http://a/b/c/","//g/./h/..");
    +226     checkResolveInvalid("http://a/b/c/","//g/./h/../");
    +227     checkResolveInvalid("http://a/b/c/h","//g/../h");
    +228     checkResolveInvalid("http://a/b/c/h/","//g/../h/.");
    +229     checkResolveInvalid("http://a/b/c/h/","//g/../h/./");
    +230     checkResolveInvalid("http://a/b/c/","//g/../h/..");
    +231     checkResolveInvalid("http://a/b/c/","//g/../h/../");
    +232     checkResolveInvalid("http://a/b/c/","//h@g");
    +233     checkResolveInvalid("http://a/b/c/","//g:1");
    +234     checkResolveInvalid("http://a/b/c/","//h@g:1");
    +235     checkResolveInvalid("http://a/b/c/i","//h@g:1/i");
    +236   }
    +237 
    +238   @org.junit.Test
    +239   public void testHostWithoutTrailingSlash() throws IOException {
    +240     checkResolveValid("http://localhost:1234/relative/path", "relative/path", "http://localhost:1234");
    +241     checkResolveValid("https://localhost:1234/relative/path", "relative/path", "https://localhost:1234");
    +242     checkResolveValid("//localhost:1234/relative/path", "relative/path", "//localhost:1234");
    +243     checkResolveValid("http://localhost:1234/absolute/path", "/absolute/path", "http://localhost:1234");
    +244     checkResolveValid("https://localhost:1234/absolute/path", "/absolute/path", "https://localhost:1234");
    +245     checkResolveValid("//localhost:1234/absolute/path", "/absolute/path", "//localhost:1234");
    +246   }
    +247 
    +248 
    +249   private void checkResolveValid(String result, String path)
    +250       throws
    +251       IOException
    +252   {
    +253     checkResolveValid(result, path, base);
    +254     URI relative = HttpResources.convert(path);
    +255   }
    +256 
    +257   private void checkResolveValid(String result, String path, String host)
    +258       throws
    +259       IOException
    +260   {
    +261     assertEquals(
    +262         URI.create(result),
    +263         HttpResources.resolve(URI.create(path), URI.create(host)));
    +264   }
    +265 
    +266   private void checkResolveInvalid(String result, String path)
    +267       throws
    +268       IOException
    +269   {
    +270     checkResolveInvalid(result, path, base);
    +271     URI relative = HttpResources.convert(path);
    +272   }
    +273 
    +274   private void checkResolveInvalid(String result, String path, String host)
    +275       throws
    +276       IOException
    +277   {
    +278     try
    +279     {
    +280       URI resolved = HttpResources.resolve(URI.create(path), URI.create(host));
    +281       fail("Resolved invalid relative path " + path + " against " + host + " as " + resolved);
    +282     }
    +283     catch (IOException e)
    +284     {
    +285     }
    +286   }
    +287 
    +288   private void checkConvertValid(String result, String url)
    +289   {
    +290     assertEquals(result, HttpResources.convert(url).toString());
    +291   }
    +292 
    +293   private void checkConvertInvalid(String url)
    +294   {
    +295     try
    +296     {
    +297       URI converted = HttpResources.convert(url);
    +298       fail("Converted invalid url path " + url + " to URI as " + converted);
    +299     }
    +300     catch (IllegalArgumentException e)
    +301     {
    +302     }
    +303   }
    +304 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/IntegrationTestBase.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/IntegrationTestBase.html new file mode 100644 index 00000000..a65b0d75 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/IntegrationTestBase.html @@ -0,0 +1,267 @@ + + + +IntegrationTestBase xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import static de.juplo.httpresources.ConfigurableNginxContainer.DEFAULT_NGINX_PORT;
    +5   import static org.mockserver.model.HttpClassCallback.callback;
    +6   import static org.mockserver.model.HttpOverrideForwardedRequest.forwardOverriddenRequest;
    +7   import static org.mockserver.model.HttpRequest.request;
    +8   import static org.mockserver.model.HttpResponse.response;
    +9   
    +10  import org.junit.jupiter.api.AfterEach;
    +11  import org.junit.jupiter.api.BeforeEach;
    +12  import org.mockserver.integration.ClientAndServer;
    +13  import org.mockserver.matchers.TimeToLive;
    +14  import org.mockserver.matchers.Times;
    +15  import org.mockserver.mock.action.ExpectationForwardAndResponseCallback;
    +16  import org.mockserver.model.HttpOverrideForwardedRequest;
    +17  import org.mockserver.model.HttpRequest;
    +18  import org.mockserver.model.HttpResponse;
    +19  import org.slf4j.Logger;
    +20  import org.slf4j.LoggerFactory;
    +21  import org.springframework.beans.factory.annotation.Autowired;
    +22  import org.springframework.cache.Cache;
    +23  import org.springframework.cache.concurrent.ConcurrentMapCache;
    +24  import org.springframework.context.annotation.Bean;
    +25  import org.springframework.context.annotation.Configuration;
    +26  import org.springframework.http.HttpStatus;
    +27  import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
    +28  import org.springframework.util.StringUtils;
    +29  import org.testcontainers.containers.NginxContainer;
    +30  import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
    +31  import org.testcontainers.shaded.org.apache.commons.lang.NotImplementedException;
    +32  
    +33  import java.time.*;
    +34  import java.time.format.DateTimeFormatter;
    +35  import java.util.Locale;
    +36  
    +37  
    +38  /**
    +39   * This class starts a
    +40   * {@link https://www.testcontainers.org/modules/nginx/ NginX-Webserver}
    +41   * via a {@link https://www.testcontainers.org/ Testcontainer} and a
    +42   * standalone {@link http://www.mock-server.com/#what-is-mockserver MockServer},
    +43   * that can be used to intercept requests for assertions / verifications.
    +44   * <p>
    +45   * We use the {@link
    +46   * https://www.testcontainers.org/test_framework_integration/manual_lifecycle_control/#singleton-containers
    +47   * Singleton Pattern} to start the NginX-Testcontainer and start the MockServer
    +48   * programmatically via the {@link
    +49   * http://www.mock-server.com/mock_server/running_mock_server.html#client_api
    +50   * Client-API}.
    +51   * @author Kai Moritz
    +52   */
    +53  public abstract class IntegrationTestBase
    +54  {
    +55    private final static Logger LOG =
    +56        LoggerFactory.getLogger(IntegrationTestBase.class);
    +57  
    +58    public static ClockStub CLOCK = new ClockStub();
    +59    public static DateTimeFormatter formatter =
    +60        DateTimeFormatter
    +61            .ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH)
    +62            .withZone(ZoneId.of("GMT"));
    +63  
    +64    public static final NginxContainer NGINX;
    +65  
    +66    static
    +67    {
    +68      NGINX =
    +69          new ConfigurableNginxContainer()
    +70              .withConfiguration("src/test/resources/nginx/nginx.conf")
    +71              .withCustomContent("src/test/resources/remote/");
    +72      NGINX.waitingFor(new HttpWaitStrategy()).start();
    +73    }
    +74  
    +75  
    +76    public static String NGINIX_IP()
    +77    {
    +78      return NGINX.getContainerIpAddress();
    +79    }
    +80  
    +81    public static int NGINX_PORT()
    +82    {
    +83      return NGINX.getMappedPort(DEFAULT_NGINX_PORT);
    +84    }
    +85  
    +86    public static String NGINX_URI()
    +87    {
    +88      return "http://" + NGINIX_IP() + ":" + NGINX_PORT();
    +89    }
    +90  
    +91    public static HttpRequest FETCH(String path)
    +92    {
    +93      return request().withPath(path);
    +94    }
    +95  
    +96    public static HttpResponse RESPONSE()
    +97    {
    +98      CLOCK.tick();
    +99      HttpResponse response =
    +100         response().withHeader("Date", formatter.format(CLOCK.instant()));
    +101     CLOCK.tick();
    +102     return response;
    +103   }
    +104 
    +105   public static HttpOverrideForwardedRequest NGINX()
    +106   {
    +107     return NGINX(null);
    +108   }
    +109 
    +110   public static HttpOverrideForwardedRequest NGINX(String path)
    +111   {
    +112     HttpRequest request = request().withSocketAddress(NGINIX_IP(),NGINX_PORT());
    +113     if (StringUtils.hasText(path))
    +114       request = request.withPath(path);
    +115     return forwardOverriddenRequest(request, RESPONSE());
    +116   }
    +117 
    +118   public static HttpResponse NOT_FOUND()
    +119   {
    +120     return RESPONSE().withStatusCode(HttpStatus.NOT_FOUND.value());
    +121   }
    +122 
    +123   public static HttpResponse INTERNAL_SERVER_ERROR()
    +124   {
    +125     return RESPONSE().withStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
    +126   }
    +127 
    +128 
    +129   @Configuration
    +130   public static class IntegrationTestConfiguration
    +131   {
    +132     @Bean(destroyMethod = "stop")
    +133     public ClientAndServer server()
    +134     {
    +135       return ClientAndServer.startClientAndServer();
    +136     }
    +137 
    +138     @Bean
    +139     public HttpResourceFetcher fetcher(Cache cache)
    +140     {
    +141       return
    +142           new HttpResourceFetcher(
    +143               new HttpComponentsClientHttpRequestFactory(),
    +144               cache,
    +145               CLOCK);
    +146     }
    +147 
    +148     @Bean
    +149     public Cache cache()
    +150     {
    +151       return new ConcurrentMapCache("TEST");
    +152     }
    +153 
    +154     @Bean
    +155     public HttpResources httpResources(HttpResourceFetcher fetcher)
    +156     {
    +157       return new HttpResources(fetcher, CLOCK);
    +158     }
    +159   }
    +160 
    +161   @Autowired
    +162   public ClientAndServer server;
    +163 
    +164 
    +165   /**
    +166    * Prepares the mock-server to forward any request to the NginX-server,
    +167    * for which no more specific expectation was specified.
    +168    */
    +169   @BeforeEach
    +170   public void prepareMockServer()
    +171   {
    +172     CLOCK.now = ZonedDateTime.now();
    +173     server
    +174         .when(request(), Times.unlimited(), TimeToLive.unlimited(), Integer.MIN_VALUE)
    +175         .forward(callback().withCallbackClass(Callback.class));
    +176   }
    +177 
    +178   @AfterEach
    +179   public void clearMockServer()
    +180   {
    +181     server.reset();
    +182   }
    +183 
    +184 
    +185   public int getMockServerPort()
    +186   {
    +187     return server.getLocalPort();
    +188   }
    +189 
    +190   public String getMockServerUri()
    +191   {
    +192     return "http://localhost:" + getMockServerPort();
    +193   }
    +194 
    +195 
    +196   public String address(String path)
    +197   {
    +198     return getMockServerUri() + path;
    +199   }
    +200 
    +201   public static class Callback implements ExpectationForwardAndResponseCallback
    +202   {
    +203     @Override
    +204     public HttpRequest handle(HttpRequest request) throws Exception
    +205     {
    +206       return request.withSocketAddress(NGINIX_IP(),NGINX_PORT());
    +207     }
    +208 
    +209     @Override
    +210     public HttpResponse handle(HttpRequest request, HttpResponse response) throws Exception
    +211     {
    +212       CLOCK.tick();
    +213       HttpResponse modifiedResponse = response.replaceHeader("Date", formatter.format(CLOCK.instant()));
    +214       CLOCK.tick();
    +215       return modifiedResponse;
    +216     }
    +217   }
    +218 
    +219   public static class ClockStub extends Clock
    +220   {
    +221     public final static Duration DEFAULT_TICK = Duration.ofMillis(100);
    +222 
    +223     public ZonedDateTime now = ZonedDateTime.now();
    +224 
    +225 
    +226     public void tick()
    +227     {
    +228       now = now.plus(DEFAULT_TICK);
    +229     }
    +230 
    +231     public void timetravel(Duration duration)
    +232     {
    +233       now = now.plus(duration);
    +234     }
    +235 
    +236     @Override
    +237     public ZoneId getZone()
    +238     {
    +239       return now.getZone();
    +240     }
    +241 
    +242     @Override
    +243     public Clock withZone(ZoneId zone)
    +244     {
    +245       throw new NotImplementedException();
    +246     }
    +247 
    +248     @Override
    +249     public Instant instant()
    +250     {
    +251       return now.toInstant();
    +252     }
    +253   };
    +254 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/TestUtil.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/TestUtil.html new file mode 100644 index 00000000..dbd85a08 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/TestUtil.html @@ -0,0 +1,264 @@ + + + +TestUtil xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import java.io.ByteArrayInputStream;
    +5   import java.io.ByteArrayOutputStream;
    +6   import java.io.IOException;
    +7   import java.net.URISyntaxException;
    +8   import java.net.URL;
    +9   import java.nio.charset.Charset;
    +10  import java.nio.file.Files;
    +11  import java.nio.file.Paths;
    +12  import java.util.Date;
    +13  import java.util.Scanner;
    +14  import java.util.stream.Collectors;
    +15  import java.util.zip.GZIPOutputStream;
    +16  import org.apache.http.Header;
    +17  import org.apache.http.HttpEntity;
    +18  import org.apache.http.HttpStatus;
    +19  import org.apache.http.ProtocolVersion;
    +20  import org.apache.http.StatusLine;
    +21  import org.apache.http.client.utils.DateUtils;
    +22  import org.apache.http.entity.ByteArrayEntity;
    +23  import org.apache.http.entity.StringEntity;
    +24  import org.apache.http.message.BasicHeader;
    +25  import org.apache.http.message.BasicStatusLine;
    +26  import org.slf4j.Logger;
    +27  import org.slf4j.LoggerFactory;
    +28  import org.springframework.core.io.Resource;
    +29  import org.springframework.http.HttpHeaders;
    +30  import org.springframework.http.MediaType;
    +31  
    +32  
    +33  /**
    +34   * @author Kai Moritz
    +35   */
    +36  public class TestUtil
    +37  {
    +38    private final static Logger LOG =
    +39        LoggerFactory.getLogger(TestUtil.class);
    +40  
    +41    final static long MAX_AGE = 600l;
    +42    final static int MIN_TTL = 666000;
    +43  
    +44    final static String STR_THEN = "Sat, 29 Oct 1994 19:43:31 GMT";
    +45    final static String STR_EXPIRED = "Mon, 14 Nov 1994 22:22:22 GMT";
    +46    final static String STR_SEND = "Tue, 15 Nov 1994 12:45:25 GMT";
    +47    final static String STR_NOW = "Tue, 15 Nov 1994 12:45:26 GMT";
    +48    final static String STR_INBETWEEN = "Thu, 17 Nov 1994 12:45:26 GMT";
    +49    final static String STR_FEATURE = "Thu, 01 Dec 1994 16:00:00 GMT";
    +50  
    +51    final static Charset UTF8;
    +52  
    +53    final static String STR_CONTENT = "hellö wörld!";
    +54    final static byte[] CONTENT;
    +55    final static byte[] CONTENT_GZIPPED;
    +56    final static String STR_CONTENT_MODIFIED = "Hellö again...";
    +57    final static byte[] CONTENT_MODIFIED;
    +58    final static String STR_CONTENT_TYPE_HTML = "text/html;charset=UTF-8";
    +59    final static String STR_CONTENT_TYPE_CSS = "text/css";
    +60    final static String STR_CONTENT_ENCODING = "gzip";
    +61    final static String STR_ETAG = "F345AB884";
    +62    final static String STR_ETAG_MODIFIED = "NewNewNew";
    +63    final static String STR_NO_CACHE = "no-cache";
    +64    final static String STR_NO_CACHE_QUALIFIED = "max-age=" + MAX_AGE + ", no-cache=\"Cookie\"";
    +65    final static String STR_MAX_AGE = "public, max-age=" + MAX_AGE;
    +66    final static String STR_MAX_AGE_0 = "public, max-age=0";
    +67    final static String STR_PRIVATE = "private, no-store";
    +68    final static String STR_REVALIDATE = STR_MAX_AGE + ", must-revalidate";
    +69  
    +70    final static HttpEntity BODY;
    +71    final static HttpEntity BODY_GZIPPED;
    +72    final static HttpEntity BODY_MODIFIED;
    +73    final static ProtocolVersion PROTOCOL = new ProtocolVersion("HTTP", 1, 1);
    +74    final static StatusLine OK = new BasicStatusLine(PROTOCOL, HttpStatus.SC_OK, "OK");
    +75    final static StatusLine NOT_MODIFIED = new BasicStatusLine(PROTOCOL, HttpStatus.SC_NOT_MODIFIED, "NOT MODIFIED");
    +76    final static StatusLine NOT_FOUND = new BasicStatusLine(PROTOCOL, HttpStatus.SC_NOT_FOUND, "NOT FOUND");
    +77    final static StatusLine SERVER_ERROR = new BasicStatusLine(PROTOCOL, HttpStatus.SC_INTERNAL_SERVER_ERROR, "INTERNAL SERVER ERROR");
    +78    final static Date THEN, EXPIRED, SEND, NOW, INBETWEEN, FEATURE;
    +79    final static long LONG_THEN, LONG_EXPIRED, LONG_SEND, LONG_NOW, LONG_INBETWEEN, LONG_FEATURE;
    +80  
    +81    final static MediaType MIME_TYPE_CONTENT_TYPE_HTML = MediaType.valueOf(STR_CONTENT_TYPE_HTML);
    +82  
    +83    final static Header CONTENT_TYPE_HTML = new BasicHeader(HttpHeaders.CONTENT_TYPE, STR_CONTENT_TYPE_HTML);
    +84    final static Header CONTENT_TYPE_CSS = new BasicHeader(HttpHeaders.CONTENT_TYPE, STR_CONTENT_TYPE_CSS);
    +85    final static Header CONTENT_ENCODING = new BasicHeader(HttpHeaders.CONTENT_ENCODING, STR_CONTENT_ENCODING);
    +86    final static Header DATE = new BasicHeader(HttpHeaders.DATE, STR_SEND);
    +87    final static Header DATE_MODIFIED = new BasicHeader(HttpHeaders.DATE, STR_NOW);
    +88    final static Header LAST_MODIFIED = new BasicHeader(HttpHeaders.LAST_MODIFIED, STR_THEN);
    +89    final static Header LAST_MODIFIED_MODIFIED = new BasicHeader(HttpHeaders.LAST_MODIFIED, STR_INBETWEEN);
    +90    final static Header ETAG = new BasicHeader(HttpHeaders.ETAG, STR_ETAG);
    +91    final static Header ETAG_MODIFIED = new BasicHeader(HttpHeaders.ETAG, STR_ETAG_MODIFIED);
    +92    final static Header EXPIRES_VALID = new BasicHeader(HttpHeaders.EXPIRES, STR_FEATURE);
    +93    final static Header EXPIRES_INVALID = new BasicHeader(HttpHeaders.EXPIRES, "0");
    +94    final static Header CACHE_CONTROL_NO_CACHE = new BasicHeader(HttpHeaders.CACHE_CONTROL, STR_NO_CACHE);
    +95    final static Header CACHE_CONTROL_NO_CACHE_QUALIFIED = new BasicHeader(HttpHeaders.CACHE_CONTROL, STR_NO_CACHE_QUALIFIED);
    +96    final static Header CACHE_CONTROL_MAX_AGE = new BasicHeader(HttpHeaders.CACHE_CONTROL, STR_MAX_AGE);
    +97    final static Header CACHE_CONTROL_MAX_AGE_0 = new BasicHeader(HttpHeaders.CACHE_CONTROL, STR_MAX_AGE_0);
    +98    final static Header CACHE_CONTROL_PRIVATE = new BasicHeader(HttpHeaders.CACHE_CONTROL, STR_PRIVATE);
    +99    final static Header CACHE_CONTROL_REVALIDATE = new BasicHeader(HttpHeaders.CACHE_CONTROL, STR_REVALIDATE);
    +100 
    +101   final static HttpHeaders HEADERS_CONTENT_TYPE_HTML;
    +102 
    +103   // The dummy-variants are used to distinguish the result from the old state
    +104   // in cases, where nothing has changed...
    +105   final static HttpData DATA_NOT_EXPIRED;
    +106   final static HttpData DATA_NOT_EXPIRED_DUMMY;
    +107   final static HttpData DATA_NOT_EXPIRED_REVALIDATION_REQUIRED;
    +108   final static HttpData DATA_EXPIRED;
    +109   final static HttpData DATA_EXPIRED_DUMMY;
    +110   final static HttpData DATA_UPDATED;
    +111   final static HttpData DATA_NOT_FOUND;
    +112 
    +113 
    +114   static
    +115   {
    +116     try
    +117     {
    +118       UTF8 = Charset.forName("UTF-8");
    +119 
    +120       BODY = new StringEntity(STR_CONTENT, UTF8);
    +121       BODY_MODIFIED = new StringEntity(STR_CONTENT_MODIFIED, UTF8);
    +122 
    +123       CONTENT = STR_CONTENT.getBytes(UTF8);
    +124       CONTENT_GZIPPED = TestUtil.gzip(CONTENT);
    +125       BODY_GZIPPED = new ByteArrayEntity(CONTENT_GZIPPED);
    +126       CONTENT_MODIFIED = STR_CONTENT_MODIFIED.getBytes(UTF8);
    +127     }
    +128     catch (IOException e)
    +129     {
    +130       throw new RuntimeException(e);
    +131     }
    +132 
    +133     THEN = DateUtils.parseDate(STR_THEN);
    +134     EXPIRED = DateUtils.parseDate(STR_EXPIRED);
    +135     SEND = DateUtils.parseDate(STR_SEND);
    +136     NOW = DateUtils.parseDate(STR_NOW);
    +137     INBETWEEN = DateUtils.parseDate(STR_INBETWEEN);
    +138     FEATURE = DateUtils.parseDate(STR_FEATURE);
    +139 
    +140     LONG_THEN = THEN.getTime();
    +141     LONG_EXPIRED = EXPIRED.getTime();
    +142     LONG_SEND = SEND.getTime();
    +143     LONG_NOW = NOW.getTime();
    +144     LONG_INBETWEEN = INBETWEEN.getTime();
    +145     LONG_FEATURE = FEATURE.getTime();
    +146 
    +147 
    +148     HEADERS_CONTENT_TYPE_HTML = new HttpHeaders();
    +149     HEADERS_CONTENT_TYPE_HTML.setContentType(MIME_TYPE_CONTENT_TYPE_HTML);
    +150 
    +151     DATA_NOT_EXPIRED_REVALIDATION_REQUIRED =
    +152         new HttpData(
    +153             STR_CONTENT.getBytes(),
    +154             HEADERS_CONTENT_TYPE_HTML,
    +155             true,
    +156             LONG_THEN,
    +157             LONG_NOW + MAX_AGE * 1000 - 2000,
    +158             STR_ETAG);
    +159 
    +160     DATA_NOT_EXPIRED =
    +161         new HttpData(
    +162             STR_CONTENT.getBytes(),
    +163             HEADERS_CONTENT_TYPE_HTML,
    +164             false,
    +165             LONG_THEN,
    +166             LONG_NOW + MAX_AGE * 1000 - 2000,
    +167             STR_ETAG);
    +168 
    +169     DATA_NOT_EXPIRED_DUMMY =
    +170         new HttpData(
    +171             STR_CONTENT.getBytes(),
    +172             HEADERS_CONTENT_TYPE_HTML,
    +173             false,
    +174             LONG_THEN,
    +175             LONG_NOW + MAX_AGE * 1000 - 2000,
    +176             STR_ETAG);
    +177 
    +178     DATA_EXPIRED =
    +179         new HttpData(
    +180             STR_CONTENT.getBytes(),
    +181             HEADERS_CONTENT_TYPE_HTML,
    +182             false,
    +183             LONG_THEN,
    +184             LONG_EXPIRED,
    +185             STR_ETAG);
    +186 
    +187     DATA_EXPIRED_DUMMY =
    +188         new HttpData(
    +189             STR_CONTENT.getBytes(),
    +190             HEADERS_CONTENT_TYPE_HTML,
    +191             false,
    +192             LONG_THEN,
    +193             LONG_EXPIRED,
    +194             STR_ETAG);
    +195 
    +196     DATA_UPDATED =
    +197         new HttpData(
    +198             STR_CONTENT_MODIFIED.getBytes(),
    +199             HEADERS_CONTENT_TYPE_HTML,
    +200             false,
    +201             LONG_INBETWEEN,
    +202             LONG_NOW + MAX_AGE * 1000,
    +203             STR_ETAG_MODIFIED);
    +204 
    +205     DATA_NOT_FOUND =
    +206         new HttpData(
    +207             null,
    +208             new HttpHeaders(),
    +209             false,
    +210             0,
    +211             LONG_NOW - 2000,
    +212             null);
    +213   }
    +214 
    +215 
    +216   static byte[] gzip(byte[] input) throws IOException
    +217   {
    +218     try (ByteArrayInputStream bais = new ByteArrayInputStream(input))
    +219     {
    +220       ByteArrayOutputStream baos = new ByteArrayOutputStream();
    +221       GZIPOutputStream gzos = new GZIPOutputStream(baos);
    +222       byte[] data = new byte[1024];
    +223       int read;
    +224       while ((read = bais.read(data)) > -1)
    +225         gzos.write(data, 0, read);
    +226       gzos.close();
    +227       baos.close();
    +228       return baos.toByteArray();
    +229     }
    +230   }
    +231 
    +232 
    +233   static StringEntity body(String resource) throws URISyntaxException, IOException
    +234   {
    +235     return new StringEntity(read(resource));
    +236   }
    +237 
    +238   static String read(String resource) throws URISyntaxException, IOException
    +239   {
    +240     URL url = TestUtil.class.getResource(resource);
    +241     if (url == null)
    +242       throw new IllegalArgumentException("Cannot find " + resource);
    +243     return Files.readAllLines(Paths.get(url.toURI())).stream().collect(Collectors.joining("\n"));
    +244   }
    +245 
    +246   static String read(Resource resource) throws URISyntaxException, IOException
    +247   {
    +248     Scanner s = new Scanner(resource.getInputStream()).useDelimiter("\\A");
    +249     return s.hasNext() ? s.next() : "";
    +250   }
    +251 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.html new file mode 100644 index 00000000..909fec7a --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.html @@ -0,0 +1,279 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/ThymeleafWithHttpResourceProtocolResolverIT.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.apache.http.entity.StringEntity;
    +4   import org.junit.jupiter.api.BeforeEach;
    +5   import org.junit.jupiter.api.Test;
    +6   import org.mockserver.integration.ClientAndServer;
    +7   import org.slf4j.Logger;
    +8   import org.slf4j.LoggerFactory;
    +9   import org.springframework.beans.factory.annotation.Autowired;
    +10  import org.springframework.boot.autoconfigure.SpringBootApplication;
    +11  import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties;
    +12  import org.springframework.boot.test.context.SpringBootTest;
    +13  import org.springframework.cache.Cache;
    +14  import org.springframework.context.ApplicationContext;
    +15  import org.springframework.context.annotation.Bean;
    +16  import org.springframework.core.io.Resource;
    +17  import org.springframework.stereotype.Controller;
    +18  import org.springframework.test.web.servlet.MockMvc;
    +19  import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    +20  import org.springframework.ui.Model;
    +21  import org.springframework.web.bind.annotation.RequestMapping;
    +22  import org.springframework.web.bind.annotation.RequestParam;
    +23  import org.springframework.web.context.WebApplicationContext;
    +24  import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    +25  import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    +26  import org.springframework.web.util.NestedServletException;
    +27  import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
    +28  
    +29  import java.io.IOException;
    +30  import java.net.URI;
    +31  import java.net.URISyntaxException;
    +32  import java.nio.file.Files;
    +33  import java.nio.file.Paths;
    +34  import java.time.Duration;
    +35  import java.util.Scanner;
    +36  import java.util.stream.Collectors;
    +37  
    +38  import static org.junit.jupiter.api.Assertions.assertThrows;
    +39  import static org.mockserver.model.HttpRequest.request;
    +40  import static org.mockserver.verify.VerificationTimes.exactly;
    +41  import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    +42  import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
    +43  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    +44  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    +45  
    +46  
    +47  /**
    +48   * This test-case showcases the usage of the {@link HttpResourceProtocolResolver}
    +49   * with Thymeleaf.
    +50   *
    +51   * Since Thymeleaf does not use the Resource-Chain mechanism, that Spring introduced
    +52   * for the handling of static resources, the {@code HttpResourceProtocolResolver} has
    +53   * to be used and the protocol has to be hardwired into the configuration as
    +54   * {@code spring.thymeleaf.prefix}.
    +55   * The downside of this approach is, that the templates are only resolved against
    +56   * the configured remote-URI and do not take part in the fallback-mechanism, that
    +57   * can be configured through {@code spring.resources.static-locations}.
    +58   *
    +59   * The test-case was addapted accordingly, to show the changed behaviour.
    +60   */
    +61  @SpringBootTest({
    +62      "juplo.http-resources.protocol-resolver.enabled=true",
    +63      "spring.thymeleaf.cache=true" })
    +64  public class ThymeleafWithHttpResourceProtocolResolverIT extends IntegrationTestBase
    +65  {
    +66    private static final Logger LOG =
    +67        LoggerFactory.getLogger(ThymeleafWithHttpResourceProtocolResolverIT.class);
    +68  
    +69  
    +70    @Autowired
    +71    HttpResources resources;
    +72    @Autowired
    +73    Cache cache;
    +74    @Autowired
    +75    WebApplicationContext context;
    +76  
    +77    MockMvc mvc;
    +78  
    +79  
    +80    @BeforeEach
    +81    public void setUp()
    +82    {
    +83      cache.clear();
    +84      mvc = MockMvcBuilders
    +85          .webAppContextSetup(context)
    +86          .alwaysDo(print())
    +87          .build();
    +88    }
    +89  
    +90  
    +91    @Test
    +92    public void testRenderLocalTemplate() throws Exception
    +93    {
    +94      LOG.info("<-- start of test-case");
    +95  
    +96      assertThrows(
    +97          NestedServletException.class,
    +98          () -> mvc.perform(get(URI.create("http://test/controller.html?template=local"))));
    +99  
    +100     server.verify(FETCH("/local.html"), exactly(2));
    +101   }
    +102 
    +103   @Test
    +104   public void testRenderRemoteTemplate() throws Exception
    +105   {
    +106     LOG.info("<-- start of test-case");
    +107 
    +108     mvc
    +109         .perform(get(URI.create("http://test/controller.html?template=remote")))
    +110         .andExpect(status().isOk())
    +111         .andExpect(content().string(read("/rendered/remote.html")));
    +112 
    +113     server.verify(FETCH("/remote.html"), exactly(1));
    +114   }
    +115 
    +116   @Test
    +117   public void testRenderCachedRemoteTemplate() throws Exception
    +118   {
    +119     LOG.info("<-- start of test-case");
    +120 
    +121     mvc
    +122         .perform(get(URI.create("http://test/controller.html?template=remote")))
    +123         .andExpect(status().isOk())
    +124         .andExpect(content().string(read("/rendered/remote.html")));
    +125 
    +126     mvc
    +127         .perform(get(URI.create("http://test/controller.html?template=remote")))
    +128         .andExpect(status().isOk())
    +129         .andExpect(content().string(read("/rendered/remote.html")));
    +130 
    +131     mvc
    +132         .perform(get(URI.create("http://test/controller.html?template=remote")))
    +133         .andExpect(status().isOk())
    +134         .andExpect(content().string(read("/rendered/remote.html")));
    +135 
    +136     mvc
    +137         .perform(get(URI.create("http://test/controller.html?template=remote")))
    +138         .andExpect(status().isOk())
    +139         .andExpect(content().string(read("/rendered/remote.html")));
    +140 
    +141     server.verify(FETCH("/remote.html"), exactly(1));
    +142   }
    +143 
    +144   @Test
    +145   public void testRenderModifiedRemoteTemplate() throws Exception
    +146   {
    +147     LOG.info("<-- start of test-case");
    +148 
    +149     mvc
    +150         .perform(get(URI.create("http://test/controller.html?template=remote")))
    +151         .andExpect(status().isOk())
    +152         .andExpect(content().string(read("/rendered/remote.html")));
    +153 
    +154     CLOCK.timetravel(Duration.ofSeconds(10));
    +155     server.when(FETCH("/remote.html")).forward(NGINX("/modified.html"));
    +156 
    +157     mvc
    +158         .perform(get(URI.create("http://test/controller.html?template=remote")))
    +159         .andExpect(status().isOk())
    +160         .andExpect(content().string(read("/rendered/modified.html")));
    +161 
    +162     server.verify(FETCH("/remote.html"), exactly(2));
    +163     server.verify(
    +164         request()
    +165             .withPath("/remote.html")
    +166             .withHeader("If-Modified-Since")
    +167             .withHeader("If-None-Match"),
    +168         exactly(1));
    +169   }
    +170 
    +171 
    +172   @Controller
    +173   public static class TestController
    +174   {
    +175 
    +176     @RequestMapping("/controller.html")
    +177     public String controller(
    +178         @RequestParam String template,
    +179         Model model
    +180         )
    +181     {
    +182       model.addAttribute("template", template);
    +183       return template;
    +184     }
    +185 
    +186   }
    +187 
    +188 
    +189   static StringEntity body(String resource) throws URISyntaxException, IOException
    +190   {
    +191     return new StringEntity(read(resource));
    +192   }
    +193 
    +194   static String read(String resource) throws URISyntaxException, IOException
    +195   {
    +196     URI uri = ThymeleafWithHttpResourceProtocolResolverIT.class.getResource(resource).toURI();
    +197     return Files.readAllLines(Paths.get(uri)).stream().collect(Collectors.joining("\n"));
    +198   }
    +199 
    +200   static String read(Resource resource) throws URISyntaxException, IOException
    +201   {
    +202     Scanner s = new Scanner(resource.getInputStream()).useDelimiter("\\A");
    +203     return s.hasNext() ? s.next() : "";
    +204   }
    +205 
    +206 
    +207   @SpringBootApplication
    +208   public static class Application implements WebMvcConfigurer
    +209   {
    +210     @Autowired
    +211     ClientAndServer server;
    +212 
    +213     /**
    +214      * This mimics the autoconfiguration of Thymeleaf in Spring-Boot.
    +215      * Reason: Found no other way to inject the property {@code spring.thymeleaf.prefix} dynamically
    +216      */
    +217     @Bean
    +218     public SpringResourceTemplateResolver defaultTemplateResolver(
    +219         ThymeleafProperties properties,
    +220         ApplicationContext applicationContext,
    +221         ClientAndServer server)
    +222     {
    +223       SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    +224       resolver.setApplicationContext(applicationContext);
    +225       resolver.setPrefix("http://localhost:" + server.getLocalPort() + "/"); // << Cannot be passed in via properties
    +226       resolver.setSuffix(properties.getSuffix());
    +227       resolver.setTemplateMode(properties.getMode());
    +228       if (properties.getEncoding() != null)
    +229       {
    +230         resolver.setCharacterEncoding(properties.getEncoding().name());
    +231       }
    +232       resolver.setCacheable(false); // << With caching enabled, the caching of HttpResources cannot be tested
    +233       Integer order = properties.getTemplateResolverOrder();
    +234       if (order != null)
    +235       {
    +236         resolver.setOrder(order);
    +237       }
    +238       resolver.setCheckExistence(properties.isCheckTemplate());
    +239       return resolver;
    +240     }
    +241 
    +242     @Bean
    +243     public TestController testController()
    +244     {
    +245       return new TestController();
    +246     }
    +247 
    +248     @Override
    +249     public void addResourceHandlers(ResourceHandlerRegistry registry)
    +250     {
    +251       LOG.info(
    +252           "{} resource-handler for static location {}",
    +253           registry.hasMappingForPattern("/**") ? "Overwriting" : "Setting",
    +254           "/**"
    +255       );
    +256       registry
    +257           .addResourceHandler("/**")
    +258           .addResourceLocations(
    +259               "classpath:/static/",
    +260               "classpath:/public/",
    +261               "http://localhost:" + server.getLocalPort(),
    +262               "classpath:/fallback/")
    +263           .resourceChain(false);
    +264     }
    +265   }
    +266 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/VersionedResourcesIT.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/VersionedResourcesIT.html new file mode 100644 index 00000000..5201cc58 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/VersionedResourcesIT.html @@ -0,0 +1,184 @@ + + + +/home/kai/Dokumente/yourshouter/http-resources/src/test/java/de/juplo/httpresources/VersionedResourcesIT.java xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.junit.jupiter.api.BeforeEach;
    +4   import org.junit.jupiter.api.Test;
    +5   import org.mockserver.integration.ClientAndServer;
    +6   import org.slf4j.Logger;
    +7   import org.slf4j.LoggerFactory;
    +8   import org.springframework.beans.factory.annotation.Autowired;
    +9   import org.springframework.boot.autoconfigure.SpringBootApplication;
    +10  import org.springframework.boot.test.context.SpringBootTest;
    +11  import org.springframework.cache.Cache;
    +12  import org.springframework.context.annotation.Bean;
    +13  import org.springframework.test.web.servlet.MockMvc;
    +14  import org.springframework.test.web.servlet.setup.MockMvcBuilders;
    +15  import org.springframework.web.context.WebApplicationContext;
    +16  import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    +17  import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    +18  import org.springframework.web.servlet.resource.VersionResourceResolver;
    +19  
    +20  import java.net.URI;
    +21  import java.time.Clock;
    +22  import java.time.Instant;
    +23  import java.time.ZoneId;
    +24  
    +25  import static de.juplo.httpresources.TestUtil.LONG_NOW;
    +26  import static de.juplo.httpresources.TestUtil.read;
    +27  import static org.mockserver.verify.VerificationTimes.exactly;
    +28  import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    +29  import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
    +30  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    +31  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    +32  
    +33  
    +34  @SpringBootTest({
    +35      "juplo.http-resources.protocol-resolver.enabled=true"
    +36      })
    +37  public class VersionedResourcesIT extends IntegrationTestBase
    +38  {
    +39    private final static Logger LOG =
    +40        LoggerFactory.getLogger(VersionedResourcesIT.class);
    +41  
    +42  
    +43    @Autowired
    +44    HttpResources resources;
    +45    @Autowired
    +46    Cache cache;
    +47    @Autowired
    +48    WebApplicationContext context;
    +49  
    +50    MockMvc mvc;
    +51  
    +52  
    +53    @BeforeEach
    +54    public void setUp()
    +55    {
    +56      cache.clear();
    +57      mvc = MockMvcBuilders
    +58          .webAppContextSetup(context)
    +59          .alwaysDo(print())
    +60          .build();
    +61    }
    +62  
    +63  
    +64    @Test
    +65    public void testTransformation() throws Exception
    +66    {
    +67      LOG.info("<-- start of test-case");
    +68  
    +69      mvc
    +70          .perform(get(URI.create("http://test/css/static.css")))
    +71          .andExpect(status().isOk())
    +72          .andExpect(content().string(read("/transformed/css/static.css")));
    +73      mvc
    +74          .perform(get(URI.create("http://test/css/sub/static.css")))
    +75          .andExpect(status().isOk())
    +76          .andExpect(content().string(read("/transformed/css/static.css")));
    +77  
    +78      mvc
    +79          .perform(get(URI.create("http://test/css/remote.css")))
    +80          .andExpect(status().isOk())
    +81          .andExpect(content().string(read("/transformed/css/remote.css")));
    +82      mvc
    +83          .perform(get(URI.create("http://test/css/sub/remote.css")))
    +84          .andExpect(status().isOk())
    +85          .andExpect(content().string(read("/transformed/css/remote.css")));
    +86      mvc
    +87          .perform(get(URI.create("http://test/css/remote-c901f3a6ab390732242f0fc09ca170e7.css")))
    +88          .andExpect(status().isOk())
    +89          .andExpect(content().string(read("/transformed/css/remote.css")));
    +90      mvc
    +91          .perform(get(URI.create("http://test/css/sub/remote-c901f3a6ab390732242f0fc09ca170e7.css")))
    +92          .andExpect(status().isOk())
    +93          .andExpect(content().string(read("/transformed/css/remote.css")));
    +94  
    +95      mvc
    +96          .perform(get(URI.create("http://test/css/fallback.css")))
    +97          .andExpect(status().isOk())
    +98          .andExpect(content().string(read("/transformed/css/static.css")));
    +99      mvc
    +100         .perform(get(URI.create("http://test/css/sub/fallback.css")))
    +101         .andExpect(status().isOk())
    +102         .andExpect(content().string(read("/transformed/css/static.css")));
    +103     mvc
    +104         .perform(get(URI.create("http://test/css/fallback-c901f3a6ab390732242f0fc09ca170e7.css")))
    +105         .andExpect(status().isOk())
    +106         .andExpect(content().string(read("/transformed/css/static.css")));
    +107     mvc
    +108         .perform(get(URI.create("http://test/css/sub/fallback-c901f3a6ab390732242f0fc09ca170e7.css")))
    +109         .andExpect(status().isOk())
    +110         .andExpect(content().string(read("/transformed/css/static.css")));
    +111 
    +112     mvc
    +113         .perform(get(URI.create("http://test/css/static-c901f3a6ab390732242f0fc09ca170e7.css")))
    +114         .andExpect(status().isOk())
    +115         .andExpect(content().string(read("/transformed/css/static.css")));
    +116     mvc
    +117         .perform(get(URI.create("http://test/css/remote.css")))
    +118         .andExpect(status().isOk())
    +119         .andExpect(content().string(read("/transformed/css/remote.css")));
    +120     mvc
    +121         .perform(get(URI.create("http://test/css/remote-c901f3a6ab390732242f0fc09ca170e7.css")))
    +122         .andExpect(status().isOk())
    +123         .andExpect(content().string(read("/transformed/css/remote.css")));
    +124     mvc
    +125         .perform(get(URI.create("http://test/css/static-c901f3a6ab390732242f0fc09ca170e7.css")))
    +126         .andExpect(status().isOk())
    +127         .andExpect(content().string(read("/transformed/css/static.css")));
    +128 
    +129     server.verify(FETCH("/css/remote.css"), exactly(1));
    +130     server.verify(FETCH("/css/fallback.css"), exactly(8));
    +131   }
    +132 
    +133 
    +134   @SpringBootApplication
    +135   public static class Application implements WebMvcConfigurer
    +136   {
    +137     @Bean
    +138     public Clock clock()
    +139     {
    +140       return Clock.fixed(Instant.ofEpochMilli(LONG_NOW), ZoneId.systemDefault());
    +141     }
    +142 
    +143     @Bean
    +144     public VersionResourceResolver versionResourceResolver()
    +145     {
    +146       VersionResourceResolver resolver = new VersionResourceResolver();
    +147       resolver.addFixedVersionStrategy("v12", "/img/**");
    +148       resolver.addContentVersionStrategy("/**");
    +149       return resolver;
    +150     }
    +151 
    +152 
    +153     @Autowired
    +154     VersionResourceResolver versionResourceResolver;
    +155     @Autowired
    +156     ClientAndServer server;
    +157 
    +158     @Override
    +159     public void addResourceHandlers(ResourceHandlerRegistry registry)
    +160     {
    +161       registry
    +162           .addResourceHandler("/**")
    +163           .addResourceLocations(
    +164               "classpath:/static/",
    +165               "http://localhost:" + server.getLocalPort(),
    +166               "classpath:/fallback/")
    +167           .resourceChain(true)
    +168           .addResolver(versionResourceResolver);
    +169     }
    +170   }
    +171 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/package-frame.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/package-frame.html new file mode 100644 index 00000000..5127151e --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/package-frame.html @@ -0,0 +1,51 @@ + + + + + + + HttpResources 2.0.0 Reference Package de.juplo.httpresources + + + +

    de.juplo.httpresources

    + + + \ No newline at end of file diff --git a/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/package-summary.html b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/package-summary.html new file mode 100644 index 00000000..7d6b77ae --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/de/juplo/httpresources/package-summary.html @@ -0,0 +1,157 @@ + + + + + + + HttpResources 2.0.0 Reference Package de.juplo.httpresources + + + + +
    + + + + +
    HttpResources 2.0.0 Reference
    +
    + + +
    +

    Package de.juplo.httpresources

    +
    + + +
    + + + + +
    HttpResources 2.0.0 Reference
    +
    + + + + + \ No newline at end of file diff --git a/dist/http-resources/2.0.0/xref-test/index.html b/dist/http-resources/2.0.0/xref-test/index.html new file mode 100644 index 00000000..e41e9e82 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/index.html @@ -0,0 +1,75 @@ + + + + + + + HttpResources 2.0.0 Reference + + + + + + + + + + <h1>Frame Alert</h1> + <p> + You don't have frames. Go <a href="overview-summary.html">here</a> + </p> + + + diff --git a/dist/http-resources/2.0.0/xref-test/overview-frame.html b/dist/http-resources/2.0.0/xref-test/overview-frame.html new file mode 100644 index 00000000..079f14b5 --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/overview-frame.html @@ -0,0 +1,24 @@ + + + + + + + HttpResources 2.0.0 Reference + + + +

    HttpResources 2.0.0 Reference

    + +
    +

    Packages

    + +
    +

     

    + + + diff --git a/dist/http-resources/2.0.0/xref-test/overview-summary.html b/dist/http-resources/2.0.0/xref-test/overview-summary.html new file mode 100644 index 00000000..2be8729a --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/overview-summary.html @@ -0,0 +1,92 @@ + + + + + + + HttpResources 2.0.0 Reference + + + +
    + + + + +
    HttpResources 2.0.0 Reference
    +
    + + +
    +

    HttpResources 2.0.0 Reference

    +
    +
    + + + + + + + + + + + + +
    Packages 
    Package
    + de.juplo.httpresources +
    +
    + +
    + + + + +
    HttpResources 2.0.0 Reference
    +
    + + + + + \ No newline at end of file diff --git a/dist/http-resources/2.0.0/xref-test/stylesheet.css b/dist/http-resources/2.0.0/xref-test/stylesheet.css new file mode 100644 index 00000000..9e10f29e --- /dev/null +++ b/dist/http-resources/2.0.0/xref-test/stylesheet.css @@ -0,0 +1,626 @@ +/* Javadoc style sheet */ +/* +Overall document style +*/ + +@import url('resources/fonts/dejavu.css'); + +body { + background-color:#ffffff; + color:#353833; + font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; + font-size:14px; + margin:0; +} +a:link, a:visited { + text-decoration:none; + color:#4A6782; +} +a:hover, a:focus { + text-decoration:none; + color:#bb7a2a; +} +a:active { + text-decoration:none; + color:#4A6782; +} +a[name] { + color:#353833; +} +a[name]:hover { + text-decoration:none; + color:#353833; +} +pre { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; +} +h1 { + font-size:20px; +} +h2 { + font-size:18px; +} +h3 { + font-size:16px; + font-style:italic; +} +h4 { + font-size:13px; +} +h5 { + font-size:12px; +} +h6 { + font-size:11px; +} +ul { + list-style-type:disc; +} +code, tt { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; + margin-top:8px; + line-height:1.4em; +} +dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; +} +table tr td dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + vertical-align:top; + padding-top:4px; +} +sup { + font-size:8px; +} +/* +Document title and Copyright styles +*/ +.clear { + clear:both; + height:0px; + overflow:hidden; +} +.aboutLanguage { + float:right; + padding:0px 21px; + font-size:11px; + z-index:200; + margin-top:-9px; +} +.legalCopy { + margin-left:.5em; +} +.bar a, .bar a:link, .bar a:visited, .bar a:active { + color:#FFFFFF; + text-decoration:none; +} +.bar a:hover, .bar a:focus { + color:#bb7a2a; +} +.tab { + background-color:#0066FF; + color:#ffffff; + padding:8px; + width:5em; + font-weight:bold; +} +/* +Navigation bar styles +*/ +.bar { + background-color:#4D7A97; + color:#FFFFFF; + padding:.8em .5em .4em .8em; + height:auto;/*height:1.8em;*/ + font-size:11px; + margin:0; +} +.topNav { + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.bottomNav { + margin-top:10px; + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.subNav { + background-color:#dee3e9; + float:left; + width:100%; + overflow:hidden; + font-size:12px; +} +.subNav div { + clear:left; + float:left; + padding:0 0 5px 6px; + text-transform:uppercase; +} +ul.navList, ul.subNavList { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.navList li{ + list-style:none; + float:left; + padding: 5px 6px; + text-transform:uppercase; +} +ul.subNavList li{ + list-style:none; + float:left; +} +.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { + color:#FFFFFF; + text-decoration:none; + text-transform:uppercase; +} +.topNav a:hover, .bottomNav a:hover { + text-decoration:none; + color:#bb7a2a; + text-transform:uppercase; +} +.navBarCell1Rev { + background-color:#F8981D; + color:#253441; + margin: auto 5px; +} +.skipNav { + position:absolute; + top:auto; + left:-9999px; + overflow:hidden; +} +/* +Page header and footer styles +*/ +.header, .footer { + clear:both; + margin:0 20px; + padding:5px 0 0 0; +} +.indexHeader { + margin:10px; + position:relative; +} +.indexHeader span{ + margin-right:15px; +} +.indexHeader h1 { + font-size:13px; +} +.title { + color:#2c4557; + margin:10px 0; +} +.subTitle { + margin:5px 0 0 0; +} +.header ul { + margin:0 0 15px 0; + padding:0; +} +.footer ul { + margin:20px 0 5px 0; +} +.header ul li, .footer ul li { + list-style:none; + font-size:13px; +} +/* +Heading styles +*/ +div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList li.blockList h3 { + padding:0; + margin:15px 0; +} +ul.blockList li.blockList h2 { + padding:0px 0 20px 0; +} +/* +Page layout container styles +*/ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + clear:both; + padding:10px 20px; + position:relative; +} +.indexContainer { + margin:10px; + position:relative; + font-size:12px; +} +.indexContainer h2 { + font-size:13px; + padding:0 0 3px 0; +} +.indexContainer ul { + margin:0; + padding:0; +} +.indexContainer ul li { + list-style:none; + padding-top:2px; +} +.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { + font-size:12px; + font-weight:bold; + margin:10px 0 0 0; + color:#4E4E4E; +} +.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { + margin:5px 0 10px 0px; + font-size:14px; + font-family:'DejaVu Sans Mono',monospace; +} +.serializedFormContainer dl.nameValue dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +.serializedFormContainer dl.nameValue dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* +List styles +*/ +ul.horizontal li { + display:inline; + font-size:0.9em; +} +ul.inheritance { + margin:0; + padding:0; +} +ul.inheritance li { + display:inline; + list-style:none; +} +ul.inheritance li ul.inheritance { + margin-left:15px; + padding-left:15px; + padding-top:1px; +} +ul.blockList, ul.blockListLast { + margin:10px 0 10px 0; + padding:0; +} +ul.blockList li.blockList, ul.blockListLast li.blockList { + list-style:none; + margin-bottom:15px; + line-height:1.4; +} +ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { + padding:0px 20px 5px 10px; + border:1px solid #ededed; + background-color:#f8f8f8; +} +ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { + padding:0 0 5px 8px; + background-color:#ffffff; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { + margin-left:0; + padding-left:0; + padding-bottom:15px; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { + list-style:none; + border-bottom:none; + padding-bottom:0; +} +table tr td dl, table tr td dl dt, table tr td dl dd { + margin-top:0; + margin-bottom:1px; +} +/* +Table styles +*/ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + width:100%; + border-left:1px solid #EEE; + border-right:1px solid #EEE; + border-bottom:1px solid #EEE; +} +.overviewSummary, .memberSummary { + padding:0px; +} +.overviewSummary caption, .memberSummary caption, .typeSummary caption, +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:#253441; + font-weight:bold; + clear:none; + overflow:hidden; + padding:0px; + padding-top:10px; + padding-left:1px; + margin:0px; + white-space:pre; +} +.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, +.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, +.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, +.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, +.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { + color:#FFFFFF; +} +.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + padding-bottom:7px; + display:inline-block; + float:left; + background-color:#F8981D; + border: none; + height:16px; +} +.memberSummary caption span.activeTableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#F8981D; + height:16px; +} +.memberSummary caption span.tableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#4D7A97; + height:16px; +} +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { + padding-top:0px; + padding-left:0px; + padding-right:0px; + background-image:none; + float:none; + display:inline; +} +.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { + display:none; + width:5px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .activeTableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .tableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + background-color:#4D7A97; + float:left; + +} +.overviewSummary td, .memberSummary td, .typeSummary td, +.useSummary td, .constantsSummary td, .deprecatedSummary td { + text-align:left; + padding:0px 0px 12px 10px; +} +th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, +td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ + vertical-align:top; + padding-right:0px; + padding-top:8px; + padding-bottom:3px; +} +th.colFirst, th.colLast, th.colOne, .constantsSummary th { + background:#dee3e9; + text-align:left; + padding:8px 3px 3px 7px; +} +td.colFirst, th.colFirst { + white-space:nowrap; + font-size:13px; +} +td.colLast, th.colLast { + font-size:13px; +} +td.colOne, th.colOne { + font-size:13px; +} +.overviewSummary td.colFirst, .overviewSummary th.colFirst, +.useSummary td.colFirst, .useSummary th.colFirst, +.overviewSummary td.colOne, .overviewSummary th.colOne, +.memberSummary td.colFirst, .memberSummary th.colFirst, +.memberSummary td.colOne, .memberSummary th.colOne, +.typeSummary td.colFirst{ + width:25%; + vertical-align:top; +} +td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { + font-weight:bold; +} +.tableSubHeadingColor { + background-color:#EEEEFF; +} +.altColor { + background-color:#FFFFFF; +} +.rowColor { + background-color:#EEEEEF; +} +/* +Content styles +*/ +.description pre { + margin-top:0; +} +.deprecatedContent { + margin:0; + padding:10px 0; +} +.docSummary { + padding:0; +} + +ul.blockList ul.blockList ul.blockList li.blockList h3 { + font-style:normal; +} + +div.block { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; +} + +td.colLast div { + padding-top:0px; +} + + +td.colLast a { + padding-bottom:3px; +} +/* +Formatting effect styles +*/ +.sourceLineNo { + color:green; + padding:0 30px 0 0; +} +h1.hidden { + visibility:hidden; + overflow:hidden; + font-size:10px; +} +.block { + display:block; + margin:3px 10px 2px 0px; + color:#474747; +} +.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, +.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, +.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { + font-weight:bold; +} +.deprecationComment, .emphasizedPhrase, .interfaceName { + font-style:italic; +} + +div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +div.block div.block span.interfaceName { + font-style:normal; +} + +div.contentContainer ul.blockList li.blockList h2{ + padding-bottom:0px; +} + +/* JXR style sheet */ +a.jxr_linenumber:link { + color: #00f; +} + +a.jxr_linenumber:visited { + color: #00a; +} + +a.jxr_linenumber:active, a.jxr_linenumber:hover { + color: #f30 !important; +} + +em.comment { + color: #390; +} + +.string { + color: #009; +} + +#overview { + padding: 2px; + font-size: 90%; + font-family: Helvetica, Arial, sans-serif; +} + +hr { + color: #000; +} + +.jxr_comment +{ + color: #390; +} + +.jxr_javadoccomment +{ + color: #A00; +} + +.jxr_string +{ + color: #009; +} + +.jxr_keyword +{ + color: #000; +} + diff --git a/dist/http-resources/2.0.0/xref/allclasses-frame.html b/dist/http-resources/2.0.0/xref/allclasses-frame.html new file mode 100644 index 00000000..eba7c98e --- /dev/null +++ b/dist/http-resources/2.0.0/xref/allclasses-frame.html @@ -0,0 +1,25 @@ + + + + + + + All Classes + + + +

    All Classes

    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpData.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpData.html new file mode 100644 index 00000000..b7db89f3 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpData.html @@ -0,0 +1,119 @@ + + + +HttpData xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.springframework.http.HttpHeaders;
    +4   import org.springframework.util.StringUtils;
    +5   
    +6   import java.util.Arrays;
    +7   import java.util.Objects;
    +8   
    +9   
    +10  /**
    +11   * Immutable container for cacheable state of an instance of {@link HttpResource}.
    +12   */
    +13  class HttpData
    +14  {
    +15    final static HttpData NOT_FETCHED =
    +16        new HttpData(
    +17            null,
    +18            new HttpHeaders(),
    +19            false,
    +20            Long.MIN_VALUE,
    +21            Long.MIN_VALUE,
    +22            null);
    +23  
    +24    final static HttpData SERVER_ERROR =
    +25        new HttpData(
    +26            null,
    +27            new HttpHeaders(),
    +28            false,
    +29            -1,
    +30            -1,
    +31            null);
    +32  
    +33    final static HttpData NOT_FOUND = SERVER_ERROR;
    +34  
    +35    final byte[] content;
    +36    final HttpHeaders headers;
    +37    final boolean revalidate;
    +38    final long lastModified;
    +39    final long expires;
    +40    final String eTag;
    +41  
    +42    private final String normalizedETag;
    +43  
    +44  
    +45    HttpData(
    +46        byte[] content,
    +47        HttpHeaders headers,
    +48        boolean revalidate,
    +49        long lastModified,
    +50        long expires,
    +51        String eTag)
    +52    {
    +53      this.content = content;
    +54      this.headers = headers;
    +55      this.revalidate = revalidate;
    +56      this.lastModified = lastModified;
    +57      this.expires = expires;
    +58      this.eTag = eTag;
    +59  
    +60      String tmp = StringUtils.hasText(eTag) ? eTag.trim() : "";
    +61      this.normalizedETag =
    +62          tmp.length() >=2 && tmp.charAt(0) == 'W' && tmp.charAt(1) == '/'
    +63              ? tmp.substring(2).trim()
    +64              : tmp;
    +65    }
    +66  
    +67  
    +68    @Override
    +69    public boolean equals(Object o)
    +70    {
    +71      if (this == o) return true;
    +72      if (!(o instanceof HttpData)) return false;
    +73      HttpData../../../de/juplo/httpresources/HttpData.html#HttpData">HttpData data = (HttpData) o;
    +74  
    +75      if (lastModified == 0 && normalizedETag.length() == 0)
    +76        return Arrays.equals(content, data.content);
    +77  
    +78      return
    +79          lastModified == data.lastModified &&
    +80          normalizedETag.equals(data.normalizedETag);
    +81    }
    +82  
    +83    @Override
    +84    public int hashCode()
    +85    {
    +86      if (lastModified == 0 && !StringUtils.hasText(eTag))
    +87        return Arrays.hashCode(content);
    +88  
    +89      return Objects.hash(lastModified, eTag);
    +90    }
    +91  
    +92    @Override
    +93    public String toString()
    +94    {
    +95      final StringBuffer sb = new StringBuffer();
    +96      sb.append("headers=").append(headers);
    +97      sb.append(", revalidate=").append(revalidate);
    +98      sb.append(", lastModified=").append(lastModified);
    +99      sb.append(", expires=").append(expires);
    +100     sb.append(", eTag='").append(eTag).append('\'');
    +101     sb.append(", content=");
    +102     if (content == null) sb.append("null");
    +103     else sb.append(new String(content));
    +104     return sb.toString();
    +105   }
    +106 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResource.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResource.html new file mode 100644 index 00000000..4c5ee197 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResource.html @@ -0,0 +1,271 @@ + + + +HttpResource xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.springframework.http.HttpHeaders;
    +4   import org.springframework.util.MimeType;
    +5   
    +6   import java.io.*;
    +7   import java.net.URI;
    +8   import java.net.URL;
    +9   import java.time.Clock;
    +10  import java.util.Objects;
    +11  
    +12  
    +13  public class HttpResource implements org.springframework.web.servlet.resource.HttpResource
    +14  {
    +15    final HttpResources resources;
    +16    final HttpResourceFetcher fetcher;
    +17    final Clock clock;
    +18    final URI uri;
    +19  
    +20    HttpData data;
    +21    boolean modified;
    +22  
    +23    HttpResource(
    +24        HttpResources resources,
    +25        HttpResourceFetcher fetcher,
    +26        Clock clock,
    +27        URI uri)
    +28    {
    +29      this(resources, fetcher, clock, uri, HttpData.NOT_FETCHED);
    +30    }
    +31  
    +32    HttpResource(
    +33          HttpResources resources,
    +34          HttpResourceFetcher fetcher,
    +35          Clock clock,
    +36          URI uri,
    +37          HttpData data)
    +38      {
    +39      this.resources = resources;
    +40      this.fetcher = fetcher;
    +41      this.clock = clock;
    +42      this.uri = uri;
    +43      this.data = data;
    +44    }
    +45  
    +46  
    +47    synchronized public long expires()
    +48    {
    +49      return data.expires;
    +50    }
    +51  
    +52    synchronized public boolean isExpired()
    +53    {
    +54      return data.expires < clock.millis();
    +55    }
    +56  
    +57    @Override
    +58    synchronized public boolean exists()
    +59    {
    +60      if (isExpired())
    +61        fetch();
    +62      return data.content != null;
    +63    }
    +64  
    +65    @Override
    +66    synchronized public boolean isReadable()
    +67    {
    +68      return exists();
    +69    }
    +70  
    +71    @Override
    +72    public boolean isOpen()
    +73    {
    +74      return false;
    +75    }
    +76  
    +77    @Override
    +78    public URL getURL() throws IOException
    +79    {
    +80      return uri.toURL();
    +81    }
    +82  
    +83    @Override
    +84    public URI getURI()
    +85    {
    +86      return uri;
    +87    }
    +88  
    +89    @Override
    +90    public File getFile() throws IOException
    +91    {
    +92      throw new FileNotFoundException("The resource " + getDescription() + " cannot be retrived as file");
    +93    }
    +94  
    +95    @Override
    +96    synchronized public long contentLength() throws IOException
    +97    {
    +98      if (!fetched())
    +99        fetch();
    +100 
    +101     if (data.content == null)
    +102       throw new FileNotFoundException("The resource " + getDescription() + " cannot be retrived");
    +103 
    +104     return data.content.length;
    +105   }
    +106 
    +107   synchronized public MimeType contentType()
    +108   {
    +109     return data.headers.getContentType();
    +110   }
    +111 
    +112   @Override
    +113   synchronized public long lastModified() throws IOException
    +114   {
    +115     if (!fetched())
    +116       fetch();
    +117 
    +118     if (data.content == null)
    +119       throw new FileNotFoundException("The resource " + getDescription() + " cannot be retrived");
    +120 
    +121     return data.lastModified;
    +122   }
    +123 
    +124   synchronized public String eTag()
    +125   {
    +126     return data.eTag;
    +127   }
    +128 
    +129   @Override
    +130   public HttpResource createRelative(String relativePath) throws IOException
    +131   {
    +132     try
    +133     {
    +134       return createRelative(HttpResources.convert(relativePath));
    +135     }
    +136     catch (IllegalArgumentException e)
    +137     {
    +138       throw new IOException("Invalid relative path: " + relativePath, e);
    +139     }
    +140   }
    +141 
    +142   public HttpResource createRelative(URI relative) throws IOException
    +143   {
    +144     return resources.getResource(HttpResources.resolve(relative, uri));
    +145   }
    +146 
    +147   @Override
    +148   public String getFilename()
    +149   {
    +150     return uri.getPath();
    +151   }
    +152 
    +153   @Override
    +154   public String getDescription()
    +155   {
    +156     return "HTTP [" + this.uri + "]";
    +157   }
    +158 
    +159   @Override
    +160   synchronized public InputStream getInputStream() throws IOException
    +161   {
    +162     if (!fetched())
    +163     {
    +164       fetch();
    +165     }
    +166     else
    +167     {
    +168       isModified();
    +169     }
    +170 
    +171     // Clear the modified-flag
    +172     modified = false;
    +173 
    +174     if (data.content == null)
    +175       throw new FileNotFoundException("The resource " + getDescription() + " cannot be retrived as file");
    +176 
    +177     return new ByteArrayInputStream(data.content);
    +178   }
    +179 
    +180   synchronized public boolean isModified()
    +181   {
    +182     if (modified)
    +183     {
    +184       return true;
    +185     }
    +186 
    +187     if (!isExpired())
    +188     {
    +189       return false;
    +190     }
    +191 
    +192     return fetch();
    +193   }
    +194 
    +195   /**
    +196    * Checks, if the remote resource was already fetched.
    +197    *
    +198    * @return {@code true}, if the resource was already fetched, otherwise
    +199    * {@code false}
    +200    */
    +201   synchronized public boolean fetched()
    +202   {
    +203     return data.expires != Long.MIN_VALUE;
    +204   }
    +205 
    +206   /**
    +207    * Fetches the remote resource and reports, if it was modified.
    +208    * <p>
    +209    * This method fetches the remote resource, if was not already fetched.
    +210    * If the resource was already fetched, it revalidates it, if necessary.
    +211    *
    +212    * @return {@code true}, if the resource has changed or was fetched for
    +213    * the first time, otherwise {@code false}
    +214    */
    +215   synchronized public boolean fetch()
    +216   {
    +217     HttpData result = fetcher.fetch(uri, data);
    +218 
    +219     // Flag the resource as modified, if the data has changed
    +220     // Otherwise, keep the old state of the modified-flag.
    +221     modified = !data.equals(result);
    +222 
    +223     data = result;
    +224 
    +225     return modified;
    +226   }
    +227 
    +228   @Override
    +229   synchronized public HttpHeaders getResponseHeaders()
    +230   {
    +231     return data.headers;
    +232   }
    +233 
    +234 
    +235   @Override
    +236   public int hashCode()
    +237   {
    +238     return uri.hashCode();
    +239   }
    +240 
    +241   @Override
    +242   public boolean equals(Object o)
    +243   {
    +244     if (o == null)
    +245       return false;
    +246     if (o == this)
    +247       return true;
    +248     if (!(o instanceof HttpResource))
    +249       return false;
    +250     return Objects.equals(uri, ((HttpResource) o).uri);
    +251   }
    +252 
    +253   @Override
    +254   public String toString()
    +255   {
    +256     return getDescription();
    +257   }
    +258 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceChainAwareResourceLoader.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceChainAwareResourceLoader.html new file mode 100644 index 00000000..2b722914 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceChainAwareResourceLoader.html @@ -0,0 +1,106 @@ + + + +HttpResourceChainAwareResourceLoader xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.slf4j.Logger;
    +4   import org.slf4j.LoggerFactory;
    +5   import org.springframework.core.io.Resource;
    +6   import org.springframework.core.io.ResourceLoader;
    +7   
    +8   import java.util.Arrays;
    +9   
    +10  public class HttpResourceChainAwareResourceLoader implements ResourceLoader
    +11  {
    +12    private static final Logger LOG =
    +13        LoggerFactory.getLogger(HttpResourceChainAwareResourceLoader.class);
    +14  
    +15  
    +16    private final ResourceLoader loader;
    +17    private final String[] sources;
    +18  
    +19  
    +20  
    +21    public HttpResourceChainAwareResourceLoader(
    +22        ResourceLoader loader,
    +23        String... sources)
    +24    {
    +25      this.loader = loader;
    +26      this.sources =
    +27          Arrays
    +28              .stream(sources)
    +29              .map(location -> location.trim())
    +30              .filter(location ->
    +31              {
    +32                if (location.length() > 0)
    +33                  return true;
    +34  
    +35                LOG.warn("Filtered out empty entry from list of sources");
    +36                return false;
    +37              })
    +38              .map(location ->
    +39              {
    +40                int length = location.length();
    +41                if (length > 0 && location.charAt(length - 1) != '/')
    +42                {
    +43                  LOG.info("Adding trailing slash to configured source {}", location);
    +44                  return location + "/";
    +45                }
    +46                else
    +47                  return location;
    +48              })
    +49              .toArray(size -> new String[size]);
    +50    }
    +51  
    +52  
    +53    /**
    +54     * Returns the first existing resource, or the first, if non of the
    +55     * resources exists.
    +56     *
    +57     * This mimics the behavior of the original resolver as closeley as possible,
    +58     * asuming, that the first source is a / the local one.
    +59     *
    +60     * @param location The name of the requested resource
    +61     * @return The first existing resource, or the first resource - never <code>null</code>.
    +62     */
    +63    @Override
    +64    public Resource getResource(String location)
    +65    {
    +66      // We assure in the constructore, that sources always end with a '/'
    +67      String relativeResourceName =
    +68          location.charAt(0) == '/'
    +69              ? location.substring(1)
    +70              : location;
    +71  
    +72      for (String source : sources)
    +73      {
    +74        Resource resource = loader.getResource(source + relativeResourceName);
    +75  
    +76        // Return the resource, if it exists.
    +77        if (resource.exists())
    +78          return resource;
    +79      }
    +80  
    +81      // If all sources were checked without success, return the resource from
    +82      // the first source, although it does not exists - the contract of an
    +83      // {@link ResourceLoader} requires, that the return-value is neve {@code null}.
    +84      // Therefore, we fall back to the behaviour of our parent-loader.
    +85      return loader.getResource(location);
    +86    }
    +87  
    +88    @Override
    +89    public ClassLoader getClassLoader()
    +90    {
    +91      return loader.getClassLoader();
    +92    }
    +93  }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceFetcher.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceFetcher.html new file mode 100644 index 00000000..47f3f093 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceFetcher.html @@ -0,0 +1,334 @@ + + + +HttpResourceFetcher xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.slf4j.Logger;
    +4   import org.slf4j.LoggerFactory;
    +5   import org.springframework.cache.Cache;
    +6   import org.springframework.http.HttpHeaders;
    +7   import org.springframework.http.HttpMethod;
    +8   import org.springframework.http.HttpStatus;
    +9   import org.springframework.http.client.ClientHttpRequest;
    +10  import org.springframework.http.client.ClientHttpRequestFactory;
    +11  import org.springframework.http.client.ClientHttpResponse;
    +12  import org.springframework.util.FileCopyUtils;
    +13  
    +14  import java.io.IOException;
    +15  import java.io.InputStream;
    +16  import java.net.URI;
    +17  import java.time.Clock;
    +18  import java.util.HashMap;
    +19  import java.util.Map;
    +20  import java.util.function.Predicate;
    +21  
    +22  import static org.springframework.http.HttpHeaders.*;
    +23  
    +24  public class HttpResourceFetcher
    +25  {
    +26    private final static Logger LOG =
    +27            LoggerFactory.getLogger(HttpResourceFetcher.class);
    +28  
    +29    public final static int DEFAULT_TTL = 3600;
    +30  
    +31    private final ClientHttpRequestFactory requestFactory;
    +32    private final Cache cache;
    +33    private final Clock clock;
    +34  
    +35    private final Predicate<String> filter;
    +36  
    +37    private final int defaultTTL;
    +38    private final int minTTL;
    +39  
    +40    private final boolean serveStale;
    +41  
    +42  
    +43    public HttpResourceFetcher(ClientHttpRequestFactory factory, Cache cache, Clock clock)
    +44    {
    +45      this(factory, cache, clock, DEFAULT_TTL, 0, true);
    +46    }
    +47  
    +48    /**
    +49     *
    +50     * @param factory
    +51     * @param clock
    +52     * @param defaultTTL default time to live in milliseconds
    +53     * Default TTL, if no according information is present in the HTTP-headers.
    +54     * If set to <code>0</code>, caching will be disabled, if no according
    +55     * HTTP-headers are present.
    +56     * @param minTTL the minimum time to live, if caching is enabled
    +57     * A minimum TTL, that will overwrite the time to live, that was extracted
    +58     * from the HTTP-headers.
    +59     * The minimum TTL is only applied, if the default TTL is set to a value
    +60     * greater than zero, hence enabling caching by default.
    +61     * @param serveStale
    +62     */
    +63    public HttpResourceFetcher(
    +64        ClientHttpRequestFactory factory,
    +65        Cache cache,
    +66        Clock clock,
    +67        int defaultTTL,
    +68        int minTTL,
    +69        boolean serveStale)
    +70    {
    +71      this.requestFactory = factory;
    +72      this.cache = cache;
    +73      this.clock = clock;
    +74      this.defaultTTL = defaultTTL;
    +75      this.minTTL = minTTL;
    +76      this.serveStale = serveStale;
    +77  
    +78      /** Filter may pass on more headers and may also be configurable later */
    +79      filter = (key) -> CONTENT_TYPE.equalsIgnoreCase(key);
    +80    }
    +81  
    +82  
    +83    /**
    +84     * Fetches the remote resource and reports, if it was modified.
    +85     *
    +86     * This method fetches the remote resource, if was not already fetched.
    +87     * If the resource was already fetched, it revalidates it, if necessary.
    +88     *
    +89     * @return {@code true}, if the resource has changed or was fetched for
    +90     * the first time, otherwise {@code false}
    +91     */
    +92    public HttpData./de/juplo/httpresources/HttpData.html#HttpData">HttpData fetch(URI uri, HttpData data)
    +93    {
    +94      HttpData cached = cache.get(uri, HttpData.class);
    +95      if (cached != null && cached != data)
    +96      {
    +97        if (cached.expires >= clock.millis())
    +98          return cached;
    +99        else
    +100         data = cached;
    +101     }
    +102 
    +103     boolean has_existed = data.content != null;
    +104     boolean must_revalidate = data.revalidate;
    +105 
    +106     ClientHttpRequest request = createGetRequest(uri);
    +107     if (has_existed)
    +108     {
    +109       if (data.eTag != null)
    +110         request.getHeaders().setIfNoneMatch(data.eTag);
    +111       if (data.lastModified > 0)
    +112         request.getHeaders().setIfModifiedSince(data.lastModified);
    +113     }
    +114 
    +115     HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
    +116     long request_time = clock.millis();
    +117 
    +118     try (ClientHttpResponse response = request.execute())
    +119     {
    +120       status = response.getStatusCode();
    +121 
    +122       LOG.debug("{} -- {}", status, uri);
    +123 
    +124       switch (status)
    +125       {
    +126         case OK:
    +127 
    +128           InputStream body = response.getBody();
    +129           byte[] content = FileCopyUtils.copyToByteArray(body);
    +130 
    +131           data = readCachingHeaders(content, response, response.getHeaders(), request_time, defaultTTL);
    +132           cache.put(uri, data);
    +133           return data;
    +134 
    +135         case NOT_MODIFIED:
    +136 
    +137           data = readCachingHeaders(data.content, response, data.headers, request_time, defaultTTL);
    +138           cache.put(uri, data);
    +139           return data;
    +140 
    +141 
    +142         case NOT_FOUND:
    +143 
    +144           // If stale data is served, 404-responses for already cached
    +145           // resources are quietly ignored
    +146           if (!serveStale)
    +147           {
    +148             data = readCachingHeaders(null, response, response.getHeaders(), request_time, 0);
    +149           }
    +150 
    +151           cache.put(uri, data);
    +152           return data;
    +153 
    +154         default:
    +155 
    +156           // TODO:
    +157           // A client has at least to distinguish the status-classes, denoted
    +158           // by the first digit of the code.
    +159           // See: https://tools.ietf.org/html/rfc7231#section-6
    +160       }
    +161     }
    +162     catch (IOException e)
    +163     {
    +164       LOG.error("Cannot retrieve {}: {}", uri, e.toString());
    +165     }
    +166 
    +167 
    +168     if ((data.content == null) || (data.revalidate && !serveStale))
    +169     {
    +170       data = HttpData.SERVER_ERROR;
    +171     }
    +172     else
    +173     {
    +174       // An existing resource can be considered still existent, if the
    +175       // request fails and the resource does not have to be revalidated.
    +176       // It will also be considered as still existent, if revalidation is
    +177       // enforced through the HTTP-protocol, but serving stale data is
    +178       // enabled.
    +179     }
    +180 
    +181     cache.put(uri, data);
    +182     return data;
    +183   }
    +184 
    +185 
    +186   private HttpData readCachingHeaders(
    +187       byte[] content,
    +188       ClientHttpResponse response,
    +189       HttpHeaders headers,
    +190       long request_time,
    +191       long defaultTTL
    +192       )
    +193   {
    +194     HttpHeaders responseHeaders = response.getHeaders();
    +195     // Calculating Freshness Lifetime
    +196     // See: https://tools.ietf.org/html/rfc7234#section-4.2.1
    +197 
    +198     long now = clock.millis();
    +199 
    +200     long date_value = responseHeaders.getDate();
    +201     long apparent_age = 0L;
    +202 
    +203     if (date_value < 0L)
    +204     {
    +205       // Use the current time, if no date-header is present
    +206       // See: https://tools.ietf.org/html/rfc7231#section-7.1.1.2
    +207       date_value = now;
    +208     }
    +209     else
    +210     {
    +211       apparent_age = now - date_value;
    +212       apparent_age = apparent_age < 0 ? 0 : apparent_age;
    +213     }
    +214 
    +215     long corrected_age_value = 0L;
    +216     String value = responseHeaders.getFirst(AGE);
    +217     if (value != null)
    +218     {
    +219       try
    +220       {
    +221         long response_delay = now - request_time;
    +222         long age_value = Long.parseLong(value) * 1000; // convert s to ms
    +223         age_value = age_value < 0 ? 0 : age_value;
    +224         corrected_age_value = age_value + response_delay;
    +225       }
    +226       catch (NumberFormatException e) {}
    +227     }
    +228 
    +229     long corrected_initial_age =
    +230         apparent_age > corrected_age_value
    +231             ? apparent_age
    +232             : corrected_age_value;
    +233 
    +234     long lastModified = responseHeaders.getLastModified();
    +235     lastModified = lastModified < 0L ? 0 : lastModified;
    +236 
    +237     String eTag = responseHeaders.getETag();
    +238 
    +239 
    +240     Map<String, String> directives = new HashMap<>();
    +241     for (String field : responseHeaders.getOrEmpty(CACHE_CONTROL))
    +242     {
    +243       for (String directive : field.split("\\s*,\\s*"))
    +244       {
    +245         String[] splitted = directive.split("\\s*=\\s*");
    +246         if (splitted.length > 2)
    +247         {
    +248           LOG.warn("Ingoring garbled directive: {}", directive);
    +249           continue;
    +250         }
    +251         directives.put(
    +252             splitted[0].trim(),
    +253             splitted.length == 2 ? splitted[1] : null
    +254              );
    +255       }
    +256     }
    +257 
    +258     long ttl = -1l;
    +259     try
    +260     {
    +261       String maxAge = directives.get("max-age");
    +262       if (maxAge != null)
    +263         ttl = Long.parseUnsignedLong(maxAge) *1000;
    +264     }
    +265     catch (NumberFormatException e) {}
    +266 
    +267     boolean revalidate = directives.containsKey("must-revalidate");
    +268     long expires = 0l;
    +269 
    +270     if (!directives.containsKey("no-cache") ||
    +271         directives.get("no-cache") != null
    +272         )
    +273     {
    +274       if (ttl < 0)
    +275       {
    +276         if (responseHeaders.get(EXPIRES) != null)
    +277         {
    +278           expires = responseHeaders.getExpires();
    +279           // If the "Expires"-header cannot be parsed to a valid date, it has
    +280           // to be interpreted as a time in the past.
    +281           // See: https://tools.ietf.org/html/rfc7234#section-5.3
    +282           expires = expires == -1 ? 0 : expires;
    +283           return new HttpData(content, filter(headers), revalidate, lastModified, expires, eTag);
    +284         }
    +285 
    +286         ttl = defaultTTL;
    +287       }
    +288 
    +289       expires = date_value + (minTTL > ttl && defaultTTL > 0 ? minTTL : ttl) - corrected_initial_age;
    +290       return new HttpData(content, filter(headers), revalidate, lastModified, expires, eTag);
    +291     }
    +292 
    +293     expires = minTTL == 0 || defaultTTL == 0 ? date_value : date_value + minTTL - corrected_initial_age;
    +294     return new HttpData(content, filter(headers), revalidate, lastModified, expires, eTag);
    +295   }
    +296 
    +297   private HttpHeaders filter(HttpHeaders headers)
    +298   {
    +299     HttpHeaders result = new HttpHeaders();
    +300     headers.forEach((key, value) ->
    +301     {
    +302       if (filter.test(key))
    +303         result.put(key, value);
    +304     });
    +305     return result;
    +306   }
    +307 
    +308   private ClientHttpRequest createGetRequest(URI uri)
    +309   {
    +310     try
    +311     {
    +312       ClientHttpRequest request = requestFactory.createRequest(uri, HttpMethod.GET);
    +313       request.getHeaders().set(ACCEPT_ENCODING, "gzip");
    +314       return request;
    +315     }
    +316     catch (IOException e)
    +317     {
    +318       throw new RuntimeException(e);
    +319     }
    +320   }
    +321 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceProtocolResolver.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceProtocolResolver.html new file mode 100644 index 00000000..95c452b9 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourceProtocolResolver.html @@ -0,0 +1,50 @@ + + + +HttpResourceProtocolResolver xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   import org.slf4j.Logger;
    +4   import org.slf4j.LoggerFactory;
    +5   import org.springframework.core.io.ProtocolResolver;
    +6   import org.springframework.core.io.ResourceLoader;
    +7   import org.springframework.util.Assert;
    +8   
    +9   
    +10  public class HttpResourceProtocolResolver implements ProtocolResolver
    +11  {
    +12    private final static Logger LOG =
    +13        LoggerFactory.getLogger(HttpResourceProtocolResolver.class);
    +14  
    +15  
    +16    private final HttpResources resources;
    +17  
    +18  
    +19    public HttpResourceProtocolResolver(HttpResources resources)
    +20    {
    +21      Assert.notNull(resources, "The HttpResources must not be null");
    +22      this.resources = resources;
    +23    }
    +24  
    +25  
    +26    @Override
    +27    public HttpResource resolve(String location, ResourceLoader resourceLoader)
    +28    {
    +29      if (HttpResources.isHttpResource(location))
    +30      {
    +31        LOG.debug("Loading HTTP-resource {}", location);
    +32        return resources.getResource(location);
    +33      }
    +34  
    +35      return null;
    +36    }
    +37  }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResources.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResources.html new file mode 100644 index 00000000..6d2a2b68 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResources.html @@ -0,0 +1,198 @@ + + + +HttpResources xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import org.slf4j.Logger;
    +5   import org.slf4j.LoggerFactory;
    +6   import org.springframework.core.io.Resource;
    +7   import org.springframework.util.Assert;
    +8   
    +9   import java.io.*;
    +10  import java.net.URI;
    +11  import java.net.URISyntaxException;
    +12  import java.time.Clock;
    +13  import java.util.regex.Pattern;
    +14  
    +15  
    +16  /**
    +17   *
    +18   * @author Kai Moritz
    +19   */
    +20  public class HttpResources
    +21  {
    +22    private final static Logger LOG =
    +23        LoggerFactory.getLogger(HttpResources.class);
    +24    private final static Pattern RESOURCE_PATH_PATTERN =
    +25        Pattern.compile("^http", Pattern.CASE_INSENSITIVE);
    +26    private final static URI ABSOLUTE_PATH = URI.create("/");
    +27  
    +28  
    +29    private final HttpResourceFetcher fetcher;
    +30    private final Clock clock;
    +31  
    +32  
    +33    public HttpResources(HttpResourceFetcher fetcher, Clock clock)
    +34    {
    +35      Assert.notNull(fetcher, "The HttpResourceFetcher must not be null");
    +36      Assert.notNull(clock, "The Clock must not be null");
    +37      this.fetcher = fetcher;
    +38      this.clock = clock;
    +39    }
    +40  
    +41  
    +42    /**
    +43     * @param uri the resource location (must be a valid <code>URI</code>)
    +44     * @return the corresponding Resource handle (never {@code null})
    +45     * @see {@link HttpResources#getResource(String)}
    +46     */
    +47    public HttpResource getResource(String uri)
    +48    {
    +49      return getResource(HttpResources.convert(uri));
    +50    }
    +51  
    +52    /**
    +53     * Returns the {@link HttpResource}, that represents the given {@link URI}.
    +54  	 * <p>Note that a Resource handle does not imply an existing resource;
    +55  	 * you need to invoke {@link Resource#exists} to check for existence.
    +56  	 * @param uri the resource location, represented as an {@link URI}
    +57  	 * @return the corresponding Resource handle (never {@code null})
    +58     */
    +59    public HttpResource getResource(URI uri)
    +60    {
    +61      HttpData data = fetcher.fetch(uri, HttpData.NOT_FETCHED);
    +62      return new HttpResource(this, fetcher, clock, uri, data);
    +63    }
    +64  
    +65  
    +66    public static URI convert(String url)
    +67    {
    +68      return HttpResources.normalize(URI.create(url));
    +69    }
    +70  
    +71    public static URI normalize(URI uri)
    +72    {
    +73      uri = uri.normalize();
    +74  
    +75      // An URI is opaque, if it is absolute and the scheme-specific part does
    +76      // not start with a slash. A HTTP-URL cannot be opaque in this meaning!
    +77      if (uri.isOpaque())
    +78        throw new IllegalArgumentException("An opaque URI is no valid HTTP-URL: " + uri);
    +79  
    +80      String scheme = null;
    +81      if (uri.isAbsolute())
    +82      {
    +83        // Enforce scheme "HTTP" or "HTTPS"
    +84        switch (uri.getScheme().toLowerCase())
    +85        {
    +86          case "http":
    +87            scheme = "http";
    +88            break;
    +89          case "https":
    +90            scheme = "https";
    +91            break;
    +92          default:
    +93            throw new IllegalArgumentException("Unallowed scheme: " + uri);
    +94        }
    +95      }
    +96  
    +97      String host = uri.getHost();
    +98      String path = uri.getRawPath();
    +99  
    +100     if (host == null)
    +101     {
    +102       if (scheme != null)
    +103         throw new IllegalArgumentException("Host is missing, although scheme is not empty: " + scheme);
    +104     }
    +105     else
    +106     {
    +107       host = host.toLowerCase();
    +108       path = path == null || path.isEmpty() ? "/" : path;
    +109     }
    +110 
    +111     try
    +112     {
    +113       return new URI(
    +114           scheme,
    +115           uri.getUserInfo(),
    +116           host,
    +117           uri.getPort(),
    +118           path,
    +119           uri.getQuery(),
    +120           uri.getFragment()
    +121           );
    +122     }
    +123     catch (URISyntaxException e)
    +124     {
    +125       throw new IllegalArgumentException("Invalid HTTP-URL: ", e);
    +126     }
    +127   }
    +128 
    +129   public static URI resolve(URI relative, URI uri) throws IOException
    +130   {
    +131     if (relative.getAuthority() != null)
    +132       throw new IOException("URI is not relative: " + relative);
    +133 
    +134     URI cleaned;
    +135     try
    +136     {
    +137       String path = relative.getRawPath();
    +138       int length = path == null ? -1 : path.length();
    +139       int i = 0;
    +140 
    +141       while (i < length)
    +142       {
    +143         switch (path.charAt(i))
    +144         {
    +145           case '.':
    +146           case '/':
    +147             i++;
    +148             break;
    +149           default:
    +150             length = -1;
    +151         }
    +152       }
    +153 
    +154       cleaned = i > 0
    +155               ? new URI(
    +156               null,
    +157               null,
    +158               null,
    +159               0,
    +160               i == path.length() ? null : path.substring(i),
    +161               relative.getQuery(),
    +162               relative.getFragment()
    +163       )
    +164               : relative;
    +165 
    +166       path = uri.getPath();
    +167       if (path == null || path.length() == 0)
    +168         uri = uri.resolve(ABSOLUTE_PATH);
    +169     }
    +170     catch (URISyntaxException e)
    +171     {
    +172       throw new IOException("Invalid relative path: " + relative, e);
    +173     }
    +174 
    +175     URI resolved = uri.resolve(cleaned);
    +176     LOG.trace("resolved {} as {} in context {}", relative, resolved, uri);
    +177     return resolved;
    +178   }
    +179 
    +180 
    +181   public static boolean isHttpResource(String resourcePath)
    +182   {
    +183     return RESOURCE_PATH_PATTERN.matcher(resourcePath).find();
    +184   }
    +185 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourcesAutoConfiguration.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourcesAutoConfiguration.html new file mode 100644 index 00000000..554762cf --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourcesAutoConfiguration.html @@ -0,0 +1,152 @@ + + + +HttpResourcesAutoConfiguration xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import java.time.Clock;
    +5   import org.slf4j.Logger;
    +6   import org.slf4j.LoggerFactory;
    +7   import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    +8   import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    +9   import org.springframework.boot.autoconfigure.web.ResourceProperties;
    +10  import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
    +11  import org.springframework.boot.context.properties.EnableConfigurationProperties;
    +12  import org.springframework.cache.Cache;
    +13  import org.springframework.cache.concurrent.ConcurrentMapCache;
    +14  import org.springframework.cache.support.NoOpCache;
    +15  import org.springframework.context.ApplicationContext;
    +16  import org.springframework.context.annotation.Bean;
    +17  import org.springframework.context.annotation.Configuration;
    +18  import org.springframework.core.io.DefaultResourceLoader;
    +19  import org.springframework.http.client.ClientHttpRequestFactory;
    +20  
    +21  
    +22  /**
    +23   * Automatic configuration
    +24   *
    +25   * @author Kai Moritz
    +26   */
    +27  @Configuration
    +28  @EnableConfigurationProperties(HttpResourcesProperties.class)
    +29  @AutoConfigureBefore(WebMvcAutoConfiguration.class)
    +30  public class HttpResourcesAutoConfiguration
    +31  {
    +32    private static final Logger LOG =
    +33        LoggerFactory.getLogger(HttpResourcesAutoConfiguration.class);
    +34  
    +35    public static final String CACHE_NAME = "http-resources-cache";
    +36  
    +37  
    +38    @ConditionalOnMissingBean(Clock.class)
    +39    @Bean
    +40    public Clock clock()
    +41    {
    +42      return Clock.systemDefaultZone();
    +43    }
    +44  
    +45    @ConditionalOnMissingBean(name = "sources")
    +46    @Bean
    +47    public String[] sources(ResourceProperties properties)
    +48    {
    +49      String[] sources = properties.getStaticLocations();
    +50  
    +51      if (sources.length == 0)
    +52        throw new IllegalArgumentException("At least one source must be configured!");
    +53  
    +54      boolean hasRemoteResource = false;
    +55      for (String source : sources)
    +56        hasRemoteResource |= HttpResources.isHttpResource(source);
    +57      if (!hasRemoteResource)
    +58        LOG.warn("No remote-resource in {}", sources);
    +59  
    +60      return sources;
    +61    }
    +62  
    +63  
    +64    @ConditionalOnMissingBean(HttpResourceFetcher.class)
    +65    @Bean
    +66    public HttpResourceFetcher fetcher(
    +67        ClientHttpRequestFactory requestFactory,
    +68        Clock clock,
    +69        HttpResourcesProperties properties)
    +70    {
    +71      LOG.info(
    +72          "Creating bean of type HttpResourceFetcher (default-ttl={}, min-ttl={}, serve-stale={})",
    +73          properties.defaultTTL,
    +74          properties.minTTL,
    +75          properties.serveStale);
    +76  
    +77      Cache cache;
    +78      if (properties.cache)
    +79      {
    +80        LOG.info("Enable caching for HttpResources");
    +81        cache = new ConcurrentMapCache(CACHE_NAME);
    +82      }
    +83      else
    +84      {
    +85        cache = new NoOpCache(CACHE_NAME);
    +86      }
    +87  
    +88      return new HttpResourceFetcher(
    +89          requestFactory,
    +90          cache,
    +91          clock,
    +92          properties.defaultTTL,
    +93          properties.minTTL,
    +94          properties.serveStale);
    +95    }
    +96  
    +97    @ConditionalOnMissingBean(HttpResources.class)
    +98    @Bean
    +99    public HttpResources httpResources(
    +100       HttpResourceFetcher fetcher,
    +101       Clock clock,
    +102       HttpResourcesProperties properties
    +103       )
    +104   {
    +105     LOG.info(
    +106         "Creating bean of type HttpResources (fetcher={}, cache={})",
    +107         properties.cache,
    +108         fetcher);
    +109 
    +110     HttpResources#HttpResources">HttpResources resources = new HttpResources(fetcher, clock);
    +111     return resources;
    +112   }
    +113 
    +114   @ConditionalOnMissingBean
    +115   @Bean
    +116   public HttpResourceProtocolResolver httpResourceProtocolResolver(
    +117       HttpResources resources,
    +118       HttpResourcesProperties properties,
    +119       DefaultResourceLoader resourceLoader
    +120       )
    +121   {
    +122     LOG.info("Creating and registrating a bean of type HttpResourceProtocolResolver");
    +123     HttpResourceProtocolResolver resolver =
    +124         new HttpResourceProtocolResolver(resources);
    +125     resourceLoader.addProtocolResolver(resolver);
    +126     return resolver;
    +127   }
    +128 
    +129   @ConditionalOnMissingBean
    +130   @Bean
    +131   public HttpResourceChainAwareResourceLoader httpResourceChainAwareResourceLoader(
    +132       ApplicationContext context,
    +133       String[] sources
    +134       )
    +135   {
    +136     LOG.info("Creating a bean of type HttpResourceChainAwareResourceLoader");
    +137     return new HttpResourceChainAwareResourceLoader(context, sources);
    +138   }
    +139 }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourcesProperties.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourcesProperties.html new file mode 100644 index 00000000..4cc5f870 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/HttpResourcesProperties.html @@ -0,0 +1,74 @@ + + + +HttpResourcesProperties xref + + + +
    +1   package de.juplo.httpresources;
    +2   
    +3   
    +4   import org.springframework.boot.context.properties.ConfigurationProperties;
    +5   
    +6   
    +7   
    +8   /**
    +9    *
    +10   * @author Kai Moritz
    +11   */
    +12  @ConfigurationProperties("juplo.http-resources")
    +13  public class HttpResourcesProperties
    +14  {
    +15    int defaultTTL = 6400;
    +16    int minTTL = 0;
    +17    boolean serveStale = true;
    +18    boolean cache = true;
    +19  
    +20  
    +21  
    +22    public int getDefaultTTL()
    +23    {
    +24      return defaultTTL;
    +25    }
    +26  
    +27    public void setDefaultTTL(int defaultTTL)
    +28    {
    +29      this.defaultTTL = defaultTTL;
    +30    }
    +31  
    +32    public int getMinTTL()
    +33    {
    +34      return minTTL;
    +35    }
    +36  
    +37    public void setMinTTL(int minTTL)
    +38    {
    +39      this.minTTL = minTTL;
    +40    }
    +41  
    +42    public boolean isServeStale()
    +43    {
    +44      return serveStale;
    +45    }
    +46  
    +47    public void setServeStale(boolean serveStale)
    +48    {
    +49      this.serveStale = serveStale;
    +50    }
    +51  
    +52    public boolean isCache()
    +53    {
    +54      return cache;
    +55    }
    +56  
    +57    public void setCache(boolean cache)
    +58    {
    +59      this.cache = cache;
    +60    }
    +61  }
    +
    +
    + + + diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/package-frame.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/package-frame.html new file mode 100644 index 00000000..8242ba15 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/package-frame.html @@ -0,0 +1,42 @@ + + + + + + + HttpResources 2.0.0 Reference Package de.juplo.httpresources + + + +

    de.juplo.httpresources

    + + + \ No newline at end of file diff --git a/dist/http-resources/2.0.0/xref/de/juplo/httpresources/package-summary.html b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/package-summary.html new file mode 100644 index 00000000..07424f6a --- /dev/null +++ b/dist/http-resources/2.0.0/xref/de/juplo/httpresources/package-summary.html @@ -0,0 +1,142 @@ + + + + + + + HttpResources 2.0.0 Reference Package de.juplo.httpresources + + + + +
    + + + + +
    HttpResources 2.0.0 Reference
    +
    + + +
    +

    Package de.juplo.httpresources

    +
    +
    + +
    + +
    + + + + +
    HttpResources 2.0.0 Reference
    +
    + + + + + \ No newline at end of file diff --git a/dist/http-resources/2.0.0/xref/index.html b/dist/http-resources/2.0.0/xref/index.html new file mode 100644 index 00000000..e41e9e82 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/index.html @@ -0,0 +1,75 @@ + + + + + + + HttpResources 2.0.0 Reference + + + + + + + + + + <h1>Frame Alert</h1> + <p> + You don't have frames. Go <a href="overview-summary.html">here</a> + </p> + + + diff --git a/dist/http-resources/2.0.0/xref/overview-frame.html b/dist/http-resources/2.0.0/xref/overview-frame.html new file mode 100644 index 00000000..079f14b5 --- /dev/null +++ b/dist/http-resources/2.0.0/xref/overview-frame.html @@ -0,0 +1,24 @@ + + + + + + + HttpResources 2.0.0 Reference + + + +

    HttpResources 2.0.0 Reference

    + +
    +

    Packages

    + +
    +

     

    + + + diff --git a/dist/http-resources/2.0.0/xref/overview-summary.html b/dist/http-resources/2.0.0/xref/overview-summary.html new file mode 100644 index 00000000..2be8729a --- /dev/null +++ b/dist/http-resources/2.0.0/xref/overview-summary.html @@ -0,0 +1,92 @@ + + + + + + + HttpResources 2.0.0 Reference + + + +
    + + + + +
    HttpResources 2.0.0 Reference
    +
    + + +
    +

    HttpResources 2.0.0 Reference

    +
    +
    + + + + + + + + + + + + +
    Packages 
    Package
    + de.juplo.httpresources +
    +
    + +
    + + + + +
    HttpResources 2.0.0 Reference
    +
    + + + + + \ No newline at end of file diff --git a/dist/http-resources/2.0.0/xref/stylesheet.css b/dist/http-resources/2.0.0/xref/stylesheet.css new file mode 100644 index 00000000..9e10f29e --- /dev/null +++ b/dist/http-resources/2.0.0/xref/stylesheet.css @@ -0,0 +1,626 @@ +/* Javadoc style sheet */ +/* +Overall document style +*/ + +@import url('resources/fonts/dejavu.css'); + +body { + background-color:#ffffff; + color:#353833; + font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; + font-size:14px; + margin:0; +} +a:link, a:visited { + text-decoration:none; + color:#4A6782; +} +a:hover, a:focus { + text-decoration:none; + color:#bb7a2a; +} +a:active { + text-decoration:none; + color:#4A6782; +} +a[name] { + color:#353833; +} +a[name]:hover { + text-decoration:none; + color:#353833; +} +pre { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; +} +h1 { + font-size:20px; +} +h2 { + font-size:18px; +} +h3 { + font-size:16px; + font-style:italic; +} +h4 { + font-size:13px; +} +h5 { + font-size:12px; +} +h6 { + font-size:11px; +} +ul { + list-style-type:disc; +} +code, tt { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; + margin-top:8px; + line-height:1.4em; +} +dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; +} +table tr td dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + vertical-align:top; + padding-top:4px; +} +sup { + font-size:8px; +} +/* +Document title and Copyright styles +*/ +.clear { + clear:both; + height:0px; + overflow:hidden; +} +.aboutLanguage { + float:right; + padding:0px 21px; + font-size:11px; + z-index:200; + margin-top:-9px; +} +.legalCopy { + margin-left:.5em; +} +.bar a, .bar a:link, .bar a:visited, .bar a:active { + color:#FFFFFF; + text-decoration:none; +} +.bar a:hover, .bar a:focus { + color:#bb7a2a; +} +.tab { + background-color:#0066FF; + color:#ffffff; + padding:8px; + width:5em; + font-weight:bold; +} +/* +Navigation bar styles +*/ +.bar { + background-color:#4D7A97; + color:#FFFFFF; + padding:.8em .5em .4em .8em; + height:auto;/*height:1.8em;*/ + font-size:11px; + margin:0; +} +.topNav { + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.bottomNav { + margin-top:10px; + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.subNav { + background-color:#dee3e9; + float:left; + width:100%; + overflow:hidden; + font-size:12px; +} +.subNav div { + clear:left; + float:left; + padding:0 0 5px 6px; + text-transform:uppercase; +} +ul.navList, ul.subNavList { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.navList li{ + list-style:none; + float:left; + padding: 5px 6px; + text-transform:uppercase; +} +ul.subNavList li{ + list-style:none; + float:left; +} +.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { + color:#FFFFFF; + text-decoration:none; + text-transform:uppercase; +} +.topNav a:hover, .bottomNav a:hover { + text-decoration:none; + color:#bb7a2a; + text-transform:uppercase; +} +.navBarCell1Rev { + background-color:#F8981D; + color:#253441; + margin: auto 5px; +} +.skipNav { + position:absolute; + top:auto; + left:-9999px; + overflow:hidden; +} +/* +Page header and footer styles +*/ +.header, .footer { + clear:both; + margin:0 20px; + padding:5px 0 0 0; +} +.indexHeader { + margin:10px; + position:relative; +} +.indexHeader span{ + margin-right:15px; +} +.indexHeader h1 { + font-size:13px; +} +.title { + color:#2c4557; + margin:10px 0; +} +.subTitle { + margin:5px 0 0 0; +} +.header ul { + margin:0 0 15px 0; + padding:0; +} +.footer ul { + margin:20px 0 5px 0; +} +.header ul li, .footer ul li { + list-style:none; + font-size:13px; +} +/* +Heading styles +*/ +div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList li.blockList h3 { + padding:0; + margin:15px 0; +} +ul.blockList li.blockList h2 { + padding:0px 0 20px 0; +} +/* +Page layout container styles +*/ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + clear:both; + padding:10px 20px; + position:relative; +} +.indexContainer { + margin:10px; + position:relative; + font-size:12px; +} +.indexContainer h2 { + font-size:13px; + padding:0 0 3px 0; +} +.indexContainer ul { + margin:0; + padding:0; +} +.indexContainer ul li { + list-style:none; + padding-top:2px; +} +.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { + font-size:12px; + font-weight:bold; + margin:10px 0 0 0; + color:#4E4E4E; +} +.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { + margin:5px 0 10px 0px; + font-size:14px; + font-family:'DejaVu Sans Mono',monospace; +} +.serializedFormContainer dl.nameValue dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +.serializedFormContainer dl.nameValue dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* +List styles +*/ +ul.horizontal li { + display:inline; + font-size:0.9em; +} +ul.inheritance { + margin:0; + padding:0; +} +ul.inheritance li { + display:inline; + list-style:none; +} +ul.inheritance li ul.inheritance { + margin-left:15px; + padding-left:15px; + padding-top:1px; +} +ul.blockList, ul.blockListLast { + margin:10px 0 10px 0; + padding:0; +} +ul.blockList li.blockList, ul.blockListLast li.blockList { + list-style:none; + margin-bottom:15px; + line-height:1.4; +} +ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { + padding:0px 20px 5px 10px; + border:1px solid #ededed; + background-color:#f8f8f8; +} +ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { + padding:0 0 5px 8px; + background-color:#ffffff; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { + margin-left:0; + padding-left:0; + padding-bottom:15px; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { + list-style:none; + border-bottom:none; + padding-bottom:0; +} +table tr td dl, table tr td dl dt, table tr td dl dd { + margin-top:0; + margin-bottom:1px; +} +/* +Table styles +*/ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + width:100%; + border-left:1px solid #EEE; + border-right:1px solid #EEE; + border-bottom:1px solid #EEE; +} +.overviewSummary, .memberSummary { + padding:0px; +} +.overviewSummary caption, .memberSummary caption, .typeSummary caption, +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:#253441; + font-weight:bold; + clear:none; + overflow:hidden; + padding:0px; + padding-top:10px; + padding-left:1px; + margin:0px; + white-space:pre; +} +.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, +.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, +.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, +.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, +.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { + color:#FFFFFF; +} +.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + padding-bottom:7px; + display:inline-block; + float:left; + background-color:#F8981D; + border: none; + height:16px; +} +.memberSummary caption span.activeTableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#F8981D; + height:16px; +} +.memberSummary caption span.tableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#4D7A97; + height:16px; +} +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { + padding-top:0px; + padding-left:0px; + padding-right:0px; + background-image:none; + float:none; + display:inline; +} +.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { + display:none; + width:5px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .activeTableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .tableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + background-color:#4D7A97; + float:left; + +} +.overviewSummary td, .memberSummary td, .typeSummary td, +.useSummary td, .constantsSummary td, .deprecatedSummary td { + text-align:left; + padding:0px 0px 12px 10px; +} +th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, +td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ + vertical-align:top; + padding-right:0px; + padding-top:8px; + padding-bottom:3px; +} +th.colFirst, th.colLast, th.colOne, .constantsSummary th { + background:#dee3e9; + text-align:left; + padding:8px 3px 3px 7px; +} +td.colFirst, th.colFirst { + white-space:nowrap; + font-size:13px; +} +td.colLast, th.colLast { + font-size:13px; +} +td.colOne, th.colOne { + font-size:13px; +} +.overviewSummary td.colFirst, .overviewSummary th.colFirst, +.useSummary td.colFirst, .useSummary th.colFirst, +.overviewSummary td.colOne, .overviewSummary th.colOne, +.memberSummary td.colFirst, .memberSummary th.colFirst, +.memberSummary td.colOne, .memberSummary th.colOne, +.typeSummary td.colFirst{ + width:25%; + vertical-align:top; +} +td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { + font-weight:bold; +} +.tableSubHeadingColor { + background-color:#EEEEFF; +} +.altColor { + background-color:#FFFFFF; +} +.rowColor { + background-color:#EEEEEF; +} +/* +Content styles +*/ +.description pre { + margin-top:0; +} +.deprecatedContent { + margin:0; + padding:10px 0; +} +.docSummary { + padding:0; +} + +ul.blockList ul.blockList ul.blockList li.blockList h3 { + font-style:normal; +} + +div.block { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; +} + +td.colLast div { + padding-top:0px; +} + + +td.colLast a { + padding-bottom:3px; +} +/* +Formatting effect styles +*/ +.sourceLineNo { + color:green; + padding:0 30px 0 0; +} +h1.hidden { + visibility:hidden; + overflow:hidden; + font-size:10px; +} +.block { + display:block; + margin:3px 10px 2px 0px; + color:#474747; +} +.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, +.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, +.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { + font-weight:bold; +} +.deprecationComment, .emphasizedPhrase, .interfaceName { + font-style:italic; +} + +div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +div.block div.block span.interfaceName { + font-style:normal; +} + +div.contentContainer ul.blockList li.blockList h2{ + padding-bottom:0px; +} + +/* JXR style sheet */ +a.jxr_linenumber:link { + color: #00f; +} + +a.jxr_linenumber:visited { + color: #00a; +} + +a.jxr_linenumber:active, a.jxr_linenumber:hover { + color: #f30 !important; +} + +em.comment { + color: #390; +} + +.string { + color: #009; +} + +#overview { + padding: 2px; + font-size: 90%; + font-family: Helvetica, Arial, sans-serif; +} + +hr { + color: #000; +} + +.jxr_comment +{ + color: #390; +} + +.jxr_javadoccomment +{ + color: #A00; +} + +.jxr_string +{ + color: #009; +} + +.jxr_keyword +{ + color: #000; +} +