[
  {
    "path": ".gitignore",
    "content": "/dist/\n/out/\n_site/\n/docs/javadoc/\n.idea/\n*.iml\n/artifacts\n/nbproject/private/\n/.nb-gradle\nbuild/\n.DS_Store\n.gradle/\n.nb-gradle-properties\n.bdb/\ntomcat.8080\n**/.lein*\n**/target\n/comsat-ring-jetty9/pom.xml\n/comsat-ring-jetty9/pom.xml.asc\n/comsat-httpkit/pom.xml\n/comsat-httpkit/pom.xml.asc\n.project\n.classpath\n.settings/\nbin/\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: java\ninstall: gradle -q assemble\nscript: set -o pipefail; gradle check | sed 's/\\e\\[?.*?[\\@-~]//g'\njdk:\n  - oraclejdk7\n  - oraclejdk8\nbranches:\n  except:\n    - gh-pages\nenv:\n  global:\n    - secure: \"I8awdba2QYgO+vKmbsIa10L7dGPpcvt/l0sfE+NH2On4ZtBFuX7X4tFncmWizHhrqa0xvoAEl8hZFZ6+RjbAOzd9kDLfdHevLVv6z8VQusvY58GbAHPP0h4yd4PA0YsSeiLv1F7X7bCH6weZo16t42lVh4NrAS2XHqSOOvMyAWo=\"\n    - DOCS_BRANCH=\"release\"\n    - GEN_APIDOCS=\"gradle javadoc\"\n\nafter_success:\n  - chmod a+x travis/build_clj.sh\n  - ./travis/build_clj.sh\n  - chmod a+x travis/post_build.sh\n  - ./travis/post_build.sh\n  \nnotifications:\n  slack: puniverse:OsnbakHrYeTcLyalVgtUeI4F\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "We are happy to receive contributions from the developer community to this free software project. If you make a non-trivial contribution and wish it merged into this project's main repository, you must first agree to and sign this [Contributor's Agreement](https://docs.google.com/a/paralleluniverse.co/forms/d/1U5GinUnRsYbvAP5W3-o11wmRkMmicD_WgRDS6Sy30HA/viewform). We appreciate your effort to making this free software better.\n\nIf you create a new GitHub Pull Request, please base bugfix changes upon the `release` branch and any other change (improvements, features etc.) upon the `master` branch.\n"
  },
  {
    "path": "LICENSE",
    "content": "COMSAT\nCopyright (C) ${year}, Parallel Universe Software Co. All rights reserved.\n\nThis program and the accompanying materials are dual-licensed under\neither the terms of the Eclipse Public License v1.0 as published by\nthe Eclipse Foundation\n \n  or (per the licensee's choosing)\n \nunder the terms of the GNU Lesser General Public License version 3.0\nas published by the Free Software Foundation."
  },
  {
    "path": "NOTICE",
    "content": "This product contains modified source code from Tomcat Library, by the Apache Software Foundation:\n\n    Copyright (c) 1999-2013 The Apache Software Foundation\n    * LICENSE: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)\n    * HOMEPAGE: http://tomcat.apache.org/\n\nThis product contains modified source code from Spring Framework:\n\n    Copyright (c) 1999-2014 The original autors\n    * LICENSE: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)\n    * HOMEPAGE: http://projects.spring.io/spring-framework/\n\nThis product contains modified source code from Spring Boot:\n\n    Copyright (c) 1999-2014 The original autors\n    * LICENSE: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)\n    * HOMEPAGE: http://projects.spring.io/spring-boot/\n\nThis product contains modified source code from Ring, by the original Authors (https://github.com/ring-clojure/ring/blob/master/CONTRIBUTORS.md)\n\n    Copyright (c) 1999-2014 The original Authors\n    * LICENSE: MIT (http://opensource.org/licenses/MIT)\n    * HOMEPAGE: https://github.com/ring-clojure/ring\n\nThis product contains modified source code from OkHttp by Square, Inc.:\n\n    Copyright (c) 1999-2014 Square, Inc.\n    * LICENSE: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)\n    * HOMEPAGE: https://github.com/square/okhttp\n\nThis product contains modified source code from The Android Open Source Project:\n\n    Copyright (C) 2011 The Android Open Source Project\n    * LICENSE: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)\n    * HOMEPAGE: https://source.android.com/\n\nThis product contains modified source code from HTTP Kit:\n\n    Copyright (C) 2012-2013 Feng Shen\n    * LICENSE: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)\n    * HOMEPAGE: http://www.http-kit.org/\n\nThis product contains modified source code from Undertow:\n\n    JBoss, Home of Professional Open Source. Copyright (C) 2014 Red Hat, Inc., and individual contributors as indicated by the @author tags\n    * LICENSE: Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)\n    * HOMEPAGE: http://undertow.io/\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# *COMSAT*<br/>Scalable, Concurrent Web Apps\n[![Build Status](http://img.shields.io/travis/puniverse/comsat.svg?style=flat)](https://travis-ci.org/puniverse/comsat) [![Dependency Status](https://www.versioneye.com/user/projects/52dfc913ec1375318800039f/badge.png?style=flat)](https://www.versioneye.com/user/projects/52dfc913ec1375318800039f) [![Version](http://img.shields.io/badge/version-0.7.0-blue.svg?style=flat)](https://github.com/puniverse/comsat/releases) [![License](http://img.shields.io/badge/license-EPL-blue.svg?style=flat)](https://www.eclipse.org/legal/epl-v10.html) [![License](http://img.shields.io/badge/license-LGPL-blue.svg?style=flat)](https://www.gnu.org/licenses/lgpl.html)\n\n## Getting started\n\nAdd the following Maven/Gradle dependencies:\n\n| Feature                                                                                                                   | Artifact\n|---------------------------------------------------------------------------------------------------------------------------|--------------------------\n| Servlet integration for defining fiber-per-request servlets.                                                              | `co.paralleluniverse:comsat-servlet:0.7.0`\n| A fiber-blocking Clojure [Ring](https://github.com/ring-clojure/ring) adapter based on Jetty 9.3.                         | `co.paralleluniverse:comsat-ring-jetty9:0.7.0`\n| [HTTP Kit](http://www.http-kit.org/client.html)-based fiber-blocking HTTP client.                                         | `co.paralleluniverse:comsat-httpkit:0.7.0`\n| [Jersey server](https://jersey.java.net/) integration for defining REST services.                                         | `co.paralleluniverse:comsat-jersey-server:0.7.0`\n| [Dropwizard](http://dropwizard.io/) integration including Jersey, ApacheHttpClient and JDBI.                              | `co.paralleluniverse:comsat-dropwizard:0.7.0`\n| [Spring Framework](http://projects.spring.io/spring-framework/) Web MVC fiber-blocking controller methods integration.    | `co.paralleluniverse:comsat-spring-webmvc:0.7.0`\n| [Spring Boot](http://projects.spring.io/spring-boot/) auto-configuration support for Web MVC controllers.                 | `co.paralleluniverse:comsat-spring-boot:0.7.0`\n| [Spring Security](http://projects.spring.io/spring-security/) configuration support for fibers.                           | `co.paralleluniverse:comsat-spring-security:0.7.0`\n| [JAX-RS client](https://jersey.java.net/documentation/latest/client.html) integration for HTTP calls with fibers.         | `co.paralleluniverse:comsat-jax-rs-client:0.7.0`\n| [ApacheHttpClient](http://hc.apache.org/httpcomponents-client-ga/) integration for HTTP calls with fibers.                | `co.paralleluniverse:comsat-httpclient:0.7.0`\n| [Retrofit](http://square.github.io/retrofit/) integration with fibers.                                                    | `co.paralleluniverse:comsat-retrofit:0.7.0`\n| [JDBI](http://jdbi.org/) integration with fibers.                                                                         | `co.paralleluniverse:comsat-jdbi:0.7.0`\n| JDBC integration with fibers.                                                                                             | `co.paralleluniverse:comsat-jdbc:0.7.0`\n| [jOOQ](http://www.jooq.org/) integration with fibers.                                                                     | `co.paralleluniverse:comsat-jooq:0.7.0`\n| MongoDB fiber-blocking integration for the [Allanbank API](http://www.allanbank.com/mongodb-async-driver/index.html).     | `co.paralleluniverse:comsat-mongodb-allanbank:0.7.0`\n| [OkHttp](https://github.com/square/okhttp) HTTP+SPDY client integration.                                                  | `co.paralleluniverse:comsat-okhttp:0.7.0`\n| The Web Actors API.                                                                                                       | `co.paralleluniverse:comsat-actors-api:0.7.0`\n| Deploy HTTP, SSE and WebSocket Web Actors as [Undertow](http://undertow.io/) handlers.                                    | `co.paralleluniverse:comsat-actors-undertow:0.7.0`\n| Deploy HTTP, SSE and WebSocket Web Actors as [Netty](http://netty.io/) handlers.                                          | `co.paralleluniverse:comsat-actors-netty:0.7.0`\n| Deploy HTTP, SSE and WebSocket Web Actors in J2EE 7 Servlet and WebSocket (JSR-356) embedded and standalone containers.   | `co.paralleluniverse:comsat-actors-servlet:0.7.0`\n| Use Comsat in the Tomcat servlet container without the java agent.                                                        | `co.paralleluniverse:comsat-tomcat-loader:0.7.0[:jdk8]` (for JDK 8 optionally add the `jdk8` classifier)\n| Use Comsat in the Jetty servlet container without the java agent.                                                         | `co.paralleluniverse:comsat-jetty-loader:0.7.0[:jdk8]` (for JDK 8 optionally add the `jdk8` classifier)\n| [Spring Framework](http://projects.spring.io/spring-framework/) Web integration allows using fiber-blocking controllers.  | `co.paralleluniverse:comsat-spring-web:0.7.0`\n| [Apache Kafka](http://kafka.apache.org/) producer integration module.                                                     | `co.paralleluniverse:comsat-kafka:0.7.0`\n| [Apache Shiro](http://shiro.apache.org/) realms integration module.                                                       | `co.paralleluniverse:comsat-shiro:0.7.0`\n\nOr, build and install from sources (after installing [Gradle](http://www.gradle.org) locally) in your local maven repository with:\n\n```\ngradle install\n```\n\nThe full testsuite can be run with `gradle build`.\n\n## Usage\n\n* [Documentation](http://docs.paralleluniverse.co/comsat/)\n* [Javadoc](http://docs.paralleluniverse.co/comsat/javadoc)\n\nA [Gradle template](https://github.com/puniverse/comsat-gradle-template) project and a [Maven archetype](https://github.com/puniverse/comsat-mvn-archetype) using various integration modules and featuring setup with both Dropwizard and standalone Tomcat are also available for jumpstart and study. Both have a `without-comsat` branch which is useful to clearly see the (minimal, if any) porting effort required (branches comparison works very well for this purporse).\n\nThere's a [Comsat-Ring Clojure Leiningen template](https://github.com/puniverse/comsat-ring-template) as well which includes an `auto-instrument` branch that doesn't need any explicit suspendable-marking code (`suspendable!`, `defsfn`, `sfn` etc.) thanks to [Pulsar's new auto-instrumentation feature](http://docs.paralleluniverse.co/pulsar/#automatic-instrumentation).\n\nYou can also have a look at [additional examples](https://github.com/puniverse/comsat-examples).\n\nFinally there are several regularly updated third-party bootstrap projects: [Comsat + Dropwizard + jOOQ](https://github.com/circlespainter/comsat-jooq-gradle-template), [Comsat Web Actors Stock Quotes (ported from Akka)](https://github.com/circlespainter/quasar-stocks), [Spring MVC + Tomcat standalone servlet container](https://github.com/circlespainter/spring4-mvc-gradle-annotation-hello-world).\n\n## Getting help\n\nQuestions and suggestions are welcome at this [forum/mailing list](https://groups.google.com/forum/#!forum/comsat-user).\n\n## Contributions (including Pull Requests)\n\nPlease have a look at some brief [information for contributors](https://github.com/puniverse/comsat/blob/master/CONTRIBUTING.md).\n\n## License\n\nCOMSAT is free software published under the following license:\n\n```\nCopyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n\nThis program and the accompanying materials are dual-licensed under\neither the terms of the Eclipse Public License v1.0 as published by\nthe Eclipse Foundation\n\n  or (per the licensee's choosing)\n\nunder the terms of the GNU Lesser General Public License version 3.0\nas published by the Free Software Foundation.\n```\n"
  },
  {
    "path": "build.gradle",
    "content": "allprojects {\n    configurations {\n        markdownDoclet\n    }\n\n    repositories {\n//        mavenLocal()\n        mavenCentral()\n    }\n\n    dependencies {\n        markdownDoclet \"ch.raffael.pegdown-doclet:pegdown-doclet:1.1.1\"\n    }\n}\n\nsubprojects {\n    apply plugin: 'java'\n\n    sourceCompatibility = '1.7'\n    targetCompatibility = '1.7'\n\n    [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'\n\n    group               = \"co.paralleluniverse\"\n    version             = \"0.7.1-SNAPSHOT\"\n    status              = \"integration\"\n    description         = \"Fibers services for web\"\n\n    ext.url             = \"http://puniverse.github.com/comsat\"\n    ext.vendor          = \"Parallel Universe Software Co.\"\n    ext.licenseName1    = \"The GNU Lesser General Public License, version 3\"\n    ext.licenseUrl1     = \"http://www.gnu.org/licenses/lgpl-3.0.txt\"\n    ext.licenseName2    = \"Eclipse Public License - v 1.0\"\n    ext.licenseUrl2     = \"http://www.eclipse.org/legal/epl-v10.html\"\n    ext.scmUrl          = \"https://github.com/puniverse/comsat\"\n    ext.scmConnection   = \"https://github.com/puniverse/comsat.git\"\n\n    ext.distDir         = \"$buildDir/dist\"\n\n    ext.isRelease       = !version.endsWith(\"SNAPSHOT\")\n\n    ext.java8 = System.properties['java.version'].startsWith('1.8')\n\n    ext.metricsVer      = '3.1.2'\n    ext.asmVer          = '5.0.4'\n\n    ext.quasarVer       = '0.7.6'\n\n    ext.jettyVer        = '9.2.14.v20151106' // '9.3.x' requires JDK8\n    ext.tomcatVer       = '8.0.33'\n    ext.undertowVer     = '1.3.19.Final'\n    ext.nettyVer        = '4.0.36.Final'\n\n    ext.osgiVer         = '6.0.0'\n    ext.jerseyVer       = '2.22.2'\n    ext.hk2apiVer       = '2.4.0'\n    ext.jerseyJettyVer  = '9.1.1.v20140108'\n\n    ext.servletVer      = '3.0.1'\n    ext.jaxrsVer        = '2.0.1'\n    ext.websocketApiVer = '1.0'\n\n    ext.dropwizardVer   = '0.9.2'\n    ext.jdbiVer         = '2.72'\n\n    ext.retrofitVer     = '1.9.0'\n    ext.jooqVer         = '3.6.4' // 3jooq.7.x support only Java 8+\n    ext.slf4jApiVer     = '1.7.21'\n    ext.log4jVer        = '1.2.17'\n    ext.guavaVer        = '19.0'\n\n    ext.okhttpVer       = '2.6.0' // TODO Upgrade to 3.2.x\n\n    ext.apacheAsyncClientVer   = '4.1.1'\n    ext.httpCoreVer            = '4.4.4'\n    ext.httpClientVer          = '4.5.2'\n\n    ext.junitVer               = '4.12'\n    ext.h2Ver                  = '1.4.191'\n\n    ext.mongodbJavaAsyncDriverVer       = '2.0.1'\n    ext.embedMongoVer                   = '1.47.0' // TODO Upgrade and troubleshoot\n\n    // ext.bytemanVer = '3.0.1'\n\n    // Spring projects\n    ext.springSecurityVer               = '4.0.4.RELEASE'\n    ext.springVer                       = '4.2.5.RELEASE'\n    ext.springBootVer                   = '1.3.3.RELEASE' // TODO Port testsuite diffs\n\n    ext.commonsLoggingVer               = '1.2'\n    ext.commonsBeanUtilsVer             = '1.9.2'\n    ext.commonsDigesterVer              = '2.1'\n    ext.commonsCollectionsVer           = '3.2.2'\n    ext.velocityVer                     = '1.7'\n    ext.hamcrestVer                     = '1.3'\n    ext.jqueryVer                       = '2.1.4'\n    ext.snakeYamlVer                    = '1.16'\n    ext.javaxELVer                      = '3.0.1-b05'\n    ext.hibernateValidatorVer           = '5.2.2.Final'\n    ext.jbossLoggingVer                 = '3.2.1.Final'\n\n    ext.jstlVer                         = '1.2'\n    ext.jolokiaVer                      = '1.3.2'\n    ext.hsqlVer                         = '2.3.3'\n    ext.bootstrapVer                    = '3.3.5'\n    ext.hibernateVer                    = '4.3.11.Final'\n\n    ext.kafkaClientsVer                 = '0.9.0.0' // ''0.8.2.2'\n    ext.shiroVer                        = '1.2.4'\n\n    configurations.all {\n        resolutionStrategy {\n            failOnVersionConflict()\n\n            force \"org.jdbi:jdbi:$jdbiVer\"\n            force \"org.ow2.asm:asm:$asmVer\"\n            force \"org.ow2.asm:asm-commons:$asmVer\"\n            force \"io.dropwizard.metrics:metrics-core:$metricsVer\"\n            force \"com.google.guava:guava:$guavaVer\"\n            force \"org.slf4j:slf4j-api:$slf4jApiVer\"\n            force \"org.apache.httpcomponents:httpcore:$httpCoreVer\"\n            force \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n            force \"javax.servlet:javax.servlet-api:$servletVer\"\n            force \"javax.ws.rs:javax.ws.rs-api:$jaxrsVer\"\n            force \"org.glassfish.jersey.core:jersey-server:$jerseyVer\"\n            force \"org.glassfish.jersey.core:jersey-client:$jerseyVer\"\n            force \"org.glassfish.jersey.core:jersey-common:$jerseyVer\"\n            force \"org.glassfish.jersey.containers:jersey-container-servlet-core:$jerseyVer\"\n            force \"org.glassfish.hk2:hk2-api:$hk2apiVer\"\n            force \"org.glassfish.hk2:hk2-locator:$hk2apiVer\"\n            force \"org.glassfish.hk2.external:javax.inject:$hk2apiVer\"\n\n            // Spring projects, moving here since changing conf. in subprojects has been deprecated in Gradle 2.5\n            force \"org.springframework:spring-aop:$springVer\"\n            force \"org.springframework:spring-beans:$springVer\"\n            force \"org.springframework:spring-context:$springVer\"\n            force \"org.springframework:spring-core:$springVer\"\n            force \"org.springframework:spring-expression:$springVer\"\n            force \"org.springframework:spring-web:$springVer\"\n            force \"org.springframework:spring-webmvc:$springVer\"\n            force \"org.springframework:spring-orm:$springVer\"\n            force \"org.springframework:spring-jdbc:$springVer\"\n            force \"org.springframework:spring-tx:$springVer\"\n            force \"org.springframework.security:spring-security-config:$springSecurityVer\"\n            force \"org.springframework.security:spring-security-web:$springSecurityVer\"\n            force \"org.webjars:jquery:$jqueryVer\"\n            force \"commons-beanutils:commons-beanutils:$commonsBeanUtilsVer\"\n            force \"commons-digester:commons-digester:$commonsDigesterVer\"\n            force \"commons-collections:commons-collections:$commonsCollectionsVer\"\n            force \"org.jboss.logging:jboss-logging:$jbossLoggingVer\"\n            force \"org.apache.velocity:velocity:$velocityVer\"\n            force \"org.hamcrest:hamcrest-core:$hamcrestVer\"\n\n            force \"org.glassfish:javax.el:$javaxELVer\"\n            force \"org.apache.tomcat.embed:tomcat-embed-core:$tomcatVer\"\n            force \"org.apache.tomcat.embed:tomcat-embed-el:$tomcatVer\"\n            force \"org.hibernate:hibernate-validator:$hibernateValidatorVer\"\n\n            force \"org.slf4j:jcl-over-slf4j:$slf4jApiVer\"\n\n            force \"junit:junit:$junitVer\"\n        }\n    }\n\n    if (!project.hasProperty(\"sonatypeUsername\") || !project.hasProperty(\"sonatypePassword\")) {\n        //        println \"sonatype username or password not set\"\n        ext.sonatypeUsername = \"\"\n        ext.sonatypePassword = \"\"\n    }\n    if (!project.hasProperty('mainClass')) { // must use project.hasProperty() rather than hasProperty in subprojects (gradle bug)\n        ext.mainClass = ''\n    }\n\n    repositories {\n        mavenLocal()\n        mavenCentral()\n        maven { url \"https://oss.sonatype.org/content/repositories/releases\" }\n        maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }\n        maven { url 'https://maven.java.net/content/repositories/snapshots' }\n        maven { url 'http://www.allanbank.com/repo/' }\n        maven { url 'http://repo.springsource.org/libs-milestone' }\n    }\n\n    configurations {\n        quasar\n        // byteman\n        provided\n        srcFiles\n    }\n\n    dependencies {\n        compile \"com.google.guava:guava:$guavaVer\"\n        quasar \"co.paralleluniverse:quasar-core:$quasarVer@jar\"\n        // byteman \"org.jboss.byteman:byteman:$bytemanVer@jar\"\n        testCompile \"junit:junit:$junitVer\"\n        provided \"co.paralleluniverse:quasar-core:$quasarVer\"\n        provided \"javax.servlet:javax.servlet-api:$servletVer\" // was 3.1.0\n    }\n\n    sourceSets {\n        main.compileClasspath = main.compileClasspath + configurations.provided\n        test.compileClasspath = test.compileClasspath + configurations.provided\n        test.runtimeClasspath = test.runtimeClasspath + configurations.provided\n    }\n\n    defaultTasks 'install'\n\n    classes {\n        doFirst{\n            println \"Executing scanSuspendables...\"\n            ant.taskdef(\n                name:'scanSuspendables', classname:'co.paralleluniverse.fibers.instrument.SuspendablesScanner',\n                classpath: \"build/classes/main:build/resources/main:${configurations.provided.asPath}:${configurations.runtime.asPath}\")\n            ant.scanSuspendables(\n                auto:false,\n                suspendablesFile: \"$sourceSets.main.output.resourcesDir/META-INF/suspendables\",\n                supersFile: \"$sourceSets.main.output.resourcesDir/META-INF/suspendable-supers\",\n                append: true) {\n                fileset(dir: sourceSets.main.output.classesDir)\n            }\n\n            //            ant.taskdef(name:'scanSuspendables',\n            //                classname:'co.paralleluniverse.fibers.instrument.OldSuspendablesScanner',\n            //                classpath: \"build/classes/main:${configurations.provided.asPath}:${configurations.runtime.asPath}\")\n            //            ant.scanSuspendables(outputFile:\"$sourceSets.main.output.resourcesDir/META-INF/suspendable-supers\",\n            //                suspendablesFile: \"$sourceSets.main.output.resourcesDir/META-INF/suspendables\"\n            //            ) {\n            //                fileset(dir: sourceSets.main.output.classesDir)\n            //            }\n        }\n    }\n\n    tasks.withType(Test) {\n        // systemProperty 'co.paralleluniverse.fibers.verifyInstrumentation', 'true'\n        // systemProperty 'co.paralleluniverse.fibers.detectRunawayFibers', 'false'\n        // systemProperty 'org.jboss.byteman.verbose', 'true'\n        // systemProperty 'org.jboss.byteman.debug', 'true'\n        jvmArgs \"-javaagent:${configurations.quasar.singleFile}\" // =v, =d, =c\n                // , \"-javaagent:${configurations.byteman.singleFile}=script:${projectDir}/script.btm\"\n    }\n\n    test {\n        beforeTest { desc ->\n            logger.quiet(\"Running test: \" + desc)\n        }\n\n        afterTest { desc, result ->\n            if(result.resultType == TestResult.ResultType.FAILURE) {\n                logger.quiet(\"Failed test ${desc.name} [${desc.className}] with exception: ${result.exception}\")\n                if(result.exception != null) {\n                    result.exception.printStackTrace()\n                }\n            }\n        }\n    }\n\n    task sourcesJar(type: Jar, dependsOn: classes) {\n        classifier = 'sources'\n        from sourceSets.main.allSource\n    }\n    // Adds license header on each java file. gradle licenseMain for check or licenseFormatMain to apply\n    apply plugin: 'license'\n    license {\n        ignoreFailures true\n        header rootProject.file('LICENSE')\n        ext.year = Calendar.getInstance().get(Calendar.YEAR)\n        strictCheck true\n        skipExistingHeaders true\n        mapping('java','SLASHSTAR_STYLE')\n    }\n\n    apply plugin: 'com.github.ben-manes.versions'\n\n    //rest of the subprojects definition in the block after subproject specific definitions\n}\n\n// Per subproject Defintions\nproject (':comsat-actors-api') {\n    dependencies {\n        compile \"co.paralleluniverse:quasar-actors:$quasarVer\"\n    }\n}\n\nproject (':comsat-actors-netty') {\n    dependencies {\n        compile \"io.netty:netty-all:$nettyVer\"\n\n        compile project (':comsat-actors-api')\n\n        provided \"co.paralleluniverse:quasar-core:$quasarVer\"\n\n        testCompile \"javax.websocket:javax.websocket-api:$websocketApiVer\"\n        testCompile project(':comsat-test-utils')\n    }\n}\n\nproject (':comsat-actors-servlet') {\n    dependencies {\n        compile project (':comsat-actors-api')\n\n        provided \"javax.websocket:javax.websocket-api:$websocketApiVer\"\n        provided \"javax.servlet:javax.servlet-api:$servletVer\" // was 3.1.0\n\n        provided \"co.paralleluniverse:quasar-core:$quasarVer\"\n\n        testCompile project(':comsat-test-utils')\n//        testRuntime \"ch.qos.logback:logback-classic:1.1.3\" // Exceeds Travis limit\n    }\n}\n\nproject (':comsat-actors-undertow') {\n    dependencies {\n        compile \"io.undertow:undertow-core:$undertowVer\"\n\n        compile project (':comsat-actors-api')\n\n        provided \"co.paralleluniverse:quasar-core:$quasarVer\"\n\n        testCompile \"javax.websocket:javax.websocket-api:$websocketApiVer\"\n        testCompile project(':comsat-test-utils')\n    }\n}\n\nproject (':comsat-dropwizard') {\n    dependencies {\n        testRuntime \"com.h2database:h2:$h2Ver\"\n        compile \"io.dropwizard:dropwizard-core:$dropwizardVer\"\n        compile \"io.dropwizard:dropwizard-client:$dropwizardVer\"\n        compile \"io.dropwizard:dropwizard-jdbi:$dropwizardVer\"\n        compile project(\":comsat-servlet\")\n        compile (project(\":comsat-httpclient\")) {\n            exclude group: 'org.apache.httpcomponents', module: 'httpclient'\n        }\n        compile project(\":comsat-jdbi\")\n        provided \"co.paralleluniverse:quasar-core:$quasarVer\"\n    }\n}\n\nproject (':comsat-httpclient') {\n    dependencies {\n        compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n        compile (\"org.apache.httpcomponents:httpasyncclient:$apacheAsyncClientVer\") {\n            exclude group: 'org.apache.httpcomponents', module: 'httpclient'\n        }\n        testCompile project(':comsat-test-utils')\n    }\n}\n\nproject (':comsat-jax-rs-client') {\n    dependencies {\n        compile \"javax.ws.rs:javax.ws.rs-api:$jaxrsVer\"\n        compile \"org.glassfish.jersey.core:jersey-client:$jerseyVer\"\n        compile \"org.glassfish.jersey.connectors:jersey-jetty-connector:$jerseyVer\"\n        testCompile (project(':comsat-test-utils')) {\n            exclude group: 'org.eclipse.jetty', module: '*'\n        }\n        testRuntime \"org.eclipse.jetty:jetty-server:$jerseyJettyVer\"\n        testRuntime \"org.eclipse.jetty:jetty-servlet:$jerseyJettyVer\"\n    }\n}\n\nproject (':comsat-jdbc') {\n    dependencies {\n        testCompile project(':comsat-test-utils')\n    }\n\n    // AOT instrumentation in order to support jdbc in container\n    compileJava {\n        doLast {\n            println(\"Instrumenting classes...\")\n            ant.taskdef(name:'instrumentation',\n                classname:'co.paralleluniverse.fibers.instrument.InstrumentationTask',\n                classpath: \"build/classes/main:${configurations.provided.asPath}:${configurations.compile.asPath}\")\n            ant.instrumentation(verbose:'true', check:'true', debug:'true') {\n                fileset(dir: sourceSets.main.output.classesDir) {\n                    exclude(name: 'co/paralleluniverse/fibers/instrument/*.class')\n                }\n            }\n        }\n    }\n}\n\nproject (':comsat-jdbi') {\n    dependencies {\n        compile \"org.jdbi:jdbi:$jdbiVer\"\n        compile project (':comsat-jdbc')\n        testCompile project(':comsat-test-utils')\n    }\n}\n\nproject (':comsat-jersey-server') {\n    dependencies {\n        compile project(':comsat-servlet')\n        compile 'org.sonatype.sisu.inject:cglib:3.1.1' // instead of old cglib in jersey\n        compile (\"org.glassfish.jersey.containers:jersey-container-servlet:$jerseyVer\") {\n            exclude group: 'org.glassfish.hk2.external', module: 'cglib'\n        }\n        provided \"org.osgi:org.osgi.core:$osgiVer\"\n        testCompile project(':comsat-test-utils')\n    }\n}\n\nproject (':comsat-jooq') {\n    dependencies {\n        compile \"org.jooq:jooq:$jooqVer\"\n        compile project (':comsat-jdbc')\n        testCompile project(':comsat-test-utils')\n    }\n}\n\nproject (':comsat-mongodb-allanbank') {\n    dependencies {\n        compile \"com.allanbank:mongodb-async-driver:$mongodbJavaAsyncDriverVer\"\n        testCompile \"de.flapdoodle.embed:de.flapdoodle.embed.mongo:$embedMongoVer\"\n        testCompile project(':comsat-test-utils')\n    }\n}\n\nproject (':comsat-okhttp') {\n    dependencies {\n        compile \"com.squareup.okhttp:okhttp:$okhttpVer\"\n        compile \"com.squareup.okhttp:okhttp-urlconnection:$okhttpVer\"\n        compile \"com.squareup.okhttp:okhttp-apache:$okhttpVer\"\n        compile project (':comsat-httpclient')\n        testCompile \"com.squareup.okhttp:mockwebserver:$okhttpVer\"\n    }\n}\n\nproject (':comsat-kafka') {\n    dependencies {\n        compile \"org.apache.kafka:kafka-clients:$kafkaClientsVer\"\n    }\n}\n\nproject (':comsat-shiro') {\n    dependencies {\n        compile \"org.apache.shiro:shiro-core:$shiroVer\"\n        testCompile \"co.paralleluniverse:quasar-core:$quasarVer\"\n        testCompile \"commons-logging:commons-logging:$commonsLoggingVer\"\n    }\n}\n\nproject (':comsat-retrofit') {\n    dependencies {\n        compile \"com.squareup.retrofit:retrofit:$retrofitVer\"\n        compile project (':comsat-httpclient')\n        compile project (':comsat-okhttp')\n        testCompile (project (':comsat-dropwizard')) {\n            exclude group: 'org.jboss.logging', module: 'jboss-logging'\n            exclude group: 'org.apache.httpcomponents', module: 'httpclient'\n        }\n        testCompile (project(':comsat-test-utils')) {\n            exclude group: 'org.eclipse.jetty', module: '*'\n            exclude group: 'org.apache.httpcomponents', module: 'httpclient'\n            exclude group: 'org.apache.tomcat', module: 'tomcat-juli'\n            //            exclude group: 'org.apache.tomcat', module: 'tomcat-dbcp'\n        }\n    }\n}\n\nproject (':comsat-servlet') { // TODO Check seemingly harmless exceptions during tests\n    dependencies {\n        testRuntime \"ch.qos.logback:logback-classic:1.1.3\"\n        testCompile project(':comsat-test-utils')\n    }\n}\n\nproject (':comsat-test-utils') {\n    dependencies {\n        compile \"org.slf4j:slf4j-api:$slf4jApiVer\"\n        compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n        compile \"com.h2database:h2:$h2Ver\"\n        compile \"org.glassfish.jersey.core:jersey-client:$jerseyVer\"\n        compile \"org.glassfish.jersey.media:jersey-media-sse:$jerseyVer\"\n\n        compile \"org.eclipse.jetty:jetty-server:$jettyVer\"\n        compile \"org.eclipse.jetty:jetty-servlet:$jettyVer\"\n        compile \"org.eclipse.jetty.websocket:javax-websocket-server-impl:$jettyVer\"\n        compile \"org.eclipse.jetty.websocket:javax-websocket-client-impl:$jettyVer\"\n        compile \"org.eclipse.jetty:jetty-annotations:$jettyVer\"\n        compile \"org.eclipse.jetty:jetty-deploy:$jettyVer\"\n\n        compile \"io.undertow:undertow-core:$undertowVer\"\n        compile \"io.undertow:undertow-servlet:$undertowVer\"\n        compile \"io.undertow:undertow-websockets-jsr:$undertowVer\"\n\n        compile \"org.apache.tomcat.embed:tomcat-embed-core:$tomcatVer\"\n        compile \"org.apache.tomcat.embed:tomcat-embed-websocket:$tomcatVer\"\n\n        compile \"junit:junit:$junitVer\"\n\n        provided \"co.paralleluniverse:quasar-core:$quasarVer\"\n        provided \"co.paralleluniverse:quasar-actors:$quasarVer\"\n        provided project (':comsat-actors-api')\n\n        runtime \"org.apache.tomcat.embed:tomcat-embed-logging-log4j:$tomcatVer\"\n        runtime \"org.apache.tomcat:tomcat-dbcp:$tomcatVer\"\n    }\n}\n\n// Can't be done in separate files since srcFiles configuration is resolved by the root javadoc task\nproject (':comsat-servlet') {\n    dependencies {\n        srcFiles \"javax.servlet:javax.servlet-api:$servletVer:sources\"\n    }\n}\n\nproject (':comsat-httpclient') {\n    dependencies {\n        srcFiles (\"org.apache.httpcomponents:httpasyncclient:$apacheAsyncClientVer:sources\") {\n            exclude group: 'org.apache.httpcomponents', module: 'httpclient'\n        }\n        srcFiles \"org.apache.httpcomponents:httpclient:$httpClientVer:sources\"\n        // srcFiles \"org.apache.httpcomponents:httpcore:$httpCoreVer:sources\"\n    }\n}\n\n/* project (':comsat-mongodb') {\ndependencies {\nsrcFiles \"com.allanbank:mongodb-async-driver:$mongodbJavaAsyncDriverVer:sources\"\n}\n} */\n\n// links are needed for javadoc external links. (eg. instead of javax.sql.DataSource link to DataSource)\next.javadocLinks =  [\n                \"http://docs.oracle.com/javaee/7/api/\",\n                \"http://hc.apache.org/httpcomponents-client-4.5.x/httpclient/apidocs/\",\n                \"http://hc.apache.org/httpcomponents-asyncclient-4.1.x/httpasyncclient/apidocs/\",\n                \"http://hc.apache.org/httpcomponents-core-4.4.x/httpcore/apidocs/\",\n                \"http://square.github.io/retrofit/1.x/retrofit/\",\n                \"http://jdbi.org/apidocs/\",\n                \"http://www.jooq.org/javadoc/3.6.x/\",\n                \"http://docs.oracle.com/javase/7/docs/api/\",\n                \"http://puniverse.github.io/quasar/javadoc/\",\n                \"http://google.github.io/guava/releases/19.0/api/docs/\",\n                \"http://jersey.java.net/apidocs/latest/jersey/\",\n                \"http://www.allanbank.com/mongodb-async-driver/apidocs/\",\n                \"http://docs.spring.io/spring/docs/current/javadoc-api/\",\n                \"http://docs.spring.io/spring-boot/docs/current/api/\",\n                \"http://docs.spring.io/autorepo/docs/spring-security/current/apidocs/\",\n                \"http://square.github.io/okhttp/2.x/okhttp/\",\n                \"http://undertow.io/javadoc/1.3.x/\",\n                \"http://netty.io/4.0/api/\"\n]\n\next.javadocExcludes = [\n        \"org/glassfish/jersey/server/internal/**\",\n        \"co/paralleluniverse/comsat/webactors/servlet/WebActorEndpoint.java\",\n    //        \"co/paralleluniverse/comsat/webactors/servlet/WebActorInitializer.java\",\n        \"co/paralleluniverse/comsat/webactors/servlet/WebActorServlet.java\",\n        \"co/paralleluniverse/comsat/webactors/netty/WebActorHandler.java\",\n        \"co/paralleluniverse/comsat/webactors/netty/AutoWebActorHandler.java\",\n        \"co/paralleluniverse/comsat/webactors/undertow/WebActorHandler.java\",\n        \"co/paralleluniverse/comsat/webactors/undertow/AutoActorHandler.java\",\n]\n\n// Rest of the subprojects common definitions\nsubprojects {\n    javadoc {\n        source = files(subprojects.collect { project -> project.sourceSets.main.allJava })\n        classpath = files(subprojects.collect { project -> project.sourceSets.main.compileClasspath })\n        options {\n            addStringOption('sourcepath', configurations.srcFiles.files.flatten().join(':'))\n            docletpath = configurations.markdownDoclet.files.asType(List)\n            doclet = 'ch.raffael.doclets.pegdown.PegdownDoclet'\n            addStringOption(\"parse-timeout\", \"10\")\n            // stylesheetFile = rootProject.file('./baselib/javadoc.css')\n            links = javadocLinks\n        }\n    }\n    task javadocJar(type: Jar, dependsOn: javadoc) {\n        classifier = 'javadoc'\n        from javadoc.destinationDir\n    }\n\n    ///////// Publish Artifacts\n    apply plugin: 'maven'\n    apply plugin: 'signing'\n\n    artifacts {\n        archives jar\n        archives sourcesJar\n        archives javadocJar\n    }\n\n    signing {\n        required { isRelease && gradle.taskGraph.hasTask(\"uploadArchives\") }\n        sign configurations.archives\n    }\n\n    uploadArchives {\n        repositories {\n            mavenDeployer {\n                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }\n\n                repository(\n                    url: (isRelease ?\n                            \"https://oss.sonatype.org/service/local/staging/deploy/maven2\" :\n                            \"https://oss.sonatype.org/content/repositories/snapshots\")) {\n                    // User and Password are taken from ~/.gradle/gradle.properties\n                    authentication(userName: sonatypeUsername, password: sonatypePassword)\n                }\n                pom.project {\n                    name project.name\n                    packaging 'jar'\n                    description project.description\n                    url project.url\n                    scm {\n                        url project.scmUrl\n                        connection project.scmConnection\n                        developerConnection project.scmConnection\n                    }\n                    licenses {\n                        license {\n                            name project.licenseName1\n                            url project.licenseUrl1\n                            distribution 'repo'\n                        }\n                        license {\n                            name project.licenseName2\n                            url project.licenseUrl2\n                            distribution 'repo'\n                        }\n                    }\n                    developers {\n                        developer {\n                            id 'eitan'\n                            name 'Eitan Yarden'\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\ntask javadoc(type: Javadoc) {\n    title = \"Comsat ${project(':comsat-actors-api').version}\"\n    destinationDir = file(\"docs/javadoc\")\n    source = files(subprojects.collect { project -> project.sourceSets.main.allJava })\n    classpath = files(subprojects.collect { project -> project.sourceSets.main.compileClasspath })\n    options {\n        addStringOption('sourcepath', subprojects.configurations.srcFiles.files.flatten().join(':'))\n        docletpath = configurations.markdownDoclet.files.asType(List)\n        doclet = 'ch.raffael.doclets.pegdown.PegdownDoclet'\n        addStringOption(\"parse-timeout\", \"10\")\n        // stylesheetFile = rootProject.file('./baselib/javadoc.css')\n        links = javadocLinks\n    }\n    excludes = javadocExcludes\n}\n\ntask clean(dependsOn: subprojects.clean) << {\n    delete 'docs/javadoc'\n}\n\nbuildscript {\n    repositories {\n        mavenCentral()\n        jcenter()\n    }\n\n    dependencies {\n        classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.10.0'\n        classpath 'com.github.ben-manes:gradle-versions-plugin:0.6'\n        classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.0'\n    }\n}\n\ndefaultTasks 'install'\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/Cookie.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\n/**\n * A HTTP cookie\n */\npublic class Cookie {\n    /**\n     * Constructs a cookie with the specified name and value.\n     *\n     * <p>The name must conform to RFC 2109. However, vendors may\n     * provide a configuration option that allows cookie names conforming\n     * to the original Netscape Cookie Specification to be accepted.\n     *\n     * <p>The name of a cookie cannot be changed once the cookie has been created.\n     *\n     * <p>The value can be anything the server chooses to send.\n     * Its value is probably of interest only to the server.\n     *\n     * <p>By default, cookies are created according to the Netscape cookie specification.\n     * The version can be changed with the {@link Builder#setVersion(int) setVersion} method.\n     *\n     * @param name  the name of the cookie\n     * @param value the value of the cookie\n     * @return a new {@link Cookie.Builder}\n     */\n    public static Builder cookie(String name, String value) {\n        return new Builder(name, value);\n    }\n\n    public static class Builder {\n        private final String name;\n        private final String value;\n        private String path;\n        private String domain;\n        private int maxAge = -1;\n        private String comment;\n        private int version;\n        private boolean httpOnly;\n        private boolean secure;\n\n        private Builder(String name, String value) {\n            this.name = name;\n            this.value = value;\n        }\n\n        /**\n         * Specifies a path for the cookie to which the client should return the cookie.\n         *\n         * <p>The cookie is visible to all the pages in the directory\n         * you specify, and all the pages in that directory's subdirectories.\n         * A cookie's path must include the servlet that set the cookie,\n         * for example, <i>/catalog</i>, which makes the cookie\n         * visible to all directories on the server under <i>/catalog</i>.\n         *\n         * <p>Consult RFC 2109 (available on the Internet) for more\n         * information on setting path names for cookies.\n         *\n         * @param uri a {@code String} specifying a path\n         *\n         * @see Cookie#getPath\n         */\n        public Builder setPath(String uri) {\n            this.path = uri;\n            return this;\n        }\n\n        /**\n         *\n         * Specifies the domain within which this cookie should be presented.\n         *\n         * <p>The form of the domain name is specified by RFC 2109.\n         * A domain name begins with a dot ({@code .foo.com}) and means that\n         * the cookie is visible to servers in a specified Domain Name System\n         * (DNS) zone (for example,\n         * {@code www.foo.com}, but not {@code a.b.foo.com}).\n         * By default, cookies are only returned to the server that sent them.\n         *\n         * @param domain the domain name within which this cookie is visible;\n         *               form is according to RFC 2109\n         *\n         * @see Cookie#getDomain\n         */\n        public Builder setDomain(String domain) {\n            this.domain = domain;\n            return this;\n        }\n\n        /**\n         * Sets the maximum age in seconds for this Cookie.\n         *\n         * <p>A positive value indicates that the cookie will expire\n         * after that many seconds have passed. Note that the value is\n         * the <i>maximum</i> age when the cookie will expire, not the cookie's\n         * current age.\n         *\n         * <p>A negative value means that the cookie is not stored persistently and will\n         * be deleted when the Web browser exits.\n         * A zero value causes the cookie to be deleted.\n         *\n         * @param maxAge an integer specifying the maximum age of the\n         *               cookie in seconds; if negative, means\n         *               the cookie is not stored; if zero, deletes the cookie\n         *\n         * @see Cookie#getMaxAge\n         */\n        public Builder setMaxAge(int maxAge) {\n            this.maxAge = maxAge;\n            return this;\n        }\n\n        /**\n         * Specifies a comment that describes a cookie's purpose.\n         * The comment is useful if the browser presents the cookie\n         * to the user. Comments\n         * are not supported by Netscape Version 0 cookies.\n         *\n         * @param comment a {@code String} specifying the comment to display to the user\n         *\n         * @see Cookie#getComment\n         */\n        public Builder setComment(String comment) {\n            this.comment = comment;\n            return this;\n        }\n\n        /**\n         * Sets the version of the cookie protocol that this Cookie complies with.\n         *\n         * <p>Version 0 complies with the original Netscape cookie specification.\n         * Version 1 complies with RFC 2109.\n         *\n         * <p>Since RFC 2109 is still somewhat new, consider\n         * version 1 as experimental; do not use it yet on production sites.\n         *\n         * @param version 0 if the cookie should comply with the original Netscape\n         *                specification; 1 if the cookie should comply with RFC 2109\n         *\n         * @see Cookie#getVersion\n         */\n        public Builder setVersion(int version) {\n            this.version = version;\n            return this;\n        }\n\n        /**\n         * Marks or unmarks this Cookie as <i>HttpOnly</i>.\n         *\n         * <p>If {@code httpOnly} is set to {@code true}, this cookie is\n         * marked as <i>HttpOnly</i>, by adding the {@code HttpOnly} attribute to it.\n         *\n         * <p><i>HttpOnly</i> cookies are not supposed to be exposed to\n         * client-side scripting code, and may therefore help mitigate certain\n         * kinds of cross-site scripting attacks.\n         *\n         * @param httpOnly {@code true} if this cookie is to be marked as <i>HttpOnly</i>, {@code false} otherwise\n         *\n         * @see Cookie#isHttpOnly()\n         */\n        public Builder setHttpOnly(boolean httpOnly) {\n            this.httpOnly = httpOnly;\n            return this;\n        }\n\n        /**\n         * Indicates to the browser whether the cookie should only be sent\n         * using a secure protocol, such as HTTPS or SSL.\n         *\n         * <p>The default value is {@code false}.\n         *\n         * @param flag if {@code true}, sends the cookie from the browser\n         *             to the server only when using a secure protocol;\n         *             if {@code false}, sent on any protocol\n         *\n         * @see Cookie#isSecure\n         */\n        public Builder setSecure(boolean flag) {\n            this.secure = flag;\n            return this;\n        }\n\n        /**\n         * Instantiates a new immutable {@link Cookie} based on the values set in this builder.\n         *\n         * @return a new {@link Cookie}\n         */\n        public Cookie build() {\n            return new Cookie(this);\n        }\n    }\n    private final String name;\n    private final String value;\n    private final String path;\n    private final String domain;\n    private final int maxAge;\n    private final String comment;\n    private final int version;\n    private final boolean httpOnly;\n    private final boolean secure;\n\n    private Cookie(Builder builder) {\n        this.name = builder.name;\n        this.value = builder.value;\n        this.path = builder.path;\n        this.domain = builder.domain;\n        this.maxAge = builder.maxAge;\n        this.comment = builder.comment;\n        this.version = builder.version;\n        this.httpOnly = builder.httpOnly;\n        this.secure = builder.secure;\n    }\n\n    /**\n     * The name of the cookie.\n     *\n     * @see #cookie(String, String)\n     */\n    public String getName() {\n        return name;\n    }\n\n    /**\n     * The value of this Cookie.\n     *\n     * @see #cookie(String, String)\n     */\n    public String getValue() {\n        return value;\n    }\n\n    /**\n     * Returns the path on the server to which the browser returns this cookie.\n     * The cookie is visible to all subpaths on the server.\n     *\n     * @return\ta {@code String} specifying a path that contains a servlet name, for example, <i>/catalog</i>\n     *\n     * @see Builder#setPath\n     */\n    public String getPath() {\n        return path;\n    }\n\n    /**\n     * The domain name of this Cookie.\n     *\n     * <p>Domain names are formatted according to RFC 2109.\n     *\n     * @see Builder#setDomain\n     */\n    public String getDomain() {\n        return domain;\n    }\n\n    /**\n     * The maximum age in seconds of this Cookie.\n     *\n     * <p>By default, {@code -1} is returned, which indicates that the cookie will persist until browser shutdown.\n     *\n     * @return an integer specifying the maximum age of the cookie in seconds;\n     *         if negative, means the cookie persists until browser shutdown\n     *\n     * @see Builder#setMaxAge\n     */\n    public int getMaxAge() {\n        return maxAge;\n    }\n\n    /**\n     * The comment describing the purpose of this cookie, or {@code null} if the cookie has no comment.\n     *\n     * @see Builder#setComment\n     */\n    public String getComment() {\n        return comment;\n    }\n\n    /**\n     * The version of the protocol this cookie complies with.\n     * Version 1 complies with RFC 2109,\n     * and version 0 complies with the original cookie specification drafted by Netscape.\n     * Cookies provided by a browser use and identify the browser's cookie version.\n     *\n     * @return {@code 0} if the cookie complies with the original Netscape specification;\n     *         {@code 1} if the cookie complies with RFC 2109\n     *\n     * @see Builder#setVersion\n     */\n    public int getVersion() {\n        return version;\n    }\n\n    /**\n     * Whether this Cookie has been marked as <i>HttpOnly</i>.\n     *\n     * @return {@code true} if this Cookie has been marked as <i>HttpOnly</i>, {@code false} otherwise\n     */\n    public boolean isHttpOnly() {\n        return httpOnly;\n    }\n\n    /**\n     * Returns {@code true} if the browser is sending cookies only over a secure protocol,\n     * or {@code false} if the browser can send cookies using any protocol.\n     *\n     * @return {@code true} if the browser uses a secure protocol, {@code false} otherwise\n     *\n     * @see Builder#setSecure\n     */\n    public boolean isSecure() {\n        return secure;\n    }\n\n    @Override\n    public String toString() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\"Cookie[\");\n        sb.append(\"name: \").append(name);\n        sb.append(\" value: \").append(value);\n        if (path != null)\n            sb.append(\" path: \").append(path);\n        if (domain != null)\n            sb.append(\" domain: \").append(domain);\n        sb.append(\" maxAge: \").append(maxAge);\n        if (comment != null)\n            sb.append(\" comment: \").append(comment);\n        sb.append(\" version: \").append(version);\n        if (httpOnly)\n            sb.append(\" httpOnly: \").append(httpOnly);\n        sb.append(\" secure: \").append(secure);\n        sb.append(']');\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/HttpMessage.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport com.google.common.collect.ListMultimap;\nimport java.nio.charset.Charset;\nimport java.util.Collection;\nimport java.util.Locale;\n\n/**\n * A message sent over an HTTP connection. Can be either a request or a response.\n */\npublic abstract class HttpMessage extends WebMessage {\n    /**\n     * A multimap of the headers contained in this message and (all) their values.\n     * If the request has no headers, returns an empty multimap.\n     *\n     * Note that header names' case is not preserved necessarily due to normalization for\n     * concordance with the HTTP specification.\n     */\n    public abstract ListMultimap<String, String> getHeaders();\n\n    /**\n     * A collection all of the {@link Cookie} objects the client sent with this message.\n     * This method returns an empty collection if no cookies were sent.\n     */\n    public abstract Collection<Cookie> getCookies();\n\n    /**\n     * The length, in bytes, of the message body and made available by the input stream,\n     * or {@code -1} if the length is not known or is greater than {@code Integer.MAX_VALUE}.\n     */\n    public abstract int getContentLength();\n\n    /**\n     * The {@link Charset} representing character encoding used in the body of this message.\n     * This method returns {@code null} if the message does not specify a character encoding.\n     */\n    public abstract Charset getCharacterEncoding();\n\n    /**\n     * The MIME type of the body of the request, or {@code null} if the type is not known\n     * For example, {@code text/html; charset=UTF-8}.\n     */\n    public abstract String getContentType();\n\n    /**\n     * Returns all values associated with the given header name\n     *\n     * @param name the header name\n     * @return all values associated with the given header name\n     */\n    public Collection<String> getHeaderValues(String name) {\n        return getHeaders().get(name);\n    }\n\n    /**\n     * Returns the value of the given header name.\n     * If the header is not found in the message, this method returns {@code null}.\n     * If the header has more than one value, this method returns the first value.\n     *\n     * In concordance with the HTTP specification, this method treats HTTP header names as case-insensitive.\n     *\n     * @param name the header name\n     * @return the (first) value of the given header name; {@code null} if the header is not found\n     */\n    public String getHeader(String name) {\n        return first(getHeaders().get(name.toLowerCase(Locale.ENGLISH)));\n    }\n\n    static <V> V first(Collection<V> c) {\n        if (c == null || c.isEmpty())\n            return null;\n        return c.iterator().next();\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/HttpRequest.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport com.google.common.collect.ImmutableList;\nimport com.google.common.collect.ImmutableListMultimap;\nimport com.google.common.collect.LinkedListMultimap;\nimport com.google.common.collect.ListMultimap;\nimport com.google.common.collect.Multimap;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.Charset;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.TimeZone;\n\n/**\n * An HTTP request message.\n */\npublic abstract class HttpRequest extends HttpMessage {\n    /**\n     * The Internet Protocol (IP) host that sent the request or {@code null} if not available.\n     */\n    public abstract String getSourceHost();\n\n    /**\n     * The Internet Protocol (IP) port from which the request was sent or {@code -1} if not available.\n     */\n    public abstract int getSourcePort();\n\n    /**\n     * A multimap of the parameters contained in this message and (all) their values.\n     * If the request has no parameters, returns an empty multimap.\n     */\n    public abstract Multimap<String, String> getParameters();\n\n    /**\n     * Returns the names values of all attributed associated with this request.\n     *\n     * <p>\n     * The container may set\n     * attributes to make available custom information about a request.\n     * For example, for requests made using HTTPS, the attribute\n     * <code>javax.servlet.request.X509Certificate</code> can be used to\n     * retrieve information on the certificate of the client.\n     *\n     * @return an {@code Object} containing the value of the attribute,\n     *         or {@code null} if the attribute does not exist\n     */\n    public abstract Map<String, Object> getAttributes();\n\n    /**\n     * Returns all values associated with the given parameter\n     *\n     * @param name the parameter name\n     * @return all values associated with the given parameter\n     */\n    public Collection<String> getParametersValues(String name) {\n        return getParameters().get(name);\n    }\n\n    /**\n     * Returns the value of the given parameter.\n     * If the parameter is not found in the message, this method returns {@code null}.\n     * If the parameter has more than one value, this method returns the first value.\n     *\n     * @param name the parameter name\n     * @return the (first) value of the given parameter name; {@code null} if the parameter is not found\n     */\n    public String getParameter(String name) {\n        return first(getParameters().get(name));\n    }\n\n    /**\n     * Returns the value of the given attribute.\n     * If the attribute is not found in the message, this method returns {@code null}.\n     *\n     * @param name the attribute name\n     * @return the value of the given attribute; {@code null} if the attribute is not found\n     */\n    public Object getAttribute(String name) {\n        return getAttributes().get(name);\n    }\n\n    /**\n     * Returns the name of the scheme used to make this request, for example, {@code http}, {@code https}, or {@code ftp}.\n     * Different schemes have different rules for constructing URLs, as noted in RFC 1738.\n     */\n    public abstract String getScheme();\n\n    /**\n     * The name of the HTTP method with which this request was made;\n     * for example, GET, POST, or PUT.\n     *\n     * @return the name of the method with which this request was made\n     */\n    public abstract String getMethod();\n\n    /**\n     * Returns the value of the specified request header as a {@code long} value that represents a {@code Date} object.\n     * Use this method with headers that contain dates, such as {@code If-Modified-Since}.\n     *\n     * <p>\n     * The date is returned as the number of milliseconds since January 1, 1970 GMT.\n     *\n     * <p>\n     * If the request does not have a header of the specified name, this method returns -1.\n     * If the header can't be converted to a date, the method throws an {@code IllegalArgumentException}.\n     *\n     * @param name the name of the header\n     *\n     * @return\ta {@code long} value representing the date specified in the header expressed as\n     *         the number of milliseconds since January 1, 1970 GMT,\n     *         or {@code -1} if the named header was not included with the request\n     *\n     * @exception IllegalArgumentException If the header value can't be converted to a date\n     */\n    public long getDateHeader(String name) {\n        String value = getHeader(name);\n        if (value == null)\n            return (-1L);\n\n        long result = parseDate(value);\n        if (result != (-1L))\n            return result;\n\n        throw new IllegalArgumentException(value);\n    }\n\n    /**\n     * Returns any extra path information associated with the URL the client sent when it made this request.\n     * The extra path information follows the servlet path but precedes the query string and will start with\n     * a \"/\" character.\n     *\n     * <p>\n     * This method returns {@code null} if there was no extra path information.\n     *\n     * @return a {@code String} decoded by the web container, specifying\n     *         extra path information that comes after the servlet path but before the query string in the request URL;\n     *         or {@code null} if the URL does not have any extra path information\n     */\n    public abstract String getPathInfo();\n\n    /**\n     * The portion of the request URI that indicates the context of the request.\n     * The context path always comes first in a request URI.\n     * The path starts with a \"/\" character but does not end with a \"/\" character.\n     * For servlets in the default (root) context, this method returns \"\".\n     * The container does not decode this string.\n     *\n     * <p>\n     * It is possible that a container may match a context by\n     * more than one context path. In such cases this method will return the\n     * actual context path used by the request.\n     *\n     * @return the portion of the request URI that indicates the context of the request\n     */\n    public abstract String getContextPath();\n\n    /**\n     * The query string that is contained in the request URL after the path,\n     * or {@code null} if the URL does not have a query string.\n     */\n    public abstract String getQueryString();\n\n    /**\n     * Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request.\n     * The web container does not decode this string.\n     * For example:\n     *\n     * <table summary=\"Examples of Returned Values\">\n     * <tr align=left>\n     * <th>First line of HTTP request </th><th> Returned Value</th>\n     * <tr><td>POST /some/path.html HTTP/1.1<td><td>/some/path.html\n     * <tr><td>GET http://foo.bar/a.html HTTP/1.0<td><td>/a.html\n     * <tr><td>HEAD /xyz?a=b HTTP/1.1<td><td>/xyz\n     * </table>\n     *\n     * @return the part of the URL from the protocol name up to the query string\n     */\n    public abstract String getRequestURI();\n\n    /**\n     * Reconstructs the URL the client used to make the request.\n     * The returned URL contains a protocol, server name, port\n     * number, and server path, but it does not include query\n     * string parameters.\n     *\n     * <p>\n     * This method is useful for creating redirect messages\n     * and for reporting errors.\n     *\n     * @return the reconstructed URL\n     */\n    public String getRequestURL() {\n        StringBuilder url = new StringBuilder();\n        String scheme = getScheme();\n        int port = getServerPort();\n        if (port < 0)\n            port = 80; // Work around java.net.URL bug\n\n        url.append(scheme);\n        url.append(\"://\");\n        url.append(getServerName());\n        if ((scheme.equals(\"http\") && (port != 80))\n                || (scheme.equals(\"https\") && (port != 443))) {\n            url.append(':');\n            url.append(port);\n        }\n        url.append(getRequestURI());\n\n        return url.toString();\n    }\n\n    /**\n     * The host name of the server to which the request was sent.\n     * It is the value of the part before \":\" in the {@code Host} header value, if any,\n     * or the resolved server name, or the server IP address.\n     */\n    public abstract String getServerName();\n\n    /**\n     * The port number to which the request was sent.\n     * It is the value of the part after \":\" in the {@code Host} header value, if any,\n     * or the server port where the client connection was accepted on.\n     *\n     * @return the port number\n     */\n    public abstract int getServerPort();\n\n    /**\n     * Returns an actor representing the client to which an {@link HttpResponse} should be sent as a response to this request.\n     * All {@code HttpRequest}s from the same session will have the same sender. It will appear to have died (i.e. send an\n     * {@link co.paralleluniverse.actors.ExitMessage ExitMessage} if {@link co.paralleluniverse.actors.Actor#watch(co.paralleluniverse.actors.ActorRef) watched})\n     * when the session is terminated.\n     *\n     * @return an actor representing the client\n     */\n    @Override\n    public abstract ActorRef<WebMessage> getFrom();\n\n    @Override\n    protected String contentString() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\" \").append(getMethod());\n        sb.append(\" sourceHost: \").append(getSourceHost());\n        sb.append(\" uri: \").append(getRequestURI());\n        sb.append(\" query: \").append(getQueryString());\n        sb.append(\" params: \").append(getParameters());\n        sb.append(\" headers: \").append(getHeaders());\n        sb.append(\" cookies: \").append(getCookies());\n        sb.append(\" contentLength: \").append(getContentLength());\n        sb.append(\" charEncoding: \").append(getCharacterEncoding());\n        sb.append(\" body: \").append(getStringBody());\n        return super.contentString() + sb;\n    }\n\n    public static class Builder {\n        private final ActorRef<WebMessage> sender;\n        private final String strBody;\n        private final ByteBuffer binBody;\n        private String sourceHost;\n        private int sourcePort;\n        private String contentType;\n        private Charset charset;\n        private List<Cookie> cookies;\n        private ListMultimap<String, String> headers;\n        private String method;\n        private String scheme;\n        private String server;\n        private int port;\n        private String path;\n        private Multimap<String, String> params;\n\n        public Builder(ActorRef<? super WebMessage> from, String body) {\n            this.sender = (ActorRef<WebMessage>) from;\n            this.strBody = body;\n            this.binBody = null;\n        }\n\n        public Builder(ActorRef<? super WebMessage> from, ByteBuffer body) {\n            this.sender = (ActorRef<WebMessage>) from;\n            this.binBody = body;\n            this.strBody = null;\n        }\n\n        public Builder(ActorRef<? super WebMessage> from) {\n            this(from, (String) null);\n        }\n\n        public Builder setSourceHost(String sourceAddress) {\n            this.sourceHost = sourceAddress;\n            return this;\n        }\n\n        public Builder setSourcePort(int sourcePort) {\n            this.sourcePort = sourcePort;\n            return this;\n        }\n\n        /**\n         * Sets the content type of the request being sent to the client.\n         * <p/>\n         * The given content type may include a character encoding\n         * specification, for example, {@code text/html;charset=UTF-8}.\n         * <p/>\n         * The {@code Content-Type} header is used to communicate the content type and the character\n         * encoding used in the response writer to the client\n         *\n         * @param contentType the MIME type of the content\n         *\n         */\n        public Builder setContentType(String contentType) {\n            this.contentType = contentType;\n            return this;\n        }\n\n        /**\n         * Sets the character encoding (MIME charset) of the response being sent to the client,\n         * for example, {@code UTF-8}.\n         * If the character encoding has already been set by {@link #setContentType}, this method overrides it.\n         * Calling {@link #setContentType} with {@code \"text/html\"} and calling this method with {@code Charset.forName(\"UTF-8\")}\n         * is equivalent with calling {@code setContentType} with {@code \"text/html; charset=UTF-8\"}.\n         * <p/>\n         * Note that the character encoding cannot be communicated via HTTP headers if\n         * content type is not specified; however, it is still used to encode text\n         * written in this response's body.\n         *\n         * @param charset only the character sets defined by IANA Character Sets\n         *                (http://www.iana.org/assignments/character-sets)\n         *\n         * @see #setContentType\n         */\n        public Builder setCharacterEncoding(Charset charset) {\n            this.charset = charset;\n            return this;\n        }\n\n        /**\n         * Adds a request header with the given name and value.\n         * This method allows response headers to have multiple values.\n         *\n         * @param name  the name of the header\n         * @param value the additional header value.\n         *              If it contains octet string, it should be encoded according to RFC 2047 (http://www.ietf.org/rfc/rfc2047.txt)\n         */\n        public Builder addHeader(final String name, final String value) {\n            if (headers == null)\n                headers = LinkedListMultimap.create();\n            // Normalize header names by their conversion to lower case\n            headers.put(name.toLowerCase(Locale.ENGLISH), value);\n            return this;\n        }\n\n        /**\n         * Adds the specified cookie to the request.\n         * This method can be called multiple times to set multiple cookies.\n         *\n         * @param cookie the {@link Cookie} to return to the client\n         * @return {@code this}\n         */\n        public Builder addCookie(Cookie cookie) {\n            if (cookies == null)\n                cookies = new ArrayList<>();\n            cookies.add(cookie);\n            return this;\n        }\n\n        public Builder setMethod(String method) {\n            this.method = method;\n            return this;\n        }\n\n        public Builder setScheme(String scheme) {\n            this.scheme = scheme;\n            return this;\n        }\n\n        public Builder setServer(String server) {\n            this.server = server;\n            return this;\n        }\n\n        public Builder setPort(int port) {\n            this.port = port;\n            return this;\n        }\n\n        public Builder setPath(String path) {\n            this.path = path;\n            return this;\n        }\n\n        /**\n         * Adds a request parameter with the given name and value.\n         *\n         * @param name  the name of the parameter\n         * @param value the additional header value.\n         *              If it contains octet string, it should be encoded according to RFC 2047 (http://www.ietf.org/rfc/rfc2047.txt)\n         */\n        public Builder addParam(final String name, final String value) {\n            if (params == null)\n                params = LinkedListMultimap.create();\n            params.put(name, value);\n            return this;\n        }\n\n        /**\n         * Instantiates a new immutable {@link HttpRequest} based on the values set in this builder.\n         *\n         * @return a new {@link HttpRequest}\n         */\n        public HttpRequest build() {\n            return new SimpleHttpRequest(sender, this);\n        }\n    }\n\n    private static class SimpleHttpRequest extends HttpRequest {\n        private final String sourceHost;\n        private final int sourcePort;\n        private final ActorRef<WebMessage> sender;\n        private final String contentType;\n        private final Charset charset;\n        private final String strBody;\n        private final ByteBuffer binBody;\n        private final Collection<Cookie> cookies;\n        private final ListMultimap<String, String> headers;\n        private final Multimap<String, String> params;\n        private final String method;\n        private final String scheme;\n        private final String server;\n        private final int port;\n        private final String uri;\n\n        /**\n         * Use when forwarding\n         *\n         * @param from\n         * @param httpRequest\n         */\n        public SimpleHttpRequest(ActorRef<? super WebMessage> from, HttpRequest httpRequest) {\n            this.sourceHost = httpRequest.getSourceHost();\n            this.sourcePort = httpRequest.getSourcePort();\n            this.sender = (ActorRef<WebMessage>) from;\n            this.contentType = httpRequest.getContentType();\n            this.charset = httpRequest.getCharacterEncoding();\n            this.strBody = httpRequest.getStringBody();\n            this.binBody = httpRequest.getByteBufferBody() != null ? httpRequest.getByteBufferBody().asReadOnlyBuffer() : null;\n            this.cookies = httpRequest.getCookies();\n            this.headers = httpRequest.getHeaders();\n            this.method = httpRequest.getMethod();\n            this.scheme = httpRequest.getScheme();\n            this.server = httpRequest.getServerName();\n            this.port = httpRequest.getServerPort();\n            this.params = httpRequest.getParameters();\n            this.uri = httpRequest.getRequestURI();\n        }\n\n        public SimpleHttpRequest(ActorRef<? super WebMessage> from, HttpRequest.Builder builder) {\n            this.sourceHost = builder.sourceHost;\n            this.sourcePort = builder.sourcePort;\n            this.sender = (ActorRef<WebMessage>) from;\n            this.contentType = builder.contentType;\n            this.charset = builder.charset;\n            this.strBody = builder.strBody;\n            this.binBody = builder.binBody != null ? builder.binBody.asReadOnlyBuffer() : null;\n            this.cookies = builder.cookies != null ? ImmutableList.copyOf(builder.cookies) : null;\n            this.headers = builder.headers != null ? ImmutableListMultimap.copyOf(builder.headers) : null;\n            this.params = builder.params != null ? ImmutableListMultimap.copyOf(builder.params) : null;\n            this.method = builder.method;\n            this.scheme = builder.scheme;\n            this.server = builder.server;\n            this.port = builder.port;\n            this.uri = builder.path;\n        }\n\n        @Override\n        public String getSourceHost() {\n            return sourceHost;\n        }\n\n        @Override\n        public int getSourcePort() {\n            return sourcePort;\n        }\n\n        @Override\n        public ActorRef<WebMessage> getFrom() {\n            return sender;\n        }\n\n        @Override\n        public String getContentType() {\n            return contentType;\n        }\n\n        @Override\n        public Charset getCharacterEncoding() {\n            return charset;\n        }\n\n        @Override\n        public int getContentLength() {\n            if (binBody != null)\n                return binBody.remaining();\n            else\n                return -1;\n        }\n\n        @Override\n        public String getStringBody() {\n            return strBody;\n        }\n\n        @Override\n        public ByteBuffer getByteBufferBody() {\n            return binBody != null ? binBody.duplicate() : null;\n        }\n\n        @Override\n        public Collection<Cookie> getCookies() {\n            return cookies;\n        }\n\n        @Override\n        public ListMultimap<String, String> getHeaders() {\n            return headers;\n        }\n\n        @Override\n        public Map<String, Object> getAttributes() {\n            return null;\n        }\n\n        @Override\n        public String getScheme() {\n            return scheme;\n        }\n\n        @Override\n        public String getMethod() {\n            return method;\n        }\n\n        @Override\n        public String getServerName() {\n            return server;\n        }\n\n        @Override\n        public int getServerPort() {\n            return port;\n        }\n\n        @Override\n        public Multimap<String, String> getParameters() {\n            return params;\n        }\n\n        @Override\n        public String getRequestURI() {\n            return uri;\n        }\n\n        @Override\n        public String getQueryString() {\n            if(params == null)\n                return null;\n            StringBuilder sb = new StringBuilder();\n            for(Map.Entry<String, String> entry : params.entries())\n                sb.append(entry.getKey()).append('=').append(entry.getValue()).append('&');\n            sb.delete(sb.length()-1, sb.length());\n            return sb.toString();\n        }\n\n        @Override\n        public String getPathInfo() {\n            throw new UnsupportedOperationException();\n        }\n\n        @Override\n        public String getContextPath() {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    /**\n     * The only date format permitted when generating HTTP headers.\n     */\n    public static final String RFC1123_DATE = \"EEE, dd MMM yyyy HH:mm:ss zzz\";\n    private static final SimpleDateFormat format = new SimpleDateFormat(RFC1123_DATE, Locale.US);\n\n    /**\n     * The set of SimpleDateFormat formats to use in getDateHeader().\n     */\n    private static final SimpleDateFormat formats[] = {\n        new SimpleDateFormat(RFC1123_DATE, Locale.US),\n        new SimpleDateFormat(\"EEEEEE, dd-MMM-yy HH:mm:ss zzz\", Locale.US),\n        new SimpleDateFormat(\"EEE MMMM d HH:mm:ss yyyy\", Locale.US)\n    };\n\n    private static final TimeZone gmtZone = TimeZone.getTimeZone(\"GMT\");\n\n    /**\n     * All HTTP dates are on GMT\n     */\n    static {\n        format.setTimeZone(gmtZone);\n        formats[0].setTimeZone(gmtZone);\n        formats[1].setTimeZone(gmtZone);\n        formats[2].setTimeZone(gmtZone);\n    }\n\n    private static long parseDate(String value) {\n        Date date = null;\n        for (int i = 0; (date == null) && (i < formats.length); i++) {\n            try {\n                date = formats[i].parse(value);\n            } catch (ParseException e) {\n                // Ignore\n            }\n        }\n        if (date == null)\n            return -1L;\n\n        return date.getTime();\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/HttpResponse.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport com.google.common.collect.ImmutableList;\nimport com.google.common.collect.ImmutableListMultimap;\nimport com.google.common.collect.LinkedListMultimap;\nimport com.google.common.collect.ListMultimap;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.Charset;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * An HTTP response message sent as a {@link HttpRequest#sender() response} to an {@link HttpRequest}.\n * When this response is sent to an {@link HttpRequest}'s {@link HttpRequest#sender() sender}, the connection stream will be closed\n * if {@link HttpRequest#openChannel() openChannel} has not been called on the request,\n * and will be flushed but not closed if {@link HttpRequest#openChannel() openChannel} <i>has</i> been called on the request.\n */\npublic abstract class HttpResponse extends HttpMessage {\n    @Override\n    public abstract ActorRef<WebMessage> getFrom();\n\n    /**\n     * The {@link HttpRequest} this is a response to.\n     */\n    public abstract HttpRequest getRequest();\n\n    /**\n     * The response's HTTP status code.\n     */\n    public abstract int getStatus();\n\n    /**\n     * An exception optionally associated with an error status code.\n     */\n    public abstract Throwable getError();\n\n    /**\n     * The redirect URL target if this is a {@link #redirect(HttpRequest, String) redirect} response.\n     */\n    public abstract String getRedirectPath();\n\n    public abstract boolean shouldStartActor();\n\n    @Override\n    protected String contentString() {\n        StringBuilder sb = new StringBuilder();\n        sb.append(\" \").append(getStatus());\n        sb.append(\" headers: \").append(getHeaders());\n        sb.append(\" cookies: \").append(getCookies());\n        sb.append(\" contentLength: \").append(getContentLength());\n        sb.append(\" charEncoding: \").append(getCharacterEncoding());\n        if (getStringBody() != null)\n            sb.append(\" body: \").append(getStringBody());\n        if (getRedirectPath() != null)\n            sb.append(\" redirectPath: \").append(getRedirectPath());\n        if (getError() != null)\n            sb.append(\" error: \").append(getError());\n        sb.append(\" shouldStartActor: \").append(shouldStartActor());\n        return super.contentString() + sb;\n    }\n\n    /**\n     * Creates an {@link HttpResponse} with a text body and response code {@code 200}.\n     *\n     * @param request the {@link HttpRequest} this is a response to.\n     * @param body    the response body\n     * @return A response {@link Builder} that can be used to add headers and other metadata to the response.\n     */\n    public static Builder ok(ActorRef<? super WebMessage> from, HttpRequest request, String body) {\n        return new Builder(from, request, body);\n    }\n\n    /**\n     * Creates an {@link HttpResponse} with a binary body and response code {@code 200}.\n     *\n     * @param request the {@link HttpRequest} this is a response to.\n     * @param body    the response body\n     * @return A response {@link Builder} that can be used to add headers and other metadata to the response.\n     */\n    public static Builder ok(ActorRef<? super WebMessage> from, HttpRequest request, ByteBuffer body) {\n        return new Builder(from, request, body);\n    }\n\n    /**\n     * Creates an {@link HttpResponse} indicating an error, with a given status code and an attached exception that may be reported\n     * back to the client.\n     *\n     * @param request the {@link HttpRequest} this is a response to.\n     * @param status  the response status code\n     * @param cause   the exception that caused the error\n     * @return A response {@link Builder} that can be used to add headers and other metadata to the response.\n     */\n    public static Builder error(ActorRef<? super WebMessage> from, HttpRequest request, int status, Throwable cause) {\n        return new Builder(from, request).status(status).error(cause);\n    }\n\n    /**\n     * Creates an {@link HttpResponse} indicating an error, with a given status code and a text body.\n     *\n     * @param request the {@link HttpRequest} this is a response to.\n     * @param status  the response status code\n     * @param body    the response body\n     * @return A response {@link Builder} that can be used to add headers and other metadata to the response.\n     */\n    public static Builder error(ActorRef<? super WebMessage> from, HttpRequest request, int status, String body) {\n        return new Builder(from, request, body).status(status);\n    }\n\n    /**\n     * Sends a temporary redirect response to the client using the\n     * specified redirect location URL and clears the buffer.\n     * The status code is set to {@code SC_FOUND} 302 (Found).\n     * This method can accept relative URLs;\n     * the container must convert the relative URL to an absolute URL before sending the response to the client.\n     * If the location is relative without a leading '/' the container interprets it as relative to\n     * the current request URI.\n     * If the location is relative with a leading '/' the container interprets it as relative to the container root.\n     * If the location is relative with two leading '/' the container interprets\n     * it as a network-path reference\n     * (see <a href=\"http://www.ietf.org/rfc/rfc3986.txt\"> RFC 3986: Uniform Resource Identifier (URI): Generic Syntax</a>, section 4.2 &quot;Relative Reference&quot;).\n     *\n     * @param redirectPath the redirect location URL\n     */\n    public static Builder redirect(HttpRequest request, String redirectPath) {\n        return new Builder(request).redirect(redirectPath);\n    }\n\n    public static class Builder {\n        private final ActorRef<WebMessage> sender;\n        private final HttpRequest request;\n        private final String strBody;\n        private final ByteBuffer binBody;\n        private String contentType;\n        private Charset charset;\n        private List<Cookie> cookies;\n        private ListMultimap<String, String> headers;\n        private int status;\n        private Throwable error;\n        private String redirectPath;\n        private boolean startActor;\n\n        public Builder(ActorRef<? super WebMessage> from, HttpRequest request, String body) {\n            this.sender = (ActorRef<WebMessage>) from;\n            this.request = request;\n            this.strBody = body;\n            this.binBody = null;\n            this.status = 200;\n        }\n\n        public Builder(ActorRef<? super WebMessage> from, HttpRequest request, ByteBuffer body) {\n            this.sender = (ActorRef<WebMessage>) from;\n            this.request = request;\n            this.binBody = body;\n            this.strBody = null;\n            this.status = 200;\n        }\n\n        public Builder(ActorRef<? super WebMessage> from, HttpRequest request) {\n            this(from, request, (String) null);\n        }\n\n        Builder(HttpRequest request, String body) {\n            this(null, request, body);\n        }\n\n        Builder(HttpRequest request, ByteBuffer body) {\n            this(null, request, body);\n        }\n\n        Builder(HttpRequest request) {\n            this(request, (String) null);\n        }\n\n        /**\n         * Sets the content type of the response being sent to the client.\n         * <p/>\n         * The given content type may include a character encoding\n         * specification, for example, {@code text/html;charset=UTF-8}.\n         * <p/>\n         * The {@code Content-Type} header is used to communicate the content type and the character\n         * encoding used in the response writer to the client\n         *\n         * @param contentType the MIME type of the content\n         *\n         */\n        public Builder setContentType(String contentType) {\n            this.contentType = contentType;\n            return this;\n        }\n\n        /**\n         * Sets the character encoding (MIME charset) of the response being sent to the client,\n         * for example, {@code UTF-8}.\n         * If the character encoding has already been set by {@link #setContentType}, this method overrides it.\n         * Calling {@link #setContentType} with {@code \"text/html\"} and calling this method with {@code Charset.forName(\"UTF-8\")}\n         * is equivalent with calling {@code setContentType} with {@code \"text/html; charset=UTF-8\"}.\n         * <p/>\n         * Note that the character encoding cannot be communicated via HTTP headers if\n         * content type is not specified; however, it is still used to encode text\n         * written in this response's body.\n         *\n         * @param charset only the character sets defined by IANA Character Sets\n         *                (http://www.iana.org/assignments/character-sets)\n         *\n         * @see #setContentType\n         */\n        public Builder setCharacterEncoding(Charset charset) {\n            this.charset = charset;\n            return this;\n        }\n\n        /**\n         * Adds a response header with the given name and value.\n         * This method allows response headers to have multiple values.\n         *\n         * @param name  the name of the header\n         * @param value the additional header value.\n         *              If it contains octet string, it should be encoded according to RFC 2047 (http://www.ietf.org/rfc/rfc2047.txt)\n         */\n        public Builder addHeader(final String name, final String value) {\n            if (headers == null)\n                headers = LinkedListMultimap.create();\n            headers.put(name, value);\n            return this;\n        }\n\n        /**\n         * Adds the specified cookie to the response.\n         * This method can be called multiple times to set multiple cookies.\n         *\n         * @param cookie the {@link Cookie} to return to the client\n         * @return {@code this}\n         */\n        public Builder addCookie(Cookie cookie) {\n            if (cookies == null)\n                cookies = new ArrayList<>();\n            cookies.add(cookie);\n            return this;\n        }\n\n        /**\n         * Sets the status code for this response.\n         *\n         * <p>\n         * This method is used to set the return status code\n         * Valid status codes are those in the 2XX, 3XX, 4XX, and 5XX ranges.\n         * Other status codes are treated as container specific.\n         * <p>\n         * codes in the 4XX and 5XX range will be treated as error codes, and\n         * will trigger the container's error reporting.\n         *\n         * @param sc the status code\n         * @return {@code this}\n         * @see #error\n         */\n        public Builder status(int sc) {\n            this.status = sc;\n            return this;\n        }\n\n        /**\n         * Associates an exception with an error status. The exception may be used in the error report\n         * which might be sent to the client.\n         *\n         * @param error the exception responsible for the error\n         * @return {@code this}\n         */\n        public Builder error(Throwable error) {\n            this.error = error;\n            return this;\n        }\n\n        /**\n         * Indicates that the connection to the client must not be closed after sending this response;\n         * rather an {@link HttpStreamOpened} message will be sent to the actor sending this response.\n         *\n         * @return {@code this}\n         */\n        public Builder startActor() {\n            this.startActor = true;\n            return this;\n        }\n\n        Builder redirect(String redirectPath) {\n            this.redirectPath = redirectPath;\n            this.status = 302;\n            return this;\n        }\n\n        /**\n         * Instantiates a new immutable {@link HttpResponse} based on the values set in this builder.\n         *\n         * @return a new {@link HttpResponse}\n         */\n        public HttpResponse build() {\n            return new SimpleHttpResponse(sender, this);\n        }\n    }\n\n    private static class SimpleHttpResponse extends HttpResponse {\n        //\n        private final ActorRef<WebMessage> sender;\n        private final HttpRequest request;\n        private final String contentType;\n        private final Charset charset;\n        private final String strBody;\n        private final ByteBuffer binBody;\n        private final Collection<Cookie> cookies;\n        private final ListMultimap<String, String> headers;\n        private final int status;\n        private final Throwable error;\n        private final String redirectPath;\n        private final boolean startActor;\n\n        /**\n         * Use when forwarding\n         *\n         * @param from\n         * @param httpResponse\n         */\n        public SimpleHttpResponse(ActorRef<? super WebMessage> from, HttpResponse httpResponse) {\n            this.sender = (ActorRef<WebMessage>) from;\n            this.request = httpResponse.getRequest();\n            this.contentType = httpResponse.getContentType();\n            this.charset = httpResponse.getCharacterEncoding();\n            this.strBody = httpResponse.getStringBody();\n            this.binBody = httpResponse.getByteBufferBody() != null ? httpResponse.getByteBufferBody().asReadOnlyBuffer() : null;\n            this.cookies = httpResponse.getCookies();\n            this.headers = httpResponse.getHeaders();\n            this.error = httpResponse.getError();\n            this.status = httpResponse.getStatus();\n            this.redirectPath = httpResponse.getRedirectPath();\n            this.startActor = httpResponse.shouldStartActor();\n        }\n\n        public SimpleHttpResponse(ActorRef<? super WebMessage> from, Builder builder) {\n            this.sender = (ActorRef<WebMessage>) from;\n            this.request = builder.request;\n            this.contentType = builder.contentType;\n            this.charset = builder.charset;\n            this.strBody = builder.strBody;\n            this.binBody = builder.binBody != null ? builder.binBody.asReadOnlyBuffer() : null;\n            this.cookies = builder.cookies != null ? ImmutableList.copyOf(builder.cookies) : null;\n            this.headers = builder.headers != null ? ImmutableListMultimap.copyOf(builder.headers) : null;\n            this.error = builder.error;\n            this.status = builder.status;\n            this.redirectPath = builder.redirectPath;\n            this.startActor = builder.startActor;\n        }\n\n        @Override\n        public ActorRef<WebMessage> getFrom() {\n            return sender;\n        }\n\n        @Override\n        public String getContentType() {\n            return contentType;\n        }\n\n        @Override\n        public Charset getCharacterEncoding() {\n            return charset;\n        }\n\n        @Override\n        public int getContentLength() {\n            if (binBody != null)\n                return binBody.remaining();\n            else\n                return -1;\n        }\n\n        @Override\n        public String getStringBody() {\n            return strBody;\n        }\n\n        @Override\n        public ByteBuffer getByteBufferBody() {\n            return binBody != null ? binBody.duplicate() : null;\n        }\n\n        @Override\n        public Collection<Cookie> getCookies() {\n            return cookies;\n        }\n\n        @Override\n        public ListMultimap<String, String> getHeaders() {\n            return headers;\n        }\n\n        /**\n         * The {@link HttpRequest} this is a response to.\n         */\n        @Override\n        public HttpRequest getRequest() {\n            return request;\n        }\n\n        /**\n         * The response's HTTP status code.\n         */\n        @Override\n        public int getStatus() {\n            return status;\n        }\n\n        /**\n         * An exception optionally associated with an error status code.\n         */\n        @Override\n        public Throwable getError() {\n            return error;\n        }\n\n        /**\n         * The redirect URL target if this is a {@link #redirect(HttpRequest, String) redirect} response.\n         */\n        @Override\n        public String getRedirectPath() {\n            return redirectPath;\n        }\n\n        @Override\n        public boolean shouldStartActor() {\n            return startActor;\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/HttpStreamOpened.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.actors.behaviors.IdMessage;\n\n/**\n * A message sent to a web actor indicating that a new stream has been opened.\n * This message is sent as a result of the web actor replying to an {@link HttpRequest}\n * with an {@link HttpResponse} whose {@link HttpResponse.Builder#startActor() startActor} method has been called.\n * The actor sending this message writes all received {@link WebDataMessage} to the HTTP response stream that's been left\n * open after the {@link HttpResponse}.\n * <p/>\n * This is usually used by SSE.\n */\npublic class HttpStreamOpened extends WebStreamOpened implements IdMessage {\n    private final HttpResponse response;\n\n    public HttpStreamOpened(ActorRef<WebDataMessage> actor, HttpResponse response) {\n        super(actor);\n        this.response = response;\n    }\n\n    /**\n     * {@inheritDoc }\n     * <p/>\n     * Returns the {@link HttpResponse} passed to the constructor.\n     */\n    @Override\n    public Object getId() {\n        return response;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/SSE.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.strands.channels.Channels;\nimport co.paralleluniverse.strands.channels.SendPort;\nimport com.google.common.base.Function;\nimport java.nio.charset.Charset;\n\n/**\n * Utility classes for SSE (<a href=\"http://dev.w3.org/html5/eventsource/\">Server-Sent Events</a>).\n * To start an SSE stream in response to an {@link HttpRequest}, do the following:\n *\n * ```java\n * request.getFrom().send(new HttpResponse(self(), SSE.startSSE(request)));\n * ```\n * This will result in a {@link HttpStreamOpened} message being sent to the web actor from a newly \n * created actor that represents the SSE connection. To send SSE events, simply send {@link WebDataMessage}s\n * to that actor:\n * \n * ```java\n * // send events\n * sseActor.send(new WebDataMessage(self(), SSE.event(\"this is an SSE event!\")));\n * ```\n * \n * You might want to consider wrapping the actor sending {@link HttpStreamOpened} with a \n * {@link co.paralleluniverse.strands.channels.Channels#mapSend(co.paralleluniverse.strands.channels.SendPort, com.google.common.base.Function) mapping channel}\n * to transform a specialized message class into {@link WebDataMessage} using the methods in this class.\n * \n * For a good tutorial on SSE, please see: <a href=\"http://www.html5rocks.com/en/tutorials/eventsource/basics/\">Stream Updates with Server-Sent Events</a>,\n * by Eric Bidelman\n */\npublic final class SSE {\n    /*\n     *see http://www.html5rocks.com/en/tutorials/eventsource/basics/\n     */\n    /**\n     * This method returns a new {@link HttpResponse HttpResponse} with\n     * its {@link HttpResponse.Builder#setContentType(String) content type}\n     * and {@link HttpResponse.Builder#setCharacterEncoding(java.nio.charset.Charset) character encoding} set\n     * in compliance with to the SSE spec, and an empty body.\n     *\n     * @param request the {@link HttpRequest} in response to which we wish to start an SSE stream.\n     * @return an {@link HttpResponse.Builder HttpResponse.Builder} (which can have other metadata, such as headers or cookies added to).\n     */\n    public static HttpResponse.Builder startSSE(ActorRef<? super WebMessage> from, HttpRequest request) {\n        return new HttpResponse.Builder(from, request)\n                .setContentType(\"text/event-stream\")\n                .setCharacterEncoding(Charset.forName(\"UTF-8\"))\n                .startActor();\n    }\n\n    /**\n     * This method returns a new {@link HttpResponse HttpResponse} with\n     * its {@link HttpResponse.Builder#setContentType(String) content type}\n     * and {@link HttpResponse.Builder#setCharacterEncoding(java.nio.charset.Charset) character encoding} set\n     * in compliance with to the SSE spec, and a body encoding a {@link #reconnectTimeout(long) reconnection timeout} indication.\n     *\n     * @param request          the {@link HttpRequest} in response to which we wish to start an SSE stream.\n     * @param reconnectTimeout the amount of time, in milliseconds, the client should wait before attempting to reconnect\n     *                         after the connection has closed (will be encoded in the message body as {@code retry: ...})\n     * @return an {@link HttpResponse.Builder HttpResponse.Builder} (which can have other metadata, such as headers or cookies added to).\n     */\n    public static HttpResponse.Builder startSSE(ActorRef<? super WebMessage> from, HttpRequest request, long reconnectTimeout) {\n        return new HttpResponse.Builder(from, request, retryString(reconnectTimeout) + '\\n')\n                .setContentType(\"text/event-stream\")\n                .setCharacterEncoding(Charset.forName(\"UTF-8\"))\n                .startActor();\n    }\n\n    /**\n     * Wrappes the whole string body\n     */\n    public static SendPort<WebDataMessage> wrapAsSSE(SendPort<WebDataMessage> actor) {\n        return Channels.mapSend(actor, new Function<WebDataMessage, WebDataMessage>() {\n            @Override\n            public WebDataMessage apply(WebDataMessage f) {\n                return new WebDataMessage(f.getFrom(), SSE.event(f.getStringBody()));\n            }\n        });\n    }\n\n    /**\n     * Returns the SSE last-event-id value from the request (the {@code Last-Event-ID} header).\n     *\n     * @param request the request\n     * @return the SSE last-event-id value from the request, or {@code -1} if not specified.\n     */\n    public static long getLastEventId(HttpRequest request) {\n        String str = request.getHeader(\"Last-Event-ID\");\n        if (str == null)\n            return -1;\n        return Long.parseLong(str);\n    }\n\n    /**\n     * Encodes a given payload as an SSE event message. The returned value can be used as the body of a {@link WebDataMessage}.\n     *\n     * @param id        the SSE event id (will be encoded in the message as {@code id: ...})\n     * @param eventType the name of the type of the event (will be encoded in the message as {@code event: ...})\n     * @param payload   the message payload (will be encoded in the message as {@code data: ...})\n     * @return the payload encoded as an SSE event\n     */\n    public static String event(long id, String eventType, String payload) {\n        return idString(id) + eventString(eventType) + dataString(payload) + '\\n';\n    }\n\n    /**\n     * Encodes a given payload as an SSE event message. The returned value can be used as the body of a {@link WebDataMessage}.\n     *\n     * @param eventType the name of the type of the event (will be encoded in the message as {@code event: ...})\n     * @param payload   the message payload (will be encoded in the message as {@code data: ...})\n     * @return the payload encoded as an SSE event\n     */\n    public static String event(String eventType, String payload) {\n        return dataString(payload) + '\\n';\n    }\n\n    /**\n     * Encodes a given payload and id as an SSE event message. The returned value can be used as the body of a {@link WebDataMessage}.\n     *\n     * @param id      the SSE event id (will be encoded in the message as {@code id: ...})\n     * @param payload the message payload (will be encoded in the message as {@code data: ...})\n     * @return the id and payload encoded as an SSE event\n     */\n    public static String event(long id, String payload) {\n        return idString(id) + dataString(payload) + '\\n';\n    }\n\n    /**\n     * Encodes a given payload as an SSE event message. The returned value can be used as the body of a {@link WebDataMessage}.\n     *\n     * @param payload the message payload the message payload (will be encoded in the message as {@code data: ...})\n     * @return the payload encoded as an SSE event\n     */\n    public static String event(String payload) {\n        return dataString(payload) + '\\n';\n    }\n\n    /**\n     * Encodes an indication to the client to attempt a reconnect if the connection is closed within the given time.\n     * This string may be concatenated ahead of a string encoding an SSE event, like so: {@code reconnectTimeout(t) + event(x)}).\n     *\n     * @param reconnectTimeout the amount of time, in milliseconds, the client should wait before attempting to reconnect\n     *                         after the connection has closed (will be encoded in the message as {@code retry: ...})\n     * @return a string encoding the reconnection timeout indication\n     */\n    public static String reconnectTimeout(long reconnectTimeout) {\n        return retryString(reconnectTimeout);\n    }\n\n    private static String idString(long id) {\n        return \"id: \" + id + '\\n';\n    }\n\n    private static String eventString(String eventName) {\n        return \"event: \" + eventName + '\\n';\n    }\n\n    private static String retryString(long reconnectTimeout) {\n        return \"retry: \" + reconnectTimeout + '\\n';\n    }\n\n    private static String dataString(String payload) {\n        String message = payload.trim();\n        if (message.charAt(message.length() - 1) == '\\n')\n            message = message.substring(0, message.length() - 1);\n        message = message.replaceAll(\"\\n\", \"\\ndata: \");\n        message = \"data: \" + message + '\\n';\n        return message;\n    }\n\n    private SSE() {\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/WebActor.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * A class annotated with this annotation will be automatically loaded by COMSAT\n * and spawned as a web actor.\n */\n@Documented\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.TYPE})\npublic @interface WebActor {\n    /**\n     * The name of the WebActor.\n     */\n    String name() default \"\";\n\n    /**\n     * Display name of this WebActor, if present.\n     */\n    String displayName() default \"\";\n\n    /**\n     * Description of this WebActor, if present.\n     */\n    String description() default \"\";\n\n    /**\n     * Array of HTTP URL patterns to which this WebActor applies.\n     * For example {@code /myservice}, or {@code /myservice/*}.\n     */\n    String[] httpUrlPatterns() default {};\n\n    /**\n     * Array of WebSocket URI patterns to which this WebActor applies.\n     * For example {@code /myservice/ws}, or {@code /myservice/ws/*}.\n     */\n    String[] webSocketUrlPatterns() default {};\n\n    /**\n     * A convenience property, to allow extremely simple annotation of a class -\n     * Array of HTTP URL patterns.\n     *\n     * @see #httpUrlPatterns()\n     */\n    String[] value() default {};\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/WebDataMessage.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport java.nio.ByteBuffer;\n\n/**\n * A message that can be received from or sent to a web client, and contains only data (and no metadata like headers).\n */\npublic class WebDataMessage extends WebMessage {\n    private final ActorRef<WebDataMessage> sender;\n    private final String string;\n    private final ByteBuffer byteBuffer;\n\n    /**\n     * Constructs a {@code WebDataMessage} with a text body.\n     * @param from the message sender\n     * @param body the message body\n     */\n    public WebDataMessage(ActorRef<? super WebDataMessage> from, String body) {\n        this.sender = (ActorRef<WebDataMessage>)from;\n        this.string = body;\n        this.byteBuffer = null;\n    }\n\n    /**\n     * Constructs a {@code WebDataMessage} with a binary body.\n     * @param from the message sender\n     * @param body the message body\n     */\n    public WebDataMessage(ActorRef<? super WebDataMessage> from, ByteBuffer body) {\n        this.sender = (ActorRef<WebDataMessage>)from;\n        this.string = null;\n        this.byteBuffer = body;\n    }\n\n    @Override\n    public ActorRef<WebDataMessage> getFrom() {\n        return sender;\n    }\n\n    /**\n     * Whether this is a binary message or a text message.\n     * @return {@code true} if this is a binary message; {@code false} if this is a text mesasge.\n     */\n    public boolean isBinary() {\n        return (byteBuffer != null);\n    }\n\n    @Override\n    public String getStringBody() {\n        return string;\n    }\n\n    @Override\n    public ByteBuffer getByteBufferBody() {\n        return byteBuffer;\n    }\n\n    @Override\n    protected String contentString() {\n        return super.contentString() + \n                \" size: \" + (string != null ? string.length() : byteBuffer != null ? byteBuffer.remaining() : 0) +\n                (isBinary() ? \"\" : \" data: \" + string);\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/WebMessage.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.actors.behaviors.ActorMessage;\nimport co.paralleluniverse.actors.behaviors.FromMessage;\nimport java.nio.ByteBuffer;\n\n/**\n * A message that is received from or can be set to a web client (via HTTP or WebSockets).\n * The message has either a {@link #getStringBody() text body} or a {@link #getByteBufferBody() binary} body (but not both).\n */\npublic abstract class WebMessage extends ActorMessage implements FromMessage {\n    /**\n     * The actor that sent this message. This can be a virtual actor representing the web client.\n     */\n    @Override\n    public abstract ActorRef<? extends WebMessage> getFrom();\n\n    /**\n     * The message's text body, if it has one; {@code null} otherwise.\n     */\n    public abstract String getStringBody();\n\n    /**\n     * The message's binary body, if it has one; {@code null} otherwise.\n     */\n    public abstract ByteBuffer getByteBufferBody();\n\n    @Override\n    protected String contentString() {\n        return super.contentString() + \" from: \" + getFrom();\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/WebSocketOpened.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.ActorRef;\n\n/**\n * A message sent to a web actor indicating that a new WebSocket has been opened by the client.\n */\npublic class WebSocketOpened extends WebStreamOpened {\n    public WebSocketOpened(ActorRef<WebDataMessage> actor) {\n        super(actor);\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/WebStreamOpened.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport java.nio.ByteBuffer;\n\n/**\n * A message sent to a web actor indicating that a new stream has been opened by the client.\n * The stream is usually a WebSocket or an SSE stream.\n */\npublic class WebStreamOpened extends WebMessage {\n    private final ActorRef<WebDataMessage> actor;\n\n    public WebStreamOpened(ActorRef<WebDataMessage> actor) {\n        this.actor = actor;\n    }\n\n    @Override\n    public ActorRef<WebDataMessage> getFrom() {\n        return actor;\n    }\n\n    /**\n     * {@inheritDoc}\n     * <p>This method returns {@code null}, as it has no body.\n     *\n     * @return {@code null}\n     */\n    @Override\n    public String getStringBody() {\n        return null;\n    }\n\n    /**\n     * {@inheritDoc}\n     * <p>This method returns {@code null}, as it has no body.\n     *\n     * @return {@code null}\n     */\n    @Override\n    public ByteBuffer getByteBufferBody() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-api/src/main/java/co/paralleluniverse/comsat/webactors/package-info.java",
    "content": "/*\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n * \n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *  \n *   or (per the licensee's choosing)\n *  \n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/**\n * The Web Actors API\n */\npackage co.paralleluniverse.comsat.webactors;\n"
  },
  {
    "path": "comsat-actors-netty/src/main/java/co/paralleluniverse/comsat/webactors/netty/AutoWebActorHandler.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.netty;\n\nimport co.paralleluniverse.actors.Actor;\nimport co.paralleluniverse.actors.ActorImpl;\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.actors.ActorSpec;\nimport co.paralleluniverse.common.reflection.AnnotationUtil;\nimport co.paralleluniverse.common.reflection.ClassLoaderUtil;\nimport co.paralleluniverse.common.util.Pair;\nimport co.paralleluniverse.comsat.webactors.WebActor;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\nimport io.netty.handler.codec.http.FullHttpRequest;\nimport io.netty.handler.codec.http.cookie.Cookie;\nimport io.netty.util.internal.logging.InternalLogger;\nimport io.netty.util.internal.logging.InternalLoggerFactory;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\nimport java.net.URLClassLoader;\nimport java.util.*;\n\n/**\n * @author circlespainter\n */\npublic class AutoWebActorHandler extends WebActorHandler {\n    private static final InternalLogger log = InternalLoggerFactory.getInstance(AutoWebActorHandler.class);\n    private static final List<Class<?>> actorClasses = new ArrayList<>(32);\n    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];\n\n    public AutoWebActorHandler() {\n        this(null, null, null, null);\n    }\n\n    public AutoWebActorHandler(List<String> packagePrefixes) {\n        this(null, null, packagePrefixes, null);\n    }\n\n    public AutoWebActorHandler(String httpResponseEncoderName, List<String> packagePrefixes) {\n        this(httpResponseEncoderName, null, packagePrefixes, null);\n    }\n\n    public AutoWebActorHandler(String httpResponseEncoderName) {\n        this(httpResponseEncoderName, null, null, null);\n    }\n\n    public AutoWebActorHandler(String httpResponseEncoderName, ClassLoader userClassLoader) {\n        this(httpResponseEncoderName, userClassLoader, null, null);\n    }\n\n    public AutoWebActorHandler(String httpResponseEncoderName, ClassLoader userClassLoader, List<String> packagePrefixes) {\n        this(httpResponseEncoderName, userClassLoader, packagePrefixes, null);\n    }\n\n    public AutoWebActorHandler(String httpResponseEncoderName, Map<Class<?>, Object[]> actorParams) {\n        this(httpResponseEncoderName, null, null, actorParams);\n    }\n\n    public AutoWebActorHandler(String httpResponseEncoderName, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams) {\n        this(httpResponseEncoderName, null, packagePrefixes, actorParams);\n    }\n\n    public AutoWebActorHandler(String httpResponseEncoderName, ClassLoader userClassLoader, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams) {\n        super(null, httpResponseEncoderName);\n        super.contextProvider = newContextProvider(userClassLoader != null ? userClassLoader : ClassLoader.getSystemClassLoader(), packagePrefixes, actorParams);\n    }\n\n    public AutoWebActorHandler(String httpResponseEncoderName, AutoContextProvider prov) {\n        super(prov, httpResponseEncoderName);\n    }\n\n    protected AutoContextProvider newContextProvider(ClassLoader userClassLoader, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams) {\n        return new AutoContextProvider(userClassLoader, packagePrefixes, actorParams);\n    }\n\n    public static class AutoContextProvider implements WebActorContextProvider {\n        private final ClassLoader userClassLoader;\n        private final List<String> packagePrefixes;\n        private final Map<Class<?>, Object[]> actorParams;\n        private final Long defaultContextValidityMS;\n\n        public AutoContextProvider(ClassLoader userClassLoader, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams) {\n            this(userClassLoader, packagePrefixes, actorParams, null);\n        }\n\n        public AutoContextProvider(ClassLoader userClassLoader, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams, Long defaultContextValidityMS) {\n            this.userClassLoader = userClassLoader;\n            this.packagePrefixes = packagePrefixes;\n            this.actorParams = actorParams;\n            this.defaultContextValidityMS = defaultContextValidityMS;\n        }\n\n        @Override\n        public final Context get(final FullHttpRequest req) {\n            final String sessionId = getSessionId(req);\n            if (sessionId != null && sessionsEnabled()) {\n                final Context actorContext = sessions.get(sessionId);\n                if (actorContext != null) {\n                    if (actorContext.renew())\n                        return actorContext;\n                    else\n                        sessions.remove(sessionId); // Evict session\n                }\n            }\n            return newActorContext(req);\n        }\n\n        protected AutoContext newActorContext(FullHttpRequest req) {\n            final AutoContext c = new AutoContext(req, packagePrefixes, actorParams, userClassLoader);\n            if (defaultContextValidityMS !=  null)\n                c.setValidityMS(defaultContextValidityMS);\n            return c;\n        }\n\n        private String getSessionId(FullHttpRequest req) {\n            final Set<Cookie> cookies = NettyHttpRequest.getNettyCookies(req);\n            if (cookies != null) {\n                for (final Cookie c : cookies) {\n                    if (c != null && SESSION_COOKIE_KEY.equals(c.name()))\n                        return c.value();\n                }\n            }\n            return null;\n        }\n    }\n\n    private static class AutoContext extends DefaultContextImpl {\n        private String id;\n\n        private final List<String> packagePrefixes;\n        private final Map<Class<?>, Object[]> actorParams;\n        private final ClassLoader userClassLoader;\n        private Class<? extends ActorImpl<? extends WebMessage>> actorClass;\n        private ActorRef<? extends WebMessage> actorRef;\n\n        public AutoContext(FullHttpRequest req, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams, ClassLoader userClassLoader) {\n            this.packagePrefixes = packagePrefixes;\n            this.actorParams = actorParams;\n            this.userClassLoader = userClassLoader;\n            fillActor(req);\n        }\n\n        private void fillActor(FullHttpRequest req) {\n            final Pair<ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>> p = autoCreateActor(req);\n            if (p != null) {\n                actorRef = p.getFirst();\n                actorClass = p.getSecond();\n            }\n        }\n\n        @Override\n        public final String getId() {\n            return id != null ? id : (id = UUID.randomUUID().toString());\n        }\n\n        @Override\n        public final void restart(FullHttpRequest req) {\n            renewed = new Date().getTime();\n            fillActor(req);\n        }\n\n        @Override\n        public final ActorRef<? extends WebMessage> getWebActor() {\n            return actorRef;\n        }\n\n        @Override\n        public final boolean handlesWithHttp(String uri) {\n            return WebActorHandler.handlesWithHttp(uri, actorClass);\n        }\n\n        @Override\n        public final boolean handlesWithWebSocket(String uri) {\n            return WebActorHandler.handlesWithWebSocket(uri, actorClass);\n        }\n\n        @Override\n        public WatchPolicy watch() {\n            return WatchPolicy.DIE_IF_EXCEPTION_ELSE_RESTART;\n        }\n\n        @SuppressWarnings(\"unchecked\")\n        private Pair<ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>> autoCreateActor(FullHttpRequest req) {\n            registerActorClasses();\n            final String uri = req.getUri();\n            for (final Class<?> c : actorClasses) {\n                if (WebActorHandler.handlesWithHttp(uri, c) || WebActorHandler.handlesWithWebSocket(uri, c))\n                    return new Pair<ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>>(\n                        Actor.newActor (\n                            new ActorSpec(c, actorParams != null ? actorParams.get(c) : EMPTY_OBJECT_ARRAY)\n                        ).spawn(),\n                        (Class<? extends ActorImpl<? extends WebMessage>>) c\n                    );\n            }\n            return null;\n        }\n\n        private synchronized void registerActorClasses() {\n            if (actorClasses.isEmpty()) {\n                try {\n                    final ClassLoader classLoader = userClassLoader != null ? userClassLoader : this.getClass().getClassLoader();\n                    ClassLoaderUtil.accept((URLClassLoader) classLoader, new ClassLoaderUtil.Visitor() {\n                        @Override\n                        public final void visit(String resource, URL url, ClassLoader cl) {\n                            if (packagePrefixes != null) {\n                                boolean found = false;\n                                for (final String packagePrefix : packagePrefixes) {\n                                    if (packagePrefix != null && resource.startsWith(packagePrefix.replace('.', '/'))) {\n                                        found = true;\n                                        break;\n                                    }\n                                }\n                                if (!found)\n                                    return;\n                            }\n                            if (!ClassLoaderUtil.isClassFile(resource))\n                                return;\n                            final String className = ClassLoaderUtil.resourceToClass(resource);\n                            try (final InputStream is = cl.getResourceAsStream(resource)) {\n                                if (AnnotationUtil.hasClassAnnotation(WebActor.class, is))\n                                    registerWebActor(cl.loadClass(className));\n                            } catch (final IOException | ClassNotFoundException e) {\n                                log.error(\"Exception while scanning class \" + className + \" for WebActor annotation\", e);\n                                throw new RuntimeException(e);\n                            }\n                        }\n\n                        private void registerWebActor(Class<?> c) {\n                            actorClasses.add(c);\n                        }\n                    });\n                } catch (final IOException e) {\n                    log.error(\"IOException while scanning classes for WebActor annotation\", e);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-actors-netty/src/main/java/co/paralleluniverse/comsat/webactors/netty/NettyHttpRequest.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.netty;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.comsat.webactors.Cookie;\nimport co.paralleluniverse.comsat.webactors.HttpRequest;\nimport co.paralleluniverse.comsat.webactors.HttpResponse;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\nimport com.google.common.collect.*;\nimport io.netty.buffer.ByteBuf;\nimport io.netty.buffer.Unpooled;\nimport io.netty.channel.ChannelHandlerContext;\nimport io.netty.handler.codec.http.FullHttpRequest;\nimport io.netty.handler.codec.http.HttpHeaders;\nimport io.netty.handler.codec.http.QueryStringDecoder;\nimport io.netty.handler.codec.http.cookie.ServerCookieDecoder;\n\nimport java.net.InetSocketAddress;\nimport java.net.SocketAddress;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.CharacterCodingException;\nimport java.nio.charset.Charset;\nimport java.nio.charset.CodingErrorAction;\nimport java.nio.charset.UnsupportedCharsetException;\nimport java.util.*;\n\nimport static io.netty.handler.codec.http.HttpHeaders.Names.*;\n\n/**\n * @author circlespainter\n */\npublic final class NettyHttpRequest extends HttpRequest {\n    public static final String CHARSET_MARKER_STRING = \"charset=\";\n\n    final ActorRef<? super HttpResponse> actorRef;\n    final FullHttpRequest req;\n    final ChannelHandlerContext ctx;\n    final String sessionId;\n\n    private static final Set<io.netty.handler.codec.http.cookie.Cookie> EMPTY_SET = new HashSet<>();\n\n    private final ByteBuf reqContent;\n\n    private InetSocketAddress sourceAddress;\n    private ImmutableMultimap<String, String> params;\n    private URI uri;\n    private Collection<Cookie> cookies;\n    private ListMultimap<String, String> heads;\n    private ByteBuffer byteBufferBody;\n    private String stringBody;\n    private Charset encoding;\n    private String contentType;\n\n    public NettyHttpRequest(ActorRef<? super HttpResponse> actorRef, ChannelHandlerContext ctx, FullHttpRequest req, String sessionId) {\n        this.actorRef = actorRef;\n        this.ctx = ctx;\n        this.req = req;\n        this.sessionId = sessionId;\n\n        reqContent = Unpooled.copiedBuffer(req.content());\n    }\n\n    @Override\n    public final String getSourceHost() {\n        fillSourceAddress();\n        return sourceAddress != null ? sourceAddress.getHostString() : null;\n    }\n\n    @Override\n    public final int getSourcePort() {\n        fillSourceAddress();\n        return sourceAddress != null ? sourceAddress.getPort() : -1;\n    }\n\n    private void fillSourceAddress() {\n        final SocketAddress remoteAddress = ctx.channel().remoteAddress();\n        if (sourceAddress == null && remoteAddress instanceof InetSocketAddress) {\n            sourceAddress = (InetSocketAddress) remoteAddress;\n        }\n    }\n\n    @Override\n    public final Multimap<String, String> getParameters() {\n        QueryStringDecoder queryStringDecoder;\n        if (params == null) {\n            queryStringDecoder = new QueryStringDecoder(req.getUri());\n            final ImmutableMultimap.Builder<String, String> builder = ImmutableMultimap.builder();\n            final Map<String, List<String>> parameters = queryStringDecoder.parameters();\n            for (final String k : parameters.keySet())\n                builder.putAll(k, parameters.get(k));\n            params = builder.build();\n        }\n        return params;\n    }\n\n    @Override\n    public final Map<String, Object> getAttributes() {\n        return ImmutableMap.of(); // No attributes in Netty; Guava's impl. will return a pre-built instance\n    }\n\n    @Override\n    public final String getScheme() {\n        initUri();\n        return uri.getScheme();\n    }\n\n    private void initUri() {\n        if (uri == null) {\n            try {\n                uri = new URI(req.getUri());\n            } catch (final URISyntaxException e) {\n                throw new RuntimeException(e);\n            }\n        }\n    }\n\n    @Override\n    public final String getMethod() {\n        return req.getMethod().name();\n    }\n\n    @Override\n    public final String getPathInfo() {\n        initUri();\n        return uri.getPath();\n    }\n\n    @Override\n    public final String getContextPath() {\n        return \"/\"; // Context path makes sense only for servlets\n    }\n\n    @Override\n    public final String getQueryString() {\n        initUri();\n        return uri.getQuery();\n    }\n\n    @Override\n    public final String getRequestURI() {\n        return req.getUri();\n    }\n\n    @Override\n    public final String getServerName() {\n        initUri();\n        return uri.getHost();\n    }\n\n    @Override\n    public final int getServerPort() {\n        initUri();\n        return uri.getPort();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public final ActorRef<WebMessage> getFrom() {\n        return (ActorRef<WebMessage>) actorRef;\n    }\n\n    @Override\n    public final ListMultimap<String, String> getHeaders() {\n        if (heads == null) {\n            heads = extractHeaders(req.headers());\n        }\n        return heads;\n    }\n\n    @Override\n    public final Collection<Cookie> getCookies() {\n        if (cookies == null) {\n            final ImmutableList.Builder<Cookie> builder = ImmutableList.builder();\n            for (io.netty.handler.codec.http.cookie.Cookie c : getNettyCookies(req)) {\n                builder.add(\n                    Cookie.cookie(c.name(), c.value())\n                        .setDomain(c.domain())\n                        .setPath(c.path())\n                        .setHttpOnly(c.isHttpOnly())\n                        .setMaxAge((int) c.maxAge())\n                        .setSecure(c.isSecure())\n                        .build()\n                );\n            }\n            cookies = builder.build();\n        }\n        return cookies;\n    }\n\n    static Set<io.netty.handler.codec.http.cookie.Cookie> getNettyCookies(FullHttpRequest req) {\n        final HttpHeaders heads = req.headers();\n        final String head = heads != null ? heads.get(HttpHeaders.Names.COOKIE) : null;\n        if (head != null)\n            return ServerCookieDecoder.LAX.decode(head);\n        else\n            return EMPTY_SET;\n    }\n\n    @Override\n    public final int getContentLength() {\n        final String stringBody = getStringBody();\n        if (stringBody != null)\n            return stringBody.length();\n        final ByteBuffer bufferBody = getByteBufferBody();\n        if (bufferBody != null)\n            return bufferBody.remaining();\n        return 0;\n    }\n\n    @Override\n    public final Charset getCharacterEncoding() {\n        if (encoding == null)\n            encoding = extractCharacterEncoding(getHeaders());\n        return encoding;\n    }\n\n    @Override\n    public final String getContentType() {\n        if (contentType == null) {\n            getHeaders();\n            if (heads != null) {\n                final List<String> cts = heads.get(CONTENT_TYPE);\n                if (cts != null && cts.size() > 0)\n                    contentType = cts.get(0);\n            }\n        }\n        return null;\n    }\n\n    @Override\n    public final String getStringBody() {\n        if (stringBody == null) {\n            if (byteBufferBody != null)\n                return null;\n            decodeStringBody();\n        }\n        return stringBody;\n    }\n\n    @Override\n    public final ByteBuffer getByteBufferBody() {\n        if (byteBufferBody == null) {\n            if (stringBody != null)\n                return null;\n            if (reqContent != null)\n                byteBufferBody = reqContent.nioBuffer();\n        }\n        return byteBufferBody;\n    }\n\n    public final String getSessionId() {\n        return sessionId;\n    }\n\n    public ChannelHandlerContext getContext() {\n        return ctx;\n    }\n\n    public FullHttpRequest getRequest() {\n        return req;\n    }\n\n    private String decodeStringBody() {\n        if (reqContent != null) {\n            try {\n                stringBody =\n                    getCharacterEncodingOrDefault()\n                        .newDecoder()\n                        .onMalformedInput(CodingErrorAction.REPORT)\n                        .onUnmappableCharacter(CodingErrorAction.REPORT)\n                        .decode(reqContent.nioBuffer())\n                        .toString();\n            } catch (CharacterCodingException ignored) {\n            }\n        }\n        return stringBody;\n    }\n\n    Charset getCharacterEncodingOrDefault() {\n        return getCharacterEncodingOrDefault(getCharacterEncoding());\n    }\n\n    static Charset extractCharacterEncodingOrDefault(HttpHeaders headers) {\n        return getCharacterEncodingOrDefault(extractCharacterEncoding(extractHeaders(headers)));\n    }\n\n    static Charset extractCharacterEncoding(ListMultimap<String, String> heads) {\n        if (heads != null) {\n            final List<String> cts = heads.get(CONTENT_TYPE);\n            if (cts != null && cts.size() > 0) {\n                final String ct = cts.get(0).trim().toLowerCase();\n                if (ct.contains(CHARSET_MARKER_STRING)) {\n                    try {\n                        return Charset.forName(ct.substring(ct.indexOf(CHARSET_MARKER_STRING) + CHARSET_MARKER_STRING.length()).trim());\n                    } catch (UnsupportedCharsetException ignored) {\n                    }\n                }\n            }\n        }\n        return null;\n    }\n\n    static ImmutableListMultimap<String, String> extractHeaders(HttpHeaders headers) {\n        if (headers != null) {\n            final ImmutableListMultimap.Builder<String, String> builder = ImmutableListMultimap.builder();\n            for (final String n : headers.names())\n                // Normalize header names by their conversion to lower case\n                builder.putAll(n.toLowerCase(Locale.ENGLISH), headers.getAll(n));\n            return builder.build();\n        }\n        return null;\n    }\n\n    private static Charset getCharacterEncodingOrDefault(Charset characterEncoding) {\n        if (characterEncoding == null)\n            return Charset.defaultCharset();\n        return characterEncoding;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-netty/src/main/java/co/paralleluniverse/comsat/webactors/netty/WebActorHandler.java",
    "content": "/*\n/*\n * COMSAT\n * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.netty;\n\nimport co.paralleluniverse.actors.*;\nimport co.paralleluniverse.common.util.Pair;\nimport co.paralleluniverse.common.util.SystemProperties;\nimport co.paralleluniverse.comsat.webactors.*;\nimport co.paralleluniverse.comsat.webactors.Cookie;\nimport co.paralleluniverse.comsat.webactors.HttpRequest;\nimport co.paralleluniverse.comsat.webactors.HttpResponse;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.strands.Timeout;\nimport co.paralleluniverse.strands.channels.SendPort;\nimport co.paralleluniverse.strands.concurrent.CountDownLatch;\nimport co.paralleluniverse.strands.concurrent.ReentrantLock;\nimport io.netty.buffer.ByteBuf;\nimport io.netty.buffer.Unpooled;\nimport io.netty.channel.*;\nimport io.netty.handler.codec.http.*;\n\nimport static io.netty.handler.codec.http.HttpResponseStatus.*;\nimport static io.netty.handler.codec.http.HttpHeaders.Names.*;\n\nimport io.netty.handler.codec.http.cookie.ServerCookieEncoder;\nimport io.netty.handler.codec.http.websocketx.*;\nimport io.netty.util.concurrent.GenericFutureListener;\nimport io.netty.util.internal.logging.InternalLogger;\nimport io.netty.util.internal.logging.InternalLoggerFactory;\n\nimport java.nio.ByteBuffer;\nimport java.nio.charset.Charset;\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicReference;\n\n/**\n * @author circlespainter\n */\npublic class WebActorHandler extends SimpleChannelInboundHandler<Object> {\n    protected static final ScheduledExecutorService ts = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());\n\n    // @FunctionalInterface\n    public interface WebActorContextProvider {\n        Context get(FullHttpRequest req);\n    }\n\n    public interface Context {\n        String getId();\n        ReentrantLock getLock();\n\n        boolean isValid() throws SuspendExecution, InterruptedException;\n        void invalidate() throws SuspendExecution, InterruptedException;\n\n        boolean renew();\n        void restart(FullHttpRequest r);\n\n        ActorRef<? extends WebMessage> getWebActor();\n        boolean handlesWithHttp(String uri);\n        boolean handlesWithWebSocket(String uri);\n\n        enum WatchPolicy { DONT_WATCH, DIE, DIE_IF_EXCEPTION_ELSE_RESTART, RESTART }\n        WatchPolicy watch();\n\n        Map<String, Object> getAttachments();\n    }\n\n    public static abstract class DefaultContextImpl implements Context {\n        private final static String durationProp = System.getProperty(DefaultContextImpl.class.getName() + \".durationMillis\");\n        private final static long DURATION = durationProp != null ? Long.parseLong(durationProp) : 60_000L;\n        private final ReentrantLock lock = new ReentrantLock();\n        @SuppressWarnings(\"unused\")\n        private final long created;\n        private final Map<String, Object> attachments = new HashMap<>();\n\n        protected long renewed;\n        private Long validityMS;\n\n        private boolean valid = true;\n\n        public DefaultContextImpl() {\n            renewed = created = new Date().getTime();\n        }\n\n        @Override\n        public void invalidate() throws SuspendExecution, InterruptedException {\n            final HttpActorAdapter actor = (HttpActorAdapter) attachments.get(ACTOR_KEY);\n            if (actor != null)\n                actor.handleDie(null);\n            attachments.clear();\n            valid = false;\n        }\n\n        @Override\n        public final boolean isValid() throws SuspendExecution, InterruptedException {\n            final boolean ret = valid && (new Date().getTime() - renewed) <= getValidityMS();\n            if (!ret)\n                invalidate();\n            return ret;\n        }\n\n        @Override\n        public final boolean renew() {\n            if (!valid)\n                return false;\n\n            renewed = new Date().getTime();\n            return true;\n        }\n\n        @Override\n        public final Map<String, Object> getAttachments() {\n            return attachments;\n        }\n\n        @Override\n        public final ReentrantLock getLock() {\n            return lock;\n        }\n\n        public void setValidityMS(long validityMS) {\n            this.validityMS = validityMS;\n        }\n\n        public long getValidityMS() {\n            return validityMS != null ? validityMS : DURATION;\n        }\n    }\n\n    public WebActorHandler(WebActorContextProvider contextProvider) {\n        this(contextProvider, null);\n    }\n\n    public WebActorHandler(WebActorContextProvider contextProvider, String httpResponseEncoderName) {\n        this.contextProvider = contextProvider;\n        this.httpResponseEncoderName = httpResponseEncoderName;\n    }\n\n    @Override\n    public final void channelReadComplete(ChannelHandlerContext ctx) {\n        ctx.flush();\n    }\n\n    @Override\n    public final void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {\n        if (ctx.channel().isOpen())\n            ctx.close();\n        log.error(\"Exception caught\", cause);\n    }\n\n    @Override\n    protected final void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {\n        if (msg instanceof FullHttpRequest) {\n            handleHttpRequest(ctx, (FullHttpRequest) msg);\n        } else if (msg instanceof WebSocketFrame) {\n            handleWebSocketFrame(ctx, (WebSocketFrame) msg);\n        } else {\n            throw new AssertionError(\"Unexpected message \" + msg);\n        }\n    }\n\n    protected static boolean sessionsEnabled() {\n        return \"always\".equals(trackSession) || \"sse\".equals(trackSession);\n    }\n\n    protected final static String SESSION_COOKIE_KEY = \"JSESSIONID\";\n    protected final static String TRACK_SESSION_PROP = HttpChannelAdapter.class.getName() + \".trackSession\";\n    protected final static String trackSession = System.getProperty(TRACK_SESSION_PROP, \"sse\");\n\n    protected final static String OMIT_DATE_HEADER_PROP = HttpChannelAdapter.class.getName() + \".omitDateHeader\";\n    protected final static Boolean omitDateHeader = SystemProperties.isEmptyOrTrue(OMIT_DATE_HEADER_PROP);\n\n    protected final static ConcurrentHashMap<String, Context> sessions = new ConcurrentHashMap<>();\n    protected final static ReentrantLock sessionsLock = new ReentrantLock();\n\n    protected WebActorContextProvider contextProvider;\n    protected String httpResponseEncoderName;\n\n    private static final String ACTOR_KEY = \"co.paralleluniverse.comsat.webactors.sessionActor\";\n\n    private static final WeakHashMap<Class<?>, List<Pair<String, String>>> classToUrlPatterns = new WeakHashMap<>();\n    private static final InternalLogger log = InternalLoggerFactory.getInstance(AutoWebActorHandler.class);\n\n    private WebSocketServerHandshaker handshaker;\n    private WebSocketActorAdapter webSocketActor;\n\n    private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {\n        // Check for closing frame\n        if (frame instanceof CloseWebSocketFrame) {\n            handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain());\n            return;\n        }\n\n        if (frame instanceof PingWebSocketFrame) {\n            ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content().retain()));\n            return;\n        }\n\n        if (frame instanceof ContinuationWebSocketFrame)\n            return;\n\n        if (frame instanceof TextWebSocketFrame)\n            webSocketActor.onMessage(((TextWebSocketFrame) frame).text());\n        else\n            webSocketActor.onMessage(frame.content().nioBuffer());\n    }\n\n    private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) throws SuspendExecution, InterruptedException {\n        // Handle a bad request.\n        if (!req.getDecoderResult().isSuccess()) {\n            sendHttpError(ctx, req, new DefaultFullHttpResponse(req.getProtocolVersion(), BAD_REQUEST));\n            return;\n        }\n\n        final String uri = req.getUri();\n\n        final Context actorCtx = contextProvider.get(req);\n        assert actorCtx != null;\n        final String sessionId = actorCtx.getId();\n        assert sessionId != null;\n\n        final ReentrantLock lock = actorCtx.getLock();\n        assert lock != null;\n\n        lock.lock();\n\n        try {\n            final ActorRef<? extends WebMessage> userActorRef = actorCtx.getWebActor();\n            ActorImpl internalActor = (ActorImpl) actorCtx.getAttachments().get(ACTOR_KEY);\n\n            if (userActorRef != null) {\n                if (actorCtx.handlesWithWebSocket(uri)) {\n                    if (internalActor == null || !(internalActor instanceof WebSocketActorAdapter)) {\n                        //noinspection unchecked\n                        webSocketActor = new WebSocketActorAdapter(ctx, (ActorRef<? super WebMessage>) userActorRef);\n                        addActorToContextAndUnlock(actorCtx, webSocketActor, lock);\n                    }\n                    // Handshake\n                    final WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(uri, null, true);\n                    handshaker = wsFactory.newHandshaker(req);\n                    if (handshaker == null) {\n                        WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());\n                    } else {\n                        @SuppressWarnings(\"unchecked\") final ActorRef<WebMessage> userActorRef0 = (ActorRef<WebMessage>) webSocketActor.userActor;\n                        handshaker.handshake(ctx.channel(), req).addListener(new GenericFutureListener<ChannelFuture>() {\n                            @Override\n                            @Suspendable\n                            public void operationComplete(ChannelFuture future) throws Exception {\n                                userActorRef0.send(new WebSocketOpened(WebActorHandler.this.webSocketActor.ref()));\n                            }\n                        });\n                    }\n                    return;\n                } else if (actorCtx.handlesWithHttp(uri)) {\n                    if (internalActor == null || !(internalActor instanceof HttpActorAdapter)) {\n                        //noinspection unchecked\n                        internalActor = new HttpActorAdapter((ActorRef<HttpRequest>) userActorRef, actorCtx, httpResponseEncoderName);\n                        addActorToContextAndUnlock(actorCtx, internalActor, lock);\n                    }\n                    //noinspection unchecked\n                    ((HttpActorAdapter) internalActor).handleRequest(new NettyHttpRequest(internalActor.ref(), ctx, req, sessionId));\n                    return;\n                }\n            }\n        } finally {\n            if (lock.isHeldByCurrentStrand() && lock.isLocked())\n                lock.unlock();\n        }\n\n        sendHttpError(ctx, req, new DefaultFullHttpResponse(req.getProtocolVersion(), NOT_FOUND));\n    }\n\n    static void addActorToContextAndUnlock(Context actorContext, ActorImpl actor, ReentrantLock lock) {\n        try {\n            actorContext.getAttachments().put(ACTOR_KEY, actor);\n        } finally {\n            if (lock.isLocked() && lock.isHeldByCurrentStrand())\n                lock.unlock();\n        }\n    }\n\n    private static final class WebSocketActorAdapter extends FakeActor<WebDataMessage> {\n        ActorRef<? super WebMessage> userActor;\n\n        private ChannelHandlerContext ctx;\n\n        public WebSocketActorAdapter(ChannelHandlerContext ctx, ActorRef<? super WebMessage> userActor) {\n            super(userActor.getName(), new WebSocketChannelAdapter(ctx));\n            ((WebSocketChannelAdapter) (SendPort) getMailbox()).actor = this;\n            this.ctx = ctx;\n            this.userActor = userActor;\n            watch(userActor);\n        }\n\n        @Override\n        public final void interrupt() {\n            die(new InterruptedException());\n        }\n\n        @Override\n        public final String toString() {\n            return \"WebSocketActorAdapter{\" + \"userActor=\" + userActor + '}';\n        }\n\n        private void onMessage(final ByteBuffer message) {\n            try {\n                userActor.send(new WebDataMessage(ref(), message));\n            } catch (SuspendExecution ex) {\n                throw new AssertionError(ex);\n            }\n        }\n\n        private void onMessage(final String message) {\n            try {\n                userActor.send(new WebDataMessage(ref(), message));\n            } catch (SuspendExecution ex) {\n                throw new AssertionError(ex);\n            }\n        }\n\n        @Override\n        protected final WebDataMessage handleLifecycleMessage(LifecycleMessage m) {\n            if (m instanceof ExitMessage) {\n                ExitMessage em = (ExitMessage) m;\n                if (em.getActor() != null && em.getActor().equals(userActor))\n                    die(em.getCause());\n            }\n            return null;\n        }\n\n        @Override\n        protected final void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        protected final void die(Throwable cause) {\n            super.die(cause);\n            if (ctx.channel().isOpen())\n                ctx.close();\n\n            // Ensure to release server references\n            userActor = null;\n            ctx = null;\n        }\n    }\n\n    private static final class WebSocketChannelAdapter implements SendPort<WebDataMessage> {\n        private final ChannelHandlerContext ctx;\n\n        WebSocketActorAdapter actor;\n\n        public WebSocketChannelAdapter(ChannelHandlerContext ctx) {\n            this.ctx = ctx;\n        }\n\n        @Override\n        public final void send(WebDataMessage message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            return trySend(message);\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        public final boolean trySend(WebDataMessage message) {\n            if (!message.isBinary())\n                ctx.writeAndFlush(new TextWebSocketFrame(message.getStringBody()));\n            else\n                ctx.writeAndFlush(new BinaryWebSocketFrame(Unpooled.wrappedBuffer(message.getByteBufferBody())));\n            return true;\n        }\n\n        @Override\n        public final void close() {\n            if (ctx.channel().isOpen())\n                ctx.close();\n            actor.die(null);\n        }\n\n        @Override\n        public final void close(Throwable t) {\n            actor.die(t);\n            close();\n        }\n    }\n\n    private static final class HttpActorAdapter extends FakeActor<HttpResponse> {\n        private final static String replyTimeoutProp = System.getProperty(HttpActorAdapter.class.getName() + \".replyTimeout\");\n        private static final long REPLY_TIMEOUT = replyTimeoutProp != null ? Long.parseLong(replyTimeoutProp) : 120_000L;\n\n        private final AtomicReference<CountDownLatch> gate = new AtomicReference<>();\n\n        private final String httpResponseEncoderName;\n\n        private volatile ActorRef<? super HttpRequest> userActor;\n        private volatile Context context;\n\n        private volatile ChannelHandlerContext ctx;\n        private volatile FullHttpRequest req;\n        private volatile boolean needsRestart;\n\n        private volatile Object watchToken;\n        private volatile boolean dead;\n\n        private volatile ScheduledFuture<?> cancelTask;\n\n        HttpActorAdapter(ActorRef<? super HttpRequest> userActor, Context actorContext, String httpResponseEncoderName) {\n            super(\"HttpActorAdapter\", new HttpChannelAdapter());\n\n            ((HttpChannelAdapter) (SendPort) getMailbox()).actor = this;\n            if (actorContext.watch() != Context.WatchPolicy.DONT_WATCH) {\n                if (userActor != null)\n                    watchToken = watch(userActor);\n            }\n\n            this.userActor = userActor;\n            this.context = actorContext;\n            this.httpResponseEncoderName = httpResponseEncoderName;\n        }\n\n        @Override\n        public final String toString() {\n            return \"HttpActorAdapter{\" + userActor + \"}\";\n        }\n\n        @Override\n        @Suspendable\n        protected final HttpResponse handleLifecycleMessage(LifecycleMessage m) {\n            handleLifecycle(m);\n            return null;\n        }\n\n        @Override\n        @Suspendable\n        protected final void die(Throwable cause) {\n            handleDie(cause);\n        }\n\n        @Override\n        @Suspendable\n        protected final void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        @Suspendable\n        protected final void interrupt() {\n            die(new InterruptedException());\n        }\n\n        final boolean handleLifecycle(LifecycleMessage l) {\n            if (l instanceof ExitMessage) {\n                final ExitMessage em = (ExitMessage) l;\n                if (em.getActor() != null && em.getActor().equals(userActor)) {\n                    possiblyReplyDeadAndUnblock(em.getCause());\n\n                    final Context.WatchPolicy wp = context.watch();\n                    //noinspection ThrowableResultOfMethodCallIgnored\n                    if (wp == Context.WatchPolicy.RESTART ||\n                        wp == Context.WatchPolicy.DIE_IF_EXCEPTION_ELSE_RESTART && em.getCause() == null) {\n                        needsRestart = true;\n                    } else {\n                        die(em.getCause());\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        final void handleRequest(NettyHttpRequest s) throws SuspendExecution, InterruptedException {\n            blockSessionRequests();\n\n            ctx = s.ctx;\n            req = s.req;\n            if (needsRestart) {\n                context.restart(req);\n                context.getLock().lock();\n                addActorToContextAndUnlock(context, HttpActorAdapter.this, context.getLock());\n                needsRestart = false;\n            }\n            userActor.send(s);\n        }\n\n        @Suspendable\n        final void handleReply(HttpResponse message) throws SuspendExecution, InterruptedException {\n            try {\n                final NettyHttpRequest nettyRequest = (NettyHttpRequest) message.getRequest();\n                final FullHttpRequest req = nettyRequest.req;\n                final ChannelHandlerContext ctx = nettyRequest.ctx;\n                final String sessionId = nettyRequest.getSessionId();\n\n                final HttpResponseStatus status = HttpResponseStatus.valueOf(message.getStatus());\n\n                if (message.getStatus() >= 400 && message.getStatus() < 600) {\n                    sendHttpError(ctx, req, new DefaultFullHttpResponse(req.getProtocolVersion(), status));\n                    return;\n                }\n\n                if (message.getRedirectPath() != null) {\n                    sendHttpRedirect(ctx, req, message.getRedirectPath());\n                    return;\n                }\n\n                final FullHttpResponse res;\n                if (message.getStringBody() != null)\n                    res = new DefaultFullHttpResponse(req.getProtocolVersion(), status, Unpooled.wrappedBuffer(message.getStringBody().getBytes()));\n                else if (message.getByteBufferBody() != null)\n                    res = new DefaultFullHttpResponse(req.getProtocolVersion(), status, Unpooled.wrappedBuffer(message.getByteBufferBody()));\n                else\n                    res = new DefaultFullHttpResponse(req.getProtocolVersion(), status);\n\n                if (message.getCookies() != null) {\n                    final ServerCookieEncoder enc = ServerCookieEncoder.STRICT;\n                    for (final Cookie c : message.getCookies())\n                        HttpHeaders.setHeader(res, COOKIE, enc.encode(getNettyCookie(c)));\n                }\n                if (message.getHeaders() != null) {\n                    for (final Map.Entry<String, String> h : message.getHeaders().entries())\n                        HttpHeaders.setHeader(res, h.getKey(), h.getValue());\n                }\n\n                if (message.getContentType() != null) {\n                    String ct = message.getContentType();\n                    if (message.getCharacterEncoding() != null)\n                        ct = ct + \"; charset=\" + message.getCharacterEncoding().name();\n                    HttpHeaders.setHeader(res, CONTENT_TYPE, ct);\n                }\n\n                final boolean sseStarted = message.shouldStartActor();\n                if (trackSession(sseStarted)) {\n                    res.headers().add(SET_COOKIE, ServerCookieEncoder.STRICT.encode(SESSION_COOKIE_KEY, sessionId));\n                    startSession(sessionId, context);\n                }\n                if (!sseStarted) {\n                    final String stringBody = message.getStringBody();\n                    long contentLength = 0L;\n                    if (stringBody != null)\n                        contentLength = stringBody.getBytes().length;\n                    else {\n                        final ByteBuffer byteBufferBody = message.getByteBufferBody();\n                        if (byteBufferBody != null)\n                            contentLength = byteBufferBody.remaining();\n                    }\n                    res.headers().add(CONTENT_LENGTH, contentLength);\n                }\n\n                final HttpStreamActorAdapter httpStreamActorAdapter;\n                if (sseStarted)\n                    // This will copy the request content, which must still be referenceable, doing before the request handler\n                    // unallocates it (unfortunately it is explicitly reference-counted in Netty)\n                    httpStreamActorAdapter = new HttpStreamActorAdapter(ctx, req);\n                else\n                    httpStreamActorAdapter = null;\n\n                sendHttpResponse(ctx, req, res);\n\n                if (sseStarted) {\n                    if (httpResponseEncoderName != null) {\n                        ctx.pipeline().remove(httpResponseEncoderName);\n                    } else {\n                        final ChannelPipeline pl = ctx.pipeline();\n                        final List<String> handlerKeysToBeRemoved = new ArrayList<>();\n                        for (final Map.Entry<String, ChannelHandler> e : pl) {\n                            if (e.getValue() instanceof HttpResponseEncoder)\n                                handlerKeysToBeRemoved.add(e.getKey());\n                        }\n                        for (final String k : handlerKeysToBeRemoved)\n                            pl.remove(k);\n                    }\n\n                    try {\n                        message.getFrom().send(new HttpStreamOpened(httpStreamActorAdapter.ref(), message));\n                    } catch (final SuspendExecution e) {\n                        throw new AssertionError(e);\n                    }\n                }\n            } finally {\n                unblockSessionRequests();\n            }\n        }\n\n        @Suspendable\n        final void handleDie(Throwable cause) {\n            possiblyReplyDeadAndUnblock(cause);\n\n            if (dead)\n                return;\n            dead = true;\n            HttpActorAdapter.super.die(cause);\n            try {\n                context.invalidate();\n            } catch (final Exception ignored) {\n            }\n\n            // Ensure to release references\n            if (userActor != null && watchToken != null)\n                unwatch(userActor, watchToken);\n\n            userActor = null;\n            watchToken = null;\n            context = null;\n            ctx = null;\n            req = null;\n        }\n\n        private void possiblyReplyDeadAndUnblock(Throwable cause) {\n            if (isRequestInProgress()) { // Req replied\n                try {\n                    if (cause != null) {\n                        sendHttpError(ctx, req, new DefaultFullHttpResponse(req.getProtocolVersion(), INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer((\"Actor is dead because of \" + cause.getMessage()).getBytes())));\n                    } else {\n                        sendHttpError(ctx, req, new DefaultFullHttpResponse(req.getProtocolVersion(), INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer((\"Actor has terminated.\").getBytes())));\n                    }\n                } finally {\n                    unblockSessionRequests();\n                }\n            }\n        }\n\n        @Suspendable\n        private void blockSessionRequests() throws InterruptedException {\n            while (!gate.compareAndSet(null, new CountDownLatch(1))) {\n                final CountDownLatch l = gate.get();\n                if (l != null)\n                    l.await();\n            }\n            final ChannelHandlerContext ctx1 = ctx;\n            final FullHttpRequest req1 = req;\n            cancelTask = ts.schedule(new Runnable() {\n                @Override\n                public void run() {\n                    try {\n                        sendHttpError(ctx1, req1, new DefaultFullHttpResponse(req1.getProtocolVersion(), INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer((\"Timeout while waiting for user actor to reply.\").getBytes())));\n                    } finally {\n                        unblockSessionRequests();\n                    }\n                }\n            }, REPLY_TIMEOUT, TimeUnit.MILLISECONDS);\n        }\n\n        @Suspendable\n        private void unblockSessionRequests() {\n            if (cancelTask != null)\n                cancelTask.cancel(true);\n            final CountDownLatch l = gate.getAndSet(null);\n            if (l != null)\n                l.countDown();\n        }\n\n        private boolean isRequestInProgress() {\n            return gate.get() != null;\n        }\n    }\n\n    private static final class HttpChannelAdapter implements SendPort<HttpResponse> {\n        HttpActorAdapter actor;\n\n        @Override\n        @Suspendable\n        public final void send(HttpResponse message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        @Suspendable\n        public final boolean send(HttpResponse message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            send(message);\n            return true;\n        }\n\n        @Override\n        @Suspendable\n        public final boolean send(HttpResponse message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        @Suspendable\n        public final boolean trySend(HttpResponse r) {\n            try {\n                actor.handleReply(r);\n            } catch (final SuspendExecution e) {\n                throw new AssertionError(e);\n            } catch (final InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n            return true;\n        }\n\n        @Override\n        @Suspendable\n        public final void close() {\n            actor.die(null);\n        }\n\n        @Override\n        @Suspendable\n        public final void close(Throwable t) {\n            log.error(\"Exception while closing HTTP adapter\", t);\n            actor.die(t);\n        }\n    }\n\n    protected static boolean trackSession(boolean sseStarted) {\n        return\n            trackSession != null && (\n                \"always\".equals(trackSession) ||\n                sseStarted && \"sse\".equals(trackSession)\n        );\n    }\n\n    protected static boolean handlesWithHttp(String uri, Class<?> actorClass) {\n        return match(uri, actorClass).equals(\"websocket\");\n    }\n\n    protected static boolean handlesWithWebSocket(String uri, Class<?> actorClass) {\n        return match(uri, actorClass).equals(\"ws\");\n    }\n\n    private static final class HttpStreamActorAdapter extends FakeActor<WebDataMessage> {\n        private volatile boolean dead;\n\n        public HttpStreamActorAdapter(final ChannelHandlerContext ctx, final FullHttpRequest req) {\n            super(req.toString(), new HttpStreamChannelAdapter(ctx, req));\n            ((HttpStreamChannelAdapter) (SendPort) getMailbox()).actor = this;\n        }\n\n        @Override\n        protected WebDataMessage handleLifecycleMessage(LifecycleMessage m) {\n            if (m instanceof ShutdownMessage) {\n                die(null);\n            }\n            return null;\n        }\n\n        @Override\n        protected void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        public void interrupt() {\n            die(new InterruptedException());\n        }\n\n        @Override\n        protected void die(Throwable cause) {\n            if (dead)\n                return;\n            this.dead = true;\n            mailbox().close();\n            super.die(cause);\n        }\n\n        @Override\n        public String toString() {\n            return \"HttpStreamActorAdapter{request + \" + getName() + \"}\";\n        }\n    }\n\n    private static final class HttpStreamChannelAdapter implements SendPort<WebDataMessage> {\n        private final Charset encoding;\n        private final ChannelHandlerContext ctx;\n\n        HttpStreamActorAdapter actor;\n\n        public HttpStreamChannelAdapter(ChannelHandlerContext ctx, FullHttpRequest req) {\n            this.ctx = ctx;\n            this.encoding = NettyHttpRequest.extractCharacterEncodingOrDefault(req.headers());\n        }\n\n        @Override\n        public final void send(WebDataMessage message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            send(message);\n            return true;\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        public final boolean trySend(WebDataMessage res) {\n            final ByteBuf buf;\n            final String stringBody = res.getStringBody();\n            if (stringBody != null) {\n                byte[] bs = stringBody.getBytes(encoding);\n                buf = Unpooled.wrappedBuffer(bs);\n            } else {\n                buf = Unpooled.wrappedBuffer(res.getByteBufferBody());\n            }\n            ctx.writeAndFlush(buf);\n            return true;\n        }\n\n        @Override\n        public final void close() {\n            if (ctx.channel().isOpen())\n                ctx.close();\n            actor.die(null);\n        }\n\n        @Override\n        public final void close(Throwable t) {\n            actor.die(t);\n            close();\n        }\n    }\n\n    static void startSession(String sessionId, Context actorContext) throws SuspendExecution, InterruptedException {\n        sessionsLock.lock();\n        try {\n            cleanSessions();\n            sessions.put(sessionId, actorContext);\n        } finally {\n            sessionsLock.unlock();\n        }\n    }\n\n    private static void cleanSessions() throws SuspendExecution, InterruptedException {\n        // TODO less often\n        final Collection<String> toBeRemoved = new ArrayList<>(1024);\n        for (final Map.Entry<String, Context> e : sessions.entrySet()) {\n            if (!e.getValue().isValid())\n                toBeRemoved.add(e.getKey());\n        }\n        for (final String s : toBeRemoved)\n            sessions.remove(s);\n    }\n\n    static io.netty.handler.codec.http.cookie.Cookie getNettyCookie(Cookie c) {\n        io.netty.handler.codec.http.cookie.Cookie ret = new io.netty.handler.codec.http.cookie.DefaultCookie(c.getName(), c.getValue());\n        ret.setDomain(c.getDomain());\n        ret.setHttpOnly(c.isHttpOnly());\n        ret.setMaxAge(c.getMaxAge());\n        ret.setPath(c.getPath());\n        ret.setSecure(c.isSecure());\n        return ret;\n    }\n\n    static void sendHttpRedirect(ChannelHandlerContext ctx, FullHttpRequest req, String newUri) {\n        final FullHttpResponse res = new DefaultFullHttpResponse(req.getProtocolVersion(), FOUND);\n        HttpHeaders.setHeader(res, LOCATION, newUri);\n        writeHttpResponse(ctx, req, res, true);\n    }\n\n    static void sendHttpError(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {\n        sendHttpResponse(ctx, req, res, true);\n    }\n\n    static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {\n        sendHttpResponse(ctx, req, res, false);\n    }\n\n    private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res, boolean close) {\n        writeHttpResponse(ctx, req, res, close);\n    }\n\n    private static void writeHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res, boolean close) {\n        if (!omitDateHeader && !res.headers().contains(DefaultHttpHeaders.Names.DATE))\n            DefaultHttpHeaders.addDateHeader(res, DefaultHttpHeaders.Names.DATE, new Date());\n\n        // Reply the response and close the connection if necessary.\n        if (!HttpHeaders.isKeepAlive(req) || close) {\n            res.headers().set(CONNECTION, HttpHeaders.Values.CLOSE);\n            ctx.writeAndFlush(res).addListener(ChannelFutureListener.CLOSE);\n        } else {\n            res.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);\n            write(ctx, res);\n        }\n    }\n\n    private static ChannelFuture write(ChannelHandlerContext ctx, Object res) {\n        return ctx.writeAndFlush(res);\n        // : ctx.write(res);\n    }\n\n    private static String match(String uri, Class<?> actorClass) {\n        if (uri != null && actorClass != null) {\n            for (final Pair<String, String> e : lookupOrInsert(actorClass)) {\n                if (servletMatch(e.getFirst(), uri))\n                    return e.getSecond();\n            }\n        }\n        return \"\";\n    }\n\n    private static List<Pair<String, String>> lookupOrInsert(Class<?> actorClass) {\n        if (actorClass != null) {\n            final List<Pair<String, String>> lookup = classToUrlPatterns.get(actorClass);\n            if (lookup != null)\n                return lookup;\n            return insert(actorClass);\n        }\n        return null;\n    }\n\n    private static List<Pair<String, String>> insert(Class<?> actorClass) {\n        if (actorClass != null) {\n            final WebActor wa = actorClass.getAnnotation(WebActor.class);\n            final List<Pair<String, String>> ret = new ArrayList<>(4);\n            for (String httpP : wa.httpUrlPatterns())\n                addPattern(ret, httpP, \"websocket\");\n            for (String wsP : wa.webSocketUrlPatterns())\n                addPattern(ret, wsP, \"ws\");\n            classToUrlPatterns.put(actorClass, ret);\n            return ret;\n        }\n        return null;\n    }\n\n    private static void addPattern(List<Pair<String, String>> ret, String p, String type) {\n        if (p != null) {\n            @SuppressWarnings(\"MismatchedQueryAndUpdateOfCollection\") final Pair<String, String> entry = new Pair<>(p, type);\n            if (p.endsWith(\"*\") || p.startsWith(\"*.\") || p.equals(\"/\")) // Wildcard -> end\n                ret.add(entry);\n            else // Exact -> beginning\n                ret.add(0, entry);\n        }\n    }\n\n    private static boolean servletMatch(String pattern, String uri) {\n        // As per servlet spec\n        if (pattern != null && uri != null) {\n            if (pattern.startsWith(\"/\") && pattern.endsWith(\"*\"))\n                return uri.startsWith(pattern.substring(0, pattern.length() - 1));\n            if (pattern.startsWith(\"*.\"))\n                return uri.endsWith(pattern.substring(2));\n            if (pattern.isEmpty())\n                return uri.equals(\"/\");\n            return pattern.equals(\"/\") || pattern.equals(uri);\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-netty/src/main/java/co/paralleluniverse/comsat/webactors/netty/package-info.java",
    "content": "/*\n * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved.\n * \n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *  \n *   or (per the licensee's choosing)\n *  \n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/**\n * A Web Actors backend implementation based on Netty\n */\npackage co.paralleluniverse.comsat.webactors.netty;\n"
  },
  {
    "path": "comsat-actors-netty/src/test/java/co/paralleluniverse/comsat/webactors/netty/HttpRequestWrapperTest.java",
    "content": "package co.paralleluniverse.comsat.webactors.netty;\n\nimport io.netty.buffer.EmptyByteBuf;\nimport io.netty.buffer.UnpooledByteBufAllocator;\nimport io.netty.handler.codec.http.DefaultFullHttpRequest;\nimport io.netty.handler.codec.http.HttpMethod;\nimport io.netty.handler.codec.http.HttpVersion;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author rodedb\n */\npublic class HttpRequestWrapperTest {\n\n    @Test\n    public void httpHeaderCaseInsensitivity() {\n        DefaultFullHttpRequest httpRequest =\n                new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, \"uri\", new EmptyByteBuf(UnpooledByteBufAllocator.DEFAULT));\n        String headerValue = \"application/json\";\n        httpRequest.headers().add(\"Content-Type\", headerValue);\n        NettyHttpRequest requestWrapper = new NettyHttpRequest(null, null, httpRequest, \"sessionId\");\n        assertEquals(headerValue, requestWrapper.getHeader(\"content-type\"));\n    }\n}"
  },
  {
    "path": "comsat-actors-netty/src/test/java/co/paralleluniverse/comsat/webactors/netty/NettyWebActor.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.netty;\n\nimport co.paralleluniverse.comsat.webactors.MyWebActor;\nimport co.paralleluniverse.comsat.webactors.WebActor;\n\n/**\n * @author circlespainter\n */\n@WebActor(httpUrlPatterns = {\"/*\"}, webSocketUrlPatterns = {\"/ws\"})\npublic final class NettyWebActor extends MyWebActor {}\n"
  },
  {
    "path": "comsat-actors-netty/src/test/java/co/paralleluniverse/comsat/webactors/netty/WebActorTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2015-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.netty;\n\nimport co.paralleluniverse.actors.Actor;\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.comsat.webactors.AbstractWebActorTest;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\n\nimport co.paralleluniverse.embedded.containers.AbstractEmbeddedServer;\nimport io.netty.bootstrap.ServerBootstrap;\nimport io.netty.channel.ChannelFuture;\nimport io.netty.channel.ChannelInitializer;\nimport io.netty.channel.ChannelPipeline;\nimport io.netty.channel.nio.NioEventLoopGroup;\nimport io.netty.channel.socket.SocketChannel;\nimport io.netty.channel.socket.nio.NioServerSocketChannel;\nimport io.netty.handler.codec.http.*;\nimport io.netty.handler.logging.LogLevel;\nimport io.netty.handler.logging.LoggingHandler;\nimport org.junit.*;\n\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n/**\n * @author circlespainter\n */\n@RunWith(Parameterized.class)\npublic class WebActorTest extends AbstractWebActorTest {\n    private static final int INET_PORT = 8080;\n\n    private static final String HTTP_RESPONSE_ENCODER_KEY = \"httpResponseEncoder\";\n\n    private static final Actor actor = new NettyWebActor();\n    @SuppressWarnings(\"unchecked\")\n    private static final ActorRef<? extends WebMessage> actorRef = actor.spawn();\n\n    private static final WebActorHandler.DefaultContextImpl context = new WebActorHandler.DefaultContextImpl() {\n        @Override\n        public String getId() {\n            return \"CONSTANT\";\n        }\n\n        @SuppressWarnings(\"unchecked\")\n        @Override\n        public ActorRef<? extends WebMessage> getWebActor() {\n            return actorRef;\n        }\n\n        @Override\n        public void restart(FullHttpRequest r) {\n            // Nothing to do\n        }\n\n        @Override\n        public final boolean handlesWithWebSocket(String uri) {\n            return uri.startsWith(\"/ws\");\n        }\n\n        @Override\n        public WatchPolicy watch() {\n            return WatchPolicy.DIE;\n        }\n\n        @Override\n        public final boolean handlesWithHttp(String uri) {\n            return !handlesWithWebSocket(uri);\n        }\n    };\n\n    private static final Callable<WebActorHandler> basicWebActorHandlerCreator = new Callable<WebActorHandler>() {\n        @Override\n        public WebActorHandler call() throws Exception {\n            return new WebActorHandler(new WebActorHandler.WebActorContextProvider() {\n                @Override\n                public WebActorHandler.Context get(FullHttpRequest req) {\n                    return context;\n                }\n            });\n        }\n    };\n\n    private static final Callable<WebActorHandler> autoWebActorHandlerCreator = new Callable<WebActorHandler>() {\n        @Override\n        public WebActorHandler call() throws Exception {\n            return new AutoWebActorHandler();\n        }\n    };\n\n    @Parameterized.Parameters(name = \"{index}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {basicWebActorHandlerCreator},\n            {autoWebActorHandlerCreator}\n        });\n    }\n\n    private ChannelFuture ch;\n    private NioEventLoopGroup group;\n    private Callable<WebActorHandler> webActorHandlerCreatorInEffect;\n\n    public WebActorTest(Callable<WebActorHandler> webActorHandlerCreator) {\n        webActorHandlerCreatorInEffect = webActorHandlerCreator;\n    }\n\n    @Before\n    public void setUp() throws InterruptedException, IOException {\n        System.out.println(\"Clearing sessions\");\n        WebActorHandler.sessions.clear();\n\n        group = new NioEventLoopGroup();\n        final ServerBootstrap b = new ServerBootstrap();\n        b.group(group)\n            .channel(NioServerSocketChannel.class)\n            .handler(new LoggingHandler(LogLevel.INFO))\n            .childHandler(new ChannelInitializer<SocketChannel>() {\n                @Override\n                public void initChannel(SocketChannel ch) throws Exception {\n                    ChannelPipeline pipeline = ch.pipeline();\n                    pipeline.addLast(new LoggingHandler(LogLevel.INFO));\n                    pipeline.addLast(new HttpRequestDecoder());\n                    pipeline.addLast(new LoggingHandler(LogLevel.INFO));\n                    pipeline.addLast(HTTP_RESPONSE_ENCODER_KEY, new HttpResponseEncoder());\n                    pipeline.addLast(new LoggingHandler(LogLevel.INFO));\n                    pipeline.addLast(new HttpObjectAggregator(65536));\n                    pipeline.addLast(new LoggingHandler(LogLevel.INFO));\n                    pipeline.addLast(webActorHandlerCreatorInEffect.call());\n                }\n            });\n\n        ch = b.bind(INET_PORT).sync();\n\n        AbstractEmbeddedServer.waitUrlAvailable(\"http://localhost:\" + INET_PORT);\n\n        System.err.println(\"Server is up\");\n    }\n\n    @Override\n    @Test\n    public final void testDie() throws IOException, InterruptedException, ExecutionException {\n        Assume.assumeTrue(webActorHandlerCreatorInEffect == autoWebActorHandlerCreator);\n\n        super.testDie();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        ch.channel().close();\n        group.shutdownGracefully().sync();\n\n        System.out.println(\"Server is down\");\n    }\n\n    @Override\n    protected String getSessionIdCookieName() {\n        return WebActorHandler.SESSION_COOKIE_KEY;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-servlet/build.gradle",
    "content": "dependencies {\n    testCompile \"org.springframework:spring-test:$springVer\"\n}"
  },
  {
    "path": "comsat-actors-servlet/src/main/java/co/paralleluniverse/comsat/webactors/servlet/EmbedHttpSessionWsConfigurator.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n\nimport javax.servlet.http.HttpSession;\nimport javax.websocket.HandshakeResponse;\nimport javax.websocket.server.HandshakeRequest;\nimport javax.websocket.server.ServerEndpointConfig;\nimport javax.websocket.server.ServerEndpointConfig.Configurator;\n\nclass EmbedHttpSessionWsConfigurator extends Configurator {\n    @Override\n    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {\n        // save the http session based on idea from\n        // http://stackoverflow.com/questions/17936440/accessing-httpsession-from-httpservletrequest-in-a-web-socket-socketendpoint\n        final Object httpSession = request.getHttpSession();\n        if (httpSession != null)\n            sec.getUserProperties().put(HttpSession.class.getName(), httpSession);\n        super.modifyHandshake(sec, request, response);\n    }\n}\n"
  },
  {
    "path": "comsat-actors-servlet/src/main/java/co/paralleluniverse/comsat/webactors/servlet/ServletHttpRequest.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.comsat.webactors.Cookie;\nimport static co.paralleluniverse.comsat.webactors.Cookie.*;\nimport co.paralleluniverse.comsat.webactors.HttpRequest;\nimport co.paralleluniverse.comsat.webactors.HttpResponse;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\nimport com.google.common.collect.ImmutableCollection;\nimport com.google.common.collect.ImmutableList;\nimport com.google.common.collect.ImmutableListMultimap;\nimport com.google.common.collect.ImmutableMap;\nimport com.google.common.collect.ListMultimap;\nimport com.google.common.collect.Multimap;\nimport com.google.common.io.ByteStreams;\nimport java.io.IOException;\nimport java.io.UnsupportedEncodingException;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.Charset;\nimport java.nio.charset.UnsupportedCharsetException;\nimport java.util.Collection;\nimport java.util.Enumeration;\nimport java.util.Locale;\nimport java.util.Map;\nimport javax.servlet.ServletInputStream;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * Wraps a {@link HttpServletRequest} as a {@link HttpRequest}\n */\npublic final class ServletHttpRequest extends HttpRequest {\n    final HttpServletRequest request;\n    final HttpServletResponse response;\n\n    private ListMultimap<String, String> headers;\n    private Multimap<String, String> params;\n    private Map<String, Object> attrs;\n    private final ActorRef<? super HttpResponse> sender;\n    private String strBody;\n    private byte[] binBody;\n    private Collection<Cookie> cookies;\n\n    /**\n     * Constructs a {@code HttpRequestWrapper} message\n     *\n     * @param sender this message's sender\n     * @param request the {@link HttpServletRequest}\n     * @param response the {@link HttpServletResponse}\n     */\n    public ServletHttpRequest(ActorRef<? super HttpResponse> sender, HttpServletRequest request, HttpServletResponse response) {\n        this.sender = sender;\n        this.request = request;\n        this.response = response;\n    }\n\n    public HttpServletRequest getServletRequest() {\n        return request;\n    }\n\n    public HttpServletResponse getServletResponse() {\n        return response;\n    }\n\n    @Override\n    public final String getSourceHost() {\n        return request.getRemoteHost();\n    }\n\n    @Override\n    public final int getSourcePort() {\n        return request.getRemotePort();\n    }\n\n    //    @Override\n//    public String getRequestURL() {\n//        return request.getRequestURL().toString();\n//    }\n    @Override\n    public final String getStringBody() {\n        if (strBody == null) {\n            if (binBody != null)\n                return null;\n            final byte[] ba = readBody();\n            final String enc = request.getCharacterEncoding();\n            try {\n                this.strBody = enc!=null ?  new String(ba, enc) : new String(ba);\n            } catch (final UnsupportedEncodingException e) {\n                throw new UnsupportedCharsetException(enc);\n            }\n        }\n        return strBody;\n    }\n\n    @Override\n    public final ByteBuffer getByteBufferBody() {\n        if (binBody == null) {\n            if (strBody != null)\n                return null;\n            this.binBody = readBody();\n        }\n        return ByteBuffer.wrap(binBody).asReadOnlyBuffer();\n    }\n\n    private byte[] readBody() {\n        try {\n            final ServletInputStream is = request.getInputStream();\n            final int length = request.getContentLength();\n            final byte[] ba;\n            if (length < 0)\n                ba = ByteStreams.toByteArray(is);\n            else {\n                ba = new byte[length];\n                ByteStreams.readFully(is, ba);\n            }\n            return ba;\n        } catch (final IOException ex) {\n            throw new RuntimeException(ex);\n        }\n    }\n\n    @Override\n    public final ListMultimap<String, String> getHeaders() {\n        if (headers == null) {\n            final ImmutableListMultimap.Builder<String, String> mm = ImmutableListMultimap.builder();// LinkedHashMultimap.create();\n            for (final Enumeration<String> hs = request.getHeaderNames(); hs.hasMoreElements();) {\n                final String h = hs.nextElement();\n                for (final Enumeration<String> hv = request.getHeaders(h); hv.hasMoreElements();)\n                    // Normalize header names by their conversion to lower case\n                    mm.put(h.toLowerCase(Locale.ENGLISH), hv.nextElement());\n            }\n            this.headers = mm.build();\n        }\n        return headers;\n    }\n\n    @Override\n    public final Multimap<String, String> getParameters() {\n        if (params == null) {\n            final ImmutableListMultimap.Builder<String, String> mm = ImmutableListMultimap.builder();\n            for (final Enumeration<String> ps = request.getParameterNames(); ps.hasMoreElements();) {\n                final String p = ps.nextElement();\n                final String[] pvs = request.getParameterValues(p);\n                if (pvs != null) {\n                    for (final String pv : pvs)\n                        mm.put(p, pv);\n                }\n            }\n            this.params = mm.build();\n        }\n        return params;\n    }\n\n    @Override\n    public final Map<String, Object> getAttributes() {\n        if (attrs == null) {\n            final ImmutableMap.Builder<String, Object> m = ImmutableMap.builder();\n            for (final Enumeration<String> as = request.getAttributeNames(); as.hasMoreElements();) {\n                final String a = as.nextElement();\n                final Object v = request.getAttribute(a);\n                m.put(a, v);\n            }\n            this.attrs = m.build();\n        }\n        return attrs;\n    }\n\n    @Override\n    public final Collection<Cookie> getCookies() {\n        if (cookies == null) {\n            final javax.servlet.http.Cookie[] cs = request.getCookies();\n            final ImmutableCollection.Builder<Cookie> collb = ImmutableList.builder();\n            if (cs != null) {\n                for (final javax.servlet.http.Cookie c : cs) {\n                    collb.add(cookie(c.getName(), c.getValue())\n                            .setComment(c.getComment())\n                            .setDomain(c.getDomain())\n                            .setMaxAge(c.getMaxAge())\n                            .setHttpOnly(c.isHttpOnly())\n                            .setPath(c.getPath())\n                            .setSecure(c.getSecure())\n                            .setVersion(c.getVersion())\n                            .build());\n                }\n            }\n            this.cookies = collb.build();\n        }\n        return cookies;\n    }\n\n    @Override\n    public final long getDateHeader(String name) {\n        return request.getDateHeader(name);\n    }\n\n    @Override\n    public final String getMethod() {\n        return request.getMethod();\n    }\n\n    @Override\n    public final String getScheme() {\n        return request.getScheme();\n    }\n\n    \n    @Override\n    public final String getQueryString() {\n        return request.getQueryString();\n    }\n\n    @Override\n    public final String getServerName() {\n        return request.getServerName();\n    }\n\n    @Override\n    public final int getServerPort() {\n        return request.getServerPort();\n    }\n\n    @Override\n    public final String getContextPath() {\n        return request.getContextPath();\n    }\n\n    @Override\n    public final String getRequestURI() {\n        return request.getRequestURI();\n    }\n\n    @Override\n    public final int getContentLength() {\n        return request.getContentLength();\n    }\n\n    @Override\n    public final String getContentType() {\n        return request.getContentType();\n    }\n\n    @Override\n    public final String getPathInfo() {\n        return request.getPathInfo();\n    }\n\n    @Override\n    public final Charset getCharacterEncoding() {\n        return request.getCharacterEncoding() != null ? Charset.forName(request.getCharacterEncoding()) : null;\n    }\n\n    @Override\n    public final ActorRef<WebMessage> getFrom() {\n        //noinspection unchecked\n        return (ActorRef<WebMessage>) sender;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-servlet/src/main/java/co/paralleluniverse/comsat/webactors/servlet/ServletWebActors.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.comsat.webactors.HttpRequest;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.concurrent.Callable;\nimport javax.servlet.ServletContext;\nimport javax.servlet.http.HttpSession;\nimport javax.websocket.DeploymentException;\nimport javax.websocket.Endpoint;\nimport javax.websocket.EndpointConfig;\nimport javax.websocket.Session;\nimport javax.websocket.server.ServerContainer;\nimport javax.websocket.server.ServerEndpointConfig;\n\n/**\n * Static methods to attach web actors with HTTP and WebSocket sessions\n */\npublic final class ServletWebActors {\n    /**\n     * Attaches the given web actor to the given {@link HttpSession}.\n     *\n     * @param session the session\n     * @param actor   the web actor\n     * @return {@code actor}\n     */\n    public static <T> ActorRef<T> attachWebActor(final HttpSession session, final ActorRef<T> actor) {\n        //noinspection unchecked,ConstantConditions\n        return WebActorServlet.getOrAttachSessionActor(session, new Callable<WebActorServlet.HttpActorAdapter>() {\n            @Override\n            public WebActorServlet.HttpActorAdapter call() throws Exception {\n                return new WebActorServlet.HttpActorAdapter(new Callable<ActorRef>() {\n                    @Override\n                    public ActorRef call() throws Exception {\n                        return actor;\n                    }\n                }, session);\n            }\n        }).userWebActorRef;\n    }\n\n    /**\n     * Checks whether a web actor is attached to an {@link HttpSession}.\n     */\n    public static boolean isWebActorAttached(HttpSession session) {\n        return WebActorServlet.isWebActorAttached(session);\n    }\n\n    /**\n     * Returns the web actor attached to the given {@link HttpSession}.\n     *\n     * @param session the session\n     * @return the web actor attached to the session, or {@code null} if none.\n     */\n    public static ActorRef<? super HttpRequest> getWebActor(HttpSession session) {\n        return WebActorServlet.getWebActor(session);\n    }\n\n    /**\n     * Attaches the given web actor to the given WebSocket session\n     *\n     * @param session     the WebSocket {@link Session}\n     * @param httpSession the WebSocket's associated HTTP session\n     * @param actor       the web actor\n     * @return {@code actor}\n     */\n    public static <T> ActorRef<T> attachWebActor(Session session, HttpSession httpSession, ActorRef<T> actor) {\n        WebActorEndpoint.attachWebActor(session, httpSession, (ActorRef<WebMessage>) actor);\n        return actor;\n    }\n\n    /**\n     * Attaches the given web actor to the given WebSocket session\n     *\n     * @param session the WebSocket {@link Session}\n     * @param config  the WebSocket endpoint's configuration\n     * @param actor   the web actor\n     * @return {@code actor}\n     */\n    public static <T> ActorRef<T> attachWebActor(Session session, EndpointConfig config, ActorRef<T> actor) {\n        WebActorEndpoint.attachWebActor(session, config, (ActorRef<WebMessage>) actor);\n        return actor;\n    }\n\n    /**\n     * Attaches the given web actor to web socket sessions that will be opened at the given URI (or URI pattern).\n     * This method installs a new WebSocket {@link Endpoint}.\n     *\n     * @param sc           the {@link ServletContext}\n     * @param webSocketURI the WebSocket's URI (or URI pattern)\n     * @param actor        the web actor\n     * @return {@code actor}\n     */\n    public static <T> ActorRef<T> attachWebActor(ServletContext sc, String webSocketURI, ActorRef<T> actor) {\n        return attachWebActor(sc, Collections.singleton(webSocketURI), actor);\n    }\n\n    /**\n     * Attaches the given web actor to web socket sessions that will be opened at the given URIs (or URI patterns).\n     * This method installs new WebSocket {@link Endpoint}s.\n     *\n     * @param sc            the {@link ServletContext}\n     * @param webSocketURIs the WebSockets' URI (or URI pattern)\n     * @param actor         the web actor\n     * @return {@code actor}\n     */\n    public static <T> ActorRef<T> attachWebActor(ServletContext sc, Collection<String> webSocketURIs, ActorRef<T> actor) {\n        final ServerContainer scon = (ServerContainer) sc.getAttribute(\"javax.websocket.server.ServerContainer\");\n        for (String webSocketURI : webSocketURIs) {\n            try {\n                scon.addEndpoint(ServerEndpointConfig.Builder.create(WebActorEndpoint.class, webSocketURI).configurator(new EmbedHttpSessionWsConfigurator()).build());\n            } catch (DeploymentException ex) {\n                sc.log(\"Unable to deploy endpoint\", ex);\n            }\n        }\n        return actor;\n    }\n\n    private ServletWebActors() {\n    }\n}\n"
  },
  {
    "path": "comsat-actors-servlet/src/main/java/co/paralleluniverse/comsat/webactors/servlet/WebActorEndpoint.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.actors.ExitMessage;\nimport co.paralleluniverse.actors.FakeActor;\nimport co.paralleluniverse.actors.LifecycleMessage;\nimport co.paralleluniverse.comsat.webactors.WebDataMessage;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\nimport co.paralleluniverse.comsat.webactors.WebSocketOpened;\nimport co.paralleluniverse.fibers.FiberUtil;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport co.paralleluniverse.strands.Timeout;\nimport co.paralleluniverse.strands.channels.SendPort;\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.TimeUnit;\nimport javax.servlet.http.HttpSession;\nimport javax.websocket.CloseReason;\nimport javax.websocket.Endpoint;\nimport javax.websocket.EndpointConfig;\nimport javax.websocket.MessageHandler;\nimport javax.websocket.Session;\n\n/**\n * A WebSocket endpoint that forwards requests to a web actor.\n */\npublic final class WebActorEndpoint extends Endpoint {\n    private static final String ACTOR_SESSION_KEY = WebActorEndpoint.class.getName() + \".session.actor\";\n    private volatile EndpointConfig config;\n\n    @Override\n    public final void onOpen(Session session, EndpointConfig config) {\n        if (this.config == null)\n            this.config = config;\n        final ActorRef webActor = getUserWebActor(config);\n        if (webActor != null) {\n            //noinspection unchecked\n            final WebSocketActor wsa = attachWebActor(session, config, webActor);\n            wsa.onOpen();\n        } else {\n            try {\n                session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, \"session actor not found\"));\n            } catch (final IOException ex) {\n                getHttpSession(config).getServletContext().log(\"IOException\", ex);\n            }\n        }\n    }\n\n//    private ActorRef getUserWebActor(EndpointConfig config) {\n//        final WebActorServlet.SessionData psd = WebActorServlet.sessionToWebActor.get(getHttpSession(config).getId());\n//        return psd != null ? psd.httpSessionActor.userWebActorRef : null;\n//    }\n\n    private ActorRef getUserWebActor(EndpointConfig config) {\n        final WebActorServlet.HttpActorAdapter a =\n            (WebActorServlet.HttpActorAdapter) getHttpSession(config).getAttribute(WebActorServlet.SESSION_KEY_ACTOR);\n        return a != null ? a.userWebActorRef : null;\n    }\n\n    static WebSocketActor attachWebActor(Session session, EndpointConfig config, ActorRef<? super WebMessage> actor) {\n        return attachWebActor(session, getHttpSession(config), actor);\n    }\n\n    static WebSocketActor attachWebActor(Session session, HttpSession httpSession, ActorRef<? super WebMessage> actor) {\n        if (session.getUserProperties().containsKey(ACTOR_SESSION_KEY))\n            throw new RuntimeException(\"Session is already attached to an actor.\");\n        final WebSocketActor wsa = new WebSocketActor(session, httpSession, actor);\n        session.getUserProperties().put(ACTOR_SESSION_KEY, wsa);\n        return wsa;\n    }\n\n    @Override\n    public final void onError(Session session, Throwable t) {\n        getSessionActor(session).onError(t);\n    }\n\n    @Override\n    public final void onClose(Session session, CloseReason closeReason) {\n        getSessionActor(session).onClose(closeReason);\n    }\n\n    private static WebSocketActor getSessionActor(Session session) {\n        return (WebSocketActor) session.getUserProperties().get(ACTOR_SESSION_KEY);\n    }\n\n    private static HttpSession getHttpSession(EndpointConfig config) {\n        return (HttpSession) config.getUserProperties().get(HttpSession.class.getName());\n    }\n\n    static final class WebSocketActor extends FakeActor<WebDataMessage> {\n        private final Session session;\n        private final HttpSession httpSession;\n        private final ActorRef<? super WebMessage> webActor;\n\n        public WebSocketActor(Session session, HttpSession httpSession, ActorRef<? super WebMessage> webActor) {\n            super(session.toString(), new WebSocketChannel(session, httpSession));\n\n            ((WebSocketChannel) (SendPort) getMailbox()).actor = this;\n\n            this.session = session;\n            this.httpSession = httpSession;\n            this.webActor = webActor;\n            watch(webActor);\n\n            session.addMessageHandler(new MessageHandler.Whole<ByteBuffer>() {\n                @Override\n                public final void onMessage(final ByteBuffer message) {\n                    try {\n                        WebSocketActor.this.webActor.send(new WebDataMessage(WebSocketActor.this.ref(), message));\n                    } catch (final SuspendExecution ex) {\n                        throw new AssertionError(ex);\n                    }\n                }\n            });\n            session.addMessageHandler(new MessageHandler.Whole<String>() {\n                @Override\n                public final void onMessage(final String message) {\n                    try {\n                        WebSocketActor.this.webActor.send(new WebDataMessage(WebSocketActor.this.ref(), message));\n                    } catch (final SuspendExecution ex) {\n                        throw new AssertionError(ex);\n                    }\n                }\n            });\n        }\n\n        final void onOpen() {\n            try {\n                FiberUtil.runInFiber(new SuspendableRunnable() {\n                    @Override\n                    public final void run() throws SuspendExecution, InterruptedException {\n                        webActor.send(new WebSocketOpened(WebSocketActor.this.ref()));\n                    }\n                });\n            } catch (final ExecutionException e) {\n                log(\"Exception in onOpen\", e.getCause());\n            } catch (final InterruptedException e) {\n                throw new RuntimeException();\n            }\n        }\n\n        final void onClose(CloseReason closeReason) {\n            // don't call die because the session is already closed.\n            super.die(closeReason.getCloseCode() == CloseReason.CloseCodes.NORMAL_CLOSURE ? null : new RuntimeException(closeReason.toString()));\n        }\n\n        final void onError(Throwable t) {\n            log(\"onError\", t);\n        }\n\n        @Override\n        protected final WebDataMessage handleLifecycleMessage(LifecycleMessage m) {\n            if (m instanceof ExitMessage) {\n                final ExitMessage em = (ExitMessage) m;\n                if (em.getActor() != null && em.getActor().equals(webActor))\n                    die(em.getCause());\n            }\n            return null;\n        }\n\n        @Override\n        protected final void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        public final void interrupt() {\n            die(new InterruptedException());\n        }\n\n        @Override\n        protected final void die(Throwable cause) {\n            super.die(cause);\n            try {\n                session.close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, cause != null ? (cause.getClass() + \": \" + cause.getMessage()) : \"\"));\n            } catch (final IOException ex) {\n                log(\"IOException on interrupt\", ex);\n            }\n        }\n\n        private void log(String message, Throwable t) {\n            httpSession.getServletContext().log(message, t);\n        }\n\n        @Override\n        public String toString() {\n            return \"WebSocketActor{\" + \"session=\" + session + \", webActor=\" + webActor + '}';\n        }\n    }\n\n    private static final class WebSocketChannel implements SendPort<WebDataMessage> {\n        private final Session session;\n        private final HttpSession httpSession;\n\n        WebSocketActor actor;\n\n        public WebSocketChannel(Session session, HttpSession httpSession) {\n            this.session = session;\n            this.httpSession = httpSession;\n        }\n\n        @Override\n        public final void send(WebDataMessage message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            return trySend(message);\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        public final boolean trySend(WebDataMessage message) {\n            if (!session.isOpen())\n                return false;\n            // TODO: use fiber async instead of servlet Async ?\n            if (!message.isBinary())\n                session.getAsyncRemote().sendText(message.getStringBody());\n            else\n                session.getAsyncRemote().sendBinary(message.getByteBufferBody());\n            return true;\n        }\n\n        @Override\n        public final void close() {\n            try {\n                session.close();\n            } catch (final IOException ex) {\n                httpSession.getServletContext().log(\"IOException on close\", ex);\n            } finally {\n                if (actor != null)\n                    actor.die(null);\n            }\n        }\n\n        @Override\n        public final void close(Throwable t) {\n            if (actor != null)\n                actor.die(t);\n            close();\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-actors-servlet/src/main/java/co/paralleluniverse/comsat/webactors/servlet/WebActorInitializer.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n\nimport co.paralleluniverse.common.reflection.AnnotationUtil;\nimport co.paralleluniverse.common.reflection.ClassLoaderUtil;\nimport co.paralleluniverse.comsat.webactors.WebActor;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\nimport java.net.URLClassLoader;\nimport javax.servlet.ServletContext;\nimport javax.servlet.ServletContextEvent;\nimport javax.servlet.ServletContextListener;\nimport javax.servlet.ServletRegistration.Dynamic;\nimport javax.servlet.annotation.WebListener;\nimport javax.websocket.DeploymentException;\nimport javax.websocket.server.ServerContainer;\nimport javax.websocket.server.ServerEndpointConfig;\n\n/**\n * Registers WebActors annotated with the {@link WebActor} annotation.\n * Scan classes of the servletContext classLoader for WebActor annotated classes\n * You can set a userClassLoader with \n */\n@WebListener\npublic class WebActorInitializer implements ServletContextListener {\n    private static ClassLoader userClassLoader;\n\n    /**\n     *\n     * @param userClassLoader Scan classes of this classLoader WebActor annotated classes\n     * @return WebActorInitializer.class\n     */\n    public static Class<? extends WebActorInitializer> setUserClassLoader(ClassLoader userClassLoader) {\n        WebActorInitializer.userClassLoader = userClassLoader;\n        return WebActorInitializer.class;\n    }\n\n    @Override\n    public final void contextInitialized(ServletContextEvent sce) {\n        final ServletContext sc = sce.getServletContext();\n        try {\n            final ClassLoader classLoader = userClassLoader != null ? userClassLoader : sc.getClassLoader();\n            ClassLoaderUtil.accept((URLClassLoader)classLoader, new ClassLoaderUtil.Visitor() {\n                @Override\n                public void visit(String resource, URL url, ClassLoader cl) {\n                    if (!ClassLoaderUtil.isClassFile(resource))\n                        return;\n                    final String className = ClassLoaderUtil.resourceToClass(resource);\n                    try (final InputStream is = cl.getResourceAsStream(resource)) {\n                        if (AnnotationUtil.hasClassAnnotation(WebActor.class, is))\n                            registerWebActor(sc, cl.loadClass(className));\n                    } catch (final IOException | ClassNotFoundException e) {\n                        sc.log(\"Exception while scanning class \" + className + \" for WebActor annotation\", e);\n                        throw new RuntimeException(e);\n                    }\n                }\n            });\n//            final ClassPath classpath = ClassPath.from(cl);\n//            for (ClassPath.ClassInfo ci : classpath.getTopLevelClasses()) {\n//                try {\n//                    if (AnnotationUtil.hasClassAnnotation(WebActor.class, cl.getResourceAsStream(ci.getName().replace('.', '/') + \".class\")))\n//                        registerWebActor(sc, ci.load());\n//                } catch (IOException e) {\n//                    sc.log(\"IOException while scanning class \" + ci.getName() + \" for WebActor annotation\", e);\n//                }\n//            }\n        } catch (final IOException e) {\n            sc.log(\"IOException while scanning classes for WebActor annotation\", e);\n        }\n    }\n\n    public static void registerWebActor(ServletContext sc, Class<?> webActorClass) {\n        final WebActor waAnn = webActorClass.getAnnotation(WebActor.class);\n        final String name = (waAnn.name() != null && !waAnn.name().isEmpty()) ? waAnn.name() : webActorClass.getName();\n        // servlet\n        final Dynamic d = sc.addServlet(name, WebActorServlet.class);\n        d.setInitParameter(WebActorServlet.ACTOR_CLASS_PARAM, webActorClass.getName());\n        d.setAsyncSupported(true);\n        d.addMapping(waAnn.httpUrlPatterns());\n        d.addMapping(waAnn.value());\n\n        // web socket\n        if (waAnn.webSocketUrlPatterns().length > 0) {\n            // we wouldn't want to fail the assert if we don't listen to any websocket\n            final ServerContainer scon = (ServerContainer) sc.getAttribute(\"javax.websocket.server.ServerContainer\");\n            assert scon != null : \"Container does not support websockets !!!\";\n            for (final String wsPath : waAnn.webSocketUrlPatterns()) {\n                try {\n                    scon.addEndpoint(ServerEndpointConfig.Builder.create(WebActorEndpoint.class, wsPath)\n                            .configurator(new EmbedHttpSessionWsConfigurator()).build());\n                } catch (final DeploymentException ex) {\n                    sc.log(\"Unable to deploy endpoint\", ex);\n                }\n            }\n        }\n    }\n\n    @Override\n    public final void contextDestroyed(ServletContextEvent sce) {\n    }\n}\n"
  },
  {
    "path": "comsat-actors-servlet/src/main/java/co/paralleluniverse/comsat/webactors/servlet/WebActorServlet.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Sotware Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n\nimport co.paralleluniverse.actors.*;\nimport co.paralleluniverse.common.util.SystemProperties;\nimport co.paralleluniverse.comsat.webactors.Cookie;\nimport co.paralleluniverse.comsat.webactors.*;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.strands.Timeout;\nimport co.paralleluniverse.strands.channels.SendPort;\nimport co.paralleluniverse.strands.concurrent.CountDownLatch;\n\nimport javax.servlet.*;\nimport javax.servlet.annotation.WebListener;\nimport javax.servlet.http.*;\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicReference;\n\n/**\n * A servlet that forwards requests to a web actor.\n */\n@WebListener\npublic final class WebActorServlet extends HttpServlet implements HttpSessionListener {\n    protected static final String SESSION_KEY_ACTOR = WebActorServlet.class.getName() + \".actor\";\n\n    protected static final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());\n\n    protected static final ScheduledExecutorService ts = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());\n\n    static final String ACTOR_CLASS_PARAM = \"actor\";\n    static final String ACTOR_PARAM_PREFIX = \"actorParam\";\n\n    private static final String DISPATCH_INTERNAL_ERROR_EXCEPTION_REQUEST_KEY = WebActorServlet.class.getName() + \".reqAttr.internalErrorException\";\n    private static final String DISPATCH_ERROR_STATUS_REQUEST_KEY = WebActorServlet.class.getName() + \".reqAttr.errorStatus\";\n    private static final String DISPATCH_ERROR_MESSAGE_REQUEST_KEY = WebActorServlet.class.getName() + \".reqAttr.errorMessage\";\n\n    public static final String PROP_DISABLE_SYNC_ERRORS = WebActorServlet.class.getName() + \".disableSyncErrors\";\n    static final boolean disableSyncErrorsGlobal = SystemProperties.isEmptyOrTrue(PROP_DISABLE_SYNC_ERRORS);\n\n    public static final String PROP_ACTOR_END_ACTION = WebActorServlet.class.getName() + \".actorEndAction\";\n    public static final String PROP_ACTOR_END_ACTION_VALUE_DIE_IF_ERROR_ELSE_RESTART = \"dieIfErrorElseRestart\";\n    public static final String PROP_ACTOR_END_ACTION_VALUE_RESTART = \"restart\";\n//    public static final String PROP_ACTOR_END_ACTION_VALUE_DIE = \"die\";\n    static final String actorEndActionGlobal = System.getProperty(PROP_ACTOR_END_ACTION, PROP_ACTOR_END_ACTION_VALUE_DIE_IF_ERROR_ELSE_RESTART);\n\n    public static final String PROP_ASYNC_TIMEOUT = WebActorServlet.class.getName() + \".asyncTimeout\";\n    static final long reqTimeoutMS;\n\n    static {\n        reqTimeoutMS = getLong(PROP_ASYNC_TIMEOUT, 120_000_000L);\n    }\n\n    private final AtomicReference<ActorSpec> specAR = new AtomicReference<>();\n\n    private String redirectPath = null;\n    private String actorClassName = null;\n    private String[] actorParams = null;\n\n    @Override\n    public final void init(ServletConfig config) throws ServletException {\n        super.init(config);\n\n        final Enumeration<String> initParameterNames = config.getInitParameterNames();\n        final SortedMap<Integer, String> map = new TreeMap<>();\n        while (initParameterNames.hasMoreElements()) {\n            final String name = initParameterNames.nextElement();\n\n            if (name.equals(\"redirectNoSessionPath\"))\n                setRedirectNoSessionPath(config.getInitParameter(name));\n            else if (name.equals(ACTOR_CLASS_PARAM))\n                setActorClassName(config.getInitParameter(name));\n            else if (name.startsWith(ACTOR_PARAM_PREFIX)) {\n                try {\n                    final int num = Integer.parseInt(name.substring(\"actorParam\".length()));\n                    map.put(num, config.getInitParameter(name));\n                } catch (final NumberFormatException nfe) {\n                    getServletContext().log(\"Wrong actor parameter number: \", nfe);\n                }\n            }\n        }\n        final Collection<String> values = map.values();\n        actorParams = values.toArray(new String[values.size()]);\n    }\n\n\n    public final WebActorServlet setRedirectNoSessionPath(String path) {\n        this.redirectPath = path;\n        return this;\n    }\n\n    public final WebActorServlet setActorClassName(String className) {\n        this.actorClassName = className;\n        return this;\n    }\n\n    static HttpActorAdapter getOrAttachSessionActor(final HttpSession session, Callable<HttpActorAdapter> sessionActorProducer) {\n        if (session.getAttribute(SESSION_KEY_ACTOR) != null)\n            return (HttpActorAdapter) session.getAttribute(SESSION_KEY_ACTOR);\n\n        final HttpActorAdapter actor;\n        try {\n            actor = sessionActorProducer.call();\n        } catch (final Exception e) {\n            throw new AssertionError(e); // Will not happen\n        }\n        session.setAttribute(SESSION_KEY_ACTOR, actor);\n        return actor;\n    }\n\n    @Override\n    public final void sessionCreated(HttpSessionEvent se) {\n        // Simply forbid override for implementation extension control purposes\n    }\n\n    @Override\n    public final void sessionDestroyed(HttpSessionEvent se) {\n        se.getSession().removeAttribute(SESSION_KEY_ACTOR);\n    }\n\n    static boolean isWebActorAttached(final HttpSession session) {\n        return session.getAttribute(SESSION_KEY_ACTOR) != null;\n    }\n\n    static <T> ActorRef<T> getWebActor(final HttpSession session) {\n        final HttpActorAdapter a = (HttpActorAdapter) session.getAttribute(SESSION_KEY_ACTOR);\n        //noinspection unchecked\n        return a != null ? (ActorRef<T>) a.userWebActorRef : null;\n    }\n\n    @Override\n    protected final void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {\n        if (!disableSyncErrorsGlobal && DispatcherType.ASYNC.equals(req.getDispatcherType())) {\n            final Throwable ex = (Throwable) req.getAttribute(DISPATCH_INTERNAL_ERROR_EXCEPTION_REQUEST_KEY);\n            if (ex != null)\n                throw new ServletException(ex);\n            final Integer status = (Integer) req.getAttribute(DISPATCH_ERROR_STATUS_REQUEST_KEY);\n            if (status != null) {\n                resp.sendError(status, (String) req.getAttribute(DISPATCH_ERROR_MESSAGE_REQUEST_KEY));\n                return;\n            }\n        }\n\n        if (isTomcat(req.getClass()))\n            req.setAttribute(\"org.apache.catalina.ASYNC_SUPPORTED\", true);\n        final AsyncContext ctx = req.startAsync();\n\n        try {\n            //noinspection unchecked\n            specAR.compareAndSet(null, new ActorSpec(Class.forName(actorClassName), actorParams));\n        } catch (final ClassNotFoundException ex) {\n            internalError(req, ctx, resp, new RuntimeException(\"Unable to load actorClass: \" + ex.getMessage()));\n            return;\n        }\n\n        try {\n            if (actorClassName != null) {\n                //noinspection unchecked\n                final Callable<ActorRef> actorRefBuilder = new Callable<ActorRef>() {\n                    @Override\n                    public ActorRef call() throws Exception {\n                        //noinspection unchecked\n                        return Actor.newActor(specAR.get()).spawn();\n                    }\n                };\n                //noinspection unchecked\n                getOrAttachSessionActor (\n                    req.getSession(), new Callable<HttpActorAdapter>() {\n                        @Override\n                        public HttpActorAdapter call() throws Exception {\n                            return new HttpActorAdapter(actorRefBuilder, req.getSession());\n                        }\n                    }\n                ).handleRequest(ctx, req, resp);\n            } else if (redirectPath != null) {\n                redirect(ctx, resp, redirectPath);\n            } else {\n                internalError(req, ctx, resp, new RuntimeException(\"Actor not found\"));\n            }\n        } catch (final ServletException | IOException | InterruptedException | SuspendExecution e) {\n            internalError(req, ctx, resp, e);\n        }\n    }\n\n    static void redirect(AsyncContext ac, HttpServletResponse res, String path) throws IOException {\n        res.sendRedirect(path);\n        if (isTomcat(ac.getClass())) // Seems required only by Tomcat\n            ac.complete();\n    }\n\n    static void internalError(HttpServletRequest req, AsyncContext ac, HttpServletResponse resp, Throwable t) throws IOException {\n        if (disableSyncErrorsGlobal) {\n            resp.sendError(500, t.getMessage());\n            if (isTomcat(ac.getClass())) // Seems required only by Tomcat\n                ac.complete();\n        } else {\n            req.setAttribute(DISPATCH_INTERNAL_ERROR_EXCEPTION_REQUEST_KEY, t);\n            ac.dispatch();\n        }\n    }\n\n    static void error(HttpServletRequest req, AsyncContext ac, HttpServletResponse resp, int status, String message) throws IOException {\n        if (disableSyncErrorsGlobal || isTomcat(ac.getClass())) { // Tomcat doesn't seem to support dispatching error responses\n            resp.sendError(status, message);\n            if (isTomcat(ac.getClass())) // Seems required only by Tomcat\n                ac.complete();\n        } else {\n            req.setAttribute(DISPATCH_ERROR_STATUS_REQUEST_KEY, status);\n            req.setAttribute(DISPATCH_ERROR_MESSAGE_REQUEST_KEY, message);\n            ac.dispatch();\n        }\n    }\n\n    static final class HttpActorAdapter extends FakeActor<HttpResponse> {\n        volatile HttpSession session;\n        volatile ActorRef userWebActorRef;\n\n        private final static String replyTimeoutProp = System.getProperty(HttpActorAdapter.class.getName() + \".replyTimeout\");\n        private static final long REPLY_TIMEOUT = replyTimeoutProp != null ? Long.parseLong(replyTimeoutProp) : 120_000L;\n\n        private final AtomicReference<co.paralleluniverse.strands.concurrent.CountDownLatch> gate = new AtomicReference<>();\n\n        private volatile Callable<ActorRef> userWebActorRefBuilder;\n\n        private volatile AsyncContext asyncCtx;\n        private volatile HttpServletRequest req;\n        private volatile HttpServletResponse res;\n\n        private volatile boolean needsRestart;\n\n        private volatile Object watchToken;\n        private volatile boolean dead;\n\n        private volatile ScheduledFuture<?> cancelTask;\n\n        public HttpActorAdapter(Callable<ActorRef> userWebActorRefBuilder, HttpSession session) {\n            super(\"HttpActorAdapter-\" + UUID.randomUUID(), new HttpRequestChannel());\n\n            this.userWebActorRefBuilder = userWebActorRefBuilder;\n            this.session = session;\n\n            ((HttpRequestChannel) (SendPort) getMailbox()).actor = this;\n\n            try {\n                this.userWebActorRef = userWebActorRefBuilder.call();\n            } catch (final Exception e) {\n                throw new RuntimeException(e);\n            }\n            this.watchToken = watch(userWebActorRef);\n        }\n\n        final void handleRequest(final AsyncContext asyncCtx, final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException, SuspendExecution, InterruptedException {\n            blockSessionRequests();\n\n            if (needsRestart) {\n                unwatch(userWebActorRef, watchToken);\n                userWebActorRef = null;\n                watchToken = null;\n                try {\n                    userWebActorRef = userWebActorRefBuilder.call(); // New\n                    watchToken = watch(userWebActorRef);\n                } catch (final Exception e) { // Should not happen\n                    e.printStackTrace();\n                    throw new RuntimeException(e);\n                }\n                needsRestart = false;\n            }\n\n            this.asyncCtx = asyncCtx;\n            this.req = req;\n            this.res = resp;\n\n            //noinspection unchecked\n            userWebActorRef.send(new ServletHttpRequest(ref(), req, resp));\n        }\n\n        @Suspendable\n        private void blockSessionRequests() throws InterruptedException {\n            while (!gate.compareAndSet(null, new CountDownLatch(1))) {\n                final CountDownLatch l = gate.get();\n                if (l != null)\n                    l.await();\n            }\n            final HttpServletRequest req = this.req;\n            final HttpServletResponse res = this.res;\n            final AsyncContext ctx = this.asyncCtx;\n            cancelTask = ts.schedule(new Runnable() {\n                @Override\n                public void run() {\n                    try {\n                        internalError(req, ctx, res, new RuntimeException(\"Timeout while waiting for user actor to reply.\"));\n                    } catch (final IOException e) {\n                        // TODO Handle\n                        e.printStackTrace();\n                    }\n                }\n            }, REPLY_TIMEOUT, TimeUnit.MILLISECONDS);\n        }\n\n        @Suspendable\n        private void unblockSessionRequests() {\n            if (cancelTask != null)\n                cancelTask.cancel(true);\n            final CountDownLatch l = gate.getAndSet(null);\n            if (l != null)\n                l.countDown();\n        }\n\n        private boolean isRequestInProgress() {\n            return gate.get() != null;\n        }\n\n        @Override\n        protected final void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        protected final void interrupt() {\n            die(new InterruptedException());\n        }\n\n        @Override\n        protected final HttpResponse handleLifecycleMessage(LifecycleMessage m) {\n            handleLifecycle(m);\n            return null;\n        }\n\n        private boolean handleLifecycle(LifecycleMessage m) {\n            if (m instanceof ExitMessage) {\n                final ExitMessage em = (ExitMessage) m;\n                if (em.getActor() != null && em.getActor().equals(userWebActorRef)) {\n                    //noinspection ThrowableResultOfMethodCallIgnored\n                    if (actorEndActionGlobal.equals(PROP_ACTOR_END_ACTION_VALUE_RESTART) ||\n                        actorEndActionGlobal.equals(PROP_ACTOR_END_ACTION_VALUE_DIE_IF_ERROR_ELSE_RESTART) && em.getCause() == null) {\n                        needsRestart = true;\n                    } else {\n                        handleDie(em.getCause());\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        @Override\n        protected final void die(Throwable cause) {\n            handleDie(cause);\n        }\n\n        private void handleDie(Throwable cause) {\n            try {\n                possiblyReplyDeadAndUnblock(cause);\n\n                if (dead)\n                    return;\n                dead = true;\n\n                super.die(cause);\n\n                try {\n                    session.invalidate();\n                } catch (final Throwable ignored) {}\n\n                // Ensure to release references\n                if (userWebActorRef != null && watchToken != null)\n                    unwatch(userWebActorRef, watchToken);\n\n            } catch (final IOException e) {\n                throw new RuntimeException(e);\n            } finally {\n                unblockSessionRequests();\n            }\n\n            asyncCtx = null;\n            req = null;\n            session = null;\n            res = null;\n\n            userWebActorRefBuilder = null;\n            userWebActorRef = null;\n            watchToken = null;\n        }\n\n        private void possiblyReplyDeadAndUnblock(final Throwable cause) throws IOException {\n            if (isRequestInProgress()) {\n                try {\n                    if (cause != null) {\n                        cause.printStackTrace(System.err);\n                        internalError(req, asyncCtx, res, new RuntimeException(\"Actor is dead\", cause));\n                    } else {\n                        internalError(req, asyncCtx, res, new RuntimeException(\"Actor has terminated\"));\n                    }\n                } finally {\n                    unblockSessionRequests();\n                }\n            }\n        }\n\n        final void handleReply(final HttpResponse msg) throws SuspendExecution {\n            HttpServletRequest request;\n            try {\n                request = ((ServletHttpRequest) msg.getRequest()).request;\n\n                final AsyncContext ctx = request.getAsyncContext();\n                final HttpServletResponse response = (HttpServletResponse) ctx.getResponse();\n\n                try {\n                    if (msg.getCookies() != null) {\n                        for (final Cookie wc : msg.getCookies())\n                            response.addCookie(getServletCookie(wc));\n                    }\n                    if (msg.getHeaders() != null) {\n                        for (final Map.Entry<String, String> h : msg.getHeaders().entries())\n                            response.addHeader(h.getKey(), h.getValue());\n                    }\n\n                    if (msg.getStatus() >= 400 && msg.getStatus() < 600) {\n                        //noinspection ThrowableResultOfMethodCallIgnored\n                        error(request, ctx, response, msg.getStatus(), msg.getError() != null ? msg.getError().toString() : null);\n                    }\n\n                    if (msg.getRedirectPath() != null) {\n                        redirect(ctx, response, msg.getRedirectPath());\n                    }\n\n                    final boolean sse = msg.shouldStartActor();\n                    if (msg.shouldStartActor())\n                        msg.getFrom().send(new HttpStreamOpened(new HttpStreamActor(request, response, ctx).ref(), msg));\n\n                    if (isUndertow(request.getClass()))\n                        // In Undertow, sending a reply directly from a fiber produces a thread-local related leak due to unfreed buffers\n                        es.submit(new Runnable() {\n                            @Override\n                            public void run() {\n                                try {\n                                    writeResponse(ctx, msg, response, sse);\n                                } catch (final IOException e1) {\n                                    try {\n                                        internalError(req, ctx, response, new RuntimeException(e1));\n                                    } catch (final IOException e2) {\n                                        // TODO handle\n                                        throw new RuntimeException(e2);\n                                    }\n                                }\n                            }\n                        });\n                    else\n                        writeResponse(ctx, msg, response, sse);\n                } catch (final IOException ex) {\n                    if (request.getServletContext() != null)\n                        request.getServletContext().log(\"IOException\", ex);\n                    ctx.complete();\n                }\n            } finally {\n                unblockSessionRequests();\n            }\n        }\n\n        private void writeResponse(AsyncContext ctx, HttpResponse msg, HttpServletResponse response, boolean sse) throws IOException {\n            response.setStatus(msg.getStatus());\n\n            if (msg.getContentType() != null)\n                response.setContentType(msg.getContentType());\n            if (msg.getCharacterEncoding() != null)\n                response.setCharacterEncoding(msg.getCharacterEncoding().name());\n            final ServletOutputStream out = writeBody(msg, response, !msg.shouldStartActor());\n            out.flush(); // commits the response\n\n            if (!sse) {\n                out.close();\n                ctx.complete();\n            }\n        }\n    }\n\n    private static final class HttpRequestChannel implements SendPort<HttpResponse> {\n        private HttpActorAdapter actor;\n\n        HttpRequestChannel() {}\n\n        @Override\n        public final void send(HttpResponse message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        public final boolean send(HttpResponse message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            send(message);\n            return true;\n        }\n\n        @Override\n        public final boolean send(HttpResponse message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        @Suspendable\n        public final boolean trySend(HttpResponse msg) {\n            try {\n                actor.handleReply(msg);\n            } catch (final SuspendExecution e) {\n                throw new AssertionError(e);\n            }\n            return true;\n        }\n\n        @Override\n        public final void close() {\n            if (actor != null)\n                actor.die(null);\n        }\n\n        @Override\n        public final void close(Throwable t) {\n            t.printStackTrace(System.err); // TODO: log\n            if (actor != null)\n                actor.die(t);\n        }\n    }\n\n    private static final class HttpStreamActor extends FakeActor<WebDataMessage> {\n        private volatile boolean dead;\n\n        public HttpStreamActor(final HttpServletRequest request, final HttpServletResponse response, final AsyncContext ac) {\n            super(request.toString(), new HttpStreamChannel(ac, response));\n            ((HttpStreamChannel) (Object) mailbox()).actor = this;\n        }\n\n        @Override\n        protected final WebDataMessage handleLifecycleMessage(LifecycleMessage m) {\n            if (m instanceof ShutdownMessage)\n                die(null);\n            return null;\n        }\n\n        @Override\n        protected final void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        public final void interrupt() {\n            die(new InterruptedException());\n        }\n\n        @Override\n        protected final void die(Throwable cause) {\n            if (dead)\n                return;\n            dead = true;\n            mailbox().close();\n            super.die(cause);\n        }\n\n        @Override\n        public final String toString() {\n            return \"HttpStreamActor{request + \" + getName() + \"}\";\n        }\n    }\n\n    private static final class HttpStreamChannel implements SendPort<WebDataMessage> {\n        HttpStreamActor actor;\n\n        AsyncContext ctx;\n        HttpServletResponse response;\n\n        public HttpStreamChannel(AsyncContext ctx, HttpServletResponse response) {\n            this.ctx = ctx;\n            this.response = response;\n        }\n\n        @Override\n        public void send(WebDataMessage message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        public boolean send(WebDataMessage message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            send(message);\n            return true;\n        }\n\n        @Override\n        public boolean send(WebDataMessage message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        public boolean trySend(WebDataMessage message) {\n            try {\n                if (response != null) {\n                    ServletOutputStream os = writeBody(message, response, false);\n                    os.flush();\n                } else {\n                    return false;\n                }\n            } catch (final IOException ex) {\n                if (actor != null)\n                    actor.die(ex);\n                return false;\n            }\n            return true;\n        }\n\n        @Override\n        public void close() {\n            try {\n                if (response != null) {\n                    try {\n                        ServletOutputStream os = response.getOutputStream();\n                        os.close();\n                    } catch (final IOException ignored) { // TODO handle\n                        //ctx.getRequest().getServletContext().log(\"error\", e);\n                    }\n                    ctx.complete();\n                }\n            } catch (final Exception ignored) { // TODO handle\n            } finally {\n                if (actor != null)\n                    actor.die(null);\n                actor = null;\n                ctx = null;\n                response = null;\n            }\n        }\n\n        @Override\n        public void close(Throwable t) {\n            if (actor != null)\n                actor.die(t);\n            close();\n        }\n    }\n\n    static ServletOutputStream writeBody(WebMessage message, HttpServletResponse response, boolean shouldClose) throws IOException {\n        final byte[] arr;\n        final int offset;\n        final int length;\n        ByteBuffer bb;\n        String sb;\n        if ((bb = message.getByteBufferBody()) != null) {\n            if (bb.hasArray()) {\n                arr = bb.array();\n                offset = bb.arrayOffset() + bb.position();\n                length = bb.remaining();\n                bb.position(bb.limit());\n            } else {\n                arr = new byte[bb.remaining()];\n                bb.get(arr);\n                offset = 0;\n                length = arr.length;\n            }\n        } else if ((sb = message.getStringBody()) != null) {\n            arr = sb.getBytes(response.getCharacterEncoding());\n            offset = 0;\n            length = arr.length;\n        } else {\n            arr = null;\n            offset = 0;\n            length = 0;\n        }\n\n        if (!response.isCommitted() && shouldClose)\n            response.setContentLength(length);\n\n        final ServletOutputStream out = response.getOutputStream();\n        if (arr != null)\n            out.write(arr, offset, length);\n        return out;\n    }\n\n    private static javax.servlet.http.Cookie getServletCookie(Cookie wc) {\n        javax.servlet.http.Cookie c = new javax.servlet.http.Cookie(wc.getName(), wc.getValue());\n        c.setComment(wc.getComment());\n        if (wc.getDomain() != null)\n            c.setDomain(wc.getDomain());\n        c.setMaxAge(wc.getMaxAge());\n        c.setPath(wc.getPath());\n        c.setSecure(wc.isSecure());\n        c.setHttpOnly(wc.isHttpOnly());\n        c.setVersion(wc.getVersion());\n        return c;\n    }\n\n    static boolean isTomcat(Class c) {\n        return c.getName().startsWith(\"org.apache.\");\n    }\n\n    static boolean isUndertow(Class c) {\n        return c.getName().startsWith(\"io.undertow.servlet.\");\n    }\n\n    static long getLong(String propName, long def) {\n        final String longS = System.getProperty(propName);\n\n        if (longS == null)\n            return def;\n\n        long l;\n        try {\n            l = Long.parseLong(longS);\n        } catch (final NumberFormatException ignored) {\n            l = def;\n        }\n        return l;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-servlet/src/main/java/co/paralleluniverse/comsat/webactors/servlet/package-info.java",
    "content": "/*\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n * \n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *  \n *   or (per the licensee's choosing)\n *  \n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/**\n * A Web Actors backend implementation based on Servlets\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n"
  },
  {
    "path": "comsat-actors-servlet/src/test/java/co/paralleluniverse/comsat/webactors/servlet/HttpRequestWrapperTest.java",
    "content": "package co.paralleluniverse.comsat.webactors.servlet;\n\nimport org.junit.Test;\nimport org.springframework.mock.web.MockHttpServletRequest;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * @author rodedb\n */\npublic class HttpRequestWrapperTest {\n\n    @Test\n    public void httpHeaderCaseInsensitivity() {\n        MockHttpServletRequest mockRequest = new MockHttpServletRequest();\n        String headerValue = \"application/json\";\n        mockRequest.addHeader(\"Authorization\", headerValue);\n        ServletHttpRequest requestWrapper = new ServletHttpRequest(null, mockRequest, null);\n        assertEquals(headerValue, requestWrapper.getHeader(\"authorization\"));\n    }\n}"
  },
  {
    "path": "comsat-actors-servlet/src/test/java/co/paralleluniverse/comsat/webactors/servlet/ServletWebActor.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n\nimport co.paralleluniverse.comsat.webactors.MyWebActor;\nimport co.paralleluniverse.comsat.webactors.WebActor;\n\n/**\n * @author circlespainter\n */\n@WebActor(httpUrlPatterns = {\"/*\"}, webSocketUrlPatterns = {\"/ws\"})\npublic final class ServletWebActor extends MyWebActor {}\n"
  },
  {
    "path": "comsat-actors-servlet/src/test/java/co/paralleluniverse/comsat/webactors/servlet/WebActorServletTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.servlet;\n\nimport co.paralleluniverse.comsat.webactors.AbstractWebActorTest;\nimport co.paralleluniverse.embedded.containers.*;\nimport com.google.common.collect.Lists;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport javax.websocket.ClientEndpointConfig;\nimport org.apache.http.client.CookieStore;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class WebActorServletTest extends AbstractWebActorTest {\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {JettyServer.class},\n            {TomcatServer.class},\n            {UndertowServer.class},\n        });\n    }\n    private final Class<? extends EmbeddedServer> cls;\n    private EmbeddedServer embeddedServer;\n\n    public WebActorServletTest(Class<? extends EmbeddedServer> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        this.embeddedServer = cls.newInstance();\n        // snippet WebActorInitializer\n        WebActorInitializer.setUserClassLoader(ClassLoader.getSystemClassLoader());\n        embeddedServer.addServletContextListener(WebActorInitializer.class);\n        // end of snippet\n        embeddedServer.enableWebsockets();\n        embeddedServer.start();\n        AbstractEmbeddedServer.waitUrlAvailable(\"http://localhost:8080\");\n        System.out.println(\"Server is up\");\n    }\n\n    @After\n    public void tearDown() throws Exception {       \n        embeddedServer.stop();\n    }\n\n    @Override\n    protected String getSessionIdCookieName() {\n        return JSESSIONID;\n    }\n\n    @Override\n    protected ClientEndpointConfig getClientEndPointConfig(final CookieStore cookieStore) {\n        return ClientEndpointConfig.Builder.create().configurator(new ClientEndpointConfig.Configurator() {\n            @Override\n            public void beforeRequest(Map<String, List<String>> headers) {\n                headers.put(\"Cookie\", Lists.newArrayList(JSESSIONID + '=' + getByName(cookieStore, JSESSIONID)));\n            }\n        }).build();\n    }\n\n    private static String getByName(final CookieStore cookieStore, String name) {\n        for (org.apache.http.cookie.Cookie cookie : cookieStore.getCookies())\n            if (name.equals(cookie.getName()))\n                return cookie.getValue();\n        return null;\n    }\n\n    private static final String JSESSIONID = \"JSESSIONID\";\n}\n"
  },
  {
    "path": "comsat-actors-undertow/src/main/java/co/paralleluniverse/comsat/webactors/undertow/AutoWebActorHandler.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.undertow;\n\nimport co.paralleluniverse.actors.*;\nimport co.paralleluniverse.common.reflection.AnnotationUtil;\nimport co.paralleluniverse.common.reflection.ClassLoaderUtil;\nimport co.paralleluniverse.common.util.Pair;\nimport co.paralleluniverse.comsat.webactors.WebActor;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\n\nimport io.undertow.UndertowLogger;\nimport io.undertow.server.HttpServerExchange;\nimport io.undertow.server.session.Session;\nimport io.undertow.util.Sessions;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\nimport java.net.URLClassLoader;\nimport java.util.*;\n\n/**\n * @author circlespainter\n */\npublic final class AutoWebActorHandler extends WebActorHandler {\n    private static final List<Class<?>> actorClasses = new ArrayList<>(4);\n    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];\n\n    public AutoWebActorHandler() {\n        this(null, null, null);\n    }\n\n    public AutoWebActorHandler(List<String> packagePrefixes) {\n        this(null, packagePrefixes, null);\n    }\n\n    public AutoWebActorHandler(ClassLoader userClassLoader, List<String> packagePrefixes) {\n        this(userClassLoader, packagePrefixes, null);\n    }\n\n    public AutoWebActorHandler(List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams) {\n        this(null, packagePrefixes, actorParams);\n    }\n\n    public AutoWebActorHandler(ClassLoader userClassLoader, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams) {\n        super(null);\n        super.contextProvider = newContextProvider(userClassLoader != null ? userClassLoader : ClassLoader.getSystemClassLoader(), packagePrefixes, actorParams);\n    }\n\n    public AutoWebActorHandler(AutoContextProvider prov) {\n        super(prov);\n    }\n\n    protected AutoContextProvider newContextProvider(ClassLoader userClassLoader, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams) {\n        return new AutoContextProvider(userClassLoader, packagePrefixes, actorParams);\n    }\n\n    private static class AutoContextProvider implements ContextProvider {\n        private final ClassLoader userClassLoader;\n        private final Map<Class<?>, Object[]> actorParams;\n        private final Long defaultContextValidityMS;\n        private final List<String> packagePrefixes;\n\n        public AutoContextProvider(ClassLoader userClassLoader, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams) {\n            this(userClassLoader, packagePrefixes, actorParams, null);\n        }\n\n        public AutoContextProvider(ClassLoader userClassLoader, List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams, Long defaultContextValidityMS) {\n            this.userClassLoader = userClassLoader;\n            this.packagePrefixes = packagePrefixes;\n            this.actorParams = actorParams;\n            this.defaultContextValidityMS = defaultContextValidityMS;\n        }\n\n        @Override\n        public final Context get(final HttpServerExchange xch) {\n            Session session = null;\n            Context actorContext = newContext(xch);\n            if (actorContext != null) {\n                try {\n                    session = Sessions.getOrCreateSession(xch);\n                } catch (final IllegalStateException ignored) {\n                } // No session handler\n\n                if (session != null) {\n                    Context sessionContext = (Context) session.getAttribute(ACTOR_KEY);\n                    if (sessionContext == null || !sessionContext.renew())\n                        session.setAttribute(ACTOR_KEY, actorContext);\n                    else\n                        actorContext = sessionContext;\n                }\n            }\n\n            return actorContext;\n        }\n\n        private Context newContext(final HttpServerExchange xch) {\n            final AutoActorContext c = new AutoActorContext(packagePrefixes, actorParams, userClassLoader);\n            boolean valid = c.fillActor(xch);\n            if (!valid)\n                return null;\n\n            if (defaultContextValidityMS != null)\n                c.setValidityMS(defaultContextValidityMS);\n            return c;\n        }\n    }\n\n    private static final class AutoActorContext extends DefaultContextImpl {\n        private String id;\n\n        private final List<String> packagePrefixes;\n        private final Map<Class<?>, Object[]> actorParams;\n        private final ClassLoader userClassLoader;\n        private Class<? extends ActorImpl<? extends WebMessage>> actorClass;\n        private ActorRef<? extends WebMessage> actorRef;\n\n        public AutoActorContext(List<String> packagePrefixes, Map<Class<?>, Object[]> actorParams, ClassLoader userClassLoader) {\n            this.packagePrefixes = packagePrefixes;\n            this.actorParams = actorParams;\n            this.userClassLoader = userClassLoader;\n        }\n\n        /**\n         * Associates a {@link WebActor} annotated class to an {@link HttpServerExchange}\n         * @param xch The exchange\n         * @return Whether or not an actor has been associated\n         */\n        private boolean fillActor(HttpServerExchange xch) {\n            final Pair<ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>> p = autoCreateActor(xch);\n            if (p != null) {\n                actorRef = p.getFirst();\n                actorClass = p.getSecond();\n                return true;\n            }\n            return false;\n        }\n\n        @Override\n        public final String getId() {\n            return id != null ? id : (id = UUID.randomUUID().toString());\n        }\n\n        @Override\n        public final void restart(HttpServerExchange xch) {\n            renewed = new Date().getTime();\n            fillActor(xch);\n        }\n\n        @Override\n        public final ActorRef<? extends WebMessage> getWebActor() {\n            return actorRef;\n        }\n\n        @Override\n        public final boolean handlesWithWebSocket(String uri) {\n            return WebActorHandler.handlesWithWebSocket(uri, actorClass);\n        }\n\n        @Override\n        public final boolean handlesWithHttp(String uri) {\n            return WebActorHandler.handlesWithHttp(uri, actorClass);\n        }\n\n        @Override\n        public WatchPolicy watch() {\n            return WatchPolicy.DIE_IF_EXCEPTION_ELSE_RESTART;\n        }\n\n        @SuppressWarnings(\"unchecked\")\n        private Pair<ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>> autoCreateActor(HttpServerExchange xch) {\n            registerActorClasses();\n            final String uri = xch.getRequestURI();\n            for (final Class<?> c : actorClasses) {\n                if (WebActorHandler.handlesWithHttp(uri, c) || WebActorHandler.handlesWithWebSocket(uri, c))\n                    return new Pair<ActorRef<? extends WebMessage>, Class<? extends ActorImpl<? extends WebMessage>>> (\n                        Actor.newActor (\n                            new ActorSpec(c, actorParams != null ? actorParams.get(c) : EMPTY_OBJECT_ARRAY)\n                        ).spawn(),\n                        (Class<? extends ActorImpl<? extends WebMessage>>) c\n                    );\n            }\n\n            return null;\n        }\n\n        private synchronized void registerActorClasses() {\n            if (actorClasses.isEmpty()) {\n                try {\n                    final ClassLoader classLoader = userClassLoader != null ? userClassLoader : this.getClass().getClassLoader();\n                    ClassLoaderUtil.accept((URLClassLoader) classLoader, new ClassLoaderUtil.Visitor() {\n                        @Override\n                        public final void visit(String resource, URL url, ClassLoader cl) {\n                            if (packagePrefixes != null) {\n                                boolean found = false;\n                                for (final String packagePrefix : packagePrefixes) {\n                                    if (packagePrefix != null && resource.startsWith(packagePrefix.replace('.', '/'))) {\n                                        found = true;\n                                        break;\n                                    }\n                                }\n                                if (!found)\n                                    return;\n                            }\n                            if (!ClassLoaderUtil.isClassFile(resource))\n                                return;\n                            final String className = ClassLoaderUtil.resourceToClass(resource);\n                            try (final InputStream is = cl.getResourceAsStream(resource)) {\n                                if (AnnotationUtil.hasClassAnnotation(WebActor.class, is))\n                                    registerWebActor(cl.loadClass(className));\n                            } catch (final IOException | ClassNotFoundException e) {\n                                UndertowLogger.ROOT_LOGGER.error(\"Exception while scanning class \" + className + \" for WebActor annotation\", e);\n                                throw new RuntimeException(e);\n                            }\n                        }\n\n                        private void registerWebActor(Class<?> c) {\n                            actorClasses.add(c);\n                        }\n                    });\n                } catch (final IOException e) {\n                    UndertowLogger.ROOT_LOGGER.error(\"IOException while scanning classes for WebActor annotation\", e);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-actors-undertow/src/main/java/co/paralleluniverse/comsat/webactors/undertow/ByteArrayReadChannelListener.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Adapted from Undertow's `io.undertow.util.StringReadChannelListener` class.\n * JBoss, Home of Professional Open Source. Copyright (C) 2014 Red Hat, Inc., and individual contributors as indicated by the @author tags.\n * Distributed under the Apache License Version 2.0.\n */\npackage co.paralleluniverse.comsat.webactors.undertow;\n\nimport io.undertow.UndertowLogger;\nimport io.undertow.connector.ByteBufferPool;\nimport io.undertow.connector.PooledByteBuffer;\nimport org.xnio.ChannelListener;\nimport org.xnio.IoUtils;\nimport org.xnio.channels.StreamSourceChannel;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\n\n/**\n * @author Stuart Douglas\n * @author circlespainter\n */\npublic abstract class ByteArrayReadChannelListener implements ChannelListener<StreamSourceChannel> {\n    private ByteArrayOutputStream baos = new ByteArrayOutputStream();\n    private ByteBufferPool bufferPool;\n\n    public ByteArrayReadChannelListener(final ByteBufferPool bufferPool) {\n        this.bufferPool = bufferPool;\n    }\n\n    public final void setup(final StreamSourceChannel c) {\n        partialRead(c, true);\n    }\n\n    @Override\n    public final void handleEvent(final StreamSourceChannel c) {\n        partialRead(c, false);\n    }\n\n    protected abstract void byteArrayDone(byte[] bs);\n\n    protected abstract void error(IOException e);\n\n    private void partialRead(StreamSourceChannel c, boolean setup) {\n        if (baos == null || bufferPool == null) // Already dead by exception\n            return;\n\n        PooledByteBuffer r = null;\n        ByteBuffer b;\n        try {\n            r = bufferPool.allocate();\n            b = r.getBuffer();\n            int readCount;\n            do {\n                readCount = c.read(b);\n                if (readCount == 0) {\n                    if (!setup)\n                        return;\n\n                    c.getReadSetter().set(this);\n                    c.resumeReads();\n                } else if (readCount == -1) {\n                    final byte[] result = baos.toByteArray();\n                    cleanup(c);\n                    byteArrayDone(result);\n                } else {\n                    b.flip();\n                    while (b.hasRemaining())\n                        baos.write(b.get());\n                }\n            } while (readCount > 0);\n        } catch (final IOException e) {\n            cleanup(c);\n            error(e);\n        } catch (final Throwable t) {\n            cleanup(c);\n            UndertowLogger.REQUEST_IO_LOGGER.error(\"Error in partial read\", t);\n            throw new RuntimeException(t);\n        } finally {\n            if (r != null)\n                r.close();\n        }\n    }\n\n    private void cleanup(StreamSourceChannel c) {\n        this.baos = null;\n        this.bufferPool = null;\n        c.getReadSetter().set(null);\n        IoUtils.safeClose(c);\n    }\n}\n"
  },
  {
    "path": "comsat-actors-undertow/src/main/java/co/paralleluniverse/comsat/webactors/undertow/StringWriteChannelListener.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Adapted from Undertow's `io.undertow.util.StringWriteChannelListener` class.\n * JBoss, Home of Professional Open Source. Copyright (C) 2014 Red Hat, Inc., and individual contributors as indicated by the @author tags.\n * Distributed under the Apache License Version 2.0.\n */\npackage co.paralleluniverse.comsat.webactors.undertow;\n\nimport io.undertow.UndertowLogger;\nimport org.xnio.ChannelListener;\nimport org.xnio.ChannelListeners;\nimport org.xnio.IoUtils;\nimport org.xnio.channels.StreamSinkChannel;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.Charset;\n\n/**\n * @author Stuart Douglas\n * @author circlespainter\n */\npublic final class StringWriteChannelListener implements ChannelListener<StreamSinkChannel> {\n    private ByteBuffer buffer;\n\n    public StringWriteChannelListener(String string) {\n        this(string, Charset.defaultCharset());\n    }\n\n    public StringWriteChannelListener(final String string, Charset charset) {\n        buffer = ByteBuffer.wrap(string.getBytes(charset));\n    }\n\n    public StringWriteChannelListener(final ByteBuffer buffer) {\n        this.buffer = buffer;\n    }\n\n    public final void setup(final StreamSinkChannel channel) {\n        partialWrite(channel, true);\n    }\n\n    @Override\n    public final void handleEvent(final StreamSinkChannel channel) {\n        partialWrite(channel, false);\n    }\n\n    private void partialWrite(StreamSinkChannel c, boolean setup) {\n        if (buffer == null)\n            return;\n\n        try {\n            int writeCount;\n            do {\n                writeCount = c.write(buffer);\n            } while (buffer.hasRemaining() && writeCount > 0);\n            if (buffer.hasRemaining()) {\n                if (setup)\n                    c.getWriteSetter().set(this);\n                c.resumeWrites();\n            } else {\n                writeDone(c);\n            }\n        } catch (final Throwable t) {\n            handleError(c, \"Error in 'partialWrite(setup = \" + setup + \")'\", t);\n            if (!(t instanceof IOException))\n                throw new RuntimeException(t);\n        }\n    }\n\n    private void writeDone(final StreamSinkChannel c) {\n        try {\n            cleanup();\n            c.shutdownWrites();\n\n            if (!c.flush()) {\n                c.getWriteSetter().set (\n                    ChannelListeners.flushingChannelListener (\n                        new ChannelListener<StreamSinkChannel>() {\n                            @Override\n                            public final void handleEvent(StreamSinkChannel o) {\n                                IoUtils.safeClose(c);\n                            }\n                        },\n                        ChannelListeners.closingChannelExceptionHandler()\n                    )\n                );\n                c.resumeWrites();\n            }\n        } catch (final Throwable t) {\n            handleError(c, \"Error in 'writeDone'\", t);\n            if (!(t instanceof IOException))\n                throw new RuntimeException(t);\n        }\n    }\n\n    private void handleError(StreamSinkChannel c, String m, Throwable t) {\n        if (t instanceof IOException)\n            UndertowLogger.REQUEST_IO_LOGGER.ioException((IOException) t);\n        else\n            UndertowLogger.REQUEST_IO_LOGGER.error(m, t);\n        cleanup();\n        c.getWriteSetter().set(null);\n        IoUtils.safeClose(c);\n    }\n\n    private void cleanup() {\n        if (buffer != null) {\n            buffer = null;\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-actors-undertow/src/main/java/co/paralleluniverse/comsat/webactors/undertow/UndertowHttpRequest.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.undertow;\n\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.comsat.webactors.Cookie;\nimport co.paralleluniverse.comsat.webactors.HttpRequest;\nimport co.paralleluniverse.comsat.webactors.HttpResponse;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\nimport com.google.common.collect.*;\nimport io.undertow.server.HttpServerExchange;\nimport io.undertow.util.HeaderMap;\nimport io.undertow.util.Headers;\nimport io.undertow.util.HttpString;\n\nimport java.net.InetSocketAddress;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.CharacterCodingException;\nimport java.nio.charset.Charset;\nimport java.nio.charset.CodingErrorAction;\nimport java.nio.charset.UnsupportedCharsetException;\nimport java.util.*;\n\n/**\n * @author circlespainter\n */\npublic final class UndertowHttpRequest extends HttpRequest {\n    final ActorRef<? super HttpResponse> actorRef;\n    final HttpServerExchange xch;\n    private final ByteBuffer reqContent;\n    private InetSocketAddress sourceAddress;\n    private ImmutableMultimap<String, String> params;\n    private URI uri;\n    private Collection<Cookie> cookies;\n    private ListMultimap<String, String> heads;\n    private ByteBuffer byteBufferBody;\n    private String stringBody;\n    private String contentType;\n    private Charset encoding;\n\n    public UndertowHttpRequest(ActorRef<? super HttpResponse> actorRef, HttpServerExchange xch, ByteBuffer reqContent) {\n        this.actorRef = actorRef;\n        this.xch = xch;\n        this.reqContent = reqContent;\n    }\n\n    public HttpServerExchange getServerExchange() {\n        return xch;\n    }\n\n    static ImmutableListMultimap<String, String> extractHeaders(HeaderMap headers) {\n        if (headers != null) {\n            final ImmutableListMultimap.Builder<String, String> builder = ImmutableListMultimap.builder();\n            for (final HttpString n : headers.getHeaderNames())\n                // Normalize header names by their conversion to lower case\n                builder.putAll(n.toString().toLowerCase(Locale.ENGLISH), headers.get(n));\n            return builder.build();\n        }\n        return null;\n    }\n\n    @Override\n    public final String getSourceHost() {\n        fillSourceAddress();\n        return sourceAddress != null ? sourceAddress.getHostString() : null;\n    }\n\n    @Override\n    public final int getSourcePort() {\n        fillSourceAddress();\n        return sourceAddress != null ? sourceAddress.getPort() : -1;\n    }\n\n    private void fillSourceAddress() {\n        if (sourceAddress == null)\n            sourceAddress = xch.getSourceAddress();\n    }\n\n    @Override\n    public Multimap<String, String> getParameters() {\n        if (params == null) {\n            final ImmutableMultimap.Builder<String, String> builder = ImmutableMultimap.builder();\n            final Map<String, Deque<String>> parameters = xch.getQueryParameters();\n            for (final String k : parameters.keySet())\n                builder.putAll(k, parameters.get(k));\n            params = builder.build();\n        }\n        return params;\n    }\n\n    @Override\n    public Map<String, Object> getAttributes() {\n        return null;\n    }\n\n    @Override\n    public String getScheme() {\n        initUri();\n        return uri.getScheme();\n    }\n\n    private void initUri() {\n        if (uri == null) {\n            try {\n                uri = new URI(xch.getRequestURI());\n            } catch (final URISyntaxException e) {\n                throw new RuntimeException(e);\n            }\n        }\n    }\n\n    @Override\n    public String getMethod() {\n        return xch.getRequestMethod().toString();\n    }\n\n    @Override\n    public String getPathInfo() {\n        initUri();\n        return uri.getPath();\n    }\n\n    @Override\n    public String getContextPath() {\n        return \"/\"; // Context path makes sense only for servlets\n    }\n\n    @Override\n    public String getQueryString() {\n        initUri();\n        return uri.getQuery();\n    }\n\n    @Override\n    public String getRequestURI() {\n        return xch.getRequestURI();\n    }\n\n    @Override\n    public String getServerName() {\n        return xch.getHostName();\n    }\n\n    @Override\n    public int getServerPort() {\n        return xch.getHostPort();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public ActorRef<WebMessage> getFrom() {\n        return (ActorRef<WebMessage>) actorRef;\n    }\n\n    @Override\n    public ListMultimap<String, String> getHeaders() {\n        if (heads == null) {\n            heads = extractHeaders(xch.getRequestHeaders());\n        }\n        return heads;\n    }\n\n    @Override\n    public Collection<Cookie> getCookies() {\n        if (cookies == null) {\n            final ImmutableList.Builder<Cookie> builder = ImmutableList.builder();\n            for (io.undertow.server.handlers.Cookie c : xch.getRequestCookies().values()) {\n                builder.add(\n                    Cookie.cookie(c.getName(), c.getValue())\n                        .setComment(c.getComment())\n                        .setDomain(c.getDomain())\n                        .setPath(c.getPath())\n                        .setHttpOnly(c.isHttpOnly())\n                        .setMaxAge(c.getMaxAge())\n                        .setSecure(c.isSecure())\n                        .setVersion(c.getVersion())\n                        .build()\n                );\n            }\n            cookies = builder.build();\n        }\n        return cookies;\n    }\n\n    @Override\n    public int getContentLength() {\n        return (int) xch.getRequestContentLength();\n    }\n\n    @Override\n    public Charset getCharacterEncoding() {\n        if (encoding == null) {\n            final String charsetName = xch.getRequestCharset();\n            if (charsetName != null) {\n                try {\n                    encoding = Charset.forName(charsetName);\n                } catch (final UnsupportedCharsetException ignored) {}\n            }\n\n            if (encoding == null)\n                encoding = Charset.defaultCharset();\n        }\n        return encoding;\n    }\n\n    @Override\n    public String getContentType() {\n        getHeaders();\n        if (heads != null) {\n            if (contentType == null) {\n                final List<String> cts = heads.get(Headers.CONTENT_TYPE_STRING);\n                if (cts != null && cts.size() > 0)\n                    contentType = cts.get(0);\n            }\n        }\n        return null;\n    }\n\n    @Override\n    public String getStringBody() {\n        if (stringBody == null) {\n            if (byteBufferBody != null)\n                return null;\n            decodeStringBody();\n        }\n        return stringBody;\n    }\n\n    @Override\n    public ByteBuffer getByteBufferBody() {\n        if (byteBufferBody == null) {\n            if (stringBody != null)\n                return null;\n            if (reqContent != null)\n                byteBufferBody = reqContent;\n        }\n        return byteBufferBody;\n    }\n\n    private String decodeStringBody() {\n        if (reqContent != null) {\n            try {\n                //noinspection ConstantConditions\n                stringBody =\n                    getCharacterEncoding()\n                        .newDecoder()\n                        .onMalformedInput(CodingErrorAction.REPORT)\n                        .onUnmappableCharacter(CodingErrorAction.REPORT)\n                        .decode(reqContent)\n                        .toString();\n            } catch (final CharacterCodingException ignored) {\n            }\n        }\n        return stringBody;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-undertow/src/main/java/co/paralleluniverse/comsat/webactors/undertow/WebActorHandler.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.undertow;\n\nimport co.paralleluniverse.actors.*;\nimport co.paralleluniverse.common.util.Pair;\nimport co.paralleluniverse.comsat.webactors.*;\nimport co.paralleluniverse.fibers.FiberUtil;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport co.paralleluniverse.strands.Timeout;\nimport co.paralleluniverse.strands.channels.SendPort;\nimport co.paralleluniverse.strands.concurrent.CountDownLatch;\nimport co.paralleluniverse.strands.concurrent.ReentrantLock;\nimport io.undertow.Handlers;\nimport io.undertow.UndertowLogger;\nimport io.undertow.server.HttpHandler;\nimport io.undertow.server.HttpServerExchange;\nimport io.undertow.server.handlers.CookieImpl;\nimport io.undertow.util.*;\nimport io.undertow.websockets.WebSocketConnectionCallback;\nimport io.undertow.websockets.core.*;\nimport io.undertow.websockets.spi.WebSocketHttpExchange;\nimport org.xnio.Buffers;\nimport org.xnio.ChannelListener;\nimport org.xnio.ChannelListeners;\nimport org.xnio.channels.StreamSinkChannel;\n\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\nimport java.nio.charset.Charset;\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.concurrent.atomic.AtomicReference;\n\n/**\n * @author circlespainter\n */\npublic class WebActorHandler implements HttpHandler {\n    protected static final String ACTOR_KEY = \"co.paralleluniverse.comsat.webactors.sessionActor\";\n\n    protected static final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());\n\n    protected static final ScheduledExecutorService ts = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());\n\n    // @FunctionalInterface\n    public interface ContextProvider {\n        Context get(HttpServerExchange xch);\n    }\n\n    public interface Context {\n        String getId();\n        ReentrantLock getLock();\n\n        boolean isValid() throws SuspendExecution, InterruptedException;\n        void invalidate() throws SuspendExecution, InterruptedException;\n\n        boolean renew();\n        void restart(HttpServerExchange xch);\n\n        ActorRef<? extends WebMessage> getWebActor();\n        boolean handlesWithHttp(String uri);\n        boolean handlesWithWebSocket(String uri);\n\n        enum WatchPolicy { DONT_WATCH, DIE, DIE_IF_EXCEPTION_ELSE_RESTART, RESTART }\n        WatchPolicy watch();\n\n        Map<String, Object> getAttachments();\n    }\n\n    public static abstract class DefaultContextImpl implements Context {\n        private final static String durationProp = System.getProperty(DefaultContextImpl.class.getName() + \".durationMillis\");\n        private final static long DURATION = durationProp != null ? Long.parseLong(durationProp) : 60_000L;\n        private final ReentrantLock lock = new ReentrantLock();\n        @SuppressWarnings(\"unused\")\n        private final long created;\n        final Map<String, Object> attachments = new HashMap<>();\n\n        protected long renewed;\n        private Long validityMS;\n\n        private boolean valid = true;\n\n        public DefaultContextImpl() {\n            renewed = created = new Date().getTime();\n        }\n\n        @Override\n        public final void invalidate() throws SuspendExecution, InterruptedException {\n            final HttpActorAdapter actor = (HttpActorAdapter) attachments.get(ACTOR_KEY);\n            if (actor != null)\n//                actor.ch.send(HttpActorAdapter.EXIT);\n                actor.die(null);\n            attachments.clear();\n            valid = false;\n        }\n\n        @Override\n        public final boolean isValid() throws SuspendExecution, InterruptedException {\n            final boolean ret = valid && (new Date().getTime() - renewed) <= getValidityMS();\n            if (!ret)\n                invalidate();\n            return ret;\n        }\n\n        @Override\n        public final boolean renew() {\n            if (!valid)\n                return false;\n\n            renewed = new Date().getTime();\n            return true;\n        }\n\n        @Override\n        public final Map<String, Object> getAttachments() {\n            return attachments;\n        }\n\n        @Override\n        public final ReentrantLock getLock() {\n            return lock;\n        }\n\n        public void setValidityMS(long validityMS) {\n            this.validityMS = validityMS;\n        }\n\n        public final long getValidityMS() {\n            return validityMS != null ? validityMS : DURATION;\n        }\n    }\n\n    static final WeakHashMap<Class<?>, List<Pair<String, String>>> classToUrlPatterns = new WeakHashMap<>();\n\n    protected ContextProvider contextProvider;\n    private HttpHandler fallbackHttpHandler = null;\n\n    public WebActorHandler(ContextProvider contextProvider) {\n        this.contextProvider = contextProvider;\n    }\n\n    public final void setFallbackHttpHandler(HttpHandler httpHandler) {\n        this.fallbackHttpHandler = httpHandler;\n    }\n\n    @Override\n    public final void handleRequest(final HttpServerExchange xch) throws Exception {\n\n        final Context context = contextProvider.get(xch);\n        if (context == null) {\n            handlingComplete(xch);\n            return;\n        }\n\n        final ReentrantLock lock = context.getLock();\n        assert lock != null;\n\n        lock.lock();\n\n        try {\n            final ActorRef<? extends WebMessage> userActorRef = context.getWebActor();\n            ActorImpl internalActor = (ActorImpl) context.getAttachments().get(ACTOR_KEY);\n\n            final String uri = xch.getRequestURI();\n            if (userActorRef != null) {\n                if (context.handlesWithWebSocket(uri)) {\n                    if (internalActor == null || !(internalActor instanceof WebSocketActorAdapter)) {\n                        @SuppressWarnings(\"unchecked\") final ActorRef<WebMessage> userActorRef0 = (ActorRef<WebMessage>) userActorRef;\n                        internalActor = new WebSocketActorAdapter(userActorRef0);\n\n                        //noinspection unchecked\n                        addActorToContextAndUnlock(context, internalActor, lock);\n                    }\n\n                    final WebSocketActorAdapter webSocketActor = (WebSocketActorAdapter) internalActor;\n\n                    // xch.dispatch(); // Start async\n\n                    // Handle with websocket\n                    Handlers.websocket(new WebSocketConnectionCallback() {\n                        @Override\n                        public final void onConnect(WebSocketHttpExchange exchange, WebSocketChannel channel) {\n                            webSocketActor.setChannel(channel);\n\n                            channel.getReceiveSetter().set(new AbstractReceiveListener() {\n                                @Override\n                                protected final void onFullBinaryMessage(WebSocketChannel channel, BufferedBinaryMessage message) throws IOException {\n                                    webSocketActor.onMessage(message);\n                                }\n\n                                @Override\n                                protected final void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) throws IOException {\n                                    webSocketActor.onMessage(message);\n                                }\n                            });\n\n                            channel.resumeReceives();\n\n                            try {\n                                FiberUtil.runInFiber(new SuspendableRunnable() {\n                                    @Override\n                                    public final void run() throws SuspendExecution, InterruptedException {\n                                        //noinspection unchecked\n                                        ((ActorRef) userActorRef).send(new WebSocketOpened(webSocketActor.ref()));\n                                    }\n                                });\n                            } catch (final InterruptedException | ExecutionException e) {\n                                UndertowLogger.ROOT_LOGGER.error(\"Exception while sending `WebSocketOpened` message to actor\", e);\n                                throw new RuntimeException(e);\n                            }\n                        }\n                    }).handleRequest(xch);\n\n                    return;\n                } else if (context.handlesWithHttp(uri)) {\n                    final HttpActorAdapter adapter;\n                    if (internalActor == null || !(internalActor instanceof HttpActorAdapter)) {\n                        //noinspection unchecked\n                        adapter = new HttpActorAdapter((ActorRef<? super HttpRequest>) userActorRef, context);\n                        addActorToContextAndUnlock(context, internalActor, lock);\n                    } else {\n                        adapter = (HttpActorAdapter) internalActor;\n                    }\n\n                    // Free IO thread and move to worker thread.\n                    // Doing only here as it seems to cause problems to web socket handling\n                    xch.dispatch(new Runnable() {\n                        @Override\n                        @Suspendable\n                        public void run() {\n//                            xch.dispatch(); // Start async: detach response sending from worker thread's return\n//                            // Free worker thread by starting available I/O in a fiber\n//                            new Fiber(new SuspendableRunnable() {\n//                                @Override\n//                                public void run() throws SuspendExecution, InterruptedException {\n                                    new ByteArrayReadChannelListener(xch.getConnection().getByteBufferPool()) {\n                                        @Override\n                                        @Suspendable\n                                        protected final void byteArrayDone(final byte[] ba) {\n                                            try {\n                                                // adapter.ch.send(new HttpRequestWrapper(adapter.ref(), xch, ByteBuffer.wrap(ba)));\n                                                adapter.handleRequest(new UndertowHttpRequest(adapter.ref(), xch, ByteBuffer.wrap(ba)));\n                                            } catch (final SuspendExecution e) {\n                                                throw new AssertionError(e);\n                                            } catch (final InterruptedException e) {\n                                                throw new RuntimeException(e);\n                                            }\n                                        }\n\n                                        @Override\n                                        protected final void error(IOException e) {\n                                            UndertowLogger.ROOT_LOGGER.error(\"Exception while reading HTTP request\", e);\n                                            throw new RuntimeException(e);\n                                        }\n                                    }.setup(xch.getRequestChannel());\n                                }\n//                            }).start();\n//                        }\n                    });\n                    return;\n                }\n            }\n\n            handlingComplete(xch);\n\n        } finally {\n            if (lock.isHeldByCurrentStrand() && lock.isLocked())\n                lock.unlock();\n        }\n    }\n\n    private void handlingComplete(HttpServerExchange xch) throws Exception {\n        if (fallbackHttpHandler != null)\n            fallbackHttpHandler.handleRequest(xch);\n        else\n            sendHttpResponse(xch, StatusCodes.NOT_FOUND);\n    }\n\n    static void addActorToContextAndUnlock(Context context, ActorImpl actor, ReentrantLock lock) {\n        context.getAttachments().put(ACTOR_KEY, actor);\n        lock.unlock();\n    }\n\n    private static final class WebSocketActorAdapter extends FakeActor<WebDataMessage> {\n        ActorRef<? super WebMessage> userActor;\n\n        private WebSocketChannelAdapter adapter;\n\n        private WebSocketChannel channel;\n\n        public WebSocketActorAdapter(ActorRef<? super WebMessage> userActor) {\n            super(userActor.getName(), new WebSocketChannelAdapter());\n            adapter = (WebSocketChannelAdapter) (SendPort) mailbox();\n            adapter.actor = this;\n            this.userActor = userActor;\n            watch(userActor);\n        }\n\n        final void setChannel(WebSocketChannel channel) {\n            this.channel = channel;\n            this.adapter.channel = channel;\n        }\n\n        final void onMessage(BufferedBinaryMessage message) {\n            try {\n                userActor.send(new WebDataMessage(ref(), toBuffer(message.getData().getResource()).duplicate()));\n            } catch (final SuspendExecution ex) {\n                throw new AssertionError(ex);\n            }\n        }\n\n        final void onMessage(BufferedTextMessage message) {\n            try {\n                userActor.send(new WebDataMessage(ref(), message.getData()));\n            } catch (final SuspendExecution ex) {\n                throw new AssertionError(ex);\n            }\n        }\n\n        @Override\n        protected final WebDataMessage handleLifecycleMessage(LifecycleMessage m) {\n            if (m instanceof ExitMessage) {\n                final ExitMessage em = (ExitMessage) m;\n                if (em.getActor() != null && em.getActor().equals(userActor))\n                    die(em.getCause());\n            }\n            return null;\n        }\n\n        @Override\n        protected final void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        public final void interrupt() {\n            die(new InterruptedException());\n        }\n\n        @Override\n        protected final void die(Throwable cause) {\n            super.die(cause);\n            try {\n                channel.sendClose();\n\n            } catch (final IOException e) {\n                UndertowLogger.ROOT_LOGGER.error(\"Exception while closing websocket channel during actor death\", e);\n                throw new RuntimeException(e);\n            } finally {\n                // Ensure to release server references\n                adapter = null;\n                userActor = null;\n                channel = null;\n            }\n        }\n\n        @Override\n        public final String toString() {\n            return \"WebSocketActor{\" + \"userActor=\" + userActor + '}';\n        }\n    }\n\n    private static final class WebSocketChannelAdapter implements SendPort<WebDataMessage> {\n        WebSocketChannel channel;\n\n        WebSocketActorAdapter actor;\n\n        @Override\n        public final void send(WebDataMessage message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            return trySend(message);\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        public final boolean trySend(WebDataMessage message) {\n            if (!message.isBinary())\n                WebSockets.sendText(message.getStringBody(), channel, null);\n            else\n                WebSockets.sendBinary(message.getByteBufferBody(), channel, null);\n            return true;\n        }\n\n        @Override\n        public final void close() {\n            try {\n                channel.sendClose();\n            } catch (final IOException e) {\n                UndertowLogger.ROOT_LOGGER.error(\"Exception while closing websocket channel\", e);\n                throw new RuntimeException(e);\n            } finally {\n                if (actor != null)\n                    actor.die(null);\n            }\n        }\n\n        @Override\n        public final void close(Throwable t) {\n            if (actor != null)\n                actor.die(t);\n            close();\n        }\n    }\n\n    private static final class HttpActorAdapter extends FakeActor<HttpResponse> {\n        private final static String replyTimeoutProp = System.getProperty(HttpActorAdapter.class.getName() + \".replyTimeout\");\n        private static final long REPLY_TIMEOUT = replyTimeoutProp != null ? Long.parseLong(replyTimeoutProp) : 120_000L;\n\n        private final AtomicReference<CountDownLatch> gate = new AtomicReference<>();\n\n        private volatile ActorRef<? super HttpRequest> userActor;\n        private volatile Context context;\n\n        private volatile HttpServerExchange xch;\n        private volatile boolean needsRestart;\n\n        private volatile boolean dead;\n        private volatile Object watchToken;\n\n        private volatile ScheduledFuture<?> cancelTask;\n\n        HttpActorAdapter(ActorRef<? super HttpRequest> userActor, Context actorContext) {\n            super(\"HttpActorAdapter\", new HttpChannelAdapter());\n\n            ((HttpChannelAdapter) (SendPort) getMailbox()).actor = this;\n            if (actorContext.watch() != Context.WatchPolicy.DONT_WATCH) {\n                if (userActor != null)\n                    watchToken = watch(userActor);\n            }\n\n            this.userActor = userActor;\n            this.context = actorContext;\n        }\n\n        @Override\n        public final String toString() {\n            return \"HttpActorAdapter{\" + userActor + \"}\";\n        }\n\n\n        @Override\n        @Suspendable\n        protected final HttpResponse handleLifecycleMessage(LifecycleMessage m) {\n            handleLifecycle(m);\n            return null;\n        }\n\n        @Override\n        @Suspendable\n        protected final void die(Throwable cause) {\n            handleDie(cause);\n        }\n\n        @Override\n        @Suspendable\n        protected final void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        @Suspendable\n        protected final void interrupt() {\n            die(new InterruptedException());\n        }\n\n        @Suspendable\n        final void handleRequest(UndertowHttpRequest s) throws SuspendExecution, InterruptedException {\n            blockSessionRequests();\n            xch = s.xch;\n            if (needsRestart) {\n                context.restart(xch);\n                context.getLock().lock();\n                addActorToContextAndUnlock(context, HttpActorAdapter.this, context.getLock());\n                needsRestart = false;\n            }\n            userActor.send(s);\n        }\n\n        final void handleReply(final HttpResponse message) throws InterruptedException {\n            try {\n                final UndertowHttpRequest undertowRequest = (UndertowHttpRequest) message.getRequest();\n                final HttpServerExchange xch = undertowRequest.xch;\n\n                final int status = message.getStatus();\n\n                if (status >= 400 && status < 600) {\n                    // Sending a reply directly from a fiber produces a thread-local related leak due to unfreed buffers\n                    es.submit(new Runnable() {\n                        @Override\n                        public void run() {\n                            sendHttpResponse(xch, status);\n                        }\n                    });\n                    return;\n                }\n\n                if (message.getRedirectPath() != null) {\n                    // Sending a reply directly from a fiber produces a thread-local related leak due to unfreed buffers\n                    es.submit(new Runnable() {\n                        @Override\n                        public void run() {\n                            sendHttpRedirect(xch, message.getRedirectPath());\n                        }\n                    });\n                    return;\n                }\n\n                if (message.getCookies() != null) {\n                    for (final Cookie c : message.getCookies())\n                        xch.setResponseCookie(newUndertowCookie(c));\n                }\n                final HeaderMap heads = xch.getResponseHeaders();\n                if (message.getHeaders() != null) {\n                    for (final String k : message.getHeaders().keys())\n                        heads.putAll(new HttpString(k), message.getHeaderValues(k));\n                }\n\n                if (message.getContentType() != null) {\n                    String ct = message.getContentType();\n                    if (message.getCharacterEncoding() != null)\n                        ct = ct + \"; charset=\" + message.getCharacterEncoding().name();\n                    xch.getResponseHeaders().add(Headers.CONTENT_TYPE, ct);\n                }\n\n                final boolean sseStarted = message.shouldStartActor();\n                if (sseStarted) {\n                    try {\n                        xch.getResponseHeaders().put(Headers.CONTENT_TYPE, \"text/event-stream; charset=UTF-8\");\n                        xch.setPersistent(false);\n\n                        final StreamSinkChannel sink = xch.getResponseChannel();\n                        final HttpStreamActorAdapter httpStreamActorAdapter = new HttpStreamActorAdapter(xch);\n\n                        if (!sink.flush()) {\n                            sink.getWriteSetter().set(ChannelListeners.flushingChannelListener(new ChannelListener<StreamSinkChannel>() {\n                                @Override\n                                public final void handleEvent(final StreamSinkChannel channel) {\n                                    try {\n                                        FiberUtil.runInFiber(new SuspendableRunnable() {\n                                            @Override\n                                            public void run() throws SuspendExecution, InterruptedException {\n                                                notifySSEStarted(httpStreamActorAdapter, message, channel);\n                                            }\n                                        });\n                                    } catch (final InterruptedException | ExecutionException e) {\n                                        UndertowLogger.ROOT_LOGGER.error(\"Exception while handling SSE start response event\", e);\n                                        throw new RuntimeException(e);\n                                    }\n                                }\n                            }, null));\n                            sink.resumeWrites();\n                        } else {\n                            notifySSEStarted(httpStreamActorAdapter, message, sink);\n                        }\n                    } catch (final Exception e) {\n                        UndertowLogger.ROOT_LOGGER.error(\"Exception while sending SSE start response\", e);\n                        throw new RuntimeException(e);\n                    }\n                } else {\n                    // Sending a reply directly from a fiber produces a thread-local related leak due to unfreed buffers\n                    es.submit(new Runnable() {\n                        @Override\n                        public void run() {\n                            if (message.getStringBody() != null)\n                                sendHttpResponse(xch, status, message.getStringBody());\n                            else if (message.getByteBufferBody() != null)\n                                sendHttpResponse(xch, status, message.getByteBufferBody());\n                            else\n                                sendHttpResponse(xch, status);\n                        }\n                    });\n                }\n            } finally {\n                unblockSessionRequests();\n            }\n        }\n\n        final boolean handleLifecycle(LifecycleMessage l) {\n            if (l instanceof ExitMessage) {\n                final ExitMessage em = (ExitMessage) l;\n                if (em.getActor() != null && em.getActor().equals(userActor)) {\n                    final Context.WatchPolicy wp = context.watch();\n                    //noinspection ThrowableResultOfMethodCallIgnored\n                    if (wp == Context.WatchPolicy.RESTART ||\n                        wp == Context.WatchPolicy.DIE_IF_EXCEPTION_ELSE_RESTART && em.getCause() == null) {\n                        needsRestart = true;\n                    } else {\n                        handleDie(em.getCause());\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        @Suspendable\n        final void handleDie(final Throwable cause) {\n            try {\n                possiblyReplyDeadAndUnblock(cause);\n\n                if (dead)\n                    return;\n                dead = true;\n                HttpActorAdapter.super.die(cause);\n                try {\n                    context.invalidate();\n                } catch (final Exception ignored) {\n                }\n\n                // Ensure to release references\n                if (userActor != null && watchToken != null)\n                    unwatch(userActor, watchToken);\n            } finally {\n                unblockSessionRequests();\n            }\n\n            userActor = null;\n            watchToken = null;\n            context = null;\n            xch = null;\n//            f = null;\n//            ch = null;\n        }\n\n        private void possiblyReplyDeadAndUnblock(final Throwable cause) {\n            if (isRequestInProgress()) {\n                try {\n                    final HttpServerExchange xch1 = xch;\n                    // Sending a reply directly from a fiber produces a thread-local related leak due to unfreed buffers\n                    es.submit(new Runnable() {\n                        @Override\n                        public void run() {\n                            try {\n                                if (cause != null) {\n                                    sendHttpResponse(xch1, StatusCodes.INTERNAL_SERVER_ERROR, \"Actor is dead because of \" + cause.getMessage());\n                                } else {\n                                    sendHttpResponse(xch1, StatusCodes.INTERNAL_SERVER_ERROR, \"Actor has terminated.\");\n                                }\n                            } finally {\n                                unblockSessionRequests();\n                            }\n                        }\n                    });\n                } finally {\n                    unblockSessionRequests();\n                }\n            }\n        }\n\n        private void notifySSEStarted(HttpStreamActorAdapter httpStreamActorAdapter, HttpResponse message, StreamSinkChannel channel) throws SuspendExecution {\n            httpStreamActorAdapter.setChannel(channel);\n            message.getFrom().send(new HttpStreamOpened(httpStreamActorAdapter.ref(), message));\n        }\n\n        @Suspendable\n        private void blockSessionRequests() throws InterruptedException {\n            while (!gate.compareAndSet(null, new CountDownLatch(1))) {\n                final CountDownLatch l = gate.get();\n                if (l != null)\n                    l.await();\n            }\n            final HttpServerExchange xch1 = xch;\n            cancelTask = ts.schedule(new Runnable() {\n                @Override\n                public void run() {\n                    sendHttpResponse(xch1, StatusCodes.INTERNAL_SERVER_ERROR, \"Timeout while waiting for user actor to reply.\");\n                }\n            }, REPLY_TIMEOUT, TimeUnit.MILLISECONDS);\n        }\n\n        @Suspendable\n        private void unblockSessionRequests() {\n            if (cancelTask != null)\n                cancelTask.cancel(true);\n            final CountDownLatch l = gate.getAndSet(null);\n            if (l != null)\n                l.countDown();\n        }\n\n        private boolean isRequestInProgress() {\n            return gate.get() != null;\n        }\n\n        private io.undertow.server.handlers.Cookie newUndertowCookie(Cookie c) {\n            io.undertow.server.handlers.Cookie ret = new CookieImpl(c.getName(), c.getValue());\n            ret.setComment(c.getComment());\n            ret.setDomain(c.getDomain());\n            ret.setHttpOnly(c.isHttpOnly());\n            ret.setMaxAge(c.getMaxAge());\n            ret.setPath(c.getPath());\n            ret.setVersion(c.getVersion());\n            ret.setSecure(c.isSecure());\n            return ret;\n        }\n    }\n\n    private static final class HttpChannelAdapter implements SendPort<HttpResponse> {\n        private HttpActorAdapter actor;\n\n        HttpChannelAdapter() {}\n\n        @Override\n        @Suspendable\n        public final void send(HttpResponse message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        @Suspendable\n        public final boolean send(HttpResponse message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            send(message);\n            return true;\n        }\n\n        @Override\n        @Suspendable\n        public final boolean send(HttpResponse message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        @Suspendable\n        public final boolean trySend(final HttpResponse m) {\n            try {\n                actor.handleReply(m);\n            } catch (final InterruptedException e) {\n                throw new RuntimeException(e);\n            }\n            return true;\n        }\n\n        @Override\n        public final void close() {\n            if (actor != null)\n                actor.die(null);\n        }\n\n        @Override\n        public final void close(Throwable t) {\n            UndertowLogger.ROOT_LOGGER.error(\"Exception while closing HTTP adapter\", t);\n            if (actor != null)\n                actor.die(t);\n        }\n    }\n\n    private static final class HttpStreamActorAdapter extends FakeActor<WebDataMessage> {\n        private HttpStreamChannelAdapter adapter;\n\n        private volatile boolean dead;\n\n        HttpStreamActorAdapter(HttpServerExchange xch) {\n            super(xch.toString(), new HttpStreamChannelAdapter(xch));\n            adapter = (HttpStreamChannelAdapter) (SendPort) mailbox();\n            adapter.actor = this;\n        }\n\n        @Override\n        protected final WebDataMessage handleLifecycleMessage(LifecycleMessage m) {\n            if (m instanceof ShutdownMessage)\n                die(null);\n            return null;\n        }\n\n        @Override\n        protected final void throwIn(RuntimeException e) {\n            die(e);\n        }\n\n        @Override\n        public final void interrupt() {\n            die(new InterruptedException());\n        }\n\n        @Override\n        protected final void die(Throwable cause) {\n            if (dead)\n                return;\n            dead = true;\n            mailbox().close();\n            super.die(cause);\n\n            adapter = null;\n        }\n\n        @Override\n        public final String toString() {\n            return \"HttpStreamActorAdapter{request + \" + getName() + \"}\";\n        }\n\n        public final void setChannel(StreamSinkChannel channel) {\n            adapter.setChannel(channel);\n        }\n    }\n\n    private static final class HttpStreamChannelAdapter implements SendPort<WebDataMessage> {\n        private final HttpServerExchange xch;\n\n        private StreamSinkChannel channel;\n\n        HttpStreamActorAdapter actor;\n\n        HttpStreamChannelAdapter(HttpServerExchange xch) {\n            this.xch = xch;\n        }\n\n        public final void setChannel(StreamSinkChannel channel) {\n            this.channel = channel;\n        }\n\n        @Override\n        public final void send(WebDataMessage message) throws SuspendExecution, InterruptedException {\n            trySend(message);\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, long timeout, TimeUnit unit) throws SuspendExecution, InterruptedException {\n            send(message);\n            return true;\n        }\n\n        @Override\n        public final boolean send(WebDataMessage message, Timeout timeout) throws SuspendExecution, InterruptedException {\n            return send(message, timeout.nanosLeft(), TimeUnit.NANOSECONDS);\n        }\n\n        @Override\n        public final boolean trySend(final WebDataMessage res) {\n            final String stringBody = res.getStringBody();\n            final String charset = xch.getRequestCharset();\n            final StringWriteChannelListener l;\n            if (stringBody != null) {\n                if (charset != null)\n                    l = new StringWriteChannelListener(stringBody, Charset.forName(charset));\n                else\n                    l = new StringWriteChannelListener(stringBody);\n            } else {\n                l = new StringWriteChannelListener(res.getByteBufferBody());\n            }\n            l.setup(channel);\n            return true;\n        }\n\n        @Override\n        public final void close() {\n            xch.endExchange();\n            if (actor != null)\n                actor.die(null);\n        }\n\n        @Override\n        public final void close(Throwable t) {\n            if (actor != null)\n                actor.die(t);\n            close();\n        }\n    }\n\n    static void sendHttpResponse(HttpServerExchange xch, int statusCode) {\n        sendHttpResponse(xch, statusCode, (String) null);\n    }\n\n    static void sendHttpResponse(HttpServerExchange xch, int statusCode, String body) {\n        xch.setStatusCode(statusCode);\n        if (body != null)\n            xch.getResponseSender().send(body);\n        xch.endExchange();\n    }\n\n    static void sendHttpResponse(HttpServerExchange xch, int statusCode, ByteBuffer body) {\n        xch.setStatusCode(statusCode);\n        if (body != null)\n            xch.getResponseSender().send(body);\n        xch.endExchange();\n    }\n\n    static void sendHttpRedirect(HttpServerExchange xch, String path) {\n        xch.setStatusCode(StatusCodes.FOUND);\n        xch.getResponseHeaders().add(Headers.LOCATION, xch.getProtocol() + \"://\" + xch.getHostAndPort() + path);\n        xch.endExchange();\n    }\n\n    static boolean handlesWithHttp(String uri, Class<?> actorClass) {\n        return match(uri, actorClass).equals(\"http\");\n    }\n\n    static boolean handlesWithWebSocket(String uri, Class<?> actorClass) {\n        return match(uri, actorClass).equals(\"ws\");\n    }\n\n    private static String match(String uri, Class<?> actorClass) {\n        if (uri != null && actorClass != null) {\n            for (final Pair<String, String> e : lookupOrInsert(actorClass)) {\n                if (servletMatch(e.getFirst(), uri))\n                    return e.getSecond();\n            }\n        }\n        return \"\";\n    }\n\n    private static List<Pair<String, String>> lookupOrInsert(Class<?> actorClass) {\n        if (actorClass != null) {\n            final List<Pair<String, String>> lookup = classToUrlPatterns.get(actorClass);\n            if (lookup != null)\n                return lookup;\n            return insert(actorClass);\n        }\n        return null;\n    }\n\n    private static List<Pair<String, String>> insert(Class<?> actorClass) {\n        if (actorClass != null) {\n            final WebActor wa = actorClass.getAnnotation(WebActor.class);\n            final List<Pair<String, String>> ret = new ArrayList<>(4);\n            for (String httpP : wa.httpUrlPatterns())\n                addPattern(ret, httpP, \"http\");\n            for (String wsP : wa.webSocketUrlPatterns())\n                addPattern(ret, wsP, \"ws\");\n            classToUrlPatterns.put(actorClass, ret);\n            return ret;\n        }\n        return null;\n    }\n\n    private static void addPattern(List<Pair<String, String>> ret, String p, String type) {\n        if (p != null) {\n            @SuppressWarnings(\"MismatchedQueryAndUpdateOfCollection\") final Pair<String, String> entry = new Pair<>(p, type);\n            if (p.endsWith(\"*\") || p.startsWith(\"*.\") || p.equals(\"/\")) // Wildcard -> end\n                ret.add(entry);\n            else // Exact -> beginning\n                ret.add(0, entry);\n        }\n    }\n\n    private static boolean servletMatch(String pattern, String uri) {\n        // As per servlet spec\n        if (pattern != null && uri != null) {\n            if (pattern.startsWith(\"/\") && pattern.endsWith(\"*\"))\n                return uri.startsWith(pattern.substring(0, pattern.length() - 1));\n            if (pattern.startsWith(\"*.\"))\n                return uri.endsWith(pattern.substring(2));\n            if (pattern.isEmpty())\n                return uri.equals(\"/\");\n            return pattern.equals(\"/\") || pattern.equals(uri);\n        }\n        return false;\n    }\n\n    private static ByteBuffer toBuffer(ByteBuffer... payload) {\n        if (payload.length == 1) {\n            return payload[0];\n        }\n        final int size = (int) Buffers.remaining(payload);\n        if (size == 0) {\n            return Buffers.EMPTY_BYTE_BUFFER;\n        }\n        final ByteBuffer buffer = ByteBuffer.allocate(size);\n        for (ByteBuffer buf : payload) {\n            buffer.put(buf);\n        }\n        buffer.flip();\n        return buffer;\n    }\n}\n"
  },
  {
    "path": "comsat-actors-undertow/src/main/java/co/paralleluniverse/comsat/webactors/undertow/package-info.java",
    "content": "/*\n * Copyright (c) 2015-2016, Parallel Universe Software Co. All rights reserved.\n * \n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *  \n *   or (per the licensee's choosing)\n *  \n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/**\n * A Web Actors backend implementation based on Undertow\n */\npackage co.paralleluniverse.comsat.webactors.undertow;\n"
  },
  {
    "path": "comsat-actors-undertow/src/test/java/co/paralleluniverse/comsat/webactors/undertow/HttpRequestWrapperTest.java",
    "content": "package co.paralleluniverse.comsat.webactors.undertow;\n\nimport io.undertow.server.HttpServerExchange;\nimport io.undertow.util.HttpString;\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * @author rodedb\n */\npublic class HttpRequestWrapperTest {\n\n    @Test\n    public void httpHeaderCaseInsensitivity() {\n        String headerValue = \"application/json\";\n        HttpServerExchange httpServerExchange = new HttpServerExchange(null);\n        httpServerExchange.getRequestHeaders().put(new HttpString(\"Content-Type\"), headerValue);\n        UndertowHttpRequest requestWrapper = new UndertowHttpRequest(null, httpServerExchange, null);\n        assertEquals(headerValue, requestWrapper.getHeader(\"content-type\"));\n    }\n}"
  },
  {
    "path": "comsat-actors-undertow/src/test/java/co/paralleluniverse/comsat/webactors/undertow/UndertowWebActor.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.undertow;\n\nimport co.paralleluniverse.comsat.webactors.MyWebActor;\nimport co.paralleluniverse.comsat.webactors.WebActor;\n\n/**\n * @author circlespainter\n */\n@WebActor(httpUrlPatterns = {\"/*\"}, webSocketUrlPatterns = {\"/ws\"})\npublic final class UndertowWebActor extends MyWebActor {}\n"
  },
  {
    "path": "comsat-actors-undertow/src/test/java/co/paralleluniverse/comsat/webactors/undertow/WebActorTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors.undertow;\n\nimport co.paralleluniverse.actors.Actor;\nimport co.paralleluniverse.actors.ActorRef;\nimport co.paralleluniverse.comsat.webactors.AbstractWebActorTest;\nimport co.paralleluniverse.comsat.webactors.WebMessage;\nimport co.paralleluniverse.embedded.containers.AbstractEmbeddedServer;\nimport io.undertow.Undertow;\nimport io.undertow.server.HttpServerExchange;\nimport io.undertow.server.handlers.RequestDumpingHandler;\nimport io.undertow.server.session.InMemorySessionManager;\nimport io.undertow.server.session.SessionAttachmentHandler;\nimport io.undertow.server.session.SessionCookieConfig;\nimport io.undertow.server.session.SessionManager;\nimport org.junit.After;\nimport org.junit.Assume;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\n\n/**\n * @author circlespainter\n */\n@RunWith(Parameterized.class)\npublic class WebActorTest extends AbstractWebActorTest {\n    private static final Actor actor = new UndertowWebActor();\n    @SuppressWarnings(\"unchecked\")\n    private static final ActorRef<? extends WebMessage> actorRef = actor.spawn();\n\n    private static final Callable<WebActorHandler> basicWebActorHandlerCreator = new Callable<WebActorHandler>() {\n        @Override\n        public WebActorHandler call() throws Exception {\n            return new WebActorHandler(new WebActorHandler.ContextProvider() {\n                @Override\n                public WebActorHandler.Context get(HttpServerExchange xch) {\n                    return new WebActorHandler.DefaultContextImpl() {\n                        @Override\n                        public String getId() {\n                            return \"CONSTANT\";\n                        }\n\n                        @SuppressWarnings(\"unchecked\")\n                        @Override\n                        public ActorRef<? extends WebMessage> getWebActor() {\n                            return actorRef;\n                        }\n\n                        @Override\n                        public void restart(HttpServerExchange r) {\n                            // Nothing to do\n                        }\n\n                        @Override\n                        public final boolean handlesWithWebSocket(String uri) {\n                            return uri.startsWith(\"/ws\");\n                        }\n\n                        @Override\n                        public WatchPolicy watch() {\n                            return WatchPolicy.DIE;\n                        }\n\n                        @Override\n                        public final boolean handlesWithHttp(String uri) {\n                            return !handlesWithWebSocket(uri);\n                        }\n                    };\n                }\n            });\n        }\n    };\n\n    @Override\n    @Test\n    public final void testDie() throws IOException, InterruptedException, ExecutionException {\n        Assume.assumeTrue(webActorHandlerCreatorInEffect == autoWebActorHandlerCreator);\n\n        super.testDie();\n    }\n\n    private static final Callable<WebActorHandler> autoWebActorHandlerCreator = new Callable<WebActorHandler>() {\n        @Override\n        public WebActorHandler call() throws Exception {\n            return new AutoWebActorHandler();\n        }\n    };\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {basicWebActorHandlerCreator},\n            {autoWebActorHandlerCreator}\n        });\n    }\n\n    private static final int INET_PORT = 8080;\n\n    private final Callable<WebActorHandler> webActorHandlerCreatorInEffect;\n\n    private Undertow server;\n\n    public WebActorTest(Callable<WebActorHandler> webActorHandlerCreator) {\n        this.webActorHandlerCreatorInEffect = webActorHandlerCreator;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        final SessionManager sessionManager =\n            new InMemorySessionManager(\"SESSION_MANAGER\", 1, true);\n        final SessionCookieConfig sessionConfig = new SessionCookieConfig();\n        sessionConfig.setMaxAge(60);\n        final SessionAttachmentHandler sessionAttachmentHandler =\n            new SessionAttachmentHandler(sessionManager, sessionConfig);\n        server = Undertow.builder()\n            .addHttpListener(INET_PORT, \"localhost\")\n            .setHandler(new RequestDumpingHandler(sessionAttachmentHandler.setNext(webActorHandlerCreatorInEffect.call()))).build();\n        server.start();\n        AbstractEmbeddedServer.waitUrlAvailable(\"http://localhost:\" + INET_PORT);\n\n        System.err.println(\"Server is up\");\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        server.stop();\n\n        System.out.println(\"Server is down\");\n    }\n\n    @Override\n    protected String getSessionIdCookieName() {\n        return SessionCookieConfig.DEFAULT_SESSION_ID;\n    }\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/main/java/co/paralleluniverse/fibers/dropwizard/FiberApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport com.google.common.base.Function;\nimport io.dropwizard.Application;\nimport io.dropwizard.Configuration;\nimport io.dropwizard.setup.Bootstrap;\nimport io.dropwizard.setup.Environment;\nimport javax.servlet.Servlet;\nimport org.glassfish.jersey.server.ResourceConfig;\nimport org.glassfish.jersey.servlet.ServletContainer;\n\npublic abstract class FiberApplication<T extends Configuration> extends Application<T> {\n    @Override\n    public void initialize(Bootstrap<T> bootstrap) {\n    }\n\n    @Override\n    public final void run(T configuration, final Environment environment) throws Exception {\n        fiberRun(configuration, environment);\n        environment.jersey().replace(new Function<ResourceConfig, Servlet>() {\n            @Override\n            public Servlet apply(ResourceConfig f) {\n                return new FiberServletContainer((ServletContainer) environment.getJerseyServletContainer());\n            }\n        });\n    }\n\n    public abstract void fiberRun(T configuration, Environment environment) throws Exception;\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/main/java/co/paralleluniverse/fibers/dropwizard/FiberDBIFactory.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport co.paralleluniverse.fibers.jdbi.FiberDBI;\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport io.dropwizard.db.DataSourceFactory;\nimport io.dropwizard.db.ManagedDataSource;\nimport io.dropwizard.jdbi.DBIFactory;\nimport io.dropwizard.setup.Environment;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport org.skife.jdbi.v2.IDBI;\n\npublic class FiberDBIFactory {\n    private final ExecutorService es;\n    private final DBIFactory builder;\n\n    public FiberDBIFactory(final ExecutorService es) {\n        this.builder = new DBIFactory();\n        this.es = es;\n    }\n\n    public FiberDBIFactory(final int threadsNum) {\n        this(Executors.newFixedThreadPool(threadsNum, new ThreadFactoryBuilder().setNameFormat(\"jdbc-worker-%d\").setDaemon(true).build()));\n    }\n\n    public FiberDBIFactory() {\n        this(10);\n    }\n\n    public IDBI build(Environment environment, DataSourceFactory dsFactory, ManagedDataSource dataSource, String name) {\n        IDBI build = builder.build(environment, new FiberDataSourceFactory(dsFactory),\n                FiberManagedDataSource.wrap(dataSource, es), name);\n        return new FiberDBI(build);\n    }\n\n    public IDBI build(Environment environment, DataSourceFactory dsFactory, String name) throws ClassNotFoundException {\n        IDBI build = builder.build(environment, new FiberDataSourceFactory(dsFactory), name);\n        return new FiberDBI(build);\n    }\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/main/java/co/paralleluniverse/fibers/dropwizard/FiberDataSourceFactory.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport com.codahale.metrics.MetricRegistry;\nimport com.google.common.base.Optional;\nimport io.dropwizard.db.DataSourceFactory;\nimport io.dropwizard.db.ManagedDataSource;\nimport io.dropwizard.util.Duration;\nimport java.util.Map;\n\npublic class FiberDataSourceFactory extends DataSourceFactory {\n    private final DataSourceFactory dsf;\n\n    public FiberDataSourceFactory(DataSourceFactory dsf) {\n        this.dsf = dsf;\n    }\n\n    @Override\n    public ManagedDataSource build(MetricRegistry metricRegistry, String name) {\n        final ManagedDataSource ds = dsf.build(metricRegistry, name);\n        return dsf.getUrl().startsWith(\"jdbc:fiber:\")\n                ? ds : FiberManagedDataSource.wrap(ds, 10);\n    }\n\n    // Delegations\n    @Override\n    public boolean isAutoCommentsEnabled() {\n        return dsf.isAutoCommentsEnabled();\n    }\n\n    @Override\n    public void setAutoCommentsEnabled(boolean autoCommentsEnabled) {\n        dsf.setAutoCommentsEnabled(autoCommentsEnabled);\n    }\n\n    @Override\n    public String getDriverClass() {\n        return dsf.getDriverClass();\n    }\n\n    @Override\n    public void setDriverClass(String driverClass) {\n        dsf.setDriverClass(driverClass);\n    }\n\n    @Override\n    public String getUser() {\n        return dsf.getUser();\n    }\n\n    @Override\n    public void setUser(String user) {\n        dsf.setUser(user);\n    }\n\n    @Override\n    public String getPassword() {\n        return dsf.getPassword();\n    }\n\n    @Override\n    public void setPassword(String password) {\n        dsf.setPassword(password);\n    }\n\n    @Override\n    public String getUrl() {\n        return dsf.getUrl();\n    }\n\n    @Override\n    public void setUrl(String url) {\n        dsf.setUrl(url);\n    }\n\n    @Override\n    public Map<String, String> getProperties() {\n        return dsf.getProperties();\n    }\n\n    @Override\n    public void setProperties(Map<String, String> properties) {\n        dsf.setProperties(properties);\n    }\n\n    @Override\n    public Duration getMaxWaitForConnection() {\n        return dsf.getMaxWaitForConnection();\n    }\n\n    @Override\n    public void setMaxWaitForConnection(Duration maxWaitForConnection) {\n        dsf.setMaxWaitForConnection(maxWaitForConnection);\n    }\n\n    @Override\n    public String getValidationQuery() {\n        return dsf.getValidationQuery();\n    }\n\n    @Override\n    public void setValidationQuery(String validationQuery) {\n        dsf.setValidationQuery(validationQuery);\n    }\n\n    @Override\n    public int getMinSize() {\n        return dsf.getMinSize();\n    }\n\n    @Override\n    public void setMinSize(int minSize) {\n        dsf.setMinSize(minSize);\n    }\n\n    @Override\n    public int getMaxSize() {\n        return dsf.getMaxSize();\n    }\n\n    @Override\n    public void setMaxSize(int maxSize) {\n        dsf.setMaxSize(maxSize);\n    }\n\n    @Override\n    public boolean getCheckConnectionWhileIdle() {\n        return dsf.getCheckConnectionWhileIdle();\n    }\n\n    @Override\n    public void setCheckConnectionWhileIdle(boolean checkConnectionWhileIdle) {\n        dsf.setCheckConnectionWhileIdle(checkConnectionWhileIdle);\n    }\n\n    @Override\n    public boolean isDefaultReadOnly() {\n        return dsf.isDefaultReadOnly();\n    }\n\n    @Override\n    public void setDefaultReadOnly(boolean defaultReadOnly) {\n        dsf.setDefaultReadOnly(defaultReadOnly);\n    }\n\n    @Override\n    public boolean isMinSizeLessThanMaxSize() {\n        return dsf.isMinSizeLessThanMaxSize();\n    }\n\n    @Override\n    public boolean isInitialSizeLessThanMaxSize() {\n        return dsf.isInitialSizeLessThanMaxSize();\n    }\n\n    @Override\n    public boolean isInitialSizeGreaterThanMinSize() {\n        return dsf.isInitialSizeGreaterThanMinSize();\n    }\n\n    @Override\n    public int getAbandonWhenPercentageFull() {\n        return dsf.getAbandonWhenPercentageFull();\n    }\n\n    @Override\n    public void setAbandonWhenPercentageFull(int percentage) {\n        dsf.setAbandonWhenPercentageFull(percentage);\n    }\n\n    @Override\n    public boolean isAlternateUsernamesAllowed() {\n        return dsf.isAlternateUsernamesAllowed();\n    }\n\n    @Override\n    public void setAlternateUsernamesAllowed(boolean allow) {\n        dsf.setAlternateUsernamesAllowed(allow);\n    }\n\n    @Override\n    public boolean getCommitOnReturn() {\n        return dsf.getCommitOnReturn();\n    }\n\n    @Override\n    public void setCommitOnReturn(boolean commitOnReturn) {\n        dsf.setCommitOnReturn(commitOnReturn);\n    }\n\n    @Override\n    public Boolean getAutoCommitByDefault() {\n        return dsf.getAutoCommitByDefault();\n    }\n\n    @Override\n    public void setAutoCommitByDefault(Boolean autoCommit) {\n        dsf.setAutoCommitByDefault(autoCommit);\n    }\n\n    @Override\n    public String getDefaultCatalog() {\n        return dsf.getDefaultCatalog();\n    }\n\n    @Override\n    public void setDefaultCatalog(String defaultCatalog) {\n        dsf.setDefaultCatalog(defaultCatalog);\n    }\n\n    @Override\n    public Boolean getReadOnlyByDefault() {\n        return dsf.getReadOnlyByDefault();\n    }\n\n    @Override\n    public void setReadOnlyByDefault(Boolean readOnlyByDefault) {\n        dsf.setReadOnlyByDefault(readOnlyByDefault);\n    }\n\n    @Override\n    public TransactionIsolation getDefaultTransactionIsolation() {\n        return dsf.getDefaultTransactionIsolation();\n    }\n\n    @Override\n    public void setDefaultTransactionIsolation(TransactionIsolation isolation) {\n        dsf.setDefaultTransactionIsolation(isolation);\n    }\n\n    @Override\n    public boolean getUseFairQueue() {\n        return dsf.getUseFairQueue();\n    }\n\n    @Override\n    public void setUseFairQueue(boolean fair) {\n        dsf.setUseFairQueue(fair);\n    }\n\n    @Override\n    public int getInitialSize() {\n        return dsf.getInitialSize();\n    }\n\n    @Override\n    public void setInitialSize(int initialSize) {\n        dsf.setInitialSize(initialSize);\n    }\n\n    @Override\n    public String getInitializationQuery() {\n        return dsf.getInitializationQuery();\n    }\n\n    @Override\n    public void setInitializationQuery(String query) {\n        dsf.setInitializationQuery(query);\n    }\n\n    @Override\n    public boolean getLogAbandonedConnections() {\n        return dsf.getLogAbandonedConnections();\n    }\n\n    @Override\n    public void setLogAbandonedConnections(boolean log) {\n        dsf.setLogAbandonedConnections(log);\n    }\n\n    @Override\n    public boolean getLogValidationErrors() {\n        return dsf.getLogValidationErrors();\n    }\n\n    @Override\n    public void setLogValidationErrors(boolean log) {\n        dsf.setLogValidationErrors(log);\n    }\n\n    @Override\n    public Optional<Duration> getMaxConnectionAge() {\n        return dsf.getMaxConnectionAge();\n    }\n\n    @Override\n    public void setMaxConnectionAge(Duration age) {\n        dsf.setMaxConnectionAge(age);\n    }\n\n    @Override\n    public Duration getMinIdleTime() {\n        return dsf.getMinIdleTime();\n    }\n\n    @Override\n    public void setMinIdleTime(Duration time) {\n        dsf.setMinIdleTime(time);\n    }\n\n    @Override\n    public boolean getCheckConnectionOnBorrow() {\n        return dsf.getCheckConnectionOnBorrow();\n    }\n\n    @Override\n    public void setCheckConnectionOnBorrow(boolean checkConnectionOnBorrow) {\n        dsf.setCheckConnectionOnBorrow(checkConnectionOnBorrow);\n    }\n\n    @Override\n    public boolean getCheckConnectionOnConnect() {\n        return dsf.getCheckConnectionOnConnect();\n    }\n\n    @Override\n    public void setCheckConnectionOnConnect(boolean checkConnectionOnConnect) {\n        dsf.setCheckConnectionOnConnect(checkConnectionOnConnect);\n    }\n\n    @Override\n    public boolean getCheckConnectionOnReturn() {\n        return dsf.getCheckConnectionOnReturn();\n    }\n\n    @Override\n    public void setCheckConnectionOnReturn(boolean checkConnectionOnReturn) {\n        dsf.setCheckConnectionOnReturn(checkConnectionOnReturn);\n    }\n\n    @Override\n    public Duration getEvictionInterval() {\n        return dsf.getEvictionInterval();\n    }\n\n    @Override\n    public void setEvictionInterval(Duration interval) {\n        dsf.setEvictionInterval(interval);\n    }\n\n    @Override\n    public Duration getValidationInterval() {\n        return dsf.getValidationInterval();\n    }\n\n    @Override\n    public void setValidationInterval(Duration validationInterval) {\n        dsf.setValidationInterval(validationInterval);\n    }\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/main/java/co/paralleluniverse/fibers/dropwizard/FiberHttpClientBuilder.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport co.paralleluniverse.fibers.httpclient.FiberHttpClient;\nimport com.codahale.metrics.MetricRegistry;\nimport io.dropwizard.client.HttpClientConfiguration;\nimport io.dropwizard.setup.Environment;\nimport io.dropwizard.util.Duration;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.client.HttpRequestRetryHandler;\nimport org.apache.http.client.config.CookieSpecs;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.config.Registry;\nimport org.apache.http.config.RegistryBuilder;\nimport org.apache.http.conn.DnsResolver;\nimport org.apache.http.conn.scheme.SchemeRegistry;\nimport org.apache.http.conn.ssl.SSLConnectionSocketFactory;\nimport org.apache.http.conn.ssl.SSLContexts;\nimport org.apache.http.conn.ssl.SSLInitializationException;\nimport org.apache.http.impl.DefaultConnectionReuseStrategy;\nimport org.apache.http.impl.NoConnectionReuseStrategy;\nimport org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;\nimport org.apache.http.impl.client.DefaultHttpRequestRetryHandler;\nimport org.apache.http.impl.conn.SchemeRegistryFactory;\nimport org.apache.http.impl.conn.SystemDefaultDnsResolver;\nimport org.apache.http.impl.nio.client.CloseableHttpAsyncClient;\nimport org.apache.http.impl.nio.client.HttpAsyncClientBuilder;\nimport org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;\nimport org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;\nimport org.apache.http.impl.nio.reactor.IOReactorConfig;\nimport org.apache.http.nio.conn.NHttpClientConnectionManager;\nimport org.apache.http.nio.conn.NoopIOSessionStrategy;\nimport org.apache.http.nio.conn.SchemeIOSessionStrategy;\nimport org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;\nimport org.apache.http.nio.reactor.ConnectingIOReactor;\nimport org.apache.http.nio.reactor.IOReactorException;\nimport org.apache.http.protocol.HttpContext;\n\n/**\n * A convenience class for building {@link HttpClient} instances.\n * <p>\n * Among other things,\n * <ul>\n * <li>Disables stale connection checks</li>\n * <li>Disables Nagle's algorithm</li>\n * <li>Disables cookie management by default</li>\n * </ul>\n */\npublic class FiberHttpClientBuilder {\n\n    private final MetricRegistry metricRegistry;\n    private HttpClientConfiguration configuration = new HttpClientConfiguration();\n    private DnsResolver resolver = new SystemDefaultDnsResolver();\n    private HttpRequestRetryHandler httpRequestRetryHandler;\n    private SchemeRegistry registry = SchemeRegistryFactory.createSystemDefault();\n\n    public FiberHttpClientBuilder(MetricRegistry metricRegistry) {\n        this.metricRegistry = metricRegistry;\n    }\n\n    public FiberHttpClientBuilder(Environment environment) {\n        this.metricRegistry = environment.metrics();\n    }\n\n    /**\n     * Use the given {@link HttpClientConfiguration} instance.\n     *\n     * @param configuration a {@link HttpClientConfiguration} instance\n     * @return {@code this}\n     */\n    public FiberHttpClientBuilder using(HttpClientConfiguration configuration) {\n        this.configuration = configuration;\n        return this;\n    }\n\n    /**\n     * Use the given {@link DnsResolver} instance.\n     *\n     * @param resolver a {@link DnsResolver} instance\n     * @return {@code this}\n     */\n    public FiberHttpClientBuilder using(DnsResolver resolver) {\n        this.resolver = resolver;\n        return this;\n    }\n\n    /**\n     * Uses the {@link httpRequestRetryHandler} for handling request retries.\n     *\n     * @param httpRequestRetryHandler an httpRequestRetryHandler\n     * @return {@code this}\n     */\n    public FiberHttpClientBuilder using(HttpRequestRetryHandler httpRequestRetryHandler) {\n        this.httpRequestRetryHandler = httpRequestRetryHandler;\n        return this;\n    }\n\n    /**\n     * Use the given {@link SchemeRegistry} instance.\n     *\n     * @param registry a {@link SchemeRegistry} instance\n     * @return {@code this}\n     */\n    public FiberHttpClientBuilder using(SchemeRegistry registry) {\n        this.registry = registry;\n        return this;\n    }\n\n    /**\n     * Builds the {@link HttpClient}.\n     *\n     * @return an {@link HttpClient}\n     */\n    public HttpClient build(String name) {\n        RequestConfig createHttpParams = createHttpParams();\n        final NHttpClientConnectionManager manager = createConnectionManager(registry, name);\n        HttpAsyncClientBuilder clientBuilder = new InstrumentedNHttpClientBuilder(metricRegistry, name);\n        clientBuilder.setConnectionManager(manager);\n        clientBuilder.setDefaultRequestConfig(createHttpParams);\n        setStrategiesForClient(clientBuilder);\n        CloseableHttpAsyncClient client = clientBuilder.build();\n        client.start();\n        return new FiberHttpClient(client, getRetryHandler());\n    }\n\n    /**\n     * Add strategies to client such as ConnectionReuseStrategy and KeepAliveStrategy Note that this\n     * method mutates the client object by setting the strategies\n     *\n     * @param client The InstrumentedHttpClient that should be configured with strategies\n     */\n    protected void setStrategiesForClient(HttpAsyncClientBuilder client) {\n        final long keepAlive = configuration.getKeepAlive().toMilliseconds();\n\n        // don't keep alive the HTTP connection and thus don't reuse the TCP socket\n        if (keepAlive == 0) {\n            client.setConnectionReuseStrategy(new NoConnectionReuseStrategy());\n        } else {\n            client.setConnectionReuseStrategy(new DefaultConnectionReuseStrategy());\n            // either keep alive based on response header Keep-Alive,\n            // or if the server can keep a persistent connection (-1), then override based on client's configuration\n            client.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy() {\n                @Override\n                public long getKeepAliveDuration(HttpResponse response, HttpContext context) {\n                    final long duration = super.getKeepAliveDuration(response, context);\n                    return (duration == -1) ? keepAlive : duration;\n                }\n            });\n        }\n    }\n\n    private HttpRequestRetryHandler getRetryHandler() {\n        return configuration.getRetries() == 0 ? null\n                : httpRequestRetryHandler != null ? httpRequestRetryHandler\n                : new DefaultHttpRequestRetryHandler(configuration.getRetries(), false);\n    }\n\n    /**\n     * Map the parameters in HttpClientConfiguration to a BasicHttpParams object\n     *\n     * @return a BasicHttpParams object from the HttpClientConfiguration\n     */\n    protected RequestConfig createHttpParams() {\n        RequestConfig.Builder rcb = RequestConfig.custom();\n        rcb.setCookieSpec(CookieSpecs.BEST_MATCH);\n        if (configuration.isCookiesEnabled())\n            rcb.setCookieSpec(CookieSpecs.BEST_MATCH);\n        else\n            rcb.setCookieSpec(CookieSpecs.IGNORE_COOKIES);\n        rcb.setStaleConnectionCheckEnabled(false);\n        return rcb.build();\n    }\n\n    /**\n     * Create a InstrumentedClientConnManager based on the HttpClientConfiguration. It sets the\n     * maximum connections per route and the maximum total connections that the connection manager\n     * can create\n     *\n     * @param registry the SchemeRegistry\n     * @return a InstrumentedClientConnManger instance\n     */\n    protected NHttpClientConnectionManager createConnectionManager(SchemeRegistry registry, String name) {\n        final Duration ttl = configuration.getTimeToLive();\n        ConnectingIOReactor ioReactor = createDefaultIOReactor(IOReactorConfig.custom()\n                .setSoTimeout((int) configuration.getTimeout().toMilliseconds())\n                .setConnectTimeout((int) configuration.getConnectionTimeout().toMilliseconds())\n                .setTcpNoDelay(true).build());\n\n        PoolingNHttpClientConnectionManager manager\n                = new InstrumentedNClientConnManager(\n                        ioReactor, null, null, //TODO: add this parameters values\n                        metricRegistry,\n                        convertRegistry(this.registry),\n                        ttl.getQuantity(),\n                        ttl.getUnit(),\n                        resolver,\n                        name);\n        manager.setDefaultMaxPerRoute(configuration.getMaxConnectionsPerRoute());\n        manager.setMaxTotal(configuration.getMaxConnections());\n        return manager;\n    }\n\n    private static ConnectingIOReactor createDefaultIOReactor(final IOReactorConfig spec) {\n        try {\n            return new DefaultConnectingIOReactor(spec);\n        } catch (IOReactorException ex) {\n            throw new RuntimeException(ex);\n        }\n    }\n\n    private static Registry<SchemeIOSessionStrategy> convertRegistry(final SchemeRegistry oldRegistry) throws SSLInitializationException {\n        SchemeRegistry baseRegistry = oldRegistry;\n        //TODO: use values from old registry;\n        Registry<SchemeIOSessionStrategy> defaultRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create()\n                .register(\"http\", NoopIOSessionStrategy.INSTANCE)\n                .register(\"https\", new SSLIOSessionStrategy(\n                                SSLContexts.createDefault(), null, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER))\n                .build();\n        return defaultRegistry;\n    }\n\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/main/java/co/paralleluniverse/fibers/dropwizard/FiberManagedDataSource.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport co.paralleluniverse.fibers.jdbc.FiberDataSource;\nimport com.google.common.util.concurrent.ListeningExecutorService;\nimport com.google.common.util.concurrent.MoreExecutors;\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport io.dropwizard.db.ManagedDataSource;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\npublic class FiberManagedDataSource extends FiberDataSource implements ManagedDataSource {\n    private final ManagedDataSource myds;\n\n    public static ManagedDataSource wrap(ManagedDataSource ds, int numThreads) {\n        return wrap(ds, Executors.newFixedThreadPool(numThreads, new ThreadFactoryBuilder().setNameFormat(\"jdbc-worker-%d\").setDaemon(true).build()));\n    }\n\n    public static ManagedDataSource wrap(ManagedDataSource ds, ExecutorService executor) {\n        return new FiberManagedDataSource(ds, MoreExecutors.listeningDecorator(executor));\n    }\n\n    protected FiberManagedDataSource(ManagedDataSource ds, ListeningExecutorService exec) {\n        super(ds, exec);\n        this.myds = ds;\n    }\n\n    @Override\n    public void start() throws Exception {\n        myds.start();\n    }\n\n    @Override\n    public void stop() throws Exception {\n        myds.stop();\n    }\n\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/main/java/co/paralleluniverse/fibers/dropwizard/FiberServletContainer.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.fibers.servlet.FiberHttpServlet;\nimport java.io.IOException;\nimport java.util.Enumeration;\nimport javax.servlet.Filter;\nimport javax.servlet.FilterChain;\nimport javax.servlet.FilterConfig;\nimport javax.servlet.ServletConfig;\nimport javax.servlet.ServletContext;\nimport javax.servlet.ServletException;\nimport javax.servlet.ServletRequest;\nimport javax.servlet.ServletResponse;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport org.glassfish.jersey.server.ResourceConfig;\nimport org.glassfish.jersey.servlet.ServletContainer;\n\n/**\n * A Servlet for deploying root resource classes that assign a fiber per request.\n *\n * @see org.glassfish.jersey.servlet.ServletContainer\n * @author eitan\n */\npublic class FiberServletContainer extends FiberHttpServlet implements Filter {\n    private static final int DEFAULT_STACK_SIZE = 120;\n    private final ServletContainer jerseySC;\n\n    /**\n     * Create Jersey Servlet container.\n     */\n    public FiberServletContainer() {\n        this.jerseySC = new ServletContainer();\n    }\n\n    /**\n     * Create Jersey Servlet container.\n     *\n     * @param resourceConfig container configuration.\n     */\n    public FiberServletContainer(ResourceConfig resourceConfig) {\n        this.jerseySC = new ServletContainer(resourceConfig);\n    }\n\n    /**\n     * Wraps a Jerset Servlet container.\n     *\n     * @param sc the servlet container\n     */\n    public FiberServletContainer(ServletContainer sc) {\n        this.jerseySC = sc;\n    }\n\n    @Override\n    public void init(ServletConfig config) throws ServletException {\n        super.init(config);\n        if (getStackSize() <= 0)\n            setStackSize(DEFAULT_STACK_SIZE);\n    }\n\n    /**\n     * Get the servlet context for the servlet or filter, depending on\n     * how this class is registered.\n     *\n     * @return the servlet context for the servlet or filter.\n     */\n    @Override\n    public ServletContext getServletContext() {\n        return jerseySC.getServletContext();\n    }\n\n    @Override\n    @Suspendable\n    public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {\n        jerseySC.service(req, res);\n    }\n\n    // Delegations\n    @Override\n    public void destroy() {\n        jerseySC.destroy();\n    }\n\n    @Override\n    public void init() throws ServletException {\n        jerseySC.init(getServletConfig());\n    }\n\n    @Override\n    public void init(FilterConfig filterConfig) throws ServletException {\n        jerseySC.init(filterConfig);\n    }\n\n    @Override\n    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {\n        jerseySC.doFilter(servletRequest, servletResponse, filterChain);\n    }\n\n    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {\n        jerseySC.doFilter(request, response, chain);\n    }\n\n    @Override\n    public String getInitParameter(String name) {\n        return jerseySC.getInitParameter(name);\n    }\n\n    @Override\n    public Enumeration<String> getInitParameterNames() {\n        return jerseySC.getInitParameterNames();\n    }\n\n    @Override\n    public String getServletInfo() {\n        return jerseySC.getServletInfo();\n    }\n\n    @Override\n    public void log(String msg) {\n        jerseySC.log(msg);\n    }\n\n    @Override\n    public void log(String message, Throwable t) {\n        jerseySC.log(message, t);\n    }\n\n    @Override\n    public String getServletName() {\n        return jerseySC.getServletName();\n    }\n\n    @Override\n    public int hashCode() {\n        return jerseySC.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return jerseySC.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return jerseySC.toString();\n    }\n}"
  },
  {
    "path": "comsat-dropwizard/src/main/java/co/paralleluniverse/fibers/dropwizard/InstrumentedNClientConnManager.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport com.codahale.metrics.Gauge;\nimport com.codahale.metrics.MetricRegistry;\nimport static com.codahale.metrics.MetricRegistry.name;\nimport java.util.concurrent.TimeUnit;\nimport org.apache.http.config.Registry;\nimport org.apache.http.conn.DnsResolver;\nimport org.apache.http.conn.SchemePortResolver;\nimport org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;\nimport org.apache.http.nio.conn.ManagedNHttpClientConnection;\nimport org.apache.http.nio.conn.NHttpClientConnectionManager;\nimport org.apache.http.nio.conn.NHttpConnectionFactory;\nimport org.apache.http.nio.conn.SchemeIOSessionStrategy;\nimport org.apache.http.nio.reactor.ConnectingIOReactor;\n\npublic class InstrumentedNClientConnManager extends PoolingNHttpClientConnectionManager {\n\n    public InstrumentedNClientConnManager(final ConnectingIOReactor ioreactor, final NHttpConnectionFactory<ManagedNHttpClientConnection> connFactory, final SchemePortResolver schemePortResolver, final MetricRegistry metricRegistry, final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry, final long timeToLive, final TimeUnit tunit, final DnsResolver dnsResolver, final String name) {\n        super(ioreactor, connFactory, iosessionFactoryRegistry, schemePortResolver, dnsResolver, timeToLive, tunit);\n        metricRegistry.register(name(NHttpClientConnectionManager.class, name, \"available-connections\"),\n                new Gauge<Integer>() {\n                    @Override\n                    public Integer getValue() {\n                        // this acquires a lock on the connection pool; remove if contention sucks\n                        return getTotalStats().getAvailable();\n                    }\n                });\n        metricRegistry.register(name(NHttpClientConnectionManager.class, name, \"leased-connections\"),\n                new Gauge<Integer>() {\n                    @Override\n                    public Integer getValue() {\n                        // this acquires a lock on the connection pool; remove if contention sucks\n                        return getTotalStats().getLeased();\n                    }\n                });\n        metricRegistry.register(name(NHttpClientConnectionManager.class, name, \"max-connections\"),\n                new Gauge<Integer>() {\n                    @Override\n                    public Integer getValue() {\n                        // this acquires a lock on the connection pool; remove if contention sucks\n                        return getTotalStats().getMax();\n                    }\n                });\n        metricRegistry.register(name(NHttpClientConnectionManager.class, name, \"pending-connections\"),\n                new Gauge<Integer>() {\n                    @Override\n                    public Integer getValue() {\n                        // this acquires a lock on the connection pool; remove if contention sucks\n                        return getTotalStats().getPending();\n                    }\n                });\n    }\n\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/main/java/co/paralleluniverse/fibers/dropwizard/InstrumentedNHttpClientBuilder.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport com.codahale.metrics.MetricRegistry;\nimport com.codahale.metrics.Timer;\nimport com.codahale.metrics.httpclient.HttpClientMetricNameStrategies;\nimport com.codahale.metrics.httpclient.HttpClientMetricNameStrategy;\nimport java.io.IOException;\nimport java.util.concurrent.Future;\nimport org.apache.http.HttpException;\nimport org.apache.http.HttpRequest;\nimport org.apache.http.concurrent.FutureCallback;\nimport org.apache.http.impl.nio.client.CloseableHttpAsyncClient;\nimport org.apache.http.impl.nio.client.HttpAsyncClientBuilder;\nimport org.apache.http.nio.protocol.HttpAsyncRequestProducer;\nimport org.apache.http.nio.protocol.HttpAsyncResponseConsumer;\nimport org.apache.http.protocol.HttpContext;\n\npublic class InstrumentedNHttpClientBuilder extends HttpAsyncClientBuilder {\n    private final MetricRegistry metricRegistry;\n    private final String name;\n    private final HttpClientMetricNameStrategy metricNameStrategy;\n\n    public InstrumentedNHttpClientBuilder(MetricRegistry metricRegistry, HttpClientMetricNameStrategy metricNameStrategy, String name) {\n        super();\n        this.metricRegistry = metricRegistry;\n        this.metricNameStrategy = metricNameStrategy;\n        this.name = name;\n    }\n\n    public InstrumentedNHttpClientBuilder(MetricRegistry metricRegistry, String name) {\n        this(metricRegistry, HttpClientMetricNameStrategies.METHOD_ONLY, name);\n    }\n\n    private Timer timer(HttpRequest request) {\n        return metricRegistry.timer(metricNameStrategy.getNameFor(name, request));\n    }\n\n    @Override\n    public CloseableHttpAsyncClient build() {\n\n        final CloseableHttpAsyncClient ac = super.build();\n        return new CloseableHttpAsyncClient() {\n\n            @Override\n            public boolean isRunning() {\n                return ac.isRunning();\n            }\n\n            @Override\n            public void start() {\n                ac.start();\n            }\n\n            @Override\n            public <T> Future<T> execute(HttpAsyncRequestProducer requestProducer, HttpAsyncResponseConsumer<T> responseConsumer, HttpContext context, FutureCallback<T> callback) {\n                final Timer.Context timerContext;\n                try {\n                    timerContext = timer(requestProducer.generateRequest()).time();\n                } catch (IOException | HttpException ex) {\n                    throw new AssertionError();\n                }\n                try {\n                    return ac.execute(requestProducer, responseConsumer, context, callback);\n                } finally {\n                    timerContext.stop();\n                }\n            }\n\n            @Override\n            public void close() throws IOException {\n                ac.close();\n            }\n        };\n    }\n\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/main/resources/META-INF/suspendables",
    "content": "org.apache.tomcat.jdbc.pool.ProxyConnection.invoke\norg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke\norg.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke\norg.glassfish.jersey.servlet.ServletContainer.service\norg.glassfish.jersey.servlet.WebComponent.service\norg.glassfish.jersey.server.ApplicationHandler.handle\norg.glassfish.jersey.server.ServerRuntime.process\norg.glassfish.jersey.process.internal.RequestScope.runInScope\norg.glassfish.jersey.internal.Errors.process\norg.glassfish.jersey.internal.Errors$1.call\norg.glassfish.jersey.server.ServerRuntime$2.run\norg.glassfish.jersey.server.model.ResourceMethodInvoker.apply\norg.glassfish.jersey.server.model.ResourceMethodInvoker.invoke\norg.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch\norg.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch\norg.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run\norg.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke\norg.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke\norg.glassfish.jersey.servlet.WebComponent.service\norg.glassfish.jersey.servlet.WebComponent.serviceImpl\n"
  },
  {
    "path": "comsat-dropwizard/src/test/java/co/paralleluniverse/fibers/dropwizard/FiberDropwizardTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.dropwizard;\n\nimport com.google.common.io.Resources;\nimport java.io.IOException;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.conn.HttpHostConnectException;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.BeforeClass;\nimport org.junit.Test;\n\npublic class FiberDropwizardTest {\n    private static final int TIMEOUT = 10_000; // ms\n    public static final String SERVER_BASE_URL = \"http://localhost:8080\";\n\n    @BeforeClass\n    public static void setUpClass() throws InterruptedException, IOException {\n        Thread t = new Thread(new Runnable() {\n\n            @Override\n            public void run() {\n                try {\n                    new MyDropwizardApp().run(new String[]{\"server\", Resources.getResource(\"server.yml\").getPath()});\n                } catch (final Exception ignored) {}\n            }\n        });\n        t.setDaemon(true);\n        t.start();\n        waitUrlAvailable(SERVER_BASE_URL);\n    }\n    private CloseableHttpClient client;\n\n    @Before\n    public void setUp() throws Exception {\n        this.client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()\n                .setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT).setConnectionRequestTimeout(TIMEOUT)\n                .build()).build();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        client.close();\n    }\n\n    @Test\n    public void testGet() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertTrue(client.execute(new HttpGet(SERVER_BASE_URL + \"/?name=foo\"), BASIC_RESPONSE_HANDLER).contains(\"foo\"));\n    }\n\n    @Test\n    public void testHttp() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertTrue(client.execute(new HttpGet(SERVER_BASE_URL + \"/http?name=bar\"), BASIC_RESPONSE_HANDLER).contains(\"bar\"));\n    }\n\n    @Test\n    public void testFluentAPI() throws IOException, InterruptedException {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"37\", client.execute(new HttpGet(SERVER_BASE_URL + \"/fluent?id=37\"), BASIC_RESPONSE_HANDLER));\n    }\n\n    @Test\n    public void testDao() throws Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"name37\", client.execute(new HttpGet(SERVER_BASE_URL + \"/dao?id=37\"), BASIC_RESPONSE_HANDLER));\n    }\n    private static final BasicResponseHandler BASIC_RESPONSE_HANDLER = new BasicResponseHandler();\n\n    public static void waitUrlAvailable(final String url) throws InterruptedException, IOException {\n        for (;;) {\n            Thread.sleep(10);\n            try {\n                if (HttpClients.createDefault().execute(new HttpGet(url)).getStatusLine().getStatusCode() > -100)\n                    break;\n            } catch (final HttpHostConnectException ignored) {}\n        }\n    }\n\n}\n"
  },
  {
    "path": "comsat-dropwizard/src/test/java/co/paralleluniverse/fibers/dropwizard/MyDropwizardApp.java",
    "content": "/*\r\n * COMSAT\r\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\r\n *\r\n * This program and the accompanying materials are dual-licensed under\r\n * either the terms of the Eclipse Public License v1.0 as published by\r\n * the Eclipse Foundation\r\n *\r\n *   or (per the licensee's choosing)\r\n *\r\n * under the terms of the GNU Lesser General Public License version 3.0\r\n * as published by the Free Software Foundation.\r\n */\r\npackage co.paralleluniverse.fibers.dropwizard;\r\n\r\nimport co.paralleluniverse.fibers.Fiber;\r\nimport co.paralleluniverse.fibers.SuspendExecution;\r\nimport co.paralleluniverse.fibers.Suspendable;\r\nimport co.paralleluniverse.fibers.dropwizard.MyDropwizardApp.MyConfig;\r\nimport com.codahale.metrics.annotation.Timed;\r\nimport com.fasterxml.jackson.annotation.JsonProperty;\r\nimport com.google.common.base.Optional;\r\nimport io.dropwizard.Configuration;\r\nimport io.dropwizard.client.HttpClientConfiguration;\r\nimport io.dropwizard.db.DataSourceFactory;\r\nimport io.dropwizard.setup.Environment;\r\nimport java.io.IOException;\r\nimport java.util.concurrent.atomic.AtomicInteger;\r\nimport javax.inject.Singleton;\r\nimport javax.validation.Valid;\r\nimport javax.validation.constraints.NotNull;\r\nimport javax.ws.rs.GET;\r\nimport javax.ws.rs.Path;\r\nimport javax.ws.rs.Produces;\r\nimport javax.ws.rs.QueryParam;\r\nimport javax.ws.rs.core.MediaType;\r\nimport org.apache.http.client.HttpClient;\r\nimport org.apache.http.client.methods.HttpGet;\r\nimport org.apache.http.impl.client.BasicResponseHandler;\r\nimport org.hibernate.validator.constraints.Length;\r\nimport org.skife.jdbi.v2.Handle;\r\nimport org.skife.jdbi.v2.IDBI;\r\nimport org.skife.jdbi.v2.sqlobject.Bind;\r\nimport org.skife.jdbi.v2.sqlobject.SqlQuery;\r\nimport org.skife.jdbi.v2.sqlobject.SqlUpdate;\r\nimport org.skife.jdbi.v2.util.StringMapper;\r\n\r\n@Singleton\r\n@Path(\"/\")\r\n@Produces(MediaType.APPLICATION_JSON)\r\n//snippet app\r\npublic class MyDropwizardApp extends FiberApplication<MyConfig> {\r\n    private IDBI jdbi;\r\n    private MyDAO dao;\r\n    private HttpClient httpClient;\r\n\r\n    @Override\r\n    public void fiberRun(MyConfig config, Environment env) throws Exception {\r\n        this.httpClient = new FiberHttpClientBuilder(env).\r\n                using(config.getHttpClientConfiguration()).build(\"MyClient\");\r\n        this.jdbi = new FiberDBIFactory().build(env, config.getDB(), \"MyDB\");\r\n        this.dao = jdbi.onDemand(MyDAO.class);\r\n        env.jersey().register(MY_RESOURCE_OBJ);\r\n    }\r\n    // snippet_exclude_begin\r\n\r\n    public static class MyConfig extends Configuration {\r\n        @Valid\r\n        @NotNull\r\n        @JsonProperty\r\n        private final HttpClientConfiguration httpClient = new HttpClientConfiguration();\r\n\r\n        @JsonProperty\r\n        public HttpClientConfiguration getHttpClientConfiguration() {\r\n            return httpClient;\r\n        }\r\n\r\n        @Valid\r\n        @NotNull\r\n        @JsonProperty\r\n        private final DataSourceFactory database = new DataSourceFactory();\r\n\r\n        public DataSourceFactory getDB() {\r\n            return database;\r\n        }\r\n    }\r\n\r\n    public static class Saying {\r\n        private long id;\r\n\r\n        @Length(max = 3)\r\n        private String content;\r\n\r\n        public Saying() {\r\n        }\r\n\r\n        public Saying(long id, String content) {\r\n            this.id = id;\r\n            this.content = content;\r\n        }\r\n\r\n        @JsonProperty\r\n        public long getId() {\r\n            return id;\r\n        }\r\n\r\n        @JsonProperty\r\n        public String getContent() {\r\n            return content;\r\n        }\r\n    }\r\n\r\n    @Suspendable\r\n    public interface MyDAO {\r\n        @SqlUpdate(\"create table if not exists something (id int primary key, name varchar(100))\")\r\n        void createSomethingTable();\r\n\r\n        @SqlUpdate(\"drop table something\")\r\n        void dropSomethingTable();\r\n\r\n        @SqlUpdate(\"insert into something (id, name) values (:id, :name)\")\r\n        void insert(@Bind(\"id\") int id, @Bind(\"name\") String name);\r\n\r\n        @SqlQuery(\"select name from something where id = :id\")\r\n        String findNameById(@Bind(\"id\") int id);\r\n    }\r\n\r\n    private final AtomicInteger ai = new AtomicInteger();\r\n\r\n    @GET\r\n    @Timed\r\n    public Saying get(@QueryParam(\"name\") Optional<String> name,\r\n            @QueryParam(\"sleep\") Optional<Integer> sleepParameter) throws InterruptedException, SuspendExecution {\r\n        Fiber.sleep(sleepParameter.or(10));\r\n        return new Saying(ai.incrementAndGet(), name.or(\"name\"));\r\n    }\r\n\r\n    @GET\r\n    @Path(\"/http\")\r\n    @Timed\r\n    public String http(@QueryParam(\"name\") Optional<String> name) throws InterruptedException, SuspendExecution, IOException {\r\n        return httpClient.execute(new HttpGet(\"http://localhost:8080/?sleep=10&name=\" + name.or(\"name\")), new BasicResponseHandler());\r\n    }\r\n\r\n    @GET\r\n    @Path(\"/fluent\")\r\n    @Timed\r\n    public Integer fluentAPI(@QueryParam(\"id\") Optional<Integer> id) throws InterruptedException, SuspendExecution, IOException {\r\n        try (Handle h = jdbi.open()) {\r\n            h.execute(\"create table if not exists fluentAPI (id int primary key, name varchar(100))\");\r\n            for (int i = 0; i < 100; i++)\r\n                h.execute(\"insert into fluentAPI (id, name) values (?, ?)\", i, \"stranger \" + i);\r\n            int size = h.createQuery(\"select name from fluentAPI where id < :id order by id\")\r\n                    .bind(\"id\", id.or(50)).map(StringMapper.FIRST).list().size();\r\n            h.execute(\"drop table fluentAPI\");\r\n            return size;\r\n        }\r\n    }\r\n\r\n    @GET\r\n    @Path(\"/dao\")\r\n    @Timed\r\n    public String dao(@QueryParam(\"id\") Optional<Integer> id) throws InterruptedException, SuspendExecution, IOException {\r\n        dao.createSomethingTable();\r\n        for (int i = 0; i < 100; i++)\r\n            dao.insert(i, \"name\" + i);\r\n        String res = dao.findNameById(37);\r\n        dao.dropSomethingTable();\r\n        return res;\r\n    }\r\n    private Object MY_RESOURCE_OBJ = this;\r\n    // snippet_exclude_end\r\n}\r\n// end of snippet\r\n"
  },
  {
    "path": "comsat-dropwizard/src/test/resources/server.yml",
    "content": "# snippet server\nserver:\n    maxThreads: 200\n    minThreads: 200\n    maxQueuedRequests: 9999    \n    requestLog:\n      appenders: []\n# end of snippet\n\n# snippet httpclient\nhttpClient:\n    maxConnectionsPerRoute: 9999\n    maxConnections: 9999\n# end of snippet\n\n# snippet db\ndatabase:\n    driverClass: \n        org.h2.Driver\n    url:    \n        jdbc:h2:./build/h2testdb\n# end of snippet\n\n# for mysql use url such as this\n#        jdbc:fiber:mysql://localhost:3306/testjdbi?zeroDateTimeBehavior=convertToNull\n\n    properties:\n        charSet: UTF-8\n\n  # the maximum amount of time to wait on an empty pool before throwing an exception\n    maxWaitForConnection: 1s\n    user: root\n    password: root\n\n  # the SQL query to run when validating a connection's liveness\n    validationQuery: \n        \"/* MyService Health Check */ VALUES 1\"\n# for mysql use validationQuery such as this\n#        \"/* MyService Health Check */ SELECT 1\"\n\n  # the minimum number of connections to keep open\n    minSize: 8\n\n  # the maximum number of connections to keep open\n    maxSize: 32\n\n  # whether or not idle connections should be validated\n    checkConnectionWhileIdle: false\n"
  },
  {
    "path": "comsat-httpclient/src/main/java/co/paralleluniverse/fibers/httpasyncclient/FiberCloseableHttpAsyncClient.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.httpasyncclient;\n\nimport co.paralleluniverse.strands.SettableFuture;\nimport java.io.IOException;\nimport java.util.concurrent.Future;\nimport org.apache.http.HttpHost;\nimport org.apache.http.HttpRequest;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.methods.HttpUriRequest;\nimport org.apache.http.concurrent.FutureCallback;\nimport org.apache.http.impl.nio.client.CloseableHttpAsyncClient;\nimport org.apache.http.nio.protocol.HttpAsyncRequestProducer;\nimport org.apache.http.nio.protocol.HttpAsyncResponseConsumer;\nimport org.apache.http.protocol.HttpContext;\n\npublic class FiberCloseableHttpAsyncClient extends CloseableHttpAsyncClient {\n    private final CloseableHttpAsyncClient client;\n\n    private FiberCloseableHttpAsyncClient(CloseableHttpAsyncClient client) {\n        this.client = client;\n    }\n\n    public static CloseableHttpAsyncClient wrap(CloseableHttpAsyncClient client) {\n        return new FiberCloseableHttpAsyncClient(client);\n    };\n\n    @Override\n    public boolean isRunning() {\n        return client.isRunning();\n    }\n\n    @Override\n    public void start() {\n        client.start();\n    }\n\n    @Override\n    public <T> Future<T> execute(HttpAsyncRequestProducer requestProducer, HttpAsyncResponseConsumer<T> responseConsumer, final FutureCallback<T> callback) {\n        final SettableFuture<T> future = new SettableFuture<>();\n        client.execute(requestProducer, responseConsumer, wrapCallbackWithFuture(future, callback));\n        return future;\n    }\n\n    @Override\n    public Future<HttpResponse> execute(HttpHost target, HttpRequest request, HttpContext context, FutureCallback<HttpResponse> callback) {\n        final SettableFuture<HttpResponse> future = new SettableFuture<>();\n        client.execute(target, request, context, wrapCallbackWithFuture(future, callback));\n        return future;\n    }\n\n    @Override\n    public Future<HttpResponse> execute(HttpHost target, HttpRequest request, FutureCallback<HttpResponse> callback) {\n        final SettableFuture<HttpResponse> future = new SettableFuture<>();\n        client.execute(target, request, wrapCallbackWithFuture(future, callback));\n        return future;\n    }\n\n    @Override\n    public Future<HttpResponse> execute(HttpUriRequest request, FutureCallback<HttpResponse> callback) {\n        final SettableFuture<HttpResponse> future = new SettableFuture<>();\n        client.execute(request, wrapCallbackWithFuture(future, callback));\n        return future;\n    }\n\n    @Override\n    public Future<HttpResponse> execute(HttpUriRequest request, HttpContext context, FutureCallback<HttpResponse> callback) {\n        final SettableFuture<HttpResponse> future = new SettableFuture<>();\n        client.execute(request, context, wrapCallbackWithFuture(future, callback));\n        return future;\n    }\n\n    @Override\n    public void close() throws IOException {\n        client.close();\n    }\n\n    @Override\n    public <T> Future<T> execute(HttpAsyncRequestProducer requestProducer, HttpAsyncResponseConsumer<T> responseConsumer, HttpContext context, FutureCallback<T> callback) {\n        final SettableFuture<T> future = new SettableFuture<>();\n        client.execute(requestProducer, responseConsumer, context, wrapCallbackWithFuture(future, callback));\n        return future;\n    }\n\n    private static <T> FutureCallback<T> wrapCallbackWithFuture(final SettableFuture<T> future, final FutureCallback<T> callback) {\n        return new FutureCallback<T>() {\n\n            @Override\n            public void completed(T result) {\n                future.set(result);\n                callback.completed(result);\n            }\n\n            @Override\n            public void failed(Exception ex) {\n                future.setException(ex);\n                callback.failed(ex);\n            }\n\n            @Override\n            public void cancelled() {\n                future.cancel(true);\n                callback.cancelled();\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "comsat-httpclient/src/main/java/co/paralleluniverse/fibers/httpclient/AsyncHttpReq.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.httpclient;\n\nimport co.paralleluniverse.fibers.FiberAsync;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.io.IOException;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.concurrent.FutureCallback;\n\nabstract class AsyncHttpReq extends FiberAsync<HttpResponse, IOException> implements FutureCallback<HttpResponse> {\n    @Override\n    public HttpResponse run() throws IOException, SuspendExecution {\n        try {\n            return super.run();\n        } catch (InterruptedException e) {\n            throw new IOException(e);\n        }\n    }\n\n    @Override\n    public void completed(HttpResponse response) {\n        asyncCompleted(response);\n    }\n\n    @Override\n    public void failed(Exception ex) {\n        asyncFailed(ex);\n    }\n\n    @Override\n    public void cancelled() {\n        asyncFailed(new InterruptedException());\n    }\n}\n"
  },
  {
    "path": "comsat-httpclient/src/main/java/co/paralleluniverse/fibers/httpclient/DelegatingHttpResponse.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.httpclient;\n\nimport java.util.Locale;\nimport org.apache.http.Header;\nimport org.apache.http.HeaderIterator;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.ProtocolVersion;\nimport org.apache.http.StatusLine;\nimport org.apache.http.params.HttpParams;\n\n/**\n *\n * @author pron\n */\nclass DelegatingHttpResponse implements HttpResponse {\n    protected final HttpResponse response;\n\n    public DelegatingHttpResponse(HttpResponse response) {\n        this.response = response;\n    }\n    \n    @Override\n    public StatusLine getStatusLine() {\n        return response.getStatusLine();\n    }\n\n    @Override\n    public void setStatusLine(StatusLine statusline) {\n        response.setStatusLine(statusline);\n    }\n\n    @Override\n    public void setStatusLine(ProtocolVersion ver, int code) {\n        response.setStatusLine(ver, code);\n    }\n\n    @Override\n    public void setStatusLine(ProtocolVersion ver, int code, String reason) {\n        response.setStatusLine(ver, code, reason);\n    }\n\n    @Override\n    public void setStatusCode(int code) throws IllegalStateException {\n        response.setStatusCode(code);\n    }\n\n    @Override\n    public void setReasonPhrase(String reason) throws IllegalStateException {\n        response.setReasonPhrase(reason);\n    }\n\n    @Override\n    public HttpEntity getEntity() {\n        return response.getEntity();\n    }\n\n    @Override\n    public void setEntity(HttpEntity entity) {\n        response.setEntity(entity);\n    }\n\n    @Override\n    public Locale getLocale() {\n        return response.getLocale();\n    }\n\n    @Override\n    public void setLocale(Locale loc) {\n        response.setLocale(loc);\n    }\n\n    @Override\n    public ProtocolVersion getProtocolVersion() {\n        return response.getProtocolVersion();\n    }\n\n    @Override\n    public boolean containsHeader(String name) {\n        return response.containsHeader(name);\n    }\n\n    @Override\n    public Header[] getHeaders(String name) {\n        return response.getHeaders(name);\n    }\n\n    @Override\n    public Header getFirstHeader(String name) {\n        return response.getFirstHeader(name);\n    }\n\n    @Override\n    public Header getLastHeader(String name) {\n        return response.getLastHeader(name);\n    }\n\n    @Override\n    public Header[] getAllHeaders() {\n        return response.getAllHeaders();\n    }\n\n    @Override\n    public void addHeader(Header header) {\n        response.addHeader(header);\n    }\n\n    @Override\n    public void addHeader(String name, String value) {\n        response.addHeader(name, value);\n    }\n\n    @Override\n    public void setHeader(Header header) {\n        response.setHeader(header);\n    }\n\n    @Override\n    public void setHeader(String name, String value) {\n        response.setHeader(name, value);\n    }\n\n    @Override\n    public void setHeaders(Header[] headers) {\n        response.setHeaders(headers);\n    }\n\n    @Override\n    public void removeHeader(Header header) {\n        response.removeHeader(header);\n    }\n\n    @Override\n    public void removeHeaders(String name) {\n        response.removeHeaders(name);\n    }\n\n    @Override\n    public HeaderIterator headerIterator() {\n        return response.headerIterator();\n    }\n\n    @Override\n    public HeaderIterator headerIterator(String name) {\n        return response.headerIterator(name);\n    }\n\n    @Override\n    public HttpParams getParams() {\n        return response.getParams();\n    }\n\n    @Override\n    public void setParams(HttpParams params) {\n        response.setParams(params);\n    }\n\n    @Override\n    public int hashCode() {\n        return response.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return response.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return response.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-httpclient/src/main/java/co/paralleluniverse/fibers/httpclient/FiberHttpClient.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.httpclient;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\nimport java.lang.reflect.UndeclaredThrowableException;\nimport java.net.URI;\nimport java.util.List;\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpHost;\nimport org.apache.http.HttpRequest;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.ClientProtocolException;\nimport org.apache.http.client.HttpRequestRetryHandler;\nimport org.apache.http.client.ResponseHandler;\nimport org.apache.http.client.methods.CloseableHttpResponse;\nimport org.apache.http.client.methods.HttpUriRequest;\nimport org.apache.http.client.utils.URIUtils;\nimport org.apache.http.conn.ClientConnectionManager;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.nio.client.CloseableHttpAsyncClient;\nimport org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;\nimport org.apache.http.impl.nio.reactor.ExceptionEvent;\nimport org.apache.http.nio.reactor.IOReactor;\nimport org.apache.http.params.HttpParams;\nimport org.apache.http.protocol.HttpContext;\nimport org.apache.http.util.Args;\nimport org.apache.http.util.EntityUtils;\n\npublic class FiberHttpClient extends CloseableHttpClient {\n    private final Log log = LogFactory.getLog(getClass());\n    private final CloseableHttpAsyncClient client;\n    private final HttpRequestRetryHandler httpRequestRetryHandler;\n\n    private DefaultConnectingIOReactor ioreactor;\n\n    public FiberHttpClient(CloseableHttpAsyncClient client) {\n        this(client, null, null);\n    }\n\n    public FiberHttpClient(CloseableHttpAsyncClient client, IOReactor ioreactor) {\n        this(client, null, ioreactor);\n    }\n\n    public FiberHttpClient(CloseableHttpAsyncClient client, HttpRequestRetryHandler httpRequestRetryHandler) {\n        this(client, httpRequestRetryHandler, null);\n    }\n\n    public FiberHttpClient(CloseableHttpAsyncClient client, HttpRequestRetryHandler httpRequestRetryHandler, IOReactor ioreactor) {\n        this.client = client;\n        this.httpRequestRetryHandler = httpRequestRetryHandler;\n        if (ioreactor != null && ioreactor instanceof DefaultConnectingIOReactor)\n            this.ioreactor = (DefaultConnectingIOReactor) ioreactor;\n        if (!client.isRunning())\n            client.start();\n    }\n\n    @Override\n    public HttpParams getParams() {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public ClientConnectionManager getConnectionManager() {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    @Suspendable\n    protected final CloseableHttpResponse doExecute(final HttpHost target, final HttpRequest request, final HttpContext context) throws IOException, ClientProtocolException {\n        try {\n            for (int executionCount = 0;; executionCount++) {\n                try {\n                    final HttpResponse response = new AsyncHttpReq() {\n                        @Override\n                        protected void requestAsync() {\n                            client.execute(target, request, context, this);\n                        }\n                    }.run();\n                    return new CloseableHttpResponseWrapper(response);\n                } catch (IOException ex) {\n                    if (httpRequestRetryHandler != null && httpRequestRetryHandler.retryRequest(ex, executionCount, context)) {\n                        if (this.log.isInfoEnabled()) {\n                            this.log.info(\"I/O exception (\" + ex.getClass().getName()\n                                    + \") caught when processing request: \"\n                                    + ex.getMessage());\n                        }\n                        if (this.log.isDebugEnabled()) {\n                            this.log.debug(ex.getMessage(), ex);\n                        }\n                        this.log.info(\"Retrying request\");\n                    } else\n                        throw ex;\n                }\n            }\n        } catch (SuspendExecution e) {\n            throw new AssertionError();\n        } catch (IllegalStateException ise) {\n            if (ioreactor != null) {\n                final List<ExceptionEvent> events = ioreactor.getAuditLog();\n                if (events != null) {\n                    for (ExceptionEvent event : events) {\n                        final StringBuilder msg = new StringBuilder();\n                        msg.append(\"Apache Async HTTP Client I/O Reactor exception timestamp: \");\n                        msg.append(event.getTimestamp());\n                        if (event.getCause() != null) {\n                            msg.append(\", cause stacktrace:\\n\");\n                            final StringWriter sw = new StringWriter();\n                            final PrintWriter pw = new PrintWriter(sw);\n                            ise.getCause().printStackTrace(pw);\n                            msg.append(sw.toString());\n                        }\n                        this.log.fatal(msg.toString());\n                    }\n                }\n            }\n            throw ise;\n        }\n    }\n\n    private static class CloseableHttpResponseWrapper extends DelegatingHttpResponse implements CloseableHttpResponse {\n        public CloseableHttpResponseWrapper(HttpResponse response) {\n            super(response);\n        }\n\n        @Override\n        public void close() throws IOException {\n            final HttpEntity entity = this.response.getEntity();\n            EntityUtils.consume(entity);\n        }\n    }\n\n    @Override\n    public void close() throws IOException {\n        client.close();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Suspendable\n    public CloseableHttpResponse execute(final HttpUriRequest request, final HttpContext context) throws IOException, ClientProtocolException {\n        return doExecute(determineTarget(request), request, context);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Suspendable\n    public <T> T execute(final HttpUriRequest request, final ResponseHandler<? extends T> responseHandler, final HttpContext context) throws IOException, ClientProtocolException {\n        throw new UnsupportedOperationException();\n//        return execute(determineTarget(request), request, responseHandler, context);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Suspendable\n    public CloseableHttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException, ClientProtocolException {\n        Args.notNull(request, \"HTTP request\");\n        return doExecute(target, request, context);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Suspendable\n    public CloseableHttpResponse execute(HttpUriRequest request) throws IOException, ClientProtocolException {\n        return execute(request, (HttpContext) null);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Suspendable\n    public CloseableHttpResponse execute(HttpHost target, HttpRequest request) throws IOException, ClientProtocolException {\n        return execute(target, request, (HttpContext) null);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Suspendable\n    public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {\n        return execute(determineTarget(request), request, responseHandler, null);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Suspendable\n    public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {\n        return execute(target, request, responseHandler, null);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    @Override\n    @Suspendable\n    public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context) throws IOException, ClientProtocolException {\n        final HttpResponse response = doExecute(target, request, context);\n\n        final T result;\n        try {\n            result = responseHandler.handleResponse(response);\n        } catch (final Exception t) {\n            final HttpEntity entity = response.getEntity();\n            try {\n                EntityUtils.consume(entity);\n            } catch (final Exception t2) {\n                // Log this exception. The original exception is more\n                // important and will be thrown to the caller.\n                this.log.warn(\"Error consuming content after an exception.\", t2);\n            }\n            if (t instanceof RuntimeException) {\n                throw (RuntimeException) t;\n            }\n            if (t instanceof IOException) {\n                throw (IOException) t;\n            }\n            throw new UndeclaredThrowableException(t);\n        }\n\n        // Handling the response was successful. Ensure that the content has\n        // been fully consumed.\n        final HttpEntity entity = response.getEntity();\n        EntityUtils.consume(entity);\n        return result;\n    }\n\n    private static HttpHost determineTarget(final HttpUriRequest request) throws ClientProtocolException {\n        // A null target may be acceptable if there is a default target.\n        // Otherwise, the null target is detected in the director.\n        HttpHost target = null;\n\n        final URI requestURI = request.getURI();\n        if (requestURI.isAbsolute()) {\n            target = URIUtils.extractHost(requestURI);\n            if (target == null)\n                throw new ClientProtocolException(\"URI does not specify a valid host name: \" + requestURI);\n        }\n        return target;\n    }\n}\n"
  },
  {
    "path": "comsat-httpclient/src/main/java/co/paralleluniverse/fibers/httpclient/FiberHttpClientBuilder.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.httpclient;\n\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport java.util.Collection;\nimport javax.net.ssl.SSLContext;\nimport org.apache.http.ConnectionReuseStrategy;\nimport org.apache.http.Header;\nimport org.apache.http.HttpHost;\nimport org.apache.http.HttpRequestInterceptor;\nimport org.apache.http.HttpResponseInterceptor;\nimport org.apache.http.auth.AuthSchemeProvider;\nimport org.apache.http.client.AuthenticationStrategy;\nimport org.apache.http.client.CookieStore;\nimport org.apache.http.client.CredentialsProvider;\nimport org.apache.http.client.RedirectStrategy;\nimport org.apache.http.client.UserTokenHandler;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.config.ConnectionConfig;\nimport org.apache.http.config.Lookup;\nimport org.apache.http.conn.ConnectionKeepAliveStrategy;\nimport org.apache.http.conn.SchemePortResolver;\nimport org.apache.http.conn.routing.HttpRoutePlanner;\nimport org.apache.http.conn.ssl.X509HostnameVerifier;\nimport org.apache.http.cookie.CookieSpecProvider;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.nio.client.HttpAsyncClientBuilder;\nimport org.apache.http.impl.nio.reactor.IOReactorConfig;\nimport org.apache.http.nio.conn.NHttpClientConnectionManager;\nimport org.apache.http.nio.conn.SchemeIOSessionStrategy;\nimport org.apache.http.nio.reactor.IOReactor;\nimport org.apache.http.protocol.HttpProcessor;\n\n/**\n * Builder for creating fiber blocking httpClient.\n * The configuration properties are the same as those of HttpAsyncClientBuilder\n * @see HttpAsyncClientBuilder\n */\npublic class FiberHttpClientBuilder {\n    private final HttpAsyncClientBuilder builder;\n    private IOReactor ioreactor;\n\n    protected FiberHttpClientBuilder(HttpAsyncClientBuilder builder) {\n        this.builder = builder;\n    }\n\n    /**\n     * Creates Builder with one io thread.\n     * @return\n     */\n    public static FiberHttpClientBuilder create() {\n        return create(1);\n    }\n\n    /**\n     * @param ioThreadCount\n     * @return\n     */\n    public static FiberHttpClientBuilder create(int ioThreadCount) {\n        return new FiberHttpClientBuilder(HttpAsyncClientBuilder.create().\n                setThreadFactory(new ThreadFactoryBuilder().setDaemon(true).build()).\n                setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(ioThreadCount).build()));\n    }\n\n    public final FiberHttpClientBuilder setConnectionManager(NHttpClientConnectionManager connManager) {\n        builder.setConnectionManager(connManager);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setIOReactor(IOReactor ioreactor) {\n        this.ioreactor = ioreactor;\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setSchemePortResolver(SchemePortResolver schemePortResolver) {\n        builder.setSchemePortResolver(schemePortResolver);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setMaxConnTotal(int maxConnTotal) {\n        builder.setMaxConnTotal(maxConnTotal);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setMaxConnPerRoute(int maxConnPerRoute) {\n        builder.setMaxConnPerRoute(maxConnPerRoute);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setConnectionReuseStrategy(ConnectionReuseStrategy reuseStrategy) {\n        builder.setConnectionReuseStrategy(reuseStrategy);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setKeepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy) {\n        builder.setKeepAliveStrategy(keepAliveStrategy);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setUserTokenHandler(UserTokenHandler userTokenHandler) {\n        builder.setUserTokenHandler(userTokenHandler);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setTargetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy) {\n        builder.setTargetAuthenticationStrategy(targetAuthStrategy);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setProxyAuthenticationStrategy(AuthenticationStrategy proxyAuthStrategy) {\n        builder.setProxyAuthenticationStrategy(proxyAuthStrategy);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setHttpProcessor(HttpProcessor httpprocessor) {\n        builder.setHttpProcessor(httpprocessor);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder addInterceptorFirst(HttpResponseInterceptor itcp) {\n        builder.addInterceptorFirst(itcp);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder addInterceptorLast(HttpResponseInterceptor itcp) {\n        builder.addInterceptorLast(itcp);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder addInterceptorFirst(HttpRequestInterceptor itcp) {\n        builder.addInterceptorFirst(itcp);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder addInterceptorLast(HttpRequestInterceptor itcp) {\n        builder.addInterceptorLast(itcp);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setRoutePlanner(HttpRoutePlanner routePlanner) {\n        builder.setRoutePlanner(routePlanner);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setRedirectStrategy(RedirectStrategy redirectStrategy) {\n        builder.setRedirectStrategy(redirectStrategy);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setDefaultCookieStore(CookieStore cookieStore) {\n        builder.setDefaultCookieStore(cookieStore);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setDefaultCredentialsProvider(CredentialsProvider credentialsProvider) {\n        builder.setDefaultCredentialsProvider(credentialsProvider);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setDefaultAuthSchemeRegistry(Lookup<AuthSchemeProvider> authSchemeRegistry) {\n        builder.setDefaultAuthSchemeRegistry(authSchemeRegistry);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setDefaultCookieSpecRegistry(Lookup<CookieSpecProvider> cookieSpecRegistry) {\n        builder.setDefaultCookieSpecRegistry(cookieSpecRegistry);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setUserAgent(String userAgent) {\n        builder.setUserAgent(userAgent);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setProxy(HttpHost proxy) {\n        builder.setProxy(proxy);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setSSLStrategy(SchemeIOSessionStrategy strategy) {\n        builder.setSSLStrategy(strategy);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setSSLContext(SSLContext sslcontext) {\n        builder.setSSLContext(sslcontext);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setHostnameVerifier(X509HostnameVerifier hostnameVerifier) {\n        builder.setHostnameVerifier(hostnameVerifier);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setDefaultHeaders(Collection<? extends Header> defaultHeaders) {\n        builder.setDefaultHeaders(defaultHeaders);\n        return this;\n    }\n\n//    public final FiberHttpClientBuilder setDefaultIOReactorConfig(IOReactorConfig config) {\n//        builder.setDefaultIOReactorConfig(config);\n//        return this;\n//    }\n    public final FiberHttpClientBuilder setDefaultConnectionConfig(ConnectionConfig config) {\n        builder.setDefaultConnectionConfig(config);\n        return this;\n    }\n\n    public final FiberHttpClientBuilder setDefaultRequestConfig(RequestConfig config) {\n        builder.setDefaultRequestConfig(config);\n        return this;\n    }\n\n//    public final FiberHttpClientBuilder setThreadFactory(ThreadFactory threadFactory) {\n//        builder.setThreadFactory(threadFactory);\n//        return this;\n//    }\n    public final FiberHttpClientBuilder disableConnectionState() {\n        builder.disableConnectionState();\n        return this;\n    }\n\n    public final FiberHttpClientBuilder disableCookieManagement() {\n        builder.disableCookieManagement();\n        return this;\n    }\n\n    public final FiberHttpClientBuilder disableAuthCaching() {\n        builder.disableAuthCaching();\n        return this;\n    }\n\n    public final FiberHttpClientBuilder useSystemProperties() {\n        builder.useSystemProperties();\n        return this;\n    }\n\n    public FiberHttpClient build() {\n        final FiberHttpClient res =\n            ioreactor != null ?\n                new FiberHttpClient(builder.build(), ioreactor) :\n                new FiberHttpClient(builder.build());\n        return res;\n    }\n}\n"
  },
  {
    "path": "comsat-httpclient/src/main/resources/META-INF/suspendables",
    "content": "org.apache.http.impl.client.CloseableHttpClient.doExecute\norg.apache.http.impl.client.CloseableHttpClient.execute\n"
  },
  {
    "path": "comsat-httpclient/src/test/java/co/paralleluniverse/fibers/httpasyncclient/FiberHttpAsyncClientTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.httpasyncclient;\n\nimport co.paralleluniverse.embedded.containers.EmbeddedServer;\nimport co.paralleluniverse.embedded.containers.JettyServer;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.ParseException;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.impl.nio.client.CloseableHttpAsyncClient;\nimport org.apache.http.impl.nio.client.HttpAsyncClients;\nimport org.apache.http.util.EntityUtils;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class FiberHttpAsyncClientTest {\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {JettyServer.class},});\n    }\n    private final Class<? extends EmbeddedServer> cls;\n    private EmbeddedServer server;\n\n    public FiberHttpAsyncClientTest(Class<? extends EmbeddedServer> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        this.server = cls.newInstance();\n        server.addServlet(\"test\", TestServlet.class, \"/\");\n        server.start();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        server.stop();\n    }\n\n    @Test\n    public void testAsync() throws IOException, InterruptedException, ExecutionException, TimeoutException {\n        final int concurrencyLevel = 20;\n        // snippet client configuration\n        final CloseableHttpAsyncClient client = FiberCloseableHttpAsyncClient.wrap(HttpAsyncClients.\n                custom().\n                setMaxConnPerRoute(concurrencyLevel).\n                setMaxConnTotal(concurrencyLevel).\n                build());\n        client.start();\n        // end of snippet\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    // snippet future calls\n                    ArrayList<Future<HttpResponse>> futures = new ArrayList<>();\n                    for (int i = 0; i < concurrencyLevel; i++)\n                        futures.add(client.execute(new HttpGet(\"http://localhost:8080\"), null));\n                    for (Future<HttpResponse> future : futures)\n                        assertEquals(\"testGet\", EntityUtils.toString(future.get().getEntity()));\n                    // end of snippet\n                } catch (ExecutionException | IOException | ParseException ex) {\n                    fail(ex.getMessage());\n                }\n            }\n        }).start().join(5000, TimeUnit.MILLISECONDS);\n        client.close();\n    }\n\n    public static class TestServlet extends HttpServlet {\n        @Override\n        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Thread.sleep(500);\n                out.print(\"testGet\");\n            } catch (InterruptedException ex) {\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-httpclient/src/test/java/co/paralleluniverse/fibers/httpclient/FiberHttpClientBuilderTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.httpclient;\n\nimport co.paralleluniverse.embedded.containers.EmbeddedServer;\nimport co.paralleluniverse.embedded.containers.JettyServer;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class FiberHttpClientBuilderTest {\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {JettyServer.class},});\n    }\n    private final Class<? extends EmbeddedServer> cls;\n    private EmbeddedServer server;\n\n    public FiberHttpClientBuilderTest(Class<? extends EmbeddedServer> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        this.server = cls.newInstance();\n        server.addServlet(\"test\", TestServlet.class, \"/\");\n        server.start();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        server.stop();\n    }\n\n    @Test\n    public void testConcurrency() throws IOException, InterruptedException, Exception {\n        final int concurrencyLevel = 20;\n        // snippet client configuration\n        final CloseableHttpClient client = FiberHttpClientBuilder.\n                create(2). // use 2 io threads\n                setMaxConnPerRoute(concurrencyLevel).\n                setMaxConnTotal(concurrencyLevel).build();\n        // end of snippet\n        final CountDownLatch cdl = new CountDownLatch(concurrencyLevel);\n        for (int i = 0; i < concurrencyLevel; i++)\n            new Fiber<Void>(new SuspendableRunnable() {\n                @Override\n                public void run() throws SuspendExecution, InterruptedException {\n                    try {\n                        // snippet http call\n                        String response = client.execute(new HttpGet(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER);\n                        // end of snippet\n                        assertEquals(\"testGet\", response);\n                    } catch (IOException ex) {\n                        fail(ex.getMessage());\n                    } finally {\n                        cdl.countDown();\n                    }\n                }\n            }).start();\n        cdl.await(5000, TimeUnit.MILLISECONDS);\n        assertEquals(0, cdl.getCount());\n        client.close();\n    }\n\n    public static class TestServlet extends HttpServlet {\n        @Override\n        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Thread.sleep(500);\n                out.print(\"testGet\");\n            } catch (InterruptedException ex) {\n            }\n        }\n    }\n\n    private static final BasicResponseHandler BASIC_RESPONSE_HANDLER = new BasicResponseHandler();\n\n}\n"
  },
  {
    "path": "comsat-httpkit/project.clj",
    "content": "(def quasar-pulsar-version \"0.7.6\")\n\n(defproject co.paralleluniverse/comsat-httpkit \"0.7.1-SNAPSHOT\"\n  :description \"'httpkit' Quasar integration\"\n\n  :url \"https://github.com/puniverse/comsat\"\n\n  :scm {:name \"git\" :url \"https://github.com/puniverse/comsat\"}\n\n  :licenses [{:name \"Eclipse Public License\" :url \"http://www.eclipse.org/legal/epl-v10.html\"}\n             {:name \"GNU Lesser General Public License - v 3\" :url \"http://www.gnu.org/licenses/lgpl.html\"}]\n\n  :distribution :repo\n\n  :dependencies\n    [[org.clojure/clojure \"1.7.0\"]\n     [http-kit \"2.1.19\"]\n     [co.paralleluniverse/pulsar ~quasar-pulsar-version]]\n\n  :profiles {:dev {:dependencies\n    [[clj-http \"2.1.0\"]\n     [ch.qos.logback/logback-classic \"1.1.7\"]\n     [compojure \"1.5.0\"]\n     [ring/ring-jetty-adapter \"1.4.0\"]\n     [ring/ring-core \"1.4.0\"]]}}\n\n  :repositories [[\"snapshots\" \"http://oss.sonatype.org/content/repositories/snapshots\"]]\n\n  :java-agents [[co.paralleluniverse/quasar-core ~quasar-pulsar-version]]\n)\n"
  },
  {
    "path": "comsat-httpkit/src/co/paralleluniverse/fiber/httpkit/client.clj",
    "content": "; Pulsar: lightweight threads and Erlang-like actors for Clojure.\n; Copyright (C) 2015, Parallel Universe Software Co. All rights reserved.\n;\n; This program and the accompanying materials are dual-licensed under\n; either the terms of the Eclipse Public License v1.0 as published by\n; the Eclipse Foundation\n;\n;   or (per the licensee's choosing)\n;\n; under the terms of the GNU Lesser General Public License version 3.0\n; as published by the Free Software Foundation.\n\n(ns ^{:author \"circlespainter\"} co.paralleluniverse.fiber.httpkit.client\n  (:refer-clojure :exclude [get await])\n  (:require [org.httpkit.client :as hc]\n            [co.paralleluniverse.pulsar.core :refer [defsfn await]]))\n\n(defsfn request [req] (await hc/request req))\n\n(defmacro ^:private defreq [method]\n  `(defsfn\n     ~method\n     ([^String ~'url]\n       (await ~(symbol \"hc\" (name method)) ~'url {}))\n     ([^String ~'url ~'opts]\n       (await ~(symbol \"hc\" (name method)) ~'url ~'opts))))\n\n(defreq get)\n(defreq delete)\n(defreq head)\n(defreq post)\n(defreq put)\n(defreq options)\n(defreq patch)\n"
  },
  {
    "path": "comsat-httpkit/test/co/paralleluniverse/fiber/httpkit/client_test.clj",
    "content": "; Pulsar: lightweight threads and Erlang-like actors for Clojure.\n; Copyright (C) 2015, Parallel Universe Software Co. All rights reserved.\n;\n; This program and the accompanying materials are dual-licensed under\n; either the terms of the Eclipse Public License v1.0 as published by\n; the Eclipse Foundation\n;\n;   or (per the licensee's choosing)\n;\n; under the terms of the GNU Lesser General Public License version 3.0\n; as published by the Free Software Foundation.\n;\n;\n; Tests are ported from http-kit (http://www.http-kit.org/).\n; Copyright © 2012-2013 Feng Shen.\n; Distributed under the Apache License Version 2.0.\n;\n\n(ns ^{:author \"circlespainter\"} co.paralleluniverse.fiber.httpkit.client-test\n  (:use clojure.test\n        [ring.adapter.jetty :only [run-jetty]]\n        [org.httpkit.server :only [run-server]]\n        co.paralleluniverse.fiber.httpkit.test-util\n        [clojure.string :only [split]]\n        (compojure [core :only [defroutes GET PUT PATCH DELETE POST HEAD\n                                DELETE ANY context]]\n                   [handler :only [site]]\n                   [route :only [not-found]])\n        (clojure.tools [logging :only [info warn]]))\n  (:require [co.paralleluniverse.fiber.httpkit.client :as http]\n            [co.paralleluniverse.pulsar.core :refer [fiber]]\n            [org.httpkit.client :as http-orig]\n            [clj-http.client :as clj-http])\n  (:import java.nio.ByteBuffer\n           [org.httpkit HttpMethod HttpStatus HttpVersion]\n           [org.httpkit.client Decoder IRespListener]\n           (java.io InputStream FileInputStream)))\n\n(defroutes test-routes\n  (GET \"/get\" [] \"hello world\")\n  (POST \"/post\" [] \"hello world\")\n  (ANY \"/204\" [] {:status 204})\n  (ANY \"/redirect\" [] (fn [req]\n                        (let [total (-> req :params :total to-int)\n                              n (-> req :params :n to-int)\n                              code (to-int (or (-> req :params :code) \"302\"))]\n                          (if (>= n total)\n                            {:status 200 :body (-> req :request-method name)}\n                            {:status code\n                             :headers {\"location\" (str \"redirect?total=\" total \"&n=\" (inc n)\n                                                       \"&code=\" code)}}))))\n  (POST \"/multipart\" [] (fn [req] {:status 200}))\n  (PATCH \"/patch\" [] \"hello world\")\n  (POST \"/nested-param\" [] (fn [req] (pr-str (:params req))))\n  (ANY \"/method\" [] (fn [req]\n                      (let [m (:request-method req)]\n                        {:status 200\n                         :headers {\"x-method\" (pr-str m)}})))\n  (ANY \"/unicode\" [] (fn [req] (-> req :params :str)))\n  (DELETE \"/delete\" [] \"deleted\")\n  (ANY \"/ua\" [] (fn [req] ((-> req :headers) \"user-agent\")))\n  (GET \"/keep-alive\" [] (fn [req] (-> req :params :id)))\n  (GET \"/length\" [] (fn [req]\n                      (let [l (-> req :params :length to-int)]\n                        (subs const-string 0 l))))\n  (GET \"/multi-header\" [] (fn [req]\n                            {:status 200\n                             :headers {\"x-method\" [\"value1\", \"value2\"]\n                                       \"x-method2\" [\"value1\", \"value2\", \"value3\"]}}))\n  (GET \"/p\" [] (fn [req] (pr-str (:params req))))\n  (ANY \"/params\" [] (fn [req] (-> req :params :param1)))\n  (PUT \"/body\" [] (fn [req] {:body (:body req)\n                            :status 200\n                            :headers {\"content-type\" \"text/plain\"}}))\n  (GET \"/test-header\" [] (fn [{:keys [headers]}] (str (get headers \"test-header\")))))\n\n(use-fixtures :once\n  (fn [f]\n    (let [server (run-server (site test-routes) {:port 4347})\n          jetty (run-jetty (site test-routes) {:port 14347\n                                               :join? false\n                                               :ssl-port 9898\n                                               :ssl? true\n                                               :key-password \"123456\"\n                                               :keystore \"test-resources/ssl_keystore\"})]\n      (try (f) (finally (server) (.stop jetty))))))\n\n(comment\n  (defonce server1 (run-server (site test-routes) {:port 4347})))\n\n(deftest test-http-client\n  (doseq [host [\"http://127.0.0.1:4347\" \"http://127.0.0.1:14347\"]]\n    (is (= 200 (:status @(fiber (http/get (str host \"/get\"))))))\n    (is (= 404 (:status @(fiber (http/get (str host \"/404\"))))))\n    (is (= 200 (:status @(fiber (http/post (str host \"/post\"))))))\n    (is (= 200 (:status @(fiber (http/patch (str host \"/patch\"))))))\n    (is (= 200 (:status @(fiber (http/delete (str host \"/delete\"))))))\n    (is (= 200 (:status @(fiber (http/head (str host \"/get\"))))))\n    (is (= 200 (:status @(fiber (http/post (str host \"/post\"))))))\n    (is (= 404 (:status @(fiber (http/get (str host \"/404\"))))))\n    (is (= 200 (:status @(fiber (http/get (str host \"/get\"))))))\n    (is (= 404 (:status @(fiber (http/get (str host \"/404\"))))))\n    (is (= 204 (:status @(fiber (http/get (str host \"/204\"))))))\n    (let [url (str host \"/get\")]\n      (doseq [_ (range 0 10)]\n        (let [requests (doall (map (fn [u] (fiber (http/get u))) (repeat 20 url)))]\n          (doseq [r requests]\n            (is (= 200 (:status @r))))))\n      (doseq [_ (range 0 200)]\n        (is (= 200 (:status @(fiber (http/get url)))))))))\n\n\n(deftest test-unicode-encoding\n  (let [u \"高性能HTTPServer和Client\"\n        url \"http://127.0.0.1:4347/unicode\"\n        url1 (str url \"?str=\" (http-orig/url-encode u))\n        url2 (str \"http://127.0.0.1:4347/unicode?str=\" (http-orig/url-encode u))]\n    (is (= u (:body @(fiber (http/get url1)))))\n    (is (= u (:body (clj-http/get url1))))\n    (is (= u (:body @(fiber (http/post url {:form-params {:str u}})))))\n    (is (= u (:body (clj-http/post url {:form-params {:str u}}))))\n    (is (= u (:body @(fiber (http/get url2)))))\n    (is (= u (:body (clj-http/get url2))))))\n\n(defn- rand-keep-alive []\n  {:headers {\"Connection\" (cond  (> (rand-int 10) 5) \"Close\"\n                                 :else \"keep-alive\")}})\n\n(deftest test-keep-alive-does-not-messup\n  (let [url \"http://127.0.0.1:4347/keep-alive?id=\"]\n    (doseq [id (range 0 100)]\n      (is (= (str id) (:body @(fiber (http/get (str url id) (rand-keep-alive)))))))\n    (doseq [ids (partition 10 (range 0 300))]\n      (let [requests (doall (map (fn [id]\n                                   (fiber (http/get (str url id) (rand-keep-alive))))\n                                 ids))]\n        (doseq [r requests]\n          (is (= 200 (:status @r))))))))\n\n(deftest test-http-client-user-agent\n  (let [ua \"test-ua\"\n        url \"http://127.0.0.1:4347/ua\"]\n    (is (= ua (:body @(fiber (http/get url {:user-agent ua})))))\n    (is (= ua (:body @(fiber (http/post url {:user-agent ua})))))))\n\n(deftest test-query-string\n  (let [p1 \"this is a test\"\n        query-params {:query-params {:param1 p1}}]\n    (is (= p1 (:body @(fiber (http/get \"http://127.0.0.1:4347/params\" query-params)))))\n    (is (= p1 (:body @(fiber (http/post \"http://127.0.0.1:4347/params\" query-params)))))\n    (is (= p1 (:body @(fiber (http/get \"http://127.0.0.1:4347/params?a=b\" query-params)))))\n    (is (= p1 (:body @(fiber (http/post \"http://127.0.0.1:4347/params?a=b\" query-params)))))))\n\n(deftest test-jetty-204-decode-properly\n  ;; fix #52\n  (is (= 204 (:status @(fiber (http/get \"http://127.0.0.1:14347/204\" {:timeout 20})))))\n  (is (= 204 (:status @(fiber (http/post \"http://127.0.0.1:14347/204\" {:timeout 20}))))))\n\n(deftest test-http-client-form-params\n  (let [url \"http://127.0.0.1:4347/params\"\n        value \"value\"]\n    (is (= value (:body @(fiber (http/post url {:form-params {:param1 value}})))))))\n\n(deftest test-http-client-async\n  (let [url \"http://127.0.0.1:4347/params\"\n        p @(fiber (http/post url {:form-params {:param1 \"value\"}}))]\n    (is (= 200 (:status p)))\n    (is (= \"value\" (:body p))))) ;; wait\n\n(deftest test-max-body-filter\n  (is (:error @(fiber (http/get \"http://127.0.0.1:4347/get\"\n                                ;; only accept response's length < 3\n                                {:filter (http-orig/max-body-filter 3)}))))\n  (is (:status @(fiber (http/get \"http://127.0.0.1:4347/get\" ; should ok\n                                 {:filter (http-orig/max-body-filter 30000)})))))\n\n(deftest test-http-method\n  (doseq [m [:get :post :put :delete :head]]\n    (is (= m (-> @(fiber (http/request {:method m\n                                        :url \"http://127.0.0.1:4347/method\"}))\n                 :headers :x-method read-string)))))\n\n(deftest test-string-file-inputstream-body []\n  (let [length (+ (rand-int (* 1024 5)) 100)\n        file (gen-tempfile length \".txt\")\n        bodys [(subs const-string 0 length)    ;string\n               file                            ;file\n               (FileInputStream. file) ; inputstream\n               [(subs const-string 0 100) (subs const-string 100 length)] ; seqable\n               (ByteBuffer/wrap (.getBytes (subs const-string 0 length))) ; byteBuffer\n               ]]\n    (doseq [body bodys]\n      (is (= length (count (:body @(fiber (http/put \"http://127.0.0.1:4347/body\"\n                                                    {:body body})))))))))\n\n(deftest test-params\n  (let [url \"http://a.com/biti?wvr=5&topnav=1&wvr=5&mod=logo#ccc\"\n        params (-> @(fiber (http/get \"http://127.0.0.1:4347/p\"\n                                     {:query-params {:try false :rt \"url\" :to 1 :u url}}))\n                   :body read-string)]\n    (is (= url (:u params)))\n    (is (= \"false\" (:try params)))))\n\n(deftest test-output-coercion\n  (let [url \"http://localhost:4347/length?length=1024\"]\n    (let [body (:body @(fiber (http/get url {:as :text})))]\n      (is (string? body))\n      (is (= 1024 (count body))))\n    (let [body (:body @(fiber (http/get url)))] ; auto\n      (is (string? body)))\n    (let [body (:body @(fiber (http/get url {:as :auto})))] ; auto\n      (is (string? body)))\n    (let [body (:body @(fiber (http/get url {:as :stream})))]\n      (is (instance? InputStream body)))\n    (let [body (:body @(fiber (http/get url {:as :byte-array})))]\n      (is (= 1024 (alength body))))))\n\n(deftest test-https\n  (let [get-url (fn [length] (str \"https://localhost:9898/length?length=\" length))]\n    (doseq [_ (range 0 2)]\n      (doseq [length (repeatedly 40 (partial rand-int (* 4 1024)))]\n        (let [{:keys [body error _]} @(fiber (http/get (get-url length) {:insecure? true}))]\n          (if error (.printStackTrace error))\n          (is (= length (count body)))))\n      (doseq [length (repeatedly 40 (partial rand-int (* 4 1024)))]\n        (is (= length (-> @(fiber (http/get (get-url length)\n                                            {:insecure? true :keepalive -1}))\n                          :body count))))\n      (doseq [length (repeatedly 40 (partial rand-int (* 4 1024)))]\n        (is (= length (-> @(fiber (http/get (get-url length)\n                                            (assoc (rand-keep-alive) :insecure? true)))\n                          :body count)))))))\n\n;; https://github.com/http-kit/http-kit/issues/54\n(deftest test-nested-param\n  (let [url \"http://localhost:4347/nested-param\"\n        params {:card {:number \"4242424242424242\" :exp_month \"12\"}}]\n    (is (= params (read-string (:body @(fiber (http/post url {:form-params params}))))))\n    (is (= params (read-string (:body @(fiber (http/post\n                                               url\n                                               {:form-params {\"card[number]\" 4242424242424242\n                                                              \"card[exp_month]\" 12}}))))))\n    (is (= params (read-string (:body (clj-http/post url {:form-params params})))))))\n\n(deftest test-redirect\n  (let [url \"http://localhost:4347/redirect?total=5&n=0\"]\n    (is (:error @(fiber (http/get url {:max-redirects 3})))) ;; too many redirects\n    (is (= 200 (:status @(fiber (http/get url {:max-redirects 6})))))\n    (is (= 302 (:status @(fiber (http/get url {:follow-redirects false})))))\n    (is (= \"get\" (:body @(fiber (http/post url {:as :text}))))) ; should switch to get method\n    (is (= \"post\" (:body @(fiber (http/post (str url \"&code=307\") {:as :text}))))) ; should not change method\n  ))\n\n(deftest test-multipart\n  (is (= 200 (:status @(fiber (http/post \"http://localhost:4347/multipart\"\n                                         {:multipart [{:name \"comment\" :content \"httpkit's project.clj\"}\n                                                      {:name \"file\" :content (clojure.java.io/file \"project.clj\") :filename \"project.clj\"}]}))))))\n\n(deftest test-coerce-req\n  \"Headers should be the same regardless of multipart\"\n  (let [coerce-req #'org.httpkit.client/coerce-req\n        request {:basic-auth [\"user\" \"pass\"]}]\n    (is (= (keys (:headers (coerce-req request)))\n           (remove #(= % \"Content-Type\")\n                   (keys (:headers (coerce-req (assoc request :multipart [{:name \"foo\" :content \"bar\"}])))))))))\n\n(deftest test-header-multiple-values\n  (let [resp @(fiber (http/get \"http://localhost:4347/multi-header\" {:headers {\"foo\" [\"bar\" \"baz\"], \"eggplant\" \"quux\"}}))\n        resp2 (clj-http/get \"http://localhost:4347/multi-header\" {:headers {\"foo\" [\"bar\" \"baz\"], \"eggplant\" \"quux\"}})]\n    (is (= 200 (:status resp)))\n    (is (= 3 (count (split (-> resp :headers :x-method2) #\",\"))))\n    (is (= 2 (count (split (-> resp :headers :x-method) #\",\"))))\n    (is (= 200 (:status resp2)))))\n\n(deftest test-headers-stringified\n  (doseq [[sent expected] [[\"test\" \"test\"]\n                           [0 \"0\"]\n                           ['(0) \"0\"]\n                           ['(\"a\" \"b\") \"a,b\"]]]\n    (let [received (:body @(fiber (http/get \"http://localhost:4347/test-header\"\n                                            {:headers {\"test-header\" sent}})))]\n        (is (= received expected)))))\n\n(defn- utf8 [s] (ByteBuffer/wrap (.getBytes s \"UTF-8\")))\n\n(defn- decode\n  [method buffer]\n  (let [out (atom [])\n        listener (reify IRespListener\n                   (onInitialLineReceived [_ v s] (swap! out conj [:init v s]))\n                   (onHeadersReceived [_ hs]      (swap! out conj [:headers hs]))\n                   (onBodyReceived [_ buf n]      (swap! out conj [:body (into [] (take n buf))]))\n                   (onCompleted [_]               (swap! out conj [:completed]))\n                   (onThrowable [_ t]             (swap! out conj [:error t])))]\n    (.decode (Decoder. listener method) buffer)\n    @out))\n\n(deftest test-decode-partial-status-line\n  (are [method resp events] (= (decode method (utf8 resp)) events)\n    ;; The Status-Line is only parsed once there is a CRLF in the end.\n    HttpMethod/GET \"\" []\n    HttpMethod/GET \"HTTP/1.1\" []\n    HttpMethod/GET \"HTTP/1.1 200 OK\" []\n    HttpMethod/GET \"HTTP/1.1totally-broken-line\" []))\n\n(deftest test-decode-http-version\n  (are [method resp events] (= (decode method (utf8 resp)) events)\n    ;; HTTP version string is parsed.\n    HttpMethod/GET \"HTTP/1.1 200 OK\\r\\n\" [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]]\n    HttpMethod/GET \"HTTP/1.0 200 OK\\r\\n\" [[:init HttpVersion/HTTP_1_0 HttpStatus/OK]]))\n\n(deftest test-decode-empty-reason-phrase\n  (are [method resp events] (= (decode method (utf8 resp)) events)\n    ;; The Reason-Phrase (after Status-Code) may be omitted.\n    HttpMethod/GET \"HTTP/1.1 200 \\r\\n\" [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]]\n\n    ;; A Status-Line with no space after the Status-Code does not comply to the RFC 2616,\n    ;; but there is probably little reason not to allow it in the parser.\n    HttpMethod/GET \"HTTP/1.1 200\\r\\n\" [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]]))\n\n(deftest test-decode-empty-headers\n  (are [method resp events] (= (decode method (utf8 resp)) events)\n    ;; Empty headers\n    HttpMethod/GET \"HTTP/1.1 200 OK\\r\\n\\r\\n\" [[:init HttpVersion/HTTP_1_1 HttpStatus/OK] [:headers {}]]\n    HttpMethod/GET \"HTTP/1.1 200 \\r\\n\\r\\n\" [[:init HttpVersion/HTTP_1_1 HttpStatus/OK] [:headers {}]]))\n\n(deftest test-decode-headers\n  (are [method resp events] (= (decode method (utf8 resp)) events)\n    ;; Headers are not emitted before two consecutive CRLF's\n    HttpMethod/GET \"HTTP/1.1 200 OK\\r\\nContent-Length: 0\\r\\n\"\n    [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]]\n\n    ;; One header.\n    HttpMethod/GET \"HTTP/1.1 200 OK\\r\\nContent-Length: 0\\r\\n\\r\\n\"\n    [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]\n     [:headers {\"content-length\" \"0\"}]]))\n\n(deftest test-decode-body\n  (are [method resp events] (= (decode method (utf8 resp)) events)\n    ;; Empty body with zero content-length, no matter what bytes follow.\n    HttpMethod/GET \"HTTP/1.1 200 OK\\r\\nContent-Length: 0\\r\\n\\r\\n...\"\n    [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]\n     [:headers {\"content-length\" \"0\"}]]\n\n    ;; Expecting one byte, but no content available yet.\n    HttpMethod/GET \"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\n\"\n    [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]\n     [:headers {\"content-length\" \"1\"}]]\n\n     ;; One byte.\n     HttpMethod/GET \"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\n.\"\n     [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]\n      [:headers {\"content-length\" \"1\"}]\n      [:body [46]]]\n\n     ;; One byte. The rest is ignored.\n     HttpMethod/GET \"HTTP/1.1 200 OK\\r\\nContent-Length: 1\\r\\n\\r\\n...\"\n     [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]\n      [:headers {\"content-length\" \"1\"}]\n      [:body [46]]]\n\n    ;; The body is omitted for HEAD requests.\n    HttpMethod/HEAD \"HTTP/1.1 200 OK\\r\\nContent-Length: 3\\r\\n\\r\\n...\"\n    [[:init HttpVersion/HTTP_1_1 HttpStatus/OK]\n     [:headers {\"content-length\" \"3\"}]]))\n\n; Too long\n\n#_(defmacro bench [title & forms]\n  `(let [start# (. System (nanoTime))]\n     ~@forms\n     (println (str ~title \"Elapsed time: \"\n                   (/ (double (- (. System (nanoTime)) start#)) 1000000.0)\n                   \" msecs\"))))\n\n#_(deftest ^:benchmark performance-bench\n  (let [url \"http://127.0.0.1:14347/get\"]\n    ;; just for fun\n    (bench \"http-kit, concurrency 1, 3000 requests: \"\n           (doseq [_ (range 0 3000)] @(fiber (http/get url))))\n    (bench \"clj-http, concurrency 1, 3000 requests: \"\n           (doseq [_ (range 0 3000)] (clj-http/get url)))\n    (bench \"http-kit, concurrency 10, 3000 requests: \"\n           (doseq [_ (range 0 300)]\n             (let [requests (doall (map (fn [u] (fiber (http/get u)))\n                                        (repeat 10 url)))]\n               (doseq [r requests] @r))))) ; wait all finish\n  (let [url \"https://127.0.0.1:9898/get\"]\n    (bench \"http-kit, https, concurrency 1, 1000 requests: \"\n           (doseq [_ (range 0 1000)] @(fiber (http/get url {:insecure? true}))))\n    (bench \"http-kit, https, concurrency 10, 1000 requests: \"\n           (doseq [_ (range 0 100)]\n             (let [requests (doall (map (fn [u] (fiber (http/get u {:insecure? true})))\n                                        (repeat 10 url)))]\n               (doseq [r requests] @r)))) ; wait all finish\n    (bench \"clj-http, https, concurrency 1, 1000 requests: \"\n           (doseq [_ (range 0 1000)] (clj-http/get url {:insecure? true})))\n    (bench \"http-kit, https, keepalive disabled, concurrency 1, 1000 requests: \"\n           (doseq [_ (range 0 1000)] @(fiber (http/get url {:insecure? true\n                                                            :keepalive -1}))))))\n\n"
  },
  {
    "path": "comsat-httpkit/test/co/paralleluniverse/fiber/httpkit/test_util.clj",
    "content": "; Pulsar: lightweight threads and Erlang-like actors for Clojure.\n; Copyright (C) 2015, Parallel Universe Software Co. All rights reserved.\n;\n; This program and the accompanying materials are dual-licensed under\n; either the terms of the Eclipse Public License v1.0 as published by\n; the Eclipse Foundation\n;\n;   or (per the licensee's choosing)\n;\n; under the terms of the GNU Lesser General Public License version 3.0\n; as published by the Free Software Foundation.\n;\n;\n; Tests are ported from http-kit (http://www.http-kit.org/).\n; Copyright © 2012-2013 Feng Shen.\n; Distributed under the Apache License Version 2.0.\n;\n\n(ns ^{:author \"circlespainter\"} co.paralleluniverse.fiber.httpkit.test-util\n  (:use clojure.test)\n  (:import [java.io File FileOutputStream]))\n\n(defn- string-80k []\n  (apply str (map char\n                  (take (* 8 1024)                ; 80k\n                        (apply concat (repeat (range (int \\a) (int \\z))))))))\n;; [a..z]+\n(def const-string                       ; 8M string\n  (let [tmp (string-80k)]\n    (apply str (repeat 1024 tmp))))\n\n(defn ^File gen-tempfile\n  \"generate a tempfile, the file will be deleted before jvm shutdown\"\n  ([size extension]\n     (let [tmp (doto\n                   (File/createTempFile \"tmp_\" extension)\n                 (.deleteOnExit))]\n       (with-open [w (FileOutputStream. tmp)]\n         (.write w ^bytes (.getBytes (subs const-string 0 size))))\n       tmp)))\n\n(defn to-int [int-str] (Integer/valueOf int-str))\n"
  },
  {
    "path": "comsat-httpkit/test/logback-test.xml",
    "content": "<!-- for jetty -->\n\n<configuration scan=\"false\">\n\t<appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n\t\t<encoder>\n\t\t\t<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n\n\t\t\t</pattern>\n\t\t</encoder>\n\t</appender>\n\t<root level=\"INFO\">\n\t\t<appender-ref ref=\"STDOUT\" />\n\t</root>\n</configuration>"
  },
  {
    "path": "comsat-jax-rs-client/src/main/java/co/paralleluniverse/fibers/ws/rs/client/AsyncClientBuilder.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.ws.rs.client;\n\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport java.security.KeyStore;\nimport java.util.Map;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.SSLContext;\nimport javax.ws.rs.client.Client;\nimport javax.ws.rs.client.ClientBuilder;\nimport javax.ws.rs.core.Configuration;\nimport org.glassfish.jersey.client.ClientConfig;\nimport org.glassfish.jersey.client.ClientProperties;\nimport org.glassfish.jersey.jetty.connector.JettyConnectorProvider;\nimport org.glassfish.jersey.spi.ExecutorServiceProvider;\n\n/**\n * Main entry point to the client API used to bootstrap Client instances that integrate with Quasar fibers.\n */\npublic class AsyncClientBuilder extends ClientBuilder {\n    private final ClientBuilder clientBuilder;\n\n    protected AsyncClientBuilder(ClientBuilder clientBuilder) {\n        this.clientBuilder = clientBuilder;\n    }\n\n    /**\n     * Create a new {@code ClientBuilder} instance using the default client builder\n     * implementation class provided by the JAX-RS implementation provider.\n     *\n     * @return new client builder instance.\n     */\n    public static ClientBuilder newBuilder() {\n        return new AsyncClientBuilder(ClientBuilder.newBuilder().withConfig(addDefaultConfigurations(null)));\n    }\n\n    /**\n     * Create a new {@link Client} instance using the default client builder implementation\n     * class provided by the JAX-RS implementation provider.\n     *\n     * @return new client instance.\n     */\n    public static Client newClient() {\n        return newClient(null);\n    }\n\n    /**\n     * Create a new custom-configured {@link Client} instance using the default client builder\n     * implementation class provided by the JAX-RS implementation provider.\n     *\n     * @param configuration data used to provide initial configuration for the new client instance.\n     * @return a new, configured, client instance.\n     */\n    public static Client newClient(Configuration configuration) {\n        return new FiberClient(ClientBuilder.newClient(addDefaultConfigurations(configuration)));\n    }\n\n    private static ClientConfig addDefaultConfigurations(Configuration configuration) {\n        // currently there is no usage with the singleThreadPool variable due to jersey bug. See below.\n        final ExecutorServiceProvider singleThreadPool = new ExecutorServiceProvider() {\n            private ExecutorService tp = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setDaemon(true).setNameFormat(\"jersey-puniverse-single-worker-%d\").build());\n\n            @Override\n            public ExecutorService getExecutorService() {\n                return tp;\n            }\n\n            @Override\n            public void dispose(ExecutorService es) {\n            }\n        };\n        final ClientConfig config = new ClientConfig().\n                // This is commented since, jersey has major problem (since ~2.5) - it blocks the calling thread !!!\n                // When this bug will be fixed we should uncomment this line in order to enable a lot of concurrent open requsets                \n                //                register(singleThreadPool, RequestExecutorProvider.class).\n                property(ClientProperties.ASYNC_THREADPOOL_SIZE, 20);\n        if (configuration != null)\n            config.loadFrom(configuration);\n        if (config.getConnectorProvider() == null)\n            config.connectorProvider(new JettyConnectorProvider());\n        return config;\n    }\n\n    @Override\n    public Client build() {\n        return new FiberClient(clientBuilder.build());\n    }\n\n    @Override\n    public ClientBuilder withConfig(Configuration config) {\n        clientBuilder.withConfig(addDefaultConfigurations(config));\n        return this;\n    }\n\n    @Override\n    public ClientBuilder sslContext(SSLContext sslContext) {\n        clientBuilder.sslContext(sslContext);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder keyStore(KeyStore keyStore, char[] password) {\n        clientBuilder.keyStore(keyStore, password);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder keyStore(KeyStore keyStore, String password) {\n        clientBuilder.keyStore(keyStore, password);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder trustStore(KeyStore trustStore) {\n        clientBuilder.trustStore(trustStore);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder hostnameVerifier(HostnameVerifier verifier) {\n        clientBuilder.hostnameVerifier(verifier);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder property(String name, Object value) {\n        clientBuilder.property(name, value);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder register(Class<?> componentClass) {\n        clientBuilder.register(componentClass);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder register(Class<?> componentClass, int priority) {\n        clientBuilder.register(componentClass, priority);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder register(Class<?> componentClass, Class<?>... contracts) {\n        clientBuilder.register(componentClass, contracts);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {\n        clientBuilder.register(componentClass, contracts);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder register(Object component) {\n        clientBuilder.register(component);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder register(Object component, int priority) {\n        clientBuilder.register(component, priority);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder register(Object component, Class<?>... contracts) {\n        clientBuilder.register(component, contracts);\n        return this;\n    }\n\n    @Override\n    public ClientBuilder register(Object component, Map<Class<?>, Integer> contracts) {\n        clientBuilder.register(component, contracts);\n        return this;\n    }\n\n    @Override\n    public Configuration getConfiguration() {\n        return clientBuilder.getConfiguration();\n    }\n\n    @Override\n    public int hashCode() {\n        return clientBuilder.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return clientBuilder.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return clientBuilder.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jax-rs-client/src/main/java/co/paralleluniverse/fibers/ws/rs/client/AsyncRs.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.ws.rs.client;\n\nimport co.paralleluniverse.fibers.FiberAsync;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport javax.ws.rs.client.InvocationCallback;\n\nabstract class AsyncRs<ResponseType> extends FiberAsync<ResponseType, RuntimeException> implements InvocationCallback<ResponseType> {\n    @Override\n    public ResponseType run() throws SuspendExecution {\n        try {\n            final ResponseType run = super.run();\n            return run;\n        } catch (InterruptedException e) {\n            throw new AssertionError(e);\n        }\n    }\n\n    @Override\n    public void completed(ResponseType response) {\n        asyncCompleted(response);\n    }\n\n    @Override\n    public void failed(Throwable throwable) {\n        asyncFailed(throwable);\n    }\n}\n"
  },
  {
    "path": "comsat-jax-rs-client/src/main/java/co/paralleluniverse/fibers/ws/rs/client/FiberBuilder.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.ws.rs.client;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.util.Locale;\nimport javax.ws.rs.client.AsyncInvoker;\nimport javax.ws.rs.client.Entity;\nimport javax.ws.rs.client.Invocation;\nimport javax.ws.rs.client.Invocation.Builder;\nimport javax.ws.rs.core.CacheControl;\nimport javax.ws.rs.core.Cookie;\nimport javax.ws.rs.core.GenericType;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.MultivaluedMap;\nimport javax.ws.rs.core.Response;\n\nclass FiberBuilder implements Invocation.Builder {\n    private static final String GET = \"GET\";\n    private static final String PUT = \"PUT\";\n    private static final String POST = \"POST\";\n    private static final String DELETE = \"DELETE\";\n    private static final String HEAD = \"HEAD\";\n    private static final String OPTIONS = \"OPTIONS\";\n    private static final String TRACE = \"TRACE\";\n    final javax.ws.rs.client.Invocation.Builder builder;\n\n    public FiberBuilder(Builder builder) {\n        this.builder = builder;\n    }\n\n    // Wrap FiberInvocation\n    @Override\n    public Invocation build(String method) {\n        return new FiberInvocation(builder.build(method));\n    }\n\n    @Override\n    public Invocation build(String method, Entity<?> entity) {\n        return new FiberInvocation(builder.build(method, entity));\n    }\n\n    @Override\n    public Invocation buildGet() {\n        return new FiberInvocation(builder.buildGet());\n    }\n\n    @Override\n    public Invocation buildDelete() {\n        return new FiberInvocation(builder.buildDelete());\n    }\n\n    @Override\n    public Invocation buildPost(Entity<?> entity) {\n        return new FiberInvocation(builder.buildPost(entity));\n    }\n\n    @Override\n    public Invocation buildPut(Entity<?> entity) {\n        return new FiberInvocation(builder.buildPut(entity));\n    }\n\n    // Return this instead of builder\n    @Override\n    public Builder accept(String... mediaTypes) {\n        builder.accept(mediaTypes);\n        return this;\n    }\n\n    @Override\n    public Builder accept(MediaType... mediaTypes) {\n        builder.accept(mediaTypes);\n        return this;\n    }\n\n    @Override\n    public Builder acceptLanguage(Locale... locales) {\n        builder.acceptLanguage(locales);\n        return this;\n    }\n\n    @Override\n    public Builder acceptLanguage(String... locales) {\n        builder.acceptLanguage(locales);\n        return this;\n    }\n\n    @Override\n    public Builder acceptEncoding(String... encodings) {\n        builder.acceptEncoding(encodings);\n        return this;\n    }\n\n    @Override\n    public Builder cookie(Cookie cookie) {\n        builder.cookie(cookie);\n        return this;\n    }\n\n    @Override\n    public Builder cookie(String name, String value) {\n        builder.cookie(name, value);\n        return this;\n    }\n\n    @Override\n    public Builder cacheControl(CacheControl cacheControl) {\n        builder.cacheControl(cacheControl);\n        return this;\n    }\n\n    @Override\n    public Builder header(String name, Object value) {\n        builder.header(name, value);\n        return this;\n    }\n\n    @Override\n    public Builder headers(MultivaluedMap<String, Object> headers) {\n        builder.headers(headers);\n        return this;\n    }\n\n    @Override\n    public Builder property(String name, Object value) {\n        builder.property(name, value);\n        return this;\n    }\n\n    // Suspendable Functions\n    @Override\n    @Suspendable\n    public Response get() {\n        return method(GET);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T get(Class<T> responseType) {\n        return method(GET,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T get(GenericType<T> responseType) {\n        return method(GET,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public Response put(final Entity<?> entity) {\n        return method(PUT,entity);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T put(final Entity<?> entity, Class<T> responseType) {\n        return method(PUT,entity,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T put(final Entity<?> entity, GenericType<T> responseType) {\n        return method(PUT,entity,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public Response post(final Entity<?> entity) {\n        return method(POST,entity);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T post(final Entity<?> entity, Class<T> responseType) {\n        return method(POST,entity,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T post(final Entity<?> entity, GenericType<T> responseType) {\n        return method(POST,entity,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public Response delete() {\n        return method(DELETE);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T delete(Class<T> responseType) {\n        return method(DELETE,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T delete(GenericType<T> responseType) {\n        return method(DELETE,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public Response head() {\n        return method(HEAD);\n    }\n\n    @Override\n    @Suspendable\n    public Response options() {\n        return method(OPTIONS);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T options(Class<T> responseType) {\n        return method(OPTIONS,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T options(GenericType<T> responseType) {\n        return method(OPTIONS,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public Response trace() {\n        return method(TRACE);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T trace(Class<T> responseType) {\n        return method(TRACE,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public <T> T trace(GenericType<T> responseType) {\n        return method(TRACE,responseType);\n    }\n\n    @Override\n    @Suspendable\n    public Response method(final String name) {\n        try {\n            return new AsyncRs<Response>() {\n                @Override\n                protected void requestAsync() {\n                    builder.async().method(name, this);\n                }\n            }.run();\n        } catch (SuspendExecution ex) {\n            throw new AssertionError(ex);\n        }\n    }\n\n    @Override\n    @Suspendable\n    public <T> T method(final String name, Class<T> responseType) {\n        try {\n            return new AsyncRs<Response>() {\n                @Override\n                protected void requestAsync() {\n                    builder.async().method(name, this);\n                }\n            }.run().readEntity(responseType);\n        } catch (SuspendExecution ex) {\n            throw new AssertionError(ex);\n        }\n    }\n\n    @Override\n    @Suspendable\n    public <T> T method(String name, GenericType<T> responseType) {\n        return this.method(name, (Class<T>)responseType.getRawType());\n    }\n\n    @Override\n    @Suspendable\n    public Response method(final String name, final Entity<?> entity) {\n        try {\n            return new AsyncRs<Response>() {\n                @Override\n                protected void requestAsync() {\n                    builder.async().method(name, entity, this);\n                }\n            }.run();\n        } catch (SuspendExecution ex) {\n            throw new AssertionError(ex);\n        }\n    }\n\n    @Override\n    @Suspendable\n    public <T> T method(final String name, final Entity<?> entity, Class<T> responseType) {\n        try {\n            return new AsyncRs<T>() {\n                @Override\n                protected void requestAsync() {\n                    builder.async().method(name, entity, this);\n                }\n            }.run();\n        } catch (SuspendExecution ex) {\n            throw new AssertionError(ex);\n        }\n    }\n\n    @Override\n    @Suspendable\n    public <T> T method(final String name, final Entity<?> entity, GenericType<T> responseType) {\n        try {\n            return new AsyncRs<T>() {\n                @Override\n                protected void requestAsync() {\n                    builder.async().method(name, entity, this);\n                }\n            }.run();\n        } catch (SuspendExecution ex) {\n            throw new AssertionError(ex);\n        }\n    }\n\n    // Delegations\n    @Override\n    public AsyncInvoker async() {\n        return builder.async();\n    }\n\n    @Override\n    public int hashCode() {\n        return builder.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return builder.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jax-rs-client/src/main/java/co/paralleluniverse/fibers/ws/rs/client/FiberClient.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.ws.rs.client;\n\nimport java.net.URI;\nimport java.util.Map;\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.SSLContext;\nimport javax.ws.rs.client.Client;\nimport javax.ws.rs.client.Invocation.Builder;\nimport javax.ws.rs.client.WebTarget;\nimport javax.ws.rs.core.Configuration;\nimport javax.ws.rs.core.Link;\nimport javax.ws.rs.core.UriBuilder;\n\nclass FiberClient implements Client {\n    private final Client client;\n\n    public FiberClient(Client client) {\n        client.target(\"http://www.dummyCallLoadLazyObjects.com\").request().buildGet();\n        this.client = client;\n    }\n\n    // Wrap webTarget\n    @Override\n    public WebTarget target(String uri) {\n        return new FiberWebTarget(client.target(uri));\n    }\n\n    @Override\n    public WebTarget target(URI uri) {\n        return new FiberWebTarget(client.target(uri));\n    }\n\n    @Override\n    public WebTarget target(UriBuilder uriBuilder) {\n        return new FiberWebTarget(client.target(uriBuilder));\n    }\n\n    @Override\n    public WebTarget target(Link link) {\n        return new FiberWebTarget(client.target(link));\n    }\n\n    // Wrap builder\n    @Override\n    public Builder invocation(Link link) {\n        return new FiberBuilder(client.invocation(link));\n    }\n\n    // return this\n    @Override\n    public Client property(String name, Object value) {\n        client.property(name, value);\n        return this;\n    }\n\n    @Override\n    public Client register(Class<?> componentClass) {\n        client.register(componentClass);\n        return this;\n    }\n\n    @Override\n    public Client register(Class<?> componentClass, int priority) {\n        client.register(componentClass, priority);\n        return this;\n    }\n\n    @Override\n    public Client register(Class<?> componentClass, Class<?>... contracts) {\n        client.register(componentClass, contracts);\n        return this;\n    }\n\n    @Override\n    public Client register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {\n        client.register(componentClass, contracts);\n        return this;\n    }\n\n    @Override\n    public Client register(Object component) {\n        client.register(component);\n        return this;\n    }\n\n    @Override\n    public Client register(Object component, int priority) {\n        client.register(component, priority);\n        return this;\n    }\n\n    @Override\n    public Client register(Object component, Class<?>... contracts) {\n        client.register(component, contracts);\n        return this;\n    }\n\n    @Override\n    public Client register(Object component, Map<Class<?>, Integer> contracts) {\n        client.register(component, contracts);\n        return this;\n    }\n\n    // Delegations\n    @Override\n    public SSLContext getSslContext() {\n        return client.getSslContext();\n    }\n\n    @Override\n    public HostnameVerifier getHostnameVerifier() {\n        return client.getHostnameVerifier();\n    }\n\n    @Override\n    public Configuration getConfiguration() {\n        return client.getConfiguration();\n    }\n\n    @Override\n    public void close() {\n        client.close();\n    }\n\n    @Override\n    public int hashCode() {\n        return client.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return client.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return client.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jax-rs-client/src/main/java/co/paralleluniverse/fibers/ws/rs/client/FiberInvocation.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.ws.rs.client;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.strands.SettableFuture;\nimport java.util.concurrent.Future;\nimport javax.ws.rs.client.Invocation;\nimport javax.ws.rs.client.InvocationCallback;\nimport javax.ws.rs.core.GenericType;\nimport javax.ws.rs.core.Response;\n\nclass FiberInvocation implements Invocation {\n    private final Invocation invocation;\n\n    public FiberInvocation(Invocation invocation) {\n        this.invocation = invocation;\n    }\n\n    @Override\n    public FiberInvocation property(String name, Object value) {\n        invocation.property(name, value);\n        return this;\n    }\n\n    @Override\n    @Suspendable\n    public Response invoke() {\n        try {\n            return new AsyncRs<Response>() {\n                @Override\n                protected void requestAsync() {\n                    invocation.submit(this);\n                }\n            }.run();\n        } catch (SuspendExecution ex) {\n            throw new AssertionError(ex);\n        }\n    }\n\n    @Override\n    @Suspendable\n    public <T> T invoke(Class<T> responseType) {\n        try {\n            return new AsyncRs<T>() {\n                @Override\n                protected void requestAsync() {\n                    invocation.submit(this);\n                }\n            }.run();\n        } catch (SuspendExecution ex) {\n            throw new AssertionError(ex);\n        }\n    }\n\n    @Override\n    @Suspendable\n    public <T> T invoke(GenericType<T> responseType) {\n        try {\n            return new AsyncRs<T>() {\n                @Override\n                protected void requestAsync() {\n                    invocation.submit(this);\n                }\n            }.run();\n        } catch (SuspendExecution ex) {\n            throw new AssertionError(ex);\n        }\n    }\n\n    @Override\n    public Future<Response> submit() {\n        final SettableFuture<Response> responseFuture = new SettableFuture<>();\n        invocation.submit(new InvocationCallback<Response>() {\n\n            @Override\n            public void completed(Response response) {\n                responseFuture.set(response);\n            }\n\n            @Override\n            public void failed(Throwable throwable) {\n                responseFuture.setException(throwable);\n            }\n        });                \n        return responseFuture;\n    }\n\n    @Override\n    public <T> Future<T> submit(Class<T> responseType) {\n        final SettableFuture<T> responseFuture = new SettableFuture<>();\n        invocation.submit(new InvocationCallback<T>() {\n\n            @Override\n            public void completed(T response) {\n                responseFuture.set(response);\n            }\n\n            @Override\n            public void failed(Throwable throwable) {\n                responseFuture.setException(throwable);\n            }\n        });                \n        return responseFuture;\n    }\n\n    @Override\n    public <T> Future<T> submit(GenericType<T> responseType) {\n        final SettableFuture<T> responseFuture = new SettableFuture<>();\n        invocation.submit(new InvocationCallback<T>() {\n\n            @Override\n            public void completed(T response) {\n                responseFuture.set(response);\n            }\n\n            @Override\n            public void failed(Throwable throwable) {\n                responseFuture.setException(throwable);\n            }\n        });                \n        return responseFuture;\n    }\n\n    @Override\n    public <T> Future<T> submit(final InvocationCallback<T> callback) {\n        final SettableFuture<T> responseFuture = new SettableFuture<>();\n        invocation.submit(new InvocationCallback<T>() {\n\n            @Override\n            public void completed(T response) {\n                responseFuture.set(response);\n                callback.completed(response);\n            }\n\n            @Override\n            public void failed(Throwable throwable) {\n                responseFuture.setException(throwable);\n                callback.failed(throwable);\n            }\n        });                \n        return responseFuture;\n    }\n\n    @Override\n    public int hashCode() {\n        return invocation.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return invocation.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return invocation.toString();\n    }\n    \n}\n"
  },
  {
    "path": "comsat-jax-rs-client/src/main/java/co/paralleluniverse/fibers/ws/rs/client/FiberWebTarget.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.ws.rs.client;\n\nimport java.net.URI;\nimport java.util.Map;\nimport javax.ws.rs.client.Invocation.Builder;\nimport javax.ws.rs.client.WebTarget;\nimport javax.ws.rs.core.Configuration;\nimport javax.ws.rs.core.MediaType;\nimport javax.ws.rs.core.UriBuilder;\n\nclass FiberWebTarget implements WebTarget {\n    private final WebTarget webTarget;\n\n    public FiberWebTarget(WebTarget webTarget) {\n        this.webTarget = webTarget;\n    }\n\n    private static Builder wrap(Builder builder) {\n        return new FiberBuilder(builder);\n    }\n    \n    private WebTarget wrap(WebTarget webTarget) {\n        if (webTarget instanceof FiberWebTarget && ((FiberWebTarget) webTarget).webTarget == this.webTarget)\n            return this;\n        return new FiberWebTarget(webTarget);\n    }\n    \n    @Override\n    public Builder request() {\n        return wrap(webTarget.request());\n    }\n\n    @Override\n    public Builder request(String... acceptedResponseTypes) {\n        return wrap(webTarget.request(acceptedResponseTypes));\n    }\n\n    @Override\n    public Builder request(MediaType... acceptedResponseTypes) {\n        return wrap(webTarget.request(acceptedResponseTypes));\n    }\n\n    @Override\n    public WebTarget path(String path) {\n        return wrap(webTarget.path(path));\n    }\n\n    @Override\n    public WebTarget resolveTemplate(String name, Object value) {\n        return wrap(webTarget.resolveTemplate(name, value));\n    }\n\n    @Override\n    public WebTarget resolveTemplate(String name, Object value, boolean encodeSlashInPath) {\n        return wrap(webTarget.resolveTemplate(name, value, encodeSlashInPath));\n    }\n\n    @Override\n    public WebTarget resolveTemplateFromEncoded(String name, Object value) {\n        return wrap(webTarget.resolveTemplateFromEncoded(name, value));\n    }\n\n    @Override\n    public WebTarget resolveTemplates(Map<String, Object> templateValues) {\n        return wrap(webTarget.resolveTemplates(templateValues));\n    }\n\n    @Override\n    public WebTarget resolveTemplates(Map<String, Object> templateValues, boolean encodeSlashInPath) {\n        return wrap(webTarget.resolveTemplates(templateValues, encodeSlashInPath));\n    }\n\n    @Override\n    public WebTarget resolveTemplatesFromEncoded(Map<String, Object> templateValues) {\n        return wrap(webTarget.resolveTemplatesFromEncoded(templateValues));\n    }\n\n    @Override\n    public WebTarget matrixParam(String name, Object... values) {\n        return wrap(webTarget.matrixParam(name, values));\n    }\n\n    @Override\n    public WebTarget queryParam(String name, Object... values) {\n        return wrap(webTarget.queryParam(name, values));\n    }\n\n    @Override\n    public WebTarget property(String name, Object value) {\n        webTarget.property(name, value);\n        return this;\n    }\n\n    @Override\n    public WebTarget register(Class<?> componentClass) {\n        webTarget.register(componentClass);\n        return this;\n    }\n\n    @Override\n    public WebTarget register(Class<?> componentClass, int priority) {\n        webTarget.register(componentClass, priority);\n        return this;\n    }\n\n    @Override\n    public WebTarget register(Class<?> componentClass, Class<?>... contracts) {\n        webTarget.register(componentClass, contracts);\n        return this;\n    }\n\n    @Override\n    public WebTarget register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {\n        webTarget.register(componentClass, contracts);\n        return this;\n    }\n\n    @Override\n    public WebTarget register(Object component) {\n        webTarget.register(component);\n        return this;\n    }\n\n    @Override\n    public WebTarget register(Object component, int priority) {\n        webTarget.register(component, priority);\n        return this;\n    }\n\n    @Override\n    public WebTarget register(Object component, Class<?>... contracts) {\n        webTarget.register(component, contracts);\n        return this;\n    }\n\n    @Override\n    public WebTarget register(Object component, Map<Class<?>, Integer> contracts) {\n        webTarget.register(component, contracts);\n        return this;\n    }\n\n    // Delegations\n    @Override\n    public URI getUri() {\n        return webTarget.getUri();\n    }\n\n    @Override\n    public UriBuilder getUriBuilder() {\n        return webTarget.getUriBuilder();\n    }\n\n    @Override\n    public Configuration getConfiguration() {\n        return webTarget.getConfiguration();\n    }\n\n    @Override\n    public int hashCode() {\n        return webTarget.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return webTarget.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return webTarget.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jax-rs-client/src/main/java/co/paralleluniverse/fibers/ws/rs/client/package-info.java",
    "content": "/*\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n * \n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *  \n *   or (per the licensee's choosing)\n *  \n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/**\n * {@link javax.ws.rs.client JAX-RS Client} Integration for Quasar Fibers\n */\npackage co.paralleluniverse.fibers.ws.rs.client;\n"
  },
  {
    "path": "comsat-jax-rs-client/src/main/resources/META-INF/suspendable-supers",
    "content": "javax.ws.rs.client.SyncInvoker.get\njavax.ws.rs.client.SyncInvoker.put\njavax.ws.rs.client.SyncInvoker.post\njavax.ws.rs.client.SyncInvoker.delete\njavax.ws.rs.client.SyncInvoker.head\njavax.ws.rs.client.SyncInvoker.options\njavax.ws.rs.client.SyncInvoker.trace\njavax.ws.rs.client.SyncInvoker.method\njavax.ws.rs.client.Invocation.invoke"
  },
  {
    "path": "comsat-jax-rs-client/src/test/java/co/paralleluniverse/fibers/ws/rs/client/AsyncClientBuilderTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.ws.rs.client;\n\nimport co.paralleluniverse.concurrent.util.ThreadUtil;\nimport co.paralleluniverse.embedded.containers.EmbeddedServer;\nimport co.paralleluniverse.embedded.containers.JettyServer;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.ws.rs.client.AsyncClientBuilder;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.ws.rs.client.Client;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class AsyncClientBuilderTest {\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {JettyServer.class},});\n    }\n    private final Class<? extends EmbeddedServer> cls;\n    private EmbeddedServer server;\n\n    public AsyncClientBuilderTest(Class<? extends EmbeddedServer> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        this.server = cls.newInstance();\n        server.addServlet(\"test\", TestServlet.class, \"/\");\n        server.start();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        server.stop();\n    }\n\n    @Test\n    public void testConcurrency() throws IOException, InterruptedException, Exception {\n        final int concurrencyLevel = 40;\n        // snippet client creation\n        final Client client = AsyncClientBuilder.newBuilder().build();\n        // end of snippet\n        final CountDownLatch cdl = new CountDownLatch(concurrencyLevel);\n        for (int i = 0; i < concurrencyLevel; i++)\n            new Fiber<Void>(new SuspendableRunnable() {\n                @Override\n                public void run() throws SuspendExecution, InterruptedException {\n                    // snippet http call\n                    String response = client.target(\"http://localhost:8080\").request().get(String.class);\n                    // end of snippet\n                    assertEquals(\"testGet\", response);\n                    System.out.println(\"done \"+cdl.getCount());\n                    cdl.countDown();\n                }\n            }).start();\n        cdl.await(4000, TimeUnit.MILLISECONDS);\n        \n        assertEquals(0, cdl.getCount());\n        ThreadUtil.dumpThreads();\n    }\n\n    public static class TestServlet extends HttpServlet {\n        @Override\n        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Thread.sleep(300);\n                out.print(\"testGet\");\n            } catch (InterruptedException ex) {\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberArray.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.Array;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.util.Map;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author crclespainter\n */\npublic class FiberArray implements Array {\n    private final Array array;\n    private final ExecutorService executor;\n\n    public FiberArray(final Array array, final ExecutorService executor) {\n        this.array = array;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public String getBaseTypeName() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return array.getBaseTypeName();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getBaseType() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return array.getBaseType();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getArray() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return array.getArray();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getArray(final Map<String, Class<?>> map) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return array.getArray(map);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getArray(final long index, final int count) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return array.getArray(index, count);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getArray(final long index, final int count, final Map<String, Class<?>> map) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return array.getArray(index, count, map);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getResultSet() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return array.getResultSet();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getResultSet(final Map<String, Class<?>> map) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return array.getResultSet(map);\n            }\n        });\n        return new FiberResultSet(result, executor);\n\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getResultSet(final long index, final int count) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return array.getResultSet(index, count);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getResultSet(final long index, final int count, final Map<String, Class<?>> map) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return array.getResultSet(index, count, map);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public void free() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                array.free();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    public int hashCode() {\n        return array.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return array.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return array.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberBlob.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport java.sql.SQLException;\nimport java.util.concurrent.ExecutorService;\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.sql.Blob;\n\n/**\n * @author crclespainter\n */\npublic class FiberBlob implements Blob {\n    private final Blob blob;\n    private final ExecutorService executor;\n\n    public FiberBlob(final Blob blob, final ExecutorService executor) {\n        this.blob = blob;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public byte[] getBytes(final long pos, final int length) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<byte[], SQLException>() {\n            @Override\n            public byte[] call() throws SQLException {\n                return blob.getBytes(pos, length);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getBinaryStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return blob.getBinaryStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long position(final byte[] pattern, final long start) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return blob.position(pattern, start);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long position(final Blob pattern, final long start) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return blob.position(pattern, start);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int setBytes(final long pos, final byte[] bytes) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return blob.setBytes(pos, bytes);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int setBytes(final long pos, final byte[] bytes, final int offset, final int len) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return blob.setBytes(pos, bytes, offset, len);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public OutputStream setBinaryStream(final long pos) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<OutputStream, SQLException>() {\n            @Override\n            public OutputStream call() throws SQLException {\n                return blob.setBinaryStream(pos);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getBinaryStream(final long pos, final long length) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return blob.getBinaryStream(pos, length);\n            }\n        });        \n    }\n\n    @Override\n    @Suspendable\n    public long length() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return blob.length();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void truncate(final long len) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                blob.truncate(len);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void free() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                blob.free();\n                return null;\n            }\n        });\n    }\n    \n    @Override\n    public int hashCode() {\n        return blob.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return blob.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return blob.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberCallableStatement.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.CallableStatement;\nimport java.sql.Clob;\nimport java.sql.Date;\nimport java.sql.NClob;\nimport java.sql.Ref;\nimport java.sql.RowId;\nimport java.sql.SQLException;\nimport java.sql.SQLXML;\nimport java.sql.Time;\nimport java.sql.Timestamp;\nimport java.util.Calendar;\nimport java.util.Map;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author eitan\n */\npublic class FiberCallableStatement extends FiberPreparedStatement implements CallableStatement {\n    public FiberCallableStatement(final CallableStatement cs, final ExecutorService exec) {\n        super(cs, exec);\n    }\n\n    @Override\n    protected CallableStatement stmt() {\n        return (CallableStatement) super.stmt();\n    }\n\n    //Delegations\n    @Override\n    @Suspendable\n    public void registerOutParameter(final int parameterIndex, final int sqlType) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().registerOutParameter(parameterIndex, sqlType);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void registerOutParameter(final int parameterIndex, final int sqlType, final int scale) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().registerOutParameter(parameterIndex, sqlType, scale);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean wasNull() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt().wasNull();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getString(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return stmt().getString(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean getBoolean(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt().getBoolean(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public byte getByte(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Byte, SQLException>() {\n            @Override\n            public Byte call() throws SQLException {\n                return stmt().getByte(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public short getShort(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Short, SQLException>() {\n            @Override\n            public Short call() throws SQLException {\n                return stmt().getShort(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getInt(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt().getInt(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long getLong(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return stmt().getLong(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public float getFloat(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Float, SQLException>() {\n            @Override\n            public Float call() throws SQLException {\n                return stmt().getFloat(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public double getDouble(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Double, SQLException>() {\n            @Override\n            public Double call() throws SQLException {\n                return stmt().getDouble(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public BigDecimal getBigDecimal(final int parameterIndex, final int scale) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<BigDecimal, SQLException>() {\n            @Override\n            public BigDecimal call() throws SQLException {\n                return stmt().getBigDecimal(parameterIndex, scale);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public byte[] getBytes(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<byte[], SQLException>() {\n            @Override\n            public byte[] call() throws SQLException {\n                return stmt().getBytes(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Date getDate(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Date, SQLException>() {\n            @Override\n            public Date call() throws SQLException {\n                return stmt().getDate(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Time getTime(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Time, SQLException>() {\n            @Override\n            public Time call() throws SQLException {\n                return stmt().getTime(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Timestamp getTimestamp(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Timestamp, SQLException>() {\n            @Override\n            public Timestamp call() throws SQLException {\n                return stmt().getTimestamp(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return stmt().getObject(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public BigDecimal getBigDecimal(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<BigDecimal, SQLException>() {\n            @Override\n            public BigDecimal call() throws SQLException {\n                return stmt().getBigDecimal(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final int parameterIndex, final Map<String, Class<?>> map) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return stmt().getObject(parameterIndex, map);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Ref getRef(final int parameterIndex) throws SQLException {\n        final Ref ref = JDBCFiberAsync.exec(executor, new CheckedCallable<Ref, SQLException>() {\n            @Override\n            public Ref call() throws SQLException {\n                return stmt().getRef(parameterIndex);\n            }\n        });\n        return new FiberRef(ref, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Blob getBlob(final int parameterIndex) throws SQLException {\n        final Blob blob = JDBCFiberAsync.exec(executor, new CheckedCallable<Blob, SQLException>() {\n            @Override\n            public Blob call() throws SQLException {\n                return stmt().getBlob(parameterIndex);\n            }\n        });\n        return new FiberBlob(blob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Clob getClob(final int parameterIndex) throws SQLException {\n        final Clob clob = JDBCFiberAsync.exec(executor, new CheckedCallable<Clob, SQLException>() {\n            @Override\n            public Clob call() throws SQLException {\n                return stmt().getClob(parameterIndex);\n            }\n        });\n        return new FiberClob(clob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Array getArray(final int parameterIndex) throws SQLException {\n        final Array array = JDBCFiberAsync.exec(executor, new CheckedCallable<Array, SQLException>() {\n            @Override\n            public Array call() throws SQLException {\n                return stmt().getArray(parameterIndex);\n            }\n        });\n        return new FiberArray(array, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Date getDate(final int parameterIndex, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Date, SQLException>() {\n            @Override\n            public Date call() throws SQLException {\n                return stmt().getDate(parameterIndex, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Time getTime(final int parameterIndex, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Time, SQLException>() {\n            @Override\n            public Time call() throws SQLException {\n                return stmt().getTime(parameterIndex, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Timestamp getTimestamp(final int parameterIndex, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Timestamp, SQLException>() {\n            @Override\n            public Timestamp call() throws SQLException {\n                return stmt().getTimestamp(parameterIndex, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void registerOutParameter(final int parameterIndex, final int sqlType, final String typeName) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().registerOutParameter(parameterIndex, sqlType, typeName);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void registerOutParameter(final String parameterName, final int sqlType) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().registerOutParameter(parameterName, sqlType);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void registerOutParameter(final String parameterName, final int sqlType, final int scale) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().registerOutParameter(parameterName, sqlType, scale);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void registerOutParameter(final String parameterName, final int sqlType, final String typeName) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().registerOutParameter(parameterName, sqlType, typeName);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public URL getURL(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<URL, SQLException>() {\n            @Override\n            public URL call() throws SQLException {\n                return stmt().getURL(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setURL(final int parameterIndex, final URL x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setURL(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNull(final int parameterIndex, final int sqlType) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNull(parameterIndex, sqlType);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBoolean(final int parameterIndex, final boolean x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBoolean(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setByte(final int parameterIndex, final byte x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setByte(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setShort(final int parameterIndex, final short x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setShort(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setInt(final int parameterIndex, final int x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setInt(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setLong(final int parameterIndex, final long x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setLong(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setFloat(final int parameterIndex, final float x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setFloat(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setDouble(final int parameterIndex, final double x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDouble(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBigDecimal(final int parameterIndex, final BigDecimal x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBigDecimal(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setString(final int parameterIndex, final String x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setString(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBytes(final int parameterIndex, final byte[] x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBytes(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setDate(final int parameterIndex, final Date x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDate(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTime(final int parameterIndex, final Time x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTime(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTimestamp(final int parameterIndex, final Timestamp x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTimestamp(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final int parameterIndex, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final int parameterIndex, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final int parameterIndex, final Object x, final int targetSqlType, final int scaleOrLength) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterIndex, x, targetSqlType, scaleOrLength);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final int parameterIndex, final Object x, final int targetSqlType) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterIndex, x, targetSqlType);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final int parameterIndex, final Object x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCharacterStream(final int parameterIndex, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setCharacterStream(parameterIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setDate(final int parameterIndex, final Date x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDate(parameterIndex, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTime(final int parameterIndex, final Time x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTime(parameterIndex, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTimestamp(final int parameterIndex, final Timestamp x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTimestamp(parameterIndex, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNull(final int parameterIndex, final int sqlType, final String typeName) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNull(parameterIndex, sqlType, typeName);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getString(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return stmt().getString(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean getBoolean(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt().getBoolean(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public byte getByte(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Byte, SQLException>() {\n            @Override\n            public Byte call() throws SQLException {\n                return stmt().getByte(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public short getShort(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Short, SQLException>() {\n            @Override\n            public Short call() throws SQLException {\n                return stmt().getShort(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getInt(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt().getInt(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long getLong(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return stmt().getLong(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public float getFloat(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Float, SQLException>() {\n            @Override\n            public Float call() throws SQLException {\n                return stmt().getFloat(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public double getDouble(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Double, SQLException>() {\n            @Override\n            public Double call() throws SQLException {\n                return stmt().getDouble(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public byte[] getBytes(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<byte[], SQLException>() {\n            @Override\n            public byte[] call() throws SQLException {\n                return stmt().getBytes(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Date getDate(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Date, SQLException>() {\n            @Override\n            public Date call() throws SQLException {\n                return stmt().getDate(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Time getTime(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Time, SQLException>() {\n            @Override\n            public Time call() throws SQLException {\n                return stmt().getTime(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Timestamp getTimestamp(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Timestamp, SQLException>() {\n            @Override\n            public Timestamp call() throws SQLException {\n                return stmt().getTimestamp(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return stmt().getObject(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public BigDecimal getBigDecimal(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<BigDecimal, SQLException>() {\n            @Override\n            public BigDecimal call() throws SQLException {\n                return stmt().getBigDecimal(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final String parameterName, final Map<String, Class<?>> map) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return stmt().getObject(parameterName, map);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Ref getRef(final String parameterName) throws SQLException {\n        final Ref ref = JDBCFiberAsync.exec(executor, new CheckedCallable<Ref, SQLException>() {\n            @Override\n            public Ref call() throws SQLException {\n                return stmt().getRef(parameterName);\n            }\n        });\n        return new FiberRef(ref, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Blob getBlob(final String parameterName) throws SQLException {\n        final Blob blob = JDBCFiberAsync.exec(executor, new CheckedCallable<Blob, SQLException>() {\n            @Override\n            public Blob call() throws SQLException {\n                return stmt().getBlob(parameterName);\n            }\n        });\n        return new FiberBlob(blob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Clob getClob(final String parameterName) throws SQLException {\n        final Clob clob = JDBCFiberAsync.exec(executor, new CheckedCallable<Clob, SQLException>() {\n            @Override\n            public Clob call() throws SQLException {\n                return stmt().getClob(parameterName);\n            }\n        });\n        return new FiberClob(clob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Array getArray(final String parameterName) throws SQLException {\n        final Array array = JDBCFiberAsync.exec(executor, new CheckedCallable<Array, SQLException>() {\n            @Override\n            public Array call() throws SQLException {\n                return stmt().getArray(parameterName);\n            }\n        });\n        return new FiberArray(array, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Date getDate(final String parameterName, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Date, SQLException>() {\n            @Override\n            public Date call() throws SQLException {\n                return stmt().getDate(parameterName, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Time getTime(final String parameterName, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Time, SQLException>() {\n            @Override\n            public Time call() throws SQLException {\n                return stmt().getTime(parameterName, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Timestamp getTimestamp(final String parameterName, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Timestamp, SQLException>() {\n            @Override\n            public Timestamp call() throws SQLException {\n                return stmt().getTimestamp(parameterName, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public URL getURL(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<URL, SQLException>() {\n            @Override\n            public URL call() throws SQLException {\n                return stmt().getURL(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public RowId getRowId(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<RowId, SQLException>() {\n            @Override\n            public RowId call() throws SQLException {\n                return stmt().getRowId(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public RowId getRowId(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<RowId, SQLException>() {\n            @Override\n            public RowId call() throws SQLException {\n                return stmt().getRowId(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public NClob getNClob(final int parameterIndex) throws SQLException {\n        final NClob clob = JDBCFiberAsync.exec(executor, new CheckedCallable<NClob, SQLException>() {\n            @Override\n            public NClob call() throws SQLException {\n                return stmt().getNClob(parameterIndex);\n            }\n        });\n        return new FiberNClob(clob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public NClob getNClob(final String parameterName) throws SQLException {\n        final NClob clob = JDBCFiberAsync.exec(executor, new CheckedCallable<NClob, SQLException>() {\n            @Override\n            public NClob call() throws SQLException {\n                return stmt().getNClob(parameterName);\n            }\n        });\n        return new FiberNClob(clob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public SQLXML getSQLXML(final int parameterIndex) throws SQLException {\n        final SQLXML sqlxml = JDBCFiberAsync.exec(executor, new CheckedCallable<SQLXML, SQLException>() {\n            @Override\n            public SQLXML call() throws SQLException {\n                return stmt().getSQLXML(parameterIndex);\n            }\n        });\n        return new FiberSQLXML(sqlxml, executor);\n    }\n\n    @Override\n    @Suspendable\n    public SQLXML getSQLXML(final String parameterName) throws SQLException {\n        final SQLXML sqlxml = JDBCFiberAsync.exec(executor, new CheckedCallable<SQLXML, SQLException>() {\n            @Override\n            public SQLXML call() throws SQLException {\n                return stmt().getSQLXML(parameterName);\n            }\n        });\n        return new FiberSQLXML(sqlxml, executor);\n    }\n\n    @Override\n    @Suspendable\n    public String getNString(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return stmt().getString(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getNString(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return stmt().getString(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getNCharacterStream(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return stmt().getNCharacterStream(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getNCharacterStream(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return stmt().getNCharacterStream(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream(final int parameterIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return stmt().getCharacterStream(parameterIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream(final String parameterName) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return stmt().getCharacterStream(parameterName);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public <T> T getObject(final int parameterIndex, final Class<T> type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<T, SQLException>() {\n            @Override\n            public T call() throws SQLException {\n                return stmt().getObject(parameterIndex, type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public <T> T getObject(final String parameterName, final Class<T> type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<T, SQLException>() {\n            @Override\n            public T call() throws SQLException {\n                return stmt().getObject(parameterName, type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setRowId(final int parameterIndex, final RowId x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setRowId(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNString(final int parameterIndex, final String value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNString(parameterIndex, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNCharacterStream(final int parameterIndex, final Reader value, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNCharacterStream(parameterIndex, value, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final int parameterIndex, final NClob value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterIndex, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final int parameterIndex, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final int parameterIndex, final InputStream inputStream, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterIndex, inputStream, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final int parameterIndex, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setSQLXML(final int parameterIndex, final SQLXML xmlObject) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setSQLXML(parameterIndex, xmlObject);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final int parameterIndex, final Blob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final int parameterIndex, final Clob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final int parameterIndex, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final int parameterIndex, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final int parameterIndex, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final int parameterIndex, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCharacterStream(final int parameterIndex, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setCharacterStream(parameterIndex, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNCharacterStream(final int parameterIndex, final Reader value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNCharacterStream(parameterIndex, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final int parameterIndex, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterIndex, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final int parameterIndex, final InputStream inputStream) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterIndex, inputStream);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final int parameterIndex, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterIndex, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setURL(final String parameterName, final URL val) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setURL(parameterName, val);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNull(final String parameterName, final int sqlType) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNull(parameterName, sqlType);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBoolean(final String parameterName, final boolean x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBoolean(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setByte(final String parameterName, final byte x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setByte(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setShort(final String parameterName, final short x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setShort(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setInt(final String parameterName, final int x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setInt(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setLong(final String parameterName, final long x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setLong(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setFloat(final String parameterName, final float x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setFloat(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setDouble(final String parameterName, final double x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDouble(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBigDecimal(final String parameterName, final BigDecimal x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBigDecimal(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setString(final String parameterName, final String x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setString(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBytes(final String parameterName, final byte[] x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBytes(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setDate(final String parameterName, final Date x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDate(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTime(final String parameterName, final Time x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTime(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTimestamp(final String parameterName, final Timestamp x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTimestamp(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final String parameterName, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterName, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final String parameterName, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterName, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final String parameterName, final Object x, final int targetSqlType, final int scale) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterName, x, targetSqlType, scale);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final String parameterName, final Object x, final int targetSqlType) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterName, x, targetSqlType);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final String parameterName, final Object x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCharacterStream(final String parameterName, final Reader reader, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setCharacterStream(parameterName, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setDate(final String parameterName, final Date x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDate(parameterName, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTime(final String parameterName, final Time x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTime(parameterName, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTimestamp(final String parameterName, final Timestamp x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTimestamp(parameterName, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNull(final String parameterName, final int sqlType, final String typeName) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNull(parameterName, sqlType, typeName);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setRowId(final String parameterName, final RowId x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setRowId(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNString(final String parameterName, final String value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNString(parameterName, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNCharacterStream(final String parameterName, final Reader value, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNCharacterStream(parameterName, value, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final String parameterName, final NClob value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterName, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final String parameterName, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterName, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final String parameterName, final InputStream inputStream, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterName, inputStream, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final String parameterName, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterName, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setSQLXML(final String parameterName, final SQLXML xmlObject) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setSQLXML(parameterName, xmlObject);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final String parameterName, final Blob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final String parameterName, final Clob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final String parameterName, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterName, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final String parameterName, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterName, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCharacterStream(final String parameterName, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setCharacterStream(parameterName, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final String parameterName, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final String parameterName, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterName, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCharacterStream(final String parameterName, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setCharacterStream(parameterName, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNCharacterStream(final String parameterName, final Reader value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNCharacterStream(parameterName, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final String parameterName, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterName, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final String parameterName, final InputStream inputStream) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterName, inputStream);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final String parameterName, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterName, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    public int hashCode() {\n        return stmt().hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return stmt().equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return stmt().toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberClob.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.sql.Clob;\nimport java.sql.SQLException;\nimport java.util.concurrent.ExecutorService;\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\n\n/**\n * @author crclespainter\n */\npublic class FiberClob implements Clob {\n    private final Clob clob;\n    private final ExecutorService executor;\n\n    public FiberClob(final Clob clob, final ExecutorService executor) {\n        this.clob = clob;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public long length() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return clob.length();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSubString(final long pos, final int length) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return clob.getSubString(pos, length);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return clob.getCharacterStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getAsciiStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return clob.getAsciiStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long position(final String searchstr, final long start) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return clob.position(searchstr, start);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long position(final Clob searchstr, final long start) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return clob.position(searchstr, start);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int setString(final long pos, final String str) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return clob.setString(pos, str);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int setString(final long pos, final String str, final int offset, final int len) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return clob.setString(pos, str, offset, len);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public OutputStream setAsciiStream(final long pos) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<OutputStream, SQLException>() {\n            @Override\n            public OutputStream call() throws SQLException {\n                return clob.setAsciiStream(pos);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Writer setCharacterStream(final long pos) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Writer, SQLException>() {\n            @Override\n            public Writer call() throws SQLException {\n                return clob.setCharacterStream(pos);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void truncate(final long len) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                clob.truncate(len);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void free() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                clob.free();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream(final long pos, final long length) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return clob.getCharacterStream(pos, length);\n            }\n        });\n    }\n       \n    @Override\n    public int hashCode() {\n        return clob.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return clob.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return clob.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberConnection.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.CallableStatement;\nimport java.sql.Clob;\nimport java.sql.Connection;\nimport java.sql.DatabaseMetaData;\nimport java.sql.NClob;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLClientInfoException;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Savepoint;\nimport java.sql.Statement;\nimport java.sql.Struct;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author eitan\n */\npublic class FiberConnection implements Connection {\n    private final Connection conn;\n    private final ExecutorService executor;\n\n    FiberConnection(final Connection conn, final ExecutorService exec) {\n        this.conn = conn;\n        this.executor = exec;\n    }\n\n    @Override\n    @Suspendable\n    public FiberStatement createStatement() throws SQLException {\n        final Statement statement = JDBCFiberAsync.exec(executor, new CheckedCallable<Statement, SQLException>() {\n            @Override\n            public Statement call() throws SQLException {\n                return conn.createStatement();\n            }\n        });\n        return new FiberStatement(statement, executor);\n    }\n    \n    @Override\n    @Suspendable\n    public FiberPreparedStatement prepareStatement(final String sql) throws SQLException {\n        final PreparedStatement prepareStatement = JDBCFiberAsync.exec(executor, new CheckedCallable<PreparedStatement, SQLException>() {\n            @Override\n            public PreparedStatement call() throws SQLException {\n                return conn.prepareStatement(sql);\n            }\n        });\n        return new FiberPreparedStatement(prepareStatement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberPreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException {\n        final PreparedStatement prepareStatement = JDBCFiberAsync.exec(executor, new CheckedCallable<PreparedStatement, SQLException>() {\n            @Override\n            public PreparedStatement call() throws SQLException {\n                return conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);\n            }\n        });\n        return new FiberPreparedStatement(prepareStatement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberPreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException {\n        final PreparedStatement prepareStatement = JDBCFiberAsync.exec(executor, new CheckedCallable<PreparedStatement, SQLException>() {\n            @Override\n            public PreparedStatement call() throws SQLException {\n                return conn.prepareStatement(sql, autoGeneratedKeys);\n            }\n        });\n        return new FiberPreparedStatement(prepareStatement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberPreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {\n        final PreparedStatement prepareStatement = JDBCFiberAsync.exec(executor, new CheckedCallable<PreparedStatement, SQLException>() {\n            @Override\n            public PreparedStatement call() throws SQLException {\n                return conn.prepareStatement(sql, columnIndexes);\n            }\n        });\n        return new FiberPreparedStatement(prepareStatement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberPreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {\n        final PreparedStatement prepareStatement = JDBCFiberAsync.exec(executor, new CheckedCallable<PreparedStatement, SQLException>() {\n            @Override\n            public PreparedStatement call() throws SQLException {\n                return conn.prepareStatement(sql, columnNames);\n            }\n        });\n        return new FiberPreparedStatement(prepareStatement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberCallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException {\n        final CallableStatement callableStatement = JDBCFiberAsync.exec(executor, new CheckedCallable<CallableStatement, SQLException>() {\n            @Override\n            public CallableStatement call() throws SQLException {\n                return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);\n            }\n        });\n        return new FiberCallableStatement(callableStatement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberCallableStatement prepareCall(final String sql) throws SQLException {\n        final CallableStatement callableStatement = JDBCFiberAsync.exec(executor, new CheckedCallable<CallableStatement, SQLException>() {\n            @Override\n            public CallableStatement call() throws SQLException {\n                return conn.prepareCall(sql);\n            }\n        });\n        return new FiberCallableStatement(callableStatement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberCallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException {\n        final CallableStatement callableStatement = JDBCFiberAsync.exec(executor, new CheckedCallable<CallableStatement, SQLException>() {\n            @Override\n            public CallableStatement call() throws SQLException {\n                return conn.prepareCall(sql, resultSetType, resultSetConcurrency);\n            }\n        });\n        return new FiberCallableStatement(callableStatement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public String nativeSQL(final String sql) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return conn.nativeSQL(sql);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAutoCommit(final boolean autoCommit) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.setAutoCommit(autoCommit);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean getAutoCommit() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return conn.getAutoCommit();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void commit() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.commit();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void rollback() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.rollback();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void close() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.close();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isClosed() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return conn.isClosed();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberDatabaseMetaData getMetaData() throws SQLException {\n        final DatabaseMetaData dbMeta = JDBCFiberAsync.exec(executor, new CheckedCallable<DatabaseMetaData, SQLException>() {\n            @Override\n            public DatabaseMetaData call() throws SQLException {\n                return conn.getMetaData();\n            }\n        });\n        return new FiberDatabaseMetaData(dbMeta, executor);\n    }\n\n    @Override\n    @Suspendable\n    public void setReadOnly(final boolean readOnly) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.setReadOnly(readOnly);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isReadOnly() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return conn.isReadOnly();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCatalog(final String catalog) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.setCatalog(catalog);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getCatalog() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return conn.getCatalog();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTransactionIsolation(final int level) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.setTransactionIsolation(level);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getTransactionIsolation() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return conn.getTransactionIsolation();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public SQLWarning getWarnings() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<SQLWarning, SQLException>() {\n            @Override\n            public SQLWarning call() throws SQLException {\n                return conn.getWarnings();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void clearWarnings() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.clearWarnings();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberStatement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException {\n        final Statement statement = JDBCFiberAsync.exec(executor, new CheckedCallable<Statement, SQLException>() {\n            @Override\n            public Statement call() throws SQLException {\n                return conn.createStatement(resultSetType, resultSetConcurrency);\n            }\n        });\n        return new FiberStatement(statement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberPreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException {\n        final PreparedStatement stmt = JDBCFiberAsync.exec(executor, new CheckedCallable<PreparedStatement, SQLException>() {\n            @Override\n            public PreparedStatement call() throws SQLException {\n                return conn.prepareStatement(sql, resultSetType, resultSetConcurrency);\n            }\n        });\n        return new FiberPreparedStatement(stmt, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Map<String, Class<?>> getTypeMap() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable< Map<String, Class<?>>, SQLException>() {\n            @Override\n            public Map<String, Class<?>> call() throws SQLException {\n                return conn.getTypeMap();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTypeMap(final Map<String, Class<?>> map) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.setTypeMap(map);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setHoldability(final int holdability) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.setHoldability(holdability);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getHoldability() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return conn.getHoldability();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberSavepoint setSavepoint() throws SQLException {\n        final Savepoint savepoint = JDBCFiberAsync.exec(executor, new CheckedCallable<Savepoint, SQLException>() {\n            @Override\n            public Savepoint call() throws SQLException {\n                return conn.setSavepoint();\n            }\n        });\n        return new FiberSavepoint(savepoint, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberSavepoint setSavepoint(final String name) throws SQLException {\n        final Savepoint savepoint = JDBCFiberAsync.exec(executor, new CheckedCallable<Savepoint, SQLException>() {\n            @Override\n            public Savepoint call() throws SQLException {\n                return conn.setSavepoint(name);\n            }\n        });\n        return new FiberSavepoint(savepoint, executor);\n    }\n\n    @Override\n    @Suspendable\n    public void rollback(final Savepoint savepoint) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.rollback(savepoint);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void releaseSavepoint(final Savepoint savepoint) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.releaseSavepoint(savepoint);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberStatement createStatement(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException {\n        final Statement statement = JDBCFiberAsync.exec(executor, new CheckedCallable<Statement, SQLException>() {\n            @Override\n            public Statement call() throws SQLException {\n                return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);\n            }\n        });\n        return new FiberStatement(statement, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberClob createClob() throws SQLException {\n        final Clob clob = JDBCFiberAsync.exec(executor, new CheckedCallable<Clob, SQLException>() {\n            @Override\n            public Clob call() throws SQLException {\n                return conn.createClob();\n            }\n        });\n        return new FiberClob(clob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberBlob createBlob() throws SQLException {\n        final Blob blob = JDBCFiberAsync.exec(executor, new CheckedCallable<Blob, SQLException>() {\n            @Override\n            public Blob call() throws SQLException {\n                return conn.createBlob();\n            }\n        });\n        return new FiberBlob(blob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberNClob createNClob() throws SQLException {\n        final NClob nclob = JDBCFiberAsync.exec(executor, new CheckedCallable<NClob, SQLException>() {\n            @Override\n            public NClob call() throws SQLException {\n                return conn.createNClob();\n            }\n        });\n        return new FiberNClob(nclob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberSQLXML createSQLXML() throws SQLException {\n        final SQLXML sqlXML = JDBCFiberAsync.exec(executor, new CheckedCallable<SQLXML, SQLException>() {\n            @Override\n            public SQLXML call() throws SQLException {\n                return conn.createSQLXML();\n            }\n        });\n        return new FiberSQLXML(sqlXML, executor);\n    }\n\n    @Override\n    @Suspendable\n    public boolean isValid(final int timeout) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return conn.isValid(timeout);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClientInfo(final String name, final String value) throws SQLClientInfoException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLClientInfoException>() {\n            @Override\n            public Void call() throws SQLClientInfoException {\n                conn.setClientInfo(name, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClientInfo(final Properties properties) throws SQLClientInfoException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLClientInfoException>() {\n            @Override\n            public Void call() throws SQLClientInfoException {\n                conn.setClientInfo(properties);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getClientInfo(final String name) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return conn.getClientInfo(name);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Properties getClientInfo() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Properties, SQLException>() {\n            @Override\n            public Properties call() throws SQLException {\n                return conn.getClientInfo();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberArray createArrayOf(final String typeName, final Object[] elements) throws SQLException {\n        final Array array = JDBCFiberAsync.exec(executor, new CheckedCallable<Array, SQLException>() {\n            @Override\n            public Array call() throws SQLException {\n                return conn.createArrayOf(typeName, elements);\n            }\n        });\n        return new FiberArray(array, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberStruct createStruct(final String typeName, final Object[] attributes) throws SQLException {\n        final Struct struct = JDBCFiberAsync.exec(executor, new CheckedCallable<Struct, SQLException>() {\n            @Override\n            public Struct call() throws SQLException {\n                return conn.createStruct(typeName, attributes);\n            }\n        });\n        return new FiberStruct(struct, executor);\n    }\n\n    @Override\n    @Suspendable\n    public void setSchema(final String schema) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.setSchema(schema);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSchema() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return conn.getSchema();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void abort(final Executor executor) throws SQLException {\n        JDBCFiberAsync.exec(this.executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.abort(executor);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNetworkTimeout(final Executor executor, final int milliseconds) throws SQLException {\n        JDBCFiberAsync.exec(this.executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                conn.setNetworkTimeout(executor, milliseconds);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getNetworkTimeout() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return conn.getNetworkTimeout();\n            }\n        });\n    }\n\n    @Override\n    public <T> T unwrap(final Class<T> iface) throws SQLException {\n        return conn.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(final Class<?> iface) throws SQLException {\n        return conn.isWrapperFor(iface);\n    }\n\n    @Override\n    public int hashCode() {\n        return conn.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return conn.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return conn.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberDataSource.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport com.google.common.util.concurrent.MoreExecutors;\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.logging.Logger;\nimport javax.sql.DataSource;\n\n/**\n * A JDBC {@link DataSource} that creates connections that can be used in Quasar fibers.\n * This class simply wraps any JDBC data source, and executes any JDBC operations in a separate {@code ExecutorService}.\n *\n * @author eitan\n */\npublic class FiberDataSource implements DataSource {\n    private final DataSource ds;\n    private final ExecutorService executor;\n\n    /**\n     * Wraps a JDBC {@link DataSource}.\n     * @param ds The {@link DataSource} to wrap.\n     * @param executor The {@link ExecutorService} to use to actually execute JDBC operations.\n     * @return \n     */\n    public static DataSource wrap(final DataSource ds, final ExecutorService executor) {\n        return new FiberDataSource(ds, MoreExecutors.listeningDecorator(executor));\n    }\n\n    /**\n     * Wraps a JDBC {@link DataSource}.\n     * @param ds The {@link DataSource} to wrap.\n     * @param numThreads The number of threads to create in the thread pool that will be used to execute JDBC operations.\n     * @return \n     */\n    public static DataSource wrap(final DataSource ds, final int numThreads) {\n        return wrap(ds, Executors.newFixedThreadPool(numThreads, new ThreadFactoryBuilder().setNameFormat(\"jdbc-worker-%d\").setDaemon(true).build()));\n    }\n\n    /**\n     * Wraps a JDBC {@link DataSource} with fixed 10 threads pool executor.\n     * @param ds The {@link DataSource} to wrap.\n     * @return \n     */\n    public static DataSource wrap(final DataSource ds) {\n        return wrap(ds, 10);\n    }\n\n    protected FiberDataSource(final DataSource ds, final ExecutorService exec) {\n        this.ds = ds;\n        this.executor = exec;\n    }\n\n    @Override\n    @Suspendable\n    public FiberConnection getConnection() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<FiberConnection, SQLException>() {\n            @Override\n            public FiberConnection call() throws SQLException {\n                return new FiberConnection(ds.getConnection(), executor);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberConnection getConnection(final String username, final String password) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<FiberConnection, SQLException>() {\n            @Override\n            public FiberConnection call() throws SQLException {\n                return new FiberConnection(ds.getConnection(username, password), executor);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public PrintWriter getLogWriter() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<PrintWriter, SQLException>() {\n            @Override\n            public PrintWriter call() throws SQLException {\n                return ds.getLogWriter();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setLogWriter(final PrintWriter out) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                ds.setLogWriter(out);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setLoginTimeout(final int seconds) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                ds.setLoginTimeout(seconds);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getLoginTimeout() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return ds.getLoginTimeout();\n            }\n        });\n    }\n\n    @Override\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        return ds.getParentLogger();\n    }\n\n    @Override\n    public <T> T unwrap(final Class<T> iface) throws SQLException {\n        return ds.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(final Class<?> iface) throws SQLException {\n        return ds.isWrapperFor(iface);\n    }\n\n    @Override\n    public int hashCode() {\n        return ds.hashCode();\n    }\n\n    @Override\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    public boolean equals(final Object obj) {\n        return ds.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return ds.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberDataSourceFactory.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport java.util.Hashtable;\nimport javax.naming.Context;\nimport javax.naming.InitialContext;\nimport javax.naming.Name;\nimport javax.naming.NamingException;\nimport javax.naming.RefAddr;\nimport javax.naming.Reference;\nimport javax.naming.spi.ObjectFactory;\nimport javax.sql.DataSource;\n\n/**\n * @author eitan\n */\npublic class FiberDataSourceFactory implements ObjectFactory {\n    @Override\n    public Object getObjectInstance(final Object obj, final Name name, final Context nameCtx, final Hashtable<?, ?> environment) throws Exception {\n        if ((obj == null) || !(obj instanceof Reference))\n            return null;\n        final Reference ref = (Reference) obj;\n        if (!\"javax.sql.DataSource\".equals(ref.getClassName()))\n            return null;\n        RefAddr ra;\n        ra = ref.get(\"rawDataSource\");\n        if (ra == null)\n            throw new RuntimeException(\"mising rawDataSource name\");\n        final String rawDS = ra.getContent().toString();\n        ra = ref.get(\"threadsCount\");\n        if (ra == null)\n            throw new RuntimeException(\"mising rawDataSource name\");\n        final int tc = Integer.parseInt(ra.getContent().toString());\n        return create(rawDS, tc);\n    }\n\n    public static DataSource create(final String rawDS, final int tc) throws NamingException {\n        final Context envCtx = (Context) new InitialContext().lookup(\"java:comp/env\");\n        final DataSource ds = (DataSource) envCtx.lookup(rawDS);\n        return FiberDataSource.wrap(ds, tc);\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberDatabaseMetaData.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.Connection;\nimport java.sql.DatabaseMetaData;\nimport java.sql.ResultSet;\nimport java.sql.RowIdLifetime;\nimport java.sql.SQLException;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author crclespainter\n */\npublic class FiberDatabaseMetaData implements DatabaseMetaData {\n    private final DatabaseMetaData dbMeta;\n    private final ExecutorService executor;\n\n    public FiberDatabaseMetaData(final DatabaseMetaData dbMeta, final ExecutorService executor) {\n        this.dbMeta = dbMeta;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public boolean allProceduresAreCallable() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.allProceduresAreCallable();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean allTablesAreSelectable() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.allTablesAreSelectable();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getURL() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getURL();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getUserName() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getUserName();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isReadOnly() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.isReadOnly();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean nullsAreSortedHigh() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.nullsAreSortedHigh();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean nullsAreSortedLow() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.nullsAreSortedLow();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean nullsAreSortedAtStart() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.nullsAreSortedAtStart();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean nullsAreSortedAtEnd() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.nullsAreSortedAtEnd();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getDatabaseProductName() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getDatabaseProductName();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getDatabaseProductVersion() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getDatabaseProductVersion();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getDriverName() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getDriverName();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getDriverVersion() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getDriverVersion();\n            }\n        });\n    }\n\n    @Override\n    public int getDriverMajorVersion() {\n        return dbMeta.getDriverMajorVersion();\n    }\n\n    @Override\n    public int getDriverMinorVersion() {\n        return dbMeta.getDriverMinorVersion();\n    }\n\n    @Override\n    @Suspendable\n    public boolean usesLocalFiles() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.usesLocalFiles();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean usesLocalFilePerTable() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.usesLocalFilePerTable();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsMixedCaseIdentifiers() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsMixedCaseIdentifiers();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean storesUpperCaseIdentifiers() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.storesUpperCaseIdentifiers();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean storesLowerCaseIdentifiers() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.storesLowerCaseIdentifiers();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean storesMixedCaseIdentifiers() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.storesMixedCaseIdentifiers();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsMixedCaseQuotedIdentifiers();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.storesUpperCaseQuotedIdentifiers();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.storesLowerCaseQuotedIdentifiers();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.storesMixedCaseQuotedIdentifiers();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getIdentifierQuoteString() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getIdentifierQuoteString();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSQLKeywords() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getSQLKeywords();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getNumericFunctions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getNumericFunctions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getStringFunctions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getStringFunctions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSystemFunctions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getSystemFunctions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getTimeDateFunctions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getTimeDateFunctions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSearchStringEscape() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getSearchStringEscape();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getExtraNameCharacters() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getExtraNameCharacters();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsAlterTableWithAddColumn() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsAlterTableWithAddColumn();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsAlterTableWithDropColumn() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsAlterTableWithDropColumn();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsColumnAliasing() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsColumnAliasing();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean nullPlusNonNullIsNull() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.nullPlusNonNullIsNull();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsConvert() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsConvert();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsConvert(final int fromType, final int toType) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsConvert(fromType, toType);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsTableCorrelationNames() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsTableCorrelationNames();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsDifferentTableCorrelationNames() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsDifferentTableCorrelationNames();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsExpressionsInOrderBy() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsExpressionsInOrderBy();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsOrderByUnrelated() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsOrderByUnrelated();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsGroupBy() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsGroupBy();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsGroupByUnrelated() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsGroupByUnrelated();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsGroupByBeyondSelect() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsGroupByBeyondSelect();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsLikeEscapeClause() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsLikeEscapeClause();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsMultipleResultSets() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsMultipleResultSets();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsMultipleTransactions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsMultipleTransactions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsNonNullableColumns() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsNonNullableColumns();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsMinimumSQLGrammar() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsMinimumSQLGrammar();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsCoreSQLGrammar() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsCoreSQLGrammar();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsExtendedSQLGrammar() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsExtendedSQLGrammar();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsANSI92EntryLevelSQL() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsANSI92EntryLevelSQL();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsANSI92IntermediateSQL() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsANSI92IntermediateSQL();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsANSI92FullSQL() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsANSI92FullSQL();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsIntegrityEnhancementFacility() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsIntegrityEnhancementFacility();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsOuterJoins() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsOuterJoins();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsFullOuterJoins() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsFullOuterJoins();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsLimitedOuterJoins() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsFullOuterJoins();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSchemaTerm() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getSchemaTerm();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getProcedureTerm() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getProcedureTerm();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getCatalogTerm() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getCatalogTerm();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isCatalogAtStart() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.isCatalogAtStart();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getCatalogSeparator() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return dbMeta.getCatalogSeparator();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSchemasInDataManipulation() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSchemasInDataManipulation();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSchemasInProcedureCalls() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSchemasInProcedureCalls();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSchemasInTableDefinitions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSchemasInTableDefinitions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSchemasInIndexDefinitions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSchemasInIndexDefinitions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSchemasInPrivilegeDefinitions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsCatalogsInDataManipulation() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsCatalogsInDataManipulation();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsCatalogsInProcedureCalls() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsCatalogsInProcedureCalls();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsCatalogsInTableDefinitions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsCatalogsInTableDefinitions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsCatalogsInIndexDefinitions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsCatalogsInIndexDefinitions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsCatalogsInPrivilegeDefinitions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsPositionedDelete() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsPositionedDelete();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsPositionedUpdate() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsPositionedUpdate();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSelectForUpdate() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSelectForUpdate();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsStoredProcedures() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsStoredProcedures();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSubqueriesInComparisons() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSubqueriesInComparisons();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSubqueriesInExists() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSubqueriesInExists();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSubqueriesInIns() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSubqueriesInIns();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSubqueriesInQuantifieds() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSubqueriesInQuantifieds();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsCorrelatedSubqueries() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsCorrelatedSubqueries();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsUnion() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsUnion();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsUnionAll() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsUnionAll();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsOpenCursorsAcrossCommit() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsOpenCursorsAcrossCommit();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsOpenCursorsAcrossRollback() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsOpenCursorsAcrossRollback();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsOpenStatementsAcrossCommit() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsOpenStatementsAcrossCommit();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsOpenStatementsAcrossRollback() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsOpenStatementsAcrossRollback();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxBinaryLiteralLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxBinaryLiteralLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxCharLiteralLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxCharLiteralLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxColumnNameLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxColumnNameLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxColumnsInGroupBy() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxColumnsInGroupBy();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxColumnsInIndex() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxColumnsInIndex();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxColumnsInOrderBy() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxColumnsInOrderBy();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxColumnsInSelect() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxColumnsInSelect();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxColumnsInTable() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxColumnsInTable();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxConnections() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxConnections();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxCursorNameLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxCursorNameLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxIndexLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxIndexLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxSchemaNameLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxSchemaNameLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxProcedureNameLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxProcedureNameLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxCatalogNameLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxCatalogNameLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxRowSize() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxRowSize();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.doesMaxRowSizeIncludeBlobs();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxStatementLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxStatementLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxStatements() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxStatements();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxTableNameLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxTableNameLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxTablesInSelect() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxTablesInSelect();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxUserNameLength() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getMaxUserNameLength();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getDefaultTransactionIsolation() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getDefaultTransactionIsolation();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsTransactions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsTransactions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsTransactionIsolationLevel(final int level) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsTransactionIsolationLevel(level);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsDataDefinitionAndDataManipulationTransactions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsDataManipulationTransactionsOnly() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsDataManipulationTransactionsOnly();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean dataDefinitionCausesTransactionCommit() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.dataDefinitionCausesTransactionCommit();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean dataDefinitionIgnoredInTransactions() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.dataDefinitionIgnoredInTransactions();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getProcedures(catalog, schemaPattern, procedureNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getProcedureColumns(final String catalog, final String schemaPattern, final String procedureNamePattern, final String columnNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getTables(final String catalog, final String schemaPattern, final String tableNamePattern, final String[] types) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getTables(catalog, schemaPattern, tableNamePattern, types);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getSchemas() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getSchemas();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getCatalogs() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getCatalogs();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getTableTypes() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getTableTypes();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getColumnPrivileges(final String catalog, final String schema, final String table, final String columnNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getColumnPrivileges(catalog, schema, table, columnNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getTablePrivileges(catalog, schemaPattern, tableNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, final boolean nullable) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getBestRowIdentifier(catalog, schema, table, scope, nullable);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getVersionColumns(final String catalog, final String schema, final String table) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getVersionColumns(catalog, schema, table);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getPrimaryKeys(final String catalog, final String schema, final String table) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getPrimaryKeys(catalog, schema, table);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getImportedKeys(final String catalog, final String schema, final String table) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getImportedKeys(catalog, schema, table);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getExportedKeys(final String catalog, final String schema, final String table) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getExportedKeys(catalog, schema, table);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getCrossReference(final String parentCatalog, final String parentSchema, final String parentTable, final String foreignCatalog, final String foreignSchema, final String foreignTable) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getTypeInfo() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getTypeInfo();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, final boolean approximate) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getIndexInfo(catalog, schema, table, unique, approximate);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsResultSetType(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsResultSetType(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsResultSetConcurrency(final int type, final int concurrency) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsResultSetConcurrency(type, concurrency);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean ownUpdatesAreVisible(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.ownUpdatesAreVisible(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean ownDeletesAreVisible(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.ownDeletesAreVisible(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean ownInsertsAreVisible(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.ownInsertsAreVisible(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean othersUpdatesAreVisible(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.othersUpdatesAreVisible(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean othersDeletesAreVisible(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.othersDeletesAreVisible(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean othersInsertsAreVisible(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.othersInsertsAreVisible(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean updatesAreDetected(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.updatesAreDetected(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean deletesAreDetected(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.deletesAreDetected(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean insertsAreDetected(final int type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.insertsAreDetected(type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsBatchUpdates() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsBatchUpdates();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, final int[] types) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getUDTs(catalog, schemaPattern, typeNamePattern, types);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberConnection getConnection() throws SQLException {\n        final Connection conn = JDBCFiberAsync.exec(executor, new CheckedCallable<Connection, SQLException>() {\n            @Override\n            public Connection call() throws SQLException {\n                return dbMeta.getConnection();\n            }\n        });\n        return new FiberConnection(conn, executor);\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsSavepoints() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsSavepoints();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsNamedParameters() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsNamedParameters();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsMultipleOpenResults() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsMultipleOpenResults();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsGetGeneratedKeys() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsGetGeneratedKeys();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getSuperTypes(catalog, schemaPattern, typeNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getSuperTables(catalog, schemaPattern, tableNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, final String attributeNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsResultSetHoldability(final int holdability) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsResultSetHoldability(holdability);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getResultSetHoldability() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getResultSetHoldability();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getDatabaseMajorVersion() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getDatabaseMajorVersion();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getDatabaseMinorVersion() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getDatabaseMinorVersion();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getJDBCMajorVersion() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getJDBCMajorVersion();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getJDBCMinorVersion() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getJDBCMinorVersion();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getSQLStateType() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return dbMeta.getSQLStateType();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean locatorsUpdateCopy() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.locatorsUpdateCopy();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsStatementPooling() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsStatementPooling();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public RowIdLifetime getRowIdLifetime() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<RowIdLifetime, SQLException>() {\n            @Override\n            public RowIdLifetime call() throws SQLException {\n                return dbMeta.getRowIdLifetime();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getSchemas(final String catalog, final String schemaPattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getSchemas(catalog, schemaPattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.supportsStoredFunctionsUsingCallSyntax();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean autoCommitFailureClosesAllResultSets() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.autoCommitFailureClosesAllResultSets();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getClientInfoProperties() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getClientInfoProperties();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getFunctions(catalog, schemaPattern, functionNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, final String columnNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return dbMeta.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public boolean generatedKeyAlwaysReturned() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return dbMeta.generatedKeyAlwaysReturned();\n            }\n        });\n    }\n\n    @Override\n    public <T> T unwrap(final Class<T> iface) throws SQLException {\n        return dbMeta.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(final Class<?> iface) throws SQLException {\n        return dbMeta.isWrapperFor(iface);\n    }\n\n    @Override\n    public int hashCode() {\n        return dbMeta.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return dbMeta.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return dbMeta.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberDriver.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport com.google.common.util.concurrent.MoreExecutors;\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport java.sql.Connection;\nimport java.sql.Driver;\nimport java.sql.DriverManager;\nimport java.sql.DriverPropertyInfo;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.Properties;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.logging.Logger;\n\n/**\n * @author eitan\n */\npublic class FiberDriver implements Driver {\n    @Suspendable\n    @Override\n    public FiberConnection connect(final String url, final Properties info) throws SQLException {\n        final String dbURL = url.replaceFirst(\"fiber:\", \"\");\n        final int threadCount = Integer.parseInt(info.getProperty(THREADS_COUNT, \"10\"));\n        info.remove(THREADS_COUNT);\n        final ExecutorService es = Executors.newFixedThreadPool(threadCount, new ThreadFactoryBuilder().setNameFormat(\"jdbc-worker-%d\").setDaemon(true).build());\n        final Connection con = JDBCFiberAsync.exec(es, new CheckedCallable<Connection, SQLException>() {\n            @Override\n            public Connection call() throws SQLException {\n                return DriverManager.getConnection(dbURL, info);\n            }\n        });\n        return new FiberConnection(con, MoreExecutors.listeningDecorator(es));\n    }\n    private static final String THREADS_COUNT = \"threadsCount\";\n    private static final String RAW_DATA_SOURCE_URL = \"rawDataSourceURL\";\n\n    @Override\n    public boolean acceptsURL(String url) throws SQLException {\n        return url.startsWith(\"jdbc:fiber:\");\n    }\n\n    @Override\n    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {\n        String dbURL = info.getProperty(RAW_DATA_SOURCE_URL);\n        if (dbURL == null)\n            throw new SQLException(\"no rawDataSourceURL parameter\");\n        info.remove(RAW_DATA_SOURCE_URL);\n        return DriverManager.getDriver(url).getPropertyInfo(url, info);\n    }\n\n    @Override\n    public int getMajorVersion() {\n        return 2;\n    }\n\n    @Override\n    public int getMinorVersion() {\n        return 0;\n    }\n\n    @Override\n    public boolean jdbcCompliant() {\n        return false;\n    }\n\n    @Override\n    public Logger getParentLogger() throws SQLFeatureNotSupportedException {\n        throw new SQLFeatureNotSupportedException(\"Not supported yet.\");\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberNClob.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.sql.Clob;\nimport java.sql.SQLException;\nimport java.util.concurrent.ExecutorService;\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.NClob;\n\n/**\n * @author crclespainter\n */\npublic class FiberNClob implements NClob {\n    private final NClob nclob;\n    private final ExecutorService executor;\n\n    public FiberNClob(final NClob nclob, final ExecutorService executor) {\n        this.nclob = nclob;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public long length() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return nclob.length();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSubString(final long pos, final int length) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return nclob.getSubString(pos, length);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return nclob.getCharacterStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getAsciiStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return nclob.getAsciiStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long position(final String searchstr, final long start) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return nclob.position(searchstr, start);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long position(final Clob searchstr, final long start) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return nclob.position(searchstr, start);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int setString(final long pos, final String str) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return nclob.setString(pos, str);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int setString(final long pos, final String str, final int offset, final int len) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return nclob.setString(pos, str, offset, len);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public OutputStream setAsciiStream(final long pos) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<OutputStream, SQLException>() {\n            @Override\n            public OutputStream call() throws SQLException {\n                return nclob.setAsciiStream(pos);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Writer setCharacterStream(final long pos) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Writer, SQLException>() {\n            @Override\n            public Writer call() throws SQLException {\n                return nclob.setCharacterStream(pos);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void truncate(final long len) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                nclob.truncate(len);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void free() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                nclob.free();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream(final long pos, final long length) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return nclob.getCharacterStream(pos, length);\n            }\n        });\n    }\n\n    @Override\n    public int hashCode() {\n        return nclob.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return nclob.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return nclob.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberParameterMetadata.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.ParameterMetaData;\nimport java.sql.SQLException;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author circlespainter\n */\npublic class FiberParameterMetadata implements ParameterMetaData {\n    protected final ParameterMetaData pmeta;\n    protected final ExecutorService executor;\n\n    public FiberParameterMetadata(ParameterMetaData pmeta, ExecutorService executor) {\n        this.pmeta = pmeta;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public int getParameterCount() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return pmeta.getParameterCount();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int isNullable(final int param) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return pmeta.isNullable(param);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isSigned(final int param) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return pmeta.isSigned(param);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getPrecision(final int param) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return pmeta.getPrecision(param);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getScale(final int param) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return pmeta.getScale(param);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getParameterType(final int param) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return pmeta.getParameterType(param);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getParameterTypeName(final int param) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return pmeta.getParameterTypeName(param);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getParameterClassName(final int param) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return pmeta.getParameterClassName(param);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getParameterMode(final int param) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return pmeta.getParameterMode(param);\n            }\n        });\n    }\n\n    @Override\n    public <T> T unwrap(final Class<T> iface) throws SQLException {\n        return pmeta.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(final Class<?> iface) throws SQLException {\n        return pmeta.isWrapperFor(iface);\n    }\n\n    @Override\n    public int hashCode() {\n        return pmeta.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return pmeta.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return pmeta.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberPreparedStatement.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.Date;\nimport java.sql.NClob;\nimport java.sql.ParameterMetaData;\nimport java.sql.PreparedStatement;\nimport java.sql.Ref;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.RowId;\nimport java.sql.SQLException;\nimport java.sql.SQLXML;\nimport java.sql.Time;\nimport java.sql.Timestamp;\nimport java.util.Calendar;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author eitan\n */\npublic class FiberPreparedStatement extends FiberStatement implements PreparedStatement {\n    FiberPreparedStatement(final java.sql.PreparedStatement ps, final ExecutorService exec) {\n        super(ps, exec);\n    }\n\n    protected PreparedStatement stmt() {\n        return (PreparedStatement) stmt;\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet executeQuery() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return stmt().executeQuery();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public int executeUpdate() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt().executeUpdate();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean execute() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt().execute();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNull(final int parameterIndex, final int sqlType) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNull(parameterIndex, sqlType);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBoolean(final int parameterIndex, final boolean x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBoolean(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setByte(final int parameterIndex, final byte x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setByte(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setShort(final int parameterIndex, final short x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setShort(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setInt(final int parameterIndex, final int x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setInt(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setLong(final int parameterIndex, final long x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setLong(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setFloat(final int parameterIndex, final float x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setFloat(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setDouble(final int parameterIndex, final double x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDouble(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBigDecimal(final int parameterIndex, final BigDecimal x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBigDecimal(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setString(final int parameterIndex, final String x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setString(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBytes(final int parameterIndex, final byte[] x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBytes(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setDate(final int parameterIndex, final Date x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDate(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTime(final int parameterIndex, final Time x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTime(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTimestamp(final int parameterIndex, final Timestamp x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTimestamp(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final int parameterIndex, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setUnicodeStream(final int parameterIndex, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setUnicodeStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final int parameterIndex, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void clearParameters() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().clearParameters();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final int parameterIndex, final Object x, final int targetSqlType) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterIndex, x, targetSqlType);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final int parameterIndex, final Object x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void addBatch() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().addBatch();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCharacterStream(final int parameterIndex, final Reader reader, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setCharacterStream(parameterIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setRef(final int parameterIndex, final Ref x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setRef(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final int parameterIndex, final Blob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final int parameterIndex, final Clob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setArray(final int parameterIndex, final Array x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setArray(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSetMetaData getMetaData() throws SQLException {\n        final ResultSetMetaData meta = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSetMetaData, SQLException>() {\n            @Override\n            public ResultSetMetaData call() throws SQLException {\n                return stmt().getMetaData();\n            }\n        });\n        return new FiberResultSetMetaData(meta, executor);\n    }\n\n    @Override\n    @Suspendable\n    public void setDate(final int parameterIndex, final Date x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setDate(parameterIndex, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTime(final int parameterIndex, final Time x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTime(parameterIndex, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setTimestamp(final int parameterIndex, final Timestamp x, final Calendar cal) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setTimestamp(parameterIndex, x, cal);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNull(final int parameterIndex, final int sqlType, final String typeName) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNull(parameterIndex, sqlType, typeName);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setURL(final int parameterIndex, final URL x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setURL(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberParameterMetadata getParameterMetaData() throws SQLException {\n        final ParameterMetaData pmeta = JDBCFiberAsync.exec(executor, new CheckedCallable<ParameterMetaData, SQLException>() {\n            @Override\n            public ParameterMetaData call() throws SQLException {\n                return stmt().getParameterMetaData();\n            }\n        });\n        return new FiberParameterMetadata(pmeta, executor);\n    }\n\n    @Override\n    @Suspendable\n    public void setRowId(final int parameterIndex, final RowId x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setRowId(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNString(final int parameterIndex, final String value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNString(parameterIndex, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNCharacterStream(final int parameterIndex, final Reader value, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNCharacterStream(parameterIndex, value, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final int parameterIndex, final NClob value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterIndex, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final int parameterIndex, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final int parameterIndex, final InputStream inputStream, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterIndex, inputStream, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final int parameterIndex, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setSQLXML(final int parameterIndex, final SQLXML xmlObject) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setSQLXML(parameterIndex, xmlObject);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final int parameterIndex, final Object x, final int targetSqlType, final int scaleOrLength) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setObject(parameterIndex, x, targetSqlType, scaleOrLength);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final int parameterIndex, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final int parameterIndex, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCharacterStream(final int parameterIndex, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setCharacterStream(parameterIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setAsciiStream(final int parameterIndex, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setAsciiStream(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBinaryStream(final int parameterIndex, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBinaryStream(parameterIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCharacterStream(final int parameterIndex, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setCharacterStream(parameterIndex, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNCharacterStream(final int parameterIndex, final Reader value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNCharacterStream(parameterIndex, value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setClob(final int parameterIndex, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setClob(parameterIndex, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setBlob(final int parameterIndex, final InputStream inputStream) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setBlob(parameterIndex, inputStream);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setNClob(final int parameterIndex, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt().setNClob(parameterIndex, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    public int hashCode() {\n        return stmt().hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return stmt().equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return stmt().toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberRef.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.Ref;\nimport java.sql.SQLException;\nimport java.util.Map;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author crclespainter\n */\npublic class FiberRef implements Ref {\n    private final Ref ref;\n    private final ExecutorService executor;\n\n    public FiberRef(final Ref ref, final ExecutorService executor) {\n        this.ref = ref;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public String getBaseTypeName() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return ref.getBaseTypeName();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final Map<String, Class<?>> map) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return ref.getObject(map);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return ref.getObject();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setObject(final Object value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                ref.setObject(value);\n                return null;\n            }\n        });\n    }\n    \n    @Override\n    public int hashCode() {\n        return ref.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return ref.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return ref.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberResultSet.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.math.BigDecimal;\nimport java.net.URL;\nimport java.sql.Array;\nimport java.sql.Blob;\nimport java.sql.Clob;\nimport java.sql.Date;\nimport java.sql.NClob;\nimport java.sql.Ref;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.RowId;\nimport java.sql.SQLException;\n// 1.8\n//\n// import java.sql.SQLType;\nimport java.sql.SQLWarning;\nimport java.sql.SQLXML;\nimport java.sql.Statement;\nimport java.sql.Time;\nimport java.sql.Timestamp;\nimport java.util.Calendar;\nimport java.util.Map;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author crclespainter\n */\npublic class FiberResultSet implements ResultSet {\n    private final ResultSet result;\n    private final ExecutorService executor;\n\n    public FiberResultSet(final ResultSet result, final ExecutorService executor) {\n        this.result = result;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public boolean next() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.next();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void close() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.close();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean wasNull() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.wasNull();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getString(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return result.getString(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean getBoolean(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.getBoolean(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public byte getByte(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Byte, SQLException>() {\n            @Override\n            public Byte call() throws SQLException {\n                return result.getByte(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public short getShort(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Short, SQLException>() {\n            @Override\n            public Short call() throws SQLException {\n                return result.getShort(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getInt(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.getInt(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long getLong(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return result.getLong(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public float getFloat(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Float, SQLException>() {\n            @Override\n            public Float call() throws SQLException {\n                return result.getFloat(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public double getDouble(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Double, SQLException>() {\n            @Override\n            public Double call() throws SQLException {\n                return result.getDouble(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Deprecated\n    @Suspendable\n    public BigDecimal getBigDecimal(final int columnIndex, final int scale) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<BigDecimal, SQLException>() {\n            @Override\n            public BigDecimal call() throws SQLException {\n                return result.getBigDecimal(columnIndex, scale);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public byte[] getBytes(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<byte[], SQLException>() {\n            @Override\n            public byte[] call() throws SQLException {\n                return result.getBytes(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Date getDate(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Date, SQLException>() {\n            @Override\n            public Date call() throws SQLException {\n                return result.getDate(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Time getTime(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Time, SQLException>() {\n            @Override\n            public Time call() throws SQLException {\n                return result.getTime(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Timestamp getTimestamp(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Timestamp, SQLException>() {\n            @Override\n            public Timestamp call() throws SQLException {\n                return result.getTimestamp(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getAsciiStream(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return result.getAsciiStream(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Deprecated\n    @Suspendable\n    public InputStream getUnicodeStream(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return result.getUnicodeStream(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getBinaryStream(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return result.getBinaryStream(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getString(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return result.getString(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean getBoolean(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.getBoolean(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public byte getByte(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Byte, SQLException>() {\n            @Override\n            public Byte call() throws SQLException {\n                return result.getByte(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public short getShort(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Short, SQLException>() {\n            @Override\n            public Short call() throws SQLException {\n                return result.getShort(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getInt(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.getInt(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public long getLong(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Long, SQLException>() {\n            @Override\n            public Long call() throws SQLException {\n                return result.getLong(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public float getFloat(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Float, SQLException>() {\n            @Override\n            public Float call() throws SQLException {\n                return result.getFloat(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public double getDouble(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Double, SQLException>() {\n            @Override\n            public Double call() throws SQLException {\n                return result.getDouble(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Deprecated\n    @Suspendable\n    public BigDecimal getBigDecimal(final String columnLabel, final int scale) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<BigDecimal, SQLException>() {\n            @Override\n            public BigDecimal call() throws SQLException {\n                return result.getBigDecimal(columnLabel, scale);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public byte[] getBytes(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<byte[], SQLException>() {\n            @Override\n            public byte[] call() throws SQLException {\n                return result.getBytes(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Date getDate(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Date, SQLException>() {\n            @Override\n            public Date call() throws SQLException {\n                return result.getDate(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Time getTime(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Time, SQLException>() {\n            @Override\n            public Time call() throws SQLException {\n                return result.getTime(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Timestamp getTimestamp(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Timestamp, SQLException>() {\n            @Override\n            public Timestamp call() throws SQLException {\n                return result.getTimestamp(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getAsciiStream(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return result.getAsciiStream(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Deprecated\n    @Suspendable\n    public InputStream getUnicodeStream(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return result.getUnicodeStream(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getBinaryStream(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return result.getBinaryStream(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public SQLWarning getWarnings() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<SQLWarning, SQLException>() {\n            @Override\n            public SQLWarning call() throws SQLException {\n                return result.getWarnings();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void clearWarnings() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.clearWarnings();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getCursorName() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return result.getCursorName();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSetMetaData getMetaData() throws SQLException {\n        final ResultSetMetaData meta = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSetMetaData, SQLException>() {\n            @Override\n            public ResultSetMetaData call() throws SQLException {\n                return result.getMetaData();\n            }\n        });\n        return new FiberResultSetMetaData(meta, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return result.getObject(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return result.getObject(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int findColumn(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.findColumn(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return result.getCharacterStream(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return result.getCharacterStream(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public BigDecimal getBigDecimal(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<BigDecimal, SQLException>() {\n            @Override\n            public BigDecimal call() throws SQLException {\n                return result.getBigDecimal(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public BigDecimal getBigDecimal(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<BigDecimal, SQLException>() {\n            @Override\n            public BigDecimal call() throws SQLException {\n                return result.getBigDecimal(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isBeforeFirst() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.isBeforeFirst();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isAfterLast() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.isAfterLast();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isFirst() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.isFirst();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isLast() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.isLast();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void beforeFirst() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.beforeFirst();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void afterLast() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.afterLast();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean first() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.first();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean last() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.last();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getRow() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.getRow();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean absolute(final int row) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.absolute(row);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean relative(final int rows) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.absolute(rows);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean previous() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.previous();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setFetchDirection(final int direction) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.setFetchDirection(direction);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getFetchDirection() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.getFetchDirection();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setFetchSize(final int rows) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.setFetchSize(rows);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getFetchSize() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.getFetchSize();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getType() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.getType();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getConcurrency() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.getConcurrency();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean rowUpdated() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.rowUpdated();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean rowInserted() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.rowInserted();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean rowDeleted() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.rowDeleted();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNull(final int columnIndex) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNull(columnIndex);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBoolean(final int columnIndex, final boolean x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBoolean(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateByte(final int columnIndex, final byte x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateByte(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateShort(final int columnIndex, final short x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateShort(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateInt(final int columnIndex, final int x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateInt(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateLong(final int columnIndex, final long x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateLong(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateFloat(final int columnIndex, final float x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateFloat(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateDouble(final int columnIndex, final double x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateDouble(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBigDecimal(final int columnIndex, final BigDecimal x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBigDecimal(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateString(final int columnIndex, final String x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateString(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBytes(final int columnIndex, final byte[] x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBytes(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateDate(final int columnIndex, final Date x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateDate(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateTime(final int columnIndex, final Time x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateTime(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateTimestamp(final int columnIndex, final Timestamp x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateTimestamp(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateAsciiStream(final int columnIndex, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateAsciiStream(columnIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBinaryStream(final int columnIndex, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBinaryStream(columnIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateCharacterStream(final int columnIndex, final Reader x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateCharacterStream(columnIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateObject(final int columnIndex, final Object x, final int scaleOrLength) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateObject(columnIndex, x, scaleOrLength);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateObject(final int columnIndex, final Object x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateObject(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNull(final String columnLabel) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNull(columnLabel);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBoolean(final String columnLabel, final boolean x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBoolean(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateByte(final String columnLabel, final byte x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateByte(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateShort(final String columnLabel, final short x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateShort(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateInt(final String columnLabel, final int x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateInt(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateLong(final String columnLabel, final long x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateLong(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateFloat(final String columnLabel, final float x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateFloat(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateDouble(final String columnLabel, final double x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateDouble(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBigDecimal(final String columnLabel, final BigDecimal x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBigDecimal(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateString(final String columnLabel, final String x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateString(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBytes(final String columnLabel, final byte[] x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBytes(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateDate(final String columnLabel, final Date x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateDate(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateTime(final String columnLabel, final Time x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateTime(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateTimestamp(final String columnLabel, final Timestamp x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateTimestamp(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateAsciiStream(final String columnLabel, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateAsciiStream(columnLabel, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBinaryStream(final String columnLabel, final InputStream x, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBinaryStream(columnLabel, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateCharacterStream(final String columnLabel, final Reader reader, final int length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateCharacterStream(columnLabel, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateObject(final String columnLabel, final Object x, final int scaleOrLength) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateObject(columnLabel, x, scaleOrLength);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateObject(final String columnLabel, final Object x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateObject(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void insertRow() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.insertRow();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateRow() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateRow();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void deleteRow() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.deleteRow();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void refreshRow() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.refreshRow();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void cancelRowUpdates() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.cancelRowUpdates();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void moveToInsertRow() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.moveToInsertRow();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void moveToCurrentRow() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.moveToCurrentRow();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberStatement getStatement() throws SQLException {\n        final Statement s = JDBCFiberAsync.exec(executor, new CheckedCallable<Statement, SQLException>() {\n            @Override\n            public Statement call() throws SQLException {\n                return result.getStatement();\n            }\n        });\n        return new FiberStatement(s, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final int columnIndex, final Map<String, Class<?>> map) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return result.getObject(columnIndex, map);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberRef getRef(final int columnIndex) throws SQLException {\n        final Ref ref = JDBCFiberAsync.exec(executor, new CheckedCallable<Ref, SQLException>() {\n            @Override\n            public Ref call() throws SQLException {\n                return result.getRef(columnIndex);\n            }\n        });\n        return new FiberRef(ref, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberBlob getBlob(final int columnIndex) throws SQLException {\n        final Blob blob = JDBCFiberAsync.exec(executor, new CheckedCallable<Blob, SQLException>() {\n            @Override\n            public Blob call() throws SQLException {\n                return result.getBlob(columnIndex);\n            }\n        });\n        return new FiberBlob(blob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberClob getClob(final int columnIndex) throws SQLException {\n        final Clob clob = JDBCFiberAsync.exec(executor, new CheckedCallable<Clob, SQLException>() {\n            @Override\n            public Clob call() throws SQLException {\n                return result.getClob(columnIndex);\n            }\n        });\n        return new FiberClob(clob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberArray getArray(final int columnIndex) throws SQLException {\n        final Array array =  JDBCFiberAsync.exec(executor, new CheckedCallable<Array, SQLException>() {\n            @Override\n            public Array call() throws SQLException {\n                return result.getArray(columnIndex);\n            }\n        });\n        return new FiberArray(array, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Object getObject(final String columnLabel, final Map<String, Class<?>> map) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object, SQLException>() {\n            @Override\n            public Object call() throws SQLException {\n                return result.getObject(columnLabel, map);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberRef getRef(final String columnLabel) throws SQLException {\n        final Ref ref = JDBCFiberAsync.exec(executor, new CheckedCallable<Ref, SQLException>() {\n            @Override\n            public Ref call() throws SQLException {\n                return result.getRef(columnLabel);\n            }\n        });\n        return new FiberRef(ref, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberBlob getBlob(final String columnLabel) throws SQLException {\n        final Blob blob = JDBCFiberAsync.exec(executor, new CheckedCallable<Blob, SQLException>() {\n            @Override\n            public Blob call() throws SQLException {\n                return result.getBlob(columnLabel);\n            }\n        });\n        return new FiberBlob(blob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberClob getClob(final String columnLabel) throws SQLException {\n        final Clob clob = JDBCFiberAsync.exec(executor, new CheckedCallable<Clob, SQLException>() {\n            @Override\n            public Clob call() throws SQLException {\n                return result.getClob(columnLabel);\n            }\n        });\n        return new FiberClob(clob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberArray getArray(final String columnLabel) throws SQLException {\n        final Array array = JDBCFiberAsync.exec(executor, new CheckedCallable<Array, SQLException>() {\n            @Override\n            public Array call() throws SQLException {\n                return result.getArray(columnLabel);\n            }\n        });\n        return new FiberArray(array, executor);\n    }\n\n    @Override\n    @Suspendable\n    public Date getDate(final int columnIndex, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Date, SQLException>() {\n            @Override\n            public Date call() throws SQLException {\n                return result.getDate(columnIndex, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Date getDate(final String columnLabel, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Date, SQLException>() {\n            @Override\n            public Date call() throws SQLException {\n                return result.getDate(columnLabel, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Time getTime(final int columnIndex, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Time, SQLException>() {\n            @Override\n            public Time call() throws SQLException {\n                return result.getTime(columnIndex, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Time getTime(final String columnLabel, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Time, SQLException>() {\n            @Override\n            public Time call() throws SQLException {\n                return result.getTime(columnLabel, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Timestamp getTimestamp(final int columnIndex, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Timestamp, SQLException>() {\n            @Override\n            public Timestamp call() throws SQLException {\n                return result.getTimestamp(columnIndex, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Timestamp getTimestamp(final String columnLabel, final Calendar cal) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Timestamp, SQLException>() {\n            @Override\n            public Timestamp call() throws SQLException {\n                return result.getTimestamp(columnLabel, cal);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public URL getURL(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<URL, SQLException>() {\n            @Override\n            public URL call() throws SQLException {\n                return result.getURL(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public URL getURL(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<URL, SQLException>() {\n            @Override\n            public URL call() throws SQLException {\n                return result.getURL(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateRef(final int columnIndex, final Ref x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateRef(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateRef(final String columnLabel, final Ref x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateRef(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBlob(final int columnIndex, final Blob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBlob(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBlob(final String columnLabel, final Blob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBlob(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateClob(final int columnIndex, final Clob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateClob(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateClob(final String columnLabel, final Clob x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateClob(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateArray(final int columnIndex, final Array x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateArray(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateArray(final String columnLabel, final Array x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateArray(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public RowId getRowId(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<RowId, SQLException>() {\n            @Override\n            public RowId call() throws SQLException {\n                return result.getRowId(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public RowId getRowId(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<RowId, SQLException>() {\n            @Override\n            public RowId call() throws SQLException {\n                return result.getRowId(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateRowId(final int columnIndex, final RowId x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateRowId(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateRowId(final String columnLabel, final RowId x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateRowId(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getHoldability() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return result.getHoldability();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isClosed() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return result.isClosed();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNString(final int columnIndex, final String nString) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNString(columnIndex, nString);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNString(final String columnLabel, final String nString) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNString(columnLabel, nString);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNClob(final int columnIndex, final NClob nClob) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNClob(columnIndex, nClob);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNClob(final String columnLabel, final NClob nClob) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNClob(columnLabel, nClob);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberNClob getNClob(final int columnIndex) throws SQLException {\n        final NClob nclob = JDBCFiberAsync.exec(executor, new CheckedCallable<NClob, SQLException>() {\n            @Override\n            public NClob call() throws SQLException {\n                return result.getNClob(columnIndex);\n            }\n        });\n        return new FiberNClob(nclob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberNClob getNClob(final String columnLabel) throws SQLException {\n        final NClob nclob = JDBCFiberAsync.exec(executor, new CheckedCallable<NClob, SQLException>() {\n            @Override\n            public NClob call() throws SQLException {\n                return result.getNClob(columnLabel);\n            }\n        });\n        return new FiberNClob(nclob, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberSQLXML getSQLXML(final int columnIndex) throws SQLException {\n        final SQLXML sqlxml = JDBCFiberAsync.exec(executor, new CheckedCallable<SQLXML, SQLException>() {\n            @Override\n            public SQLXML call() throws SQLException {\n                return result.getSQLXML(columnIndex);\n            }\n        });\n        return new FiberSQLXML(sqlxml, executor);\n    }\n\n    @Override\n    @Suspendable\n    public FiberSQLXML getSQLXML(final String columnLabel) throws SQLException {\n        final SQLXML sqlxml = JDBCFiberAsync.exec(executor, new CheckedCallable<SQLXML, SQLException>() {\n            @Override\n            public SQLXML call() throws SQLException {\n                return result.getSQLXML(columnLabel);\n            }\n        });\n        return new FiberSQLXML(sqlxml, executor);\n    }\n\n    @Override\n    @Suspendable\n    public void updateSQLXML(final int columnIndex, final SQLXML xmlObject) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateSQLXML(columnIndex, xmlObject);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateSQLXML(final String columnLabel, final SQLXML xmlObject) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateSQLXML(columnLabel, xmlObject);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getNString(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return result.getNString(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getNString(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return result.getNString(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getNCharacterStream(final int columnIndex) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return result.getNCharacterStream(columnIndex);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getNCharacterStream(final String columnLabel) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return result.getNCharacterStream(columnLabel);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNCharacterStream(final int columnIndex, final Reader x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNCharacterStream(columnIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNCharacterStream(columnLabel, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateAsciiStream(final int columnIndex, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateAsciiStream(columnIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBinaryStream(final int columnIndex, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBinaryStream(columnIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateCharacterStream(final int columnIndex, final Reader x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateCharacterStream(columnIndex, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateAsciiStream(final String columnLabel, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateAsciiStream(columnLabel, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBinaryStream(final String columnLabel, final InputStream x, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBinaryStream(columnLabel, x, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateCharacterStream(columnLabel, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBlob(final int columnIndex, final InputStream inputStream, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBlob(columnIndex, inputStream, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBlob(final String columnLabel, final InputStream inputStream, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBlob(columnLabel, inputStream, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateClob(final int columnIndex, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateClob(columnIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateClob(final String columnLabel, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateClob(columnLabel, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNClob(final int columnIndex, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNClob(columnIndex, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNClob(final String columnLabel, final Reader reader, final long length) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNClob(columnLabel, reader, length);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNCharacterStream(final int columnIndex, final Reader x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNCharacterStream(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNCharacterStream(final String columnLabel, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNCharacterStream(columnLabel, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateAsciiStream(final int columnIndex, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateAsciiStream(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBinaryStream(final int columnIndex, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBinaryStream(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateCharacterStream(final int columnIndex, final Reader x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateCharacterStream(columnIndex, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateAsciiStream(final String columnLabel, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateAsciiStream(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBinaryStream(final String columnLabel, final InputStream x) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBinaryStream(columnLabel, x);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateCharacterStream(final String columnLabel, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateCharacterStream(columnLabel, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBlob(final int columnIndex, final InputStream inputStream) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBlob(columnIndex, inputStream);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateBlob(final String columnLabel, final InputStream inputStream) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateBlob(columnLabel, inputStream);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateClob(final int columnIndex, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateClob(columnIndex, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateClob(final String columnLabel, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateClob(columnLabel, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNClob(final int columnIndex, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNClob(columnIndex, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void updateNClob(final String columnLabel, final Reader reader) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                result.updateNClob(columnLabel, reader);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public <T> T getObject(final int columnIndex, final Class<T> type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<T, SQLException>() {\n            @Override\n            public T call() throws SQLException {\n                return result.getObject(columnIndex, type);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public <T> T getObject(final String columnLabel, final Class<T> type) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<T, SQLException>() {\n            @Override\n            public T call() throws SQLException {\n                return result.getObject(columnLabel, type);\n            }\n        });\n    }\n\n//    1.8, have default impl.\n//  \n//    @Override\n//    @Suspendable\n//    public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException {\n//        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n//            @Override\n//            public Void call() throws SQLException {\n//                result.updateObject(columnIndex, x, targetSqlType, scaleOrLength);\n//                return null;\n//            }\n//        });\n//    }\n//\n//    @Override\n//    @Suspendable\n//    public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException {\n//        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n//            @Override\n//            public Void call() throws SQLException {\n//                result.updateObject(columnLabel, x, targetSqlType, scaleOrLength);\n//                return null;\n//            }\n//        });\n//    }\n//\n//    @Override\n//    @Suspendable\n//    public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType) throws SQLException {\n//        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n//            @Override\n//            public Void call() throws SQLException {\n//                result.updateObject(columnIndex, x, targetSqlType);\n//                return null;\n//            }\n//        });\n//    }\n//\n//    @Override\n//    @Suspendable\n//    public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType) throws SQLException {\n//        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n//            @Override\n//            public Void call() throws SQLException {\n//                result.updateObject(columnLabel, x, targetSqlType);\n//                return null;\n//            }\n//        });\n//    }\n\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        return result.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        return result.isWrapperFor(iface);\n    }\n\n    @Override\n    public int hashCode() {\n        return result.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return result.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return result.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberResultSetMetaData.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author crclespainter\n */\npublic class FiberResultSetMetaData implements ResultSetMetaData {\n    private final ResultSetMetaData resultMeta;\n    private final ExecutorService executor;\n\n    public FiberResultSetMetaData(final ResultSetMetaData resultMeta, final ExecutorService executor) {\n        this.resultMeta = resultMeta;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public int getColumnCount() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return resultMeta.getColumnCount();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isAutoIncrement(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return resultMeta.isAutoIncrement(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isCaseSensitive(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return resultMeta.isCaseSensitive(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isSearchable(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return resultMeta.isSearchable(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isCurrency(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return resultMeta.isCurrency(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int isNullable(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return resultMeta.isNullable(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isSigned(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return resultMeta.isSigned(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getColumnDisplaySize(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return resultMeta.getColumnDisplaySize(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getColumnLabel(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return resultMeta.getColumnLabel(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getColumnName(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return resultMeta.getColumnName(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSchemaName(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return resultMeta.getSchemaName(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getPrecision(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return resultMeta.getPrecision(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getScale(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return resultMeta.getScale(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getTableName(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return resultMeta.getTableName(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getCatalogName(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return resultMeta.getCatalogName(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getColumnType(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return resultMeta.getColumnType(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getColumnTypeName(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return resultMeta.getColumnTypeName(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isReadOnly(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return resultMeta.isReadOnly(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isWritable(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return resultMeta.isWritable(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isDefinitelyWritable(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return resultMeta.isDefinitelyWritable(column);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getColumnClassName(final int column) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return resultMeta.getColumnClassName(column);\n            }\n        });\n    }\n\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        return resultMeta.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        return resultMeta.isWrapperFor(iface);\n    }\n\n    @Override\n    public int hashCode() {\n        return resultMeta.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return resultMeta.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return resultMeta.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberSQLXML.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport java.sql.SQLException;\nimport java.util.concurrent.ExecutorService;\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.sql.SQLXML;\nimport javax.xml.transform.Result;\nimport javax.xml.transform.Source;\n\n/**\n * @author crclespainter\n */\npublic class FiberSQLXML implements SQLXML {\n    private final SQLXML sqlXML;\n    private final ExecutorService executor;\n\n    public FiberSQLXML(final SQLXML sqlXML, final ExecutorService executor) {\n        this.sqlXML = sqlXML;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public InputStream getBinaryStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<InputStream, SQLException>() {\n            @Override\n            public InputStream call() throws SQLException {\n                return sqlXML.getBinaryStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void free() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                sqlXML.free();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public OutputStream setBinaryStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<OutputStream, SQLException>() {\n            @Override\n            public OutputStream call() throws SQLException {\n                return sqlXML.setBinaryStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Reader getCharacterStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Reader, SQLException>() {\n            @Override\n            public Reader call() throws SQLException {\n                return sqlXML.getCharacterStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Writer setCharacterStream() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Writer, SQLException>() {\n            @Override\n            public Writer call() throws SQLException {\n                return sqlXML.setCharacterStream();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getString() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return sqlXML.getString();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setString(final String value) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                sqlXML.setString(value);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public <T extends Source> T getSource(final Class<T> sourceClass) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<T, SQLException>() {\n            @Override\n            public T call() throws SQLException {\n                return sqlXML.getSource(sourceClass);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public <T extends Result> T setResult(final Class<T> resultClass) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<T, SQLException>() {\n            @Override\n            public T call() throws SQLException {\n                return sqlXML.setResult(resultClass);\n            }\n        });\n    }\n\n    @Override\n    public int hashCode() {\n        return sqlXML.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return sqlXML.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return sqlXML.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberSavepoint.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.SQLException;\nimport java.sql.Savepoint;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author crclespainter\n */\nclass FiberSavepoint implements Savepoint {\n    private final Savepoint savepoint;\n    private final ExecutorService executor;\n\n    public FiberSavepoint(final Savepoint savepoint, final ExecutorService executor) {\n        this.savepoint = savepoint;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public int getSavepointId() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return savepoint.getSavepointId();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public String getSavepointName() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return savepoint.getSavepointName();\n            }\n        });\n    }\n\n    @Override\n    public int hashCode() {\n        return savepoint.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return savepoint.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return savepoint.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberStatement.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.Connection;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.SQLWarning;\nimport java.sql.Statement;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author eitan\n */\npublic class FiberStatement implements Statement {\n    protected final Statement stmt;\n    protected final ExecutorService executor;\n\n    public FiberStatement(final Statement stmt, final ExecutorService exec) {\n        this.stmt = stmt;\n        this.executor = exec;\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet executeQuery(final String sql) throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n//                    int fetchSize = stmt.getFetchSize();\n//                    stmt.setFetchSize(99999);\n                final ResultSet executeQuery = stmt.executeQuery(sql);\n//                    stmt.setFetchSize(fetchSize);\n                return executeQuery;\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public int executeUpdate(final String sql) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.executeUpdate(sql);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void close() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.close();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxFieldSize() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getMaxFieldSize();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setMaxFieldSize(final int max) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.setMaxFieldSize(max);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getMaxRows() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getMaxRows();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setMaxRows(final int max) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.setMaxRows(max);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setEscapeProcessing(final boolean enable) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.setEscapeProcessing(enable);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getQueryTimeout() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getQueryTimeout();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setQueryTimeout(final int seconds) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.setQueryTimeout(seconds);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void cancel() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.cancel();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public SQLWarning getWarnings() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<SQLWarning, SQLException>() {\n            @Override\n            public SQLWarning call() throws SQLException {\n                return stmt.getWarnings();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void clearWarnings() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.clearWarnings();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setCursorName(final String name) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.setCursorName(name);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberResultSet getResultSet() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return stmt.getResultSet();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public int getUpdateCount() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getUpdateCount();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean getMoreResults() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.getMoreResults();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setFetchDirection(final int direction) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.setFetchDirection(direction);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getFetchDirection() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getFetchDirection();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setFetchSize(final int rows) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.setFetchSize(rows);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getFetchSize() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getFetchSize();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getResultSetConcurrency() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getResultSetConcurrency();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getResultSetType() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getResultSetType();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void addBatch(final String sql) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.addBatch(sql);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void clearBatch() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.clearBatch();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int[] executeBatch() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<int[], SQLException>() {\n            @Override\n            public int[] call() throws SQLException {\n                return stmt.executeBatch();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public FiberConnection getConnection() throws SQLException {\n        final Connection conn = JDBCFiberAsync.exec(executor, new CheckedCallable<Connection, SQLException>() {\n            @Override\n            public Connection call() throws SQLException {\n                return stmt.getConnection();\n            }\n        });\n        return new FiberConnection(conn, executor);\n    }\n\n    @Override\n    @Suspendable\n    public boolean getMoreResults(final int current) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.getMoreResults();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public ResultSet getGeneratedKeys() throws SQLException {\n        final ResultSet result = JDBCFiberAsync.exec(executor, new CheckedCallable<ResultSet, SQLException>() {\n            @Override\n            public ResultSet call() throws SQLException {\n                return stmt.getGeneratedKeys();\n            }\n        });\n        return new FiberResultSet(result, executor);\n    }\n\n    @Override\n    @Suspendable\n    public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.executeUpdate(sql, autoGeneratedKeys);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.executeUpdate(sql, columnIndexes);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int executeUpdate(final String sql, final String[] columnNames) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.executeUpdate(sql, columnNames);\n            }\n        });\n    }\n\n    @Suspendable\n    @Override\n    public boolean execute(final String sql) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.execute(sql);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.execute(sql, autoGeneratedKeys);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.execute(sql, columnIndexes);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean execute(final String sql, final String[] columnNames) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.execute(sql, columnNames);\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public int getResultSetHoldability() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Integer, SQLException>() {\n            @Override\n            public Integer call() throws SQLException {\n                return stmt.getResultSetHoldability();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isClosed() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.isClosed();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void setPoolable(final boolean poolable) throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.setPoolable(poolable);\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isPoolable() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.isPoolable();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public void closeOnCompletion() throws SQLException {\n        JDBCFiberAsync.exec(executor, new CheckedCallable<Void, SQLException>() {\n            @Override\n            public Void call() throws SQLException {\n                stmt.closeOnCompletion();\n                return null;\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public boolean isCloseOnCompletion() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Boolean, SQLException>() {\n            @Override\n            public Boolean call() throws SQLException {\n                return stmt.isCloseOnCompletion();\n            }\n        });\n    }\n\n    @Override\n    public <T> T unwrap(Class<T> iface) throws SQLException {\n        return stmt.unwrap(iface);\n    }\n\n    @Override\n    public boolean isWrapperFor(Class<?> iface) throws SQLException {\n        return stmt.isWrapperFor(iface);\n    }\n\n    @Override\n    public int hashCode() {\n        return stmt.hashCode();\n    }\n\n    @Override\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    public boolean equals(Object obj) {\n        return stmt.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return stmt.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/FiberStruct.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.sql.SQLException;\nimport java.sql.Struct;\nimport java.util.Map;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author crclespainter\n */\npublic class FiberStruct implements Struct {\n    private final Struct struct;\n    private final ExecutorService executor;\n\n    public FiberStruct(final Struct struct, final ExecutorService executor) {\n        this.struct = struct;\n        this.executor = executor;\n    }\n\n    @Override\n    @Suspendable\n    public String getSQLTypeName() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<String, SQLException>() {\n            @Override\n            public String call() throws SQLException {\n                return struct.getSQLTypeName();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object[] getAttributes() throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object[], SQLException>() {\n            @Override\n            public Object[] call() throws SQLException {\n                return struct.getAttributes();\n            }\n        });\n    }\n\n    @Override\n    @Suspendable\n    public Object[] getAttributes(final Map<String, Class<?>> map) throws SQLException {\n        return JDBCFiberAsync.exec(executor, new CheckedCallable<Object[], SQLException>() {\n            @Override\n            public Object[] call() throws SQLException {\n                return struct.getAttributes(map);\n            }\n        });\n    }\n\n    @Override\n    public int hashCode() {\n        return struct.hashCode();\n    }\n\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    @Override\n    public boolean equals(Object obj) {\n        return struct.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return struct.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/JDBCFiberAsync.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.common.util.CheckedCallable;\nimport co.paralleluniverse.fibers.FiberAsync;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.util.concurrent.ExecutorService;\n\n/**\n * @author circlespainter\n */\npublic abstract class JDBCFiberAsync<V, E extends Throwable> extends FiberAsync<V, E> {\n    @Suspendable\n    public static <V extends Object, E extends Exception> V exec(ExecutorService es, CheckedCallable<V, E> cc) throws E {\n        try {\n            return runBlocking(es, cc);\n        } catch (final SuspendExecution se) {\n            throw new AssertionError(se);\n        } catch (final InterruptedException ie) {\n            throw new RuntimeException(ie);\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/main/java/co/paralleluniverse/fibers/jdbc/package-info.java",
    "content": "/*\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n * \n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *  \n *   or (per the licensee's choosing)\n *  \n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/**\n * {@link java.sql JDBC} Integration for Quasar Fibers\n */\npackage co.paralleluniverse.fibers.jdbc;\n"
  },
  {
    "path": "comsat-jdbc/src/main/resources/META-INF/services/java.sql.Driver",
    "content": "co.paralleluniverse.fibers.jdbc.FiberDriver"
  },
  {
    "path": "comsat-jdbc/src/test/java/co/paralleluniverse/fibers/jdbc/FiberConnectionTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.embedded.db.H2JdbcDatasource;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport com.google.common.util.concurrent.MoreExecutors;\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport java.io.IOException;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.concurrent.Executors;\nimport javax.sql.DataSource;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class FiberConnectionTest {\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {H2JdbcDatasource.class},});\n    }\n    private final Class<? extends DataSource> cls;\n    private Connection conn;\n\n    public FiberConnectionTest(Class<? extends DataSource> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        final Connection connection = cls.newInstance().getConnection();\n        this.conn = new FiberConnection(connection,\n                MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10, new ThreadFactoryBuilder().setNameFormat(\"jdbc-worker-%d\").setDaemon(true).build())));\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        conn.close();\n    }\n\n    @Test\n    public void testCreateStatement() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    conn.createStatement().close();\n                } catch (SQLException ex) {\n                    fail(ex.getMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testPrepareStatement() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    conn.prepareStatement(\"create table tablename\");\n                } catch (SQLException ex) {\n                    fail(ex.getMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testPrepareCall() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    conn.prepareCall(\"create table tablename\");\n                } catch (SQLException ex) {\n                    fail(ex.getMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testCommit() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    conn.createStatement().execute(\"drop table if exists testCommit\");\n                    conn.createStatement().execute(\"create table testCommit (id int primary key, name varchar(100))\");\n                    // snippet connection usage\n                    conn.setAutoCommit(false);\n                    conn.createStatement().execute(\"insert into testCommit (id, name) values (1, 'name')\");\n                    conn.commit();\n                    boolean notEmpty = conn.createStatement().executeQuery(\"select * from testCommit\").next();\n                    // end of snippet\n                    assertTrue(notEmpty);\n                    conn.createStatement().execute(\"drop table testCommit\");\n                } catch (SQLException ex) {\n                    fail(ex.getMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testRollback() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    conn.setAutoCommit(false);\n                    conn.createStatement().execute(\"drop table if exists testRollback\");\n                    conn.createStatement().execute(\"create table testRollback (id int primary key, name varchar(100))\");\n                    conn.createStatement().execute(\"insert into testRollback (id, name) values (1, 'name')\");\n                    conn.rollback();\n                    assertFalse(conn.createStatement().executeQuery(\"select * from testRollback\").next());\n                    conn.createStatement().execute(\"drop table testRollback\");\n                } catch (SQLException ex) {\n                    fail(ex.getMessage());\n                }\n            }\n        }).start().join();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbc/src/test/java/co/paralleluniverse/fibers/jdbc/FiberDataSourceTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbc;\n\nimport co.paralleluniverse.embedded.db.H2JdbcDatasource;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport javax.sql.DataSource;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class FiberDataSourceTest {\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {H2JdbcDatasource.class},});\n    }\n    private final Class<? extends DataSource> dsCls;\n    private DataSource ds;\n\n    public FiberDataSourceTest(Class<? extends DataSource> cls) {\n        this.dsCls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        this.ds = dsCls.newInstance();\n    }\n\n    @Test\n    public void testGetConnection() throws IOException, InterruptedException, Exception {\n        // snippet DataSource wrapping\n        final DataSource fiberDs = FiberDataSource.wrap(ds);\n        // end of snippet\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    // snippet DataSource usage\n                    Connection conn = fiberDs.getConnection();\n                    // end of snippet\n                    conn.close();\n                } catch (SQLException ex) {\n                    fail(ex.getMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testGetConnectionUsername() throws IOException, InterruptedException, Exception {\n        final DataSource fiberDs = FiberDataSource.wrap(ds);\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    fiberDs.getConnection(\"\", \"\").close();\n                } catch (SQLException ex) {\n                    fail(ex.getMessage());\n                }\n            }\n        }).start().join();\n    }\n}\n"
  },
  {
    "path": "comsat-jdbi/src/main/java/co/paralleluniverse/fibers/jdbi/FiberDBI.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbi;\n\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.fibers.jdbc.FiberDataSource;\nimport com.google.common.util.concurrent.ThreadFactoryBuilder;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport javax.sql.DataSource;\n\nimport org.skife.jdbi.v2.*;\nimport org.skife.jdbi.v2.exceptions.CallbackFailedException;\nimport org.skife.jdbi.v2.tweak.HandleCallback;\nimport org.skife.jdbi.v2.tweak.HandleConsumer;\n\npublic class FiberDBI implements IDBI {\n    private final IDBI jdbi;\n    \n    /**\n     *\n     * @param jdbi jdbi based on FiberDataSource\n     */\n    public FiberDBI(IDBI jdbi) {\n        this.jdbi = jdbi;\n    }\n\n    /**\n     * Constructor for use with a DataSource which will provide\n     *\n     * @param dataSource may or may not be FiberDataSource\n     * @param es\n     */\n    public FiberDBI(DataSource dataSource, ExecutorService es) {\n        this(dataSource instanceof FiberDataSource ? new DBI(dataSource) : new DBI(FiberDataSource.wrap(dataSource, es)));\n    }\n\n    /**\n     * Constructor for use with a DataSource which will provide using fixed thread pool executor\n     *\n     * @param dataSource  may or may not be FiberDataSource\n     * @param threadCount\n     */\n    public FiberDBI(DataSource dataSource, int threadCount) {\n        this(dataSource, Executors.newFixedThreadPool(threadCount, new ThreadFactoryBuilder().setDaemon(true).build()));\n    }\n\n    /**\n     * Constructor for use with a DataSource which will provide using 10 threads fixed pool executor\n     *\n     * @param dataSource may or may not be FiberDataSource\n     */\n    public FiberDBI(DataSource dataSource) {\n        this(dataSource, 10);\n    }\n\n    @Override\n    @Suspendable\n    public Handle open() {\n        return jdbi.open();\n    }\n\n    @Override\n    @Suspendable\n    public <ReturnType> ReturnType withHandle(HandleCallback<ReturnType> callback) throws CallbackFailedException {\n        return jdbi.withHandle(callback);\n    }\n\n    @Override\n    @Suspendable\n    public void useHandle(HandleConsumer callback) throws CallbackFailedException {\n        jdbi.useHandle(callback);\n    }\n\n    @Override\n    @Suspendable\n    public <SqlObjectType> SqlObjectType open(Class<SqlObjectType> sqlObjectType) {\n        return jdbi.open(sqlObjectType);\n    }\n\n    @Override\n    @Suspendable\n    public void close(Object sqlObject) {\n        jdbi.close(sqlObject);\n    }\n\n    @Override\n    public <SqlObjectType> SqlObjectType onDemand(Class<SqlObjectType> sqlObjectType) {\n        return jdbi.onDemand(sqlObjectType);\n    }\n\n    @Override\n    @Suspendable\n    public <ReturnType> ReturnType inTransaction(TransactionCallback<ReturnType> callback) throws CallbackFailedException {\n        return jdbi.inTransaction(callback);\n    }\n\n    @Override\n    @Suspendable\n    public void useTransaction(TransactionConsumer callback) throws CallbackFailedException {\n        jdbi.useTransaction(callback);\n    }\n\n    @Override\n    @Suspendable\n    public <ReturnType> ReturnType inTransaction(TransactionIsolationLevel isolation, TransactionCallback<ReturnType> callback) throws CallbackFailedException {\n        return jdbi.inTransaction(isolation, callback);\n    }\n\n    @Override\n    @Suspendable\n    public void useTransaction(TransactionIsolationLevel isolation, TransactionConsumer callback) throws CallbackFailedException {\n        jdbi.useTransaction(isolation, callback);\n    }\n\n    @Override\n    public void define(String key, Object value) {\n        jdbi.define(key, value);\n    }\n}\n"
  },
  {
    "path": "comsat-jdbi/src/main/java/co/paralleluniverse/fibers/jdbi/JdbiClassifier.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbi;\n\nimport co.paralleluniverse.fibers.instrument.LogLevel;\nimport co.paralleluniverse.fibers.instrument.MethodDatabase;\nimport co.paralleluniverse.fibers.instrument.SimpleSuspendableClassifier;\nimport co.paralleluniverse.fibers.instrument.SuspendableClassifier;\nimport co.paralleluniverse.fibers.instrument.SuspendableHelper;\n\n/**\n * Given classes and methodRegexps, Instrumenting all the extending methods in \n * the scope of given package prefix.\n */\npublic class JdbiClassifier implements SuspendableClassifier {\n    private static final String PKG_PREFIX = \"org/skife/jdbi/v2\";\n    String[][] methodsArray = {\n        {\"org/skife/jdbi/v2/IDBI\", \"open\"},\n        {\"org/skife/jdbi/v2/Handle\", \"execute\", \"update\", \"close\", \"begin\", \"commit\", \"rollback\", \"execute\", \"checkpoint\", \"release\"},\n        {\"org/skife/jdbi/v2/ResultBearing\", \"first\", \"list\"},\n        {\"org/skife/jdbi/v2/QueryResultMunger\", \"munge\"},\n        {\"org/skife/jdbi/v2/Cleanable\", \"cleanup\"},\n\n        {\"org/skife/jdbi/v2/sqlobject/Handler\", \"invoke\"},\n        {\"org/skife/jdbi/v2/sqlobject/HandleDing\", \"getHandle\", \"release\", \"retain\"},\n        {\"org/skife/jdbi/v2/sqlobject/UpdateHandler$Returner\", \"value\"},\n        {\"org/skife/jdbi/v2/sqlobject/ResultReturnThing\", \"result\"},\n\n        {\"org/skife/jdbi/v2/sqlobject/mixins/Transactional\", \"begin\", \"commit\", \"rollback\", \"checkpoint\", \"release\"},\n\n        {\"org/skife/jdbi/v2/tweak/TransactionHandler\", \"begin\", \"commit\", \"rollback\", \"checkpoint\", \"release\"},\n        {\"org/skife/jdbi/v2/tweak/ConnectionFactory\", \"openConnection\"},\n        {\"org/skife/jdbi/v2/tweak/StatementCustomizer\", \"beforeExecution\", \"afterExecution\", \"cleanup\"},\n        {\"org/skife/jdbi/v2/tweak/RewrittenStatement\", \"bind\"},\n        {\"org/skife/jdbi/v2/tweak/ResultSetMapper\", \"map\"},\n        {\"org/skife/jdbi/v2/tweak/ResultColumnMapper\", \"mapColumn\"},\n        {\"org/skife/jdbi/v2/tweak/Argument\", \"apply\"},\n        {\"org/skife/jdbi/v2/tweak/StatementBuilder\", \"create\", \"beforeExecution\", \"close\"},\n        {\"org/skife/jdbi/v2/tweak/ConnectionFactory\", \"openConnection\"},\n\n        {\"org/skife/jdbi/v2/util/TypedMapper\", \"extractByName\", \"extractByIndex\"},\n    };\n\n    @Override\n    public MethodDatabase.SuspendableType isSuspendable (\n        MethodDatabase db,\n        String sourceName, String sourceDebugInfo,\n        boolean isInterface, String className, String superClassName, String[] interfaces,\n        String methodName, String methodDesc, String methodSignature, String[] methodExceptions\n    ) {\n        // Declares given methods as supers\n        for (String[] susExtendables : methodsArray) {\n            if (isJDBICGLibProxy(className, methodName)) {\n                return MethodDatabase.SuspendableType.SUSPENDABLE;\n            } else if (className.equals(susExtendables[0]))\n                for (int i = 1; i < susExtendables.length; i++) {\n                    if (methodName.matches(susExtendables[i])) {\n                        if (db.isVerbose())\n                            db.getLog().log(LogLevel.INFO, JdbiClassifier.class.getName() + \": \" + className + \".\" + methodName + \" supersOrEqual \" + susExtendables[0] + \".\" + susExtendables[i]);\n                        return MethodDatabase.SuspendableType.SUSPENDABLE;\n                    }\n                }\n        }\n\n        // Declares extending classes in jooq packages as suspendables\n        if (!className.startsWith(PKG_PREFIX))\n            return null;\n        for (String[] susExtendables : methodsArray) {\n            if (SimpleSuspendableClassifier.extendsOrImplements(susExtendables[0], db, className, superClassName, interfaces))\n                for (int i = 1; i < susExtendables.length; i++) {\n                    if (methodName.matches(susExtendables[i])) {\n                        if (db.isVerbose())\n                            db.getLog().log(LogLevel.INFO, JdbiClassifier.class.getName() + \": \" + className + \".\" + methodName + \" extends \" + susExtendables[0] + \".\" + susExtendables[i]);\n                        return MethodDatabase.SuspendableType.SUSPENDABLE;\n                    }\n                }\n        }\n        return null;\n    }\n\n    private boolean isJDBICGLibProxy(String className, String methodName) {\n        boolean ret = className.startsWith(\"org/skife/jdbi/v2/sqlobject/CloseInternalDoNotUseThisClass$$EnhancerByCGLIB$$\") && !methodName.startsWith(\"<\");\n        if (ret)\n            SuspendableHelper.addWaiver(className.replace(\"/\", \".\"), methodName); // @Instrumented added during instrumentation seems not to stick to CGLIB proxies, let verification know\n        return ret;\n    }\n}\n"
  },
  {
    "path": "comsat-jdbi/src/main/resources/META-INF/services/co.paralleluniverse.fibers.instrument.SuspendableClassifier",
    "content": "co.paralleluniverse.fibers.jdbi.JdbiClassifier"
  },
  {
    "path": "comsat-jdbi/src/main/resources/META-INF/suspendables",
    "content": "org.skife.jdbi.v2.SQLStatement.internalExecute\norg.skife.jdbi.v2.Update.execute\norg.skife.jdbi.v2.Update.executeAndReturnGeneratedKeys\norg.skife.jdbi.v2.Query.fold\norg.skife.jdbi.v2.BaseStatement.beforeExecution \norg.skife.jdbi.v2.BaseStatement.cleanup\norg.skife.jdbi.v2.sqlobject.SqlObject.invoke\norg.skife.jdbi.v2.sqlobject.SqlObject$1.intercept\norg.skife.jdbi.v2.sqlobject.SqlObject$2.intercept\norg.skife.jdbi.v2.sqlobject.UpdateHandler.invoke\norg.skife.jdbi.v2.sqlobject.UpdateHandler$1.value\norg.skife.jdbi.v2.sqlobject.UpdateHandler$2.value\norg.skife.jdbi.v2.sqlobject.ResultReturnThing.map\norg.skife.jdbi.v2.sqlobject.FigureItOutResultSetMapper.map\norg.skife.jdbi.v2.tweak.transactions.LocalTransactionHandler.restoreAutoCommitState\n"
  },
  {
    "path": "comsat-jdbi/src/test/java/co/paralleluniverse/fibers/jdbi/FiberFluentAPITest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbi;\n\nimport co.paralleluniverse.embedded.db.H2JdbcDatasource;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport javax.sql.DataSource;\nimport org.junit.AfterClass;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Before;\nimport org.junit.BeforeClass;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\nimport org.skife.jdbi.v2.Handle;\nimport org.skife.jdbi.v2.IDBI;\nimport org.skife.jdbi.v2.sqlobject.Bind;\nimport org.skife.jdbi.v2.sqlobject.SqlUpdate;\nimport org.skife.jdbi.v2.sqlobject.mixins.Transactional;\nimport org.skife.jdbi.v2.tweak.HandleCallback;\nimport org.skife.jdbi.v2.util.StringMapper;\n\n@RunWith(Parameterized.class)\npublic class FiberFluentAPITest {\n\n    @Suspendable\n    public interface TestDAO extends Transactional<TestDAO> {\n        @SqlUpdate(\"insert into test (id, name) values (:id, :name)\")\n        void insert(@Bind(\"id\")long id, @Bind(\"name\") String name);\n    }\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {H2JdbcDatasource.class},});\n    }\n    private final Class<? extends DataSource> cls;\n    private IDBI jdbi;\n\n    public FiberFluentAPITest(Class<? extends DataSource> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        DataSource ds = cls.newInstance();\n        // snippet creation\n        this.jdbi = new FiberDBI(ds);\n        // end of snippet\n    }\n\n    @Test\n    public void testOpen() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try (Handle h = jdbi.open()) {\n                    h.execute(\"create table if not exists testOpen (id int primary key, name varchar(100))\");\n                    h.execute(\"drop table testOpen\");\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testQueryFirst() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                // snippet usage\n                try (Handle h = jdbi.open()) {\n                    h.execute(\"create table  if not exists testQueryFirst (id int primary key, name varchar(100))\");\n                    for (int i = 0; i < 100; i++)\n                        h.execute(\"insert into testQueryFirst (id, name) values (?, ?)\", i, \"stranger \" + i);\n                    assertEquals(\"stranger 37\", h.createQuery(\"select name from testQueryFirst where id = :id\")\n                            .bind(\"id\", 37).map(StringMapper.FIRST).first());\n                    h.execute(\"drop table testQueryFirst\");\n                }\n                // end of snippet\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testQueryList() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try (Handle h = jdbi.open()) {\n                    h.execute(\"create table if not exists testQueryList (id int primary key, name varchar(100))\");\n                    for (int i = 0; i < 100; i++)\n                        h.execute(\"insert into testQueryList (id, name) values (?, ?)\", i, \"stranger \" + i);\n                    assertEquals(37, h.createQuery(\"select name from testQueryList where id < :id order by id\")\n                            .bind(\"id\", 37).map(StringMapper.FIRST).list().size());\n                    h.execute(\"drop table testQueryList\");\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testAttach() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try (Handle h = jdbi.open()) {\n                    createTest(h);\n                    TestDAO dao = h.attach(TestDAO.class);\n                    dao.insert(1, \"Name1\");\n                    dropTest(h);\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testOnDemand() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try (Handle h = jdbi.open()) {\n                    createTest(h);\n                }\n\n                TestDAO dao = jdbi.onDemand(TestDAO.class);\n                dao.insert(2, \"Name2\");\n            \n                try (Handle h = jdbi.open()) {\n                    dropTest(h);\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testTransactionalOnDemand() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try (Handle h = jdbi.open()) {\n                    createTest(h);\n                }\n\n                TestDAO dao = jdbi.onDemand(TestDAO.class);\n                dao.begin();\n                dao.insert(3, \"Name3\");\n                dao.commit();\n\n                try (Handle h = jdbi.open()) {\n                    dropTest(h);\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testWithHandle() throws IOException, InterruptedException, Exception {\n        jdbi.withHandle(new HandleCallback<Void>() {\n                @Override\n                @Suspendable\n                public Void withHandle(Handle h) throws Exception {\n                    createTest(h);\n                    final TestDAO dao = h.attach(TestDAO.class);\n                    dao.insert(4, \"Name4\");\n                    dropTest(h);\n                    return null;\n                }\n            }\n        );\n    }\n\n    @Test\n    public void testTransactionalWithHandle() throws IOException, InterruptedException, Exception {\n        jdbi.withHandle(new HandleCallback<Void>() {\n                @Override\n                @Suspendable\n                public Void withHandle(Handle h) throws Exception {\n                    createTest(h);\n                    final TestDAO dao = h.attach(TestDAO.class);\n                    dao.begin();\n                    dao.insert(5, \"Name5\");\n                    dao.commit();\n                    dropTest(h);\n                    return null;\n                }\n            }\n        );\n    }\n\n    @Suspendable\n    private static void dropTest(Handle h) {\n        h.execute(\"drop table test\");\n    }\n\n    @Suspendable\n    private static void createTest(Handle h) {\n        h.execute(\"create table if not exists test (id int primary key, name varchar(100))\");\n    }\n}\n"
  },
  {
    "path": "comsat-jdbi/src/test/java/co/paralleluniverse/fibers/jdbi/FiberSqlObjectAPITest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jdbi;\n\nimport co.paralleluniverse.embedded.db.H2JdbcDatasource;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport javax.sql.DataSource;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\nimport org.skife.jdbi.v2.sqlobject.Bind;\nimport org.skife.jdbi.v2.sqlobject.SqlQuery;\nimport org.skife.jdbi.v2.sqlobject.SqlUpdate;\n\n@RunWith(Parameterized.class)\npublic class FiberSqlObjectAPITest {\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {H2JdbcDatasource.class},});\n    }\n    private final Class<? extends DataSource> cls;\n    private MyDAO dao;\n\n    public FiberSqlObjectAPITest(Class<? extends DataSource> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        DataSource dataSource = cls.newInstance();\n        // snippet registration\n        this.dao = new FiberDBI(dataSource).onDemand(MyDAO.class);\n        // end of snippet\n    }\n\n    @Test\n    public void testDao() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                // snippet usage\n                dao.createSomethingTable();\n                for (int i = 0; i < 100; i++)\n                    dao.insert(i, \"name\" + i);\n                assertEquals(\"name37\", dao.findNameById(37));\n                dao.dropSomethingTable();\n                // end of snippet\n            }\n        }).start().join();\n    }\n\n    // snippet interface\n    @Suspendable\n    public interface MyDAO {\n        @SqlUpdate(\"create table if not exists something (id int primary key, name varchar(100))\")\n        void createSomethingTable();\n\n        @SqlUpdate(\"drop table something\")\n        void dropSomethingTable();\n\n        @SqlUpdate(\"insert into something (id, name) values (:id, :name)\")\n        void insert(@Bind(\"id\") int id, @Bind(\"name\") String name);\n\n        @SqlQuery(\"select name from something where id = :id\")\n        String findNameById(@Bind(\"id\") int id);\n    }\n    // end of snippet\n}\n"
  },
  {
    "path": "comsat-jersey-server/src/main/java/co/paralleluniverse/fibers/jersey/ServletContainer.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jersey;\n\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.fibers.servlet.FiberHttpServlet;\nimport java.io.IOException;\nimport java.net.URI;\nimport java.util.Enumeration;\nimport javax.servlet.Filter;\nimport javax.servlet.FilterChain;\nimport javax.servlet.FilterConfig;\nimport javax.servlet.ServletConfig;\nimport javax.servlet.ServletContext;\nimport javax.servlet.ServletException;\nimport javax.servlet.ServletRequest;\nimport javax.servlet.ServletResponse;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport org.glassfish.jersey.internal.util.collection.Value;\nimport org.glassfish.jersey.server.ApplicationHandler;\nimport org.glassfish.jersey.server.ResourceConfig;\nimport org.glassfish.jersey.server.spi.Container;\n\n/**\n * A Servlet for deploying root resource classes that assign a fiber per request.\n *\n * @see org.glassfish.jersey.servlet.ServletContainer\n * @author eitan\n */\npublic class ServletContainer extends FiberHttpServlet implements Filter, Container {\n    private static final int DEFAULT_STACK_SIZE = 120;\n    private final org.glassfish.jersey.servlet.ServletContainer jerseySC;\n\n    /**\n     * Create Jersey Servlet container.\n     */\n    public ServletContainer() {\n        this.jerseySC = new org.glassfish.jersey.servlet.ServletContainer();\n    }\n\n    /**\n     * Create Jersey Servlet container.\n     *\n     * @param resourceConfig container configuration.\n     */\n    public ServletContainer(ResourceConfig resourceConfig) {\n        this.jerseySC = new org.glassfish.jersey.servlet.ServletContainer(resourceConfig);\n    }\n\n    /**\n     * Wraps a Jerset Servlet container.\n     *\n     * @param sc the servlet container\n     */\n    public ServletContainer(org.glassfish.jersey.servlet.ServletContainer sc) {\n        this.jerseySC = sc;\n    }\n\n    @Override\n    public void init(ServletConfig config) throws ServletException {\n        super.init(config);\n        if (getStackSize() <= 0)\n            setStackSize(DEFAULT_STACK_SIZE);\n    }\n\n    /**\n     * Get the servlet context for the servlet or filter, depending on\n     * how this class is registered.\n     *\n     * @return the servlet context for the servlet or filter.\n     */\n    @Override\n    public ServletContext getServletContext() {\n        return jerseySC.getServletContext();\n    }\n\n    @Override\n    @Suspendable\n    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {\n        jerseySC.service(req, res);\n    }\n\n    // Delegations\n    @Override\n    public void destroy() {\n        jerseySC.destroy();\n    }\n\n    @Override\n    public void init() throws ServletException {\n        jerseySC.init(getServletConfig());\n    }\n\n    /**\n     * Dispatch client requests to a resource class.\n     *\n     * @param baseUri    the base URI of the request.\n     * @param requestUri the URI of the request.\n     * @param request    the {@link javax.servlet.http.HttpServletRequest} object that contains the request the client made to the Web component.\n     * @param response   the {@link javax.servlet.http.HttpServletResponse} object that contains the response the Web component returns to the client.\n     * @return lazily initialized response status code {@link Value value provider}.\n     * @throws IOException      if an input or output error occurs while the Web component is handling the HTTP request.\n     * @throws ServletException if the HTTP request cannot be handled.\n     */\n    public Value<Integer> service(URI baseUri, URI requestUri, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        return jerseySC.service(baseUri, requestUri, request, response);\n    }\n\n    @Override\n    public void init(FilterConfig filterConfig) throws ServletException {\n        jerseySC.init(filterConfig);\n    }\n\n    @Override\n    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {\n        jerseySC.doFilter(servletRequest, servletResponse, filterChain);\n    }\n\n    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {\n        jerseySC.doFilter(request, response, chain);\n    }\n\n    @Override\n    public ResourceConfig getConfiguration() {\n        return jerseySC.getConfiguration();\n    }\n\n    @Override\n    public void reload() {\n        jerseySC.reload();\n    }\n\n    @Override\n    public void reload(ResourceConfig configuration) {\n        jerseySC.reload(configuration);\n    }\n\n    @Override\n    public String getInitParameter(String name) {\n        return jerseySC.getInitParameter(name);\n    }\n\n    @Override\n    public Enumeration<String> getInitParameterNames() {\n        return jerseySC.getInitParameterNames();\n    }\n\n    @Override\n    public String getServletInfo() {\n        return jerseySC.getServletInfo();\n    }\n\n    @Override\n    public void log(String msg) {\n        jerseySC.log(msg);\n    }\n\n    @Override\n    public void log(String message, Throwable t) {\n        jerseySC.log(message, t);\n    }\n\n    @Override\n    public String getServletName() {\n        return jerseySC.getServletName();\n    }\n\n    @Override\n    public int hashCode() {\n        return jerseySC.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        return jerseySC.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return jerseySC.toString();\n    }\n\n    @Override\n    public ApplicationHandler getApplicationHandler() {\n        return jerseySC.getApplicationHandler();\n    }\n}"
  },
  {
    "path": "comsat-jersey-server/src/main/java/co/paralleluniverse/fibers/jersey/package-info.java",
    "content": "/*\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n * \n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *  \n *   or (per the licensee's choosing)\n *  \n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/**\n * {@link javax.ws.rs JAX-RS Server} Integration for Quasar Fibers Using <a href=\"https://jersey.java.net/\">Jersey</a>\n */\npackage co.paralleluniverse.fibers.jersey;\n"
  },
  {
    "path": "comsat-jersey-server/src/main/resources/META-INF/suspendable-supers",
    "content": "javax.ws.rs.container.ContainerRequestFilter.filter\njavax.ws.rs.container.ContainerResponseFilter.filter\norg.glassfish.jersey.process.internal.Stage.apply\n"
  },
  {
    "path": "comsat-jersey-server/src/main/resources/META-INF/suspendables",
    "content": "org.glassfish.jersey.process.Inflector.apply\norg.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke\norg.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke\norg.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch\norg.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run\norg.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch\norg.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch\norg.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$VoidOutInvoker.doDispatch\norg.glassfish.jersey.server.model.ResourceMethodInvoker.invoke\norg.glassfish.jersey.server.model.ResourceMethodInvoker.apply\norg.glassfish.jersey.server.ServerRuntime$Responder.process\norg.glassfish.jersey.server.ServerRuntime$1.run\norg.glassfish.jersey.server.ServerRuntime$2.run\norg.glassfish.jersey.server.ContainerFilteringStage.apply\norg.glassfish.jersey.server.ContainerFilteringStage$ResponseFilterStage.apply\norg.glassfish.jersey.internal.Errors$1.call\norg.glassfish.jersey.internal.Errors.process\norg.glassfish.jersey.process.internal.RequestScope.runInScope\norg.glassfish.jersey.process.internal.Stages.process\norg.glassfish.jersey.server.ServerRuntime.process\norg.glassfish.jersey.server.ApplicationHandler.handle\norg.glassfish.jersey.servlet.internal.ResponseWriter.failure\norg.glassfish.jersey.servlet.internal.ResponseWriter.rethrow\norg.glassfish.jersey.servlet.WebComponent.service\norg.glassfish.jersey.servlet.WebComponent.serviceImpl\norg.glassfish.jersey.servlet.ServletContainer.service\n"
  },
  {
    "path": "comsat-jersey-server/src/test/java/co/paralleluniverse/fibers/jersey/AddTestFiltersFeature.java",
    "content": "package co.paralleluniverse.fibers.jersey;\n\nimport java.io.IOException;\n\nimport javax.ws.rs.container.ContainerRequestContext;\nimport javax.ws.rs.container.ContainerRequestFilter;\nimport javax.ws.rs.container.ContainerResponseContext;\nimport javax.ws.rs.container.ContainerResponseFilter;\nimport javax.ws.rs.core.Feature;\nimport javax.ws.rs.core.FeatureContext;\nimport javax.ws.rs.ext.Provider;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\n\n@Provider\npublic class AddTestFiltersFeature implements Feature {\n\n    @Override\n    public boolean configure(FeatureContext context) {\n        context.register(TestRequestFilter.class);\n        context.register(TestResponseFilter.class);\n        return true;\n    }\n\n}\n\nclass TestRequestFilter implements ContainerRequestFilter {\n\n    @Override\n    @Suspendable\n    public void filter(ContainerRequestContext requestContext) throws IOException {\n        try {\n            Fiber.sleep(5);\n            requestContext.getHeaders().add(FiberServletContainerTest.REQUEST_FILTER_HEADER,\n                    FiberServletContainerTest.REQUEST_FILTER_HEADER_VALUE);\n        } catch (InterruptedException | SuspendExecution e) {\n            throw new Error(e);\n        }\n    }\n}\n\nclass TestResponseFilter implements ContainerResponseFilter {\n\n    @Override\n    @Suspendable\n    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)\n            throws IOException {\n        try {\n            Fiber.sleep(5);\n            responseContext.getHeaders().add(FiberServletContainerTest.RESPONSE_FILTER_HEADER,\n                    FiberServletContainerTest.RESPONSE_FILTER_HEADER_VALUE);\n        } catch (InterruptedException | SuspendExecution e) {\n            throw new Error(e);\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-jersey-server/src/test/java/co/paralleluniverse/fibers/jersey/FiberServletContainerTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jersey;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Collection;\n\nimport org.apache.http.Header;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.HttpResponseException;\nimport org.apache.http.client.ResponseHandler;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.impl.client.AbstractResponseHandler;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.util.EntityUtils;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.TestName;\nimport org.junit.rules.TestRule;\nimport org.junit.rules.TestWatcher;\nimport org.junit.runner.Description;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\nimport co.paralleluniverse.common.util.Debug;\nimport co.paralleluniverse.embedded.containers.EmbeddedServer;\nimport co.paralleluniverse.embedded.containers.JettyServer;\nimport co.paralleluniverse.embedded.containers.TomcatServer;\nimport co.paralleluniverse.embedded.containers.UndertowServer;\n\n@RunWith(Parameterized.class)\npublic class FiberServletContainerTest {\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {JettyServer.class},\n            {TomcatServer.class},\n            {UndertowServer.class},\n        });\n    }\n    private final Class<? extends EmbeddedServer> cls;\n    private EmbeddedServer server;\n    private CloseableHttpClient client;\n\n    public FiberServletContainerTest(Class<? extends EmbeddedServer> cls) {\n        this.cls = cls;\n    }\n    private static final String PACKAGE_NAME_PREFIX = FiberServletContainerTest.class.getPackage().getName() + \".\";\n\n    public static final String REQUEST_FILTER_HEADER = \"test.filter.request.header\";\n\n    public static final String REQUEST_FILTER_HEADER_VALUE = \"ok\";\n\n    public static final String RESPONSE_FILTER_HEADER = \"test.filter.request.header\";\n\n    public static final String RESPONSE_FILTER_HEADER_VALUE = \"ok\";\n\n    @Before\n    public void setUp() throws Exception {\n        this.server = cls.newInstance();\n        // snippet jersey registration\n        server.addServlet(\"api\", co.paralleluniverse.fibers.jersey.ServletContainer.class, \"/*\")\n                .setInitParameter(\"jersey.config.server.provider.packages\", PACKAGE_NAME_PREFIX)\n                // end of snippet\n                .setLoadOnStartup(1);\n        server.start();\n        this.client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()\n                .setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000)\n                .build()).build();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        server.stop();\n        client.close();\n    }\n\n    @Test\n    public void testGet() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            client.execute(new HttpGet(\"http://localhost:8080/service?sleep=10\"), TEST_RESPONSE_HANDLER);\n    }\n\n    @Test\n    public void testPost() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            client.execute(new HttpPost(\"http://localhost:8080/service?sleep=10\"), TEST_RESPONSE_HANDLER);\n    }\n\n    private static final ResponseHandler<Void> TEST_RESPONSE_HANDLER = new AbstractResponseHandler<Void>() {\n        @Override\n        public Void handleEntity(HttpEntity entity) throws IOException {\n            assertEquals(\"sleep was 10\", EntityUtils.toString(entity));\n            return null;\n        }\n\n        @Override\n        public Void handleResponse(HttpResponse response) throws HttpResponseException, IOException {\n            Header h = response.getFirstHeader(RESPONSE_FILTER_HEADER);\n            assertNotNull(h);\n            assertEquals(RESPONSE_FILTER_HEADER_VALUE, h.getValue());\n            return super.handleResponse(response);\n        }\n    };\n\n    @Rule\n    public TestName name = new TestName();\n    @Rule\n    public TestRule watchman = new TestWatcher() {\n        @Override\n        protected void starting(Description desc) {\n            if (Debug.isDebug()) {\n                System.out.println(\"STARTING TEST \" + desc.getMethodName());\n                Debug.record(0, \"STARTING TEST \" + desc.getMethodName());\n            }\n        }\n\n        @Override\n        public void failed(Throwable e, Description desc) {\n            System.out.println(\"FAILED TEST \" + desc.getMethodName() + \": \" + e.getMessage());\n            e.printStackTrace(System.err);\n            if (Debug.isDebug() && !(e instanceof OutOfMemoryError)) {\n                Debug.record(0, \"EXCEPTION IN THREAD \" + Thread.currentThread().getName() + \": \" + e + \" - \" + Arrays.toString(e.getStackTrace()));\n                Debug.dumpRecorder(\"~/quasar.dump\");\n            }\n        }\n\n        @Override\n        protected void succeeded(Description desc) {\n            Debug.record(0, \"DONE TEST \" + desc.getMethodName());\n        }\n    };\n\n}\n"
  },
  {
    "path": "comsat-jersey-server/src/test/java/co/paralleluniverse/fibers/jersey/TestResource.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jersey;\n\nimport javax.inject.Singleton;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.HeaderParam;\nimport javax.ws.rs.POST;\nimport javax.ws.rs.Path;\nimport javax.ws.rs.Produces;\nimport javax.ws.rs.QueryParam;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\n\n// snippet REST resource example\n@Singleton\n@Path(\"/service\")\npublic class TestResource {\n    @GET\n    @Produces(\"text/plain\")\n    @Suspendable  // <------------- FIBER\n    public String get(@QueryParam(\"sleep\") int sleep,\n            @HeaderParam(FiberServletContainerTest.REQUEST_FILTER_HEADER) String h)\n            throws SuspendExecution, InterruptedException {\n        Fiber.sleep(sleep); // <--- you may use fiber blocking calls here\n        // ensure the request filter was called\n        if (FiberServletContainerTest.REQUEST_FILTER_HEADER_VALUE.equals(h)) {\n            return \"sleep was \" + sleep;\n        } else {\n            return \"missing header!\";\n        }\n\n    }\n    // snippet_exclude_begin\n    @POST\n    @Produces(\"text/plain\")\n    @Suspendable  // <------------- FIBER\n    public String post(@QueryParam(\"sleep\") int sleep,\n            @HeaderParam(FiberServletContainerTest.REQUEST_FILTER_HEADER) String h)\n            throws SuspendExecution, InterruptedException {\n        return get(sleep, h);\n    }\n    // snippet_exclude_end\n}\n// end of snippet\n"
  },
  {
    "path": "comsat-jetty-loader/build.gradle",
    "content": "sourceSets {\n    jdk7 {\n        java {\n            srcDir 'src/main/java'\n        }\n            \n        compileClasspath += main.compileClasspath\n        runtimeClasspath += main.runtimeClasspath\n    }\n    jdk8 {\n        java {\n            srcDir 'src/main/java'\n        }\n            \n        compileClasspath += main.compileClasspath\n        runtimeClasspath += main.runtimeClasspath\n    }\n}\n\ncompileJdk7Java {\n    sourceCompatibility = '1.7'\n    targetCompatibility = '1.7'\n}\n\ncompileJdk8Java {\n    sourceCompatibility = '1.8'\n    targetCompatibility = '1.8'\n}\n\ndependencies {\n    jdk7Compile \"co.paralleluniverse:quasar-core:$quasarVer\"\n    jdk8Compile \"co.paralleluniverse:quasar-core:$quasarVer:jdk8\"\n    compile \"org.eclipse.jetty:jetty-webapp:$jettyVer\"\n    testCompile (project(':comsat-test-utils')) {\n        exclude group: 'org.apache.tomcat.embed', module: '*'         \n    }\n    testRuntime \"org.slf4j:slf4j-log4j12:$slf4jApiVer\"\n    testRuntime \"log4j:log4j:$log4jVer\"\n    testRuntime project(':comsat-jdbc')\n}\n\ndef ssets = [sourceSets.jdk7]\nif(ext.java8) {\n    ssets += sourceSets.jdk8\n}\nssets.each { set ->\n    def jarTask = task(\"${set.name}Jar\", type: Jar) {\n        from set.output\n        from { project.configurations[\"${set.name}Runtime\"].collect { it.isDirectory() ? it : zipTree(it) } }\n    } \n\n    artifacts {\n        archives jarTask\n    }\n\n    assemble.dependsOn jarTask\n}\n\nif (ext.java8) {\n    jdk8Jar {\n        classifier = 'jdk8'\n    }\n}\n\nartifacts {\n    archives sourcesJar\n    archives javadocJar\n}\n\ntask deployWar(type: Copy) {\n    evaluationDependsOn \":comsat-test-war\"\n    from project(\":comsat-test-war\").war\n    into \"build/wars\"\n    rename (\".*war\",\"dep.war\")\n}\n\ntasks.withType(Test) {\n    dependsOn deployWar\n}\n"
  },
  {
    "path": "comsat-jetty-loader/src/main/java/co/paralleluniverse/comsat/jetty/QuasarWebAppClassLoader.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.jetty;\n\nimport co.paralleluniverse.fibers.instrument.QuasarURLClassLoaderHelper;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport org.eclipse.jetty.webapp.WebAppClassLoader;\n\n/**\n * See:\n * http://wiki.eclipse.org/Jetty/Reference/Jetty_Classloading\n *\n * @author pron\n */\npublic class QuasarWebAppClassLoader extends WebAppClassLoader {\n    private final QuasarURLClassLoaderHelper helper;\n\n    public QuasarWebAppClassLoader(Context context) throws IOException {\n        super(context);\n        this.helper = new QuasarURLClassLoaderHelper(this);\n//        helper.setLog(true, true);\n    }\n\n    public QuasarWebAppClassLoader(ClassLoader parent, Context context) throws IOException {\n        super(parent, context);\n        this.helper = new QuasarURLClassLoaderHelper(this);\n//        helper.setLog(true, true);\n    }\n\n    @Override\n    protected Class<?> findClass(String name) throws ClassNotFoundException {\n        return helper.findClass(name);\n    }\n\n    @Override\n    public InputStream getResourceAsStream(String name) {\n        return helper.instrumentResourceStream(name, super.getResourceAsStream(name));\n    }\n}\n"
  },
  {
    "path": "comsat-jetty-loader/src/test/java/co/paralleluniverse/embedded/containers/JettyLoaderTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.containers;\n\nimport java.io.IOException;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.eclipse.jetty.deploy.DeploymentManager;\nimport org.eclipse.jetty.deploy.providers.WebAppProvider;\nimport org.eclipse.jetty.plus.jndi.Resource;\nimport org.eclipse.jetty.server.Server;\nimport org.eclipse.jetty.server.handler.ContextHandlerCollection;\nimport org.h2.jdbcx.JdbcDataSource;\nimport org.junit.After;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.Before;\nimport org.junit.Test;\n\npublic class JettyLoaderTest {\n    private CloseableHttpClient client;\n    private Server server;\n\n    @Before\n    public void setUp() throws Exception {\n        this.server = new Server(8080);\n        scanDirForWebApps(server, \"build/resources/test/webapps\");\n        Resource r = new Resource(\"jdbc/globalds\",\n                createDataSource(\"jdbc:h2:./build/h2testdb\"));\n        server.start();\n        this.client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()\n                .setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000)\n                .build()).build();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        server.stop();\n        client.close();\n    }\n\n    @Test\n    public void testGetDeployedWar() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++) {\n            String result = client.execute(new HttpGet(\"http://localhost:8080/\"), BASIC_RESPONSE_HANDLER);\n            assertTrue(result.contains(\"h2testdb\"));\n        }\n    }\n\n    private static final BasicResponseHandler BASIC_RESPONSE_HANDLER = new BasicResponseHandler();\n\n    private static JdbcDataSource createDataSource(final String url) {\n        JdbcDataSource ds = new JdbcDataSource();\n        ds.setURL(url);\n        return ds;\n    }\n\n    private static void scanDirForWebApps(final Server server, final String path) {\n        WebAppProvider wap = new WebAppProvider();\n        wap.setMonitoredDirName(path);\n        wap.setExtractWars(true);\n\n        DeploymentManager dm = new DeploymentManager();\n        dm.setContexts(new ContextHandlerCollection());\n        dm.addAppProvider(wap);\n\n        server.setHandler(dm.getContexts());\n        server.addBean(dm);\n    }\n}\n"
  },
  {
    "path": "comsat-jetty-loader/src/test/resources/log4j.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">\n\n<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\">\n  <appender name=\"console\" class=\"org.apache.log4j.ConsoleAppender\"> \n    <param name=\"Target\" value=\"System.out\"/> \n    <layout class=\"org.apache.log4j.PatternLayout\"> \n      <param name=\"ConversionPattern\" value=\"%-5p %c{1} - %m%n\"/> \n    </layout> \n  </appender> \n\n  <root> \n    <priority value =\"debug\" /> \n    <appender-ref ref=\"console\" /> \n  </root>\n  \n</log4j:configuration>"
  },
  {
    "path": "comsat-jetty-loader/src/test/resources/webapps/dep.xml",
    "content": "<?xml version=\"1.0\"  encoding=\"UTF-8\"?>\n<!DOCTYPE Configure PUBLIC \n    \"-//Mort Bay Consulting//DTD Configure//EN\" \n    \"http://www.eclipse.org/jetty/configure_9_0.dtd\">\n\n<!-- snippet context xml --> \n<Configure id=\"ctx\" class=\"org.eclipse.jetty.webapp.WebAppContext\">\n    <Set name=\"war\">./build/wars/dep.war</Set>\n    <!--use custom classloader in order to instrument classes by quasar-->\n    <Set name=\"classLoader\">\n        <New class=\"co.paralleluniverse.comsat.jetty.QuasarWebAppClassLoader\">\n            <Arg>\n                <Ref id=\"ctx\"/>\n            </Arg>\n        </New>\n    </Set>\n    <!-- snippet_exclude_begin -->\n    <Set name=\"configurationClasses\">\n        <Array type=\"java.lang.String\">\n            <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>\n            <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <!--jetty-env.xml-->\n            <Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item> <!--jetty-env.xml-->\n            <Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item> <!--@WebServlet-->\n        </Array>\n    </Set>\n    <!-- snippet_exclude_end -->\n</Configure>\n<!-- end of snippet -->"
  },
  {
    "path": "comsat-jooq/src/main/java/co/paralleluniverse/fibers/jooq/JooqClassifier.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.jooq;\n\nimport co.paralleluniverse.fibers.instrument.LogLevel;\nimport co.paralleluniverse.fibers.instrument.MethodDatabase;\nimport co.paralleluniverse.fibers.instrument.SimpleSuspendableClassifier;\nimport co.paralleluniverse.fibers.instrument.SuspendableClassifier;\n\n/**\n * Given classes and methodRegexps, Instrumenting all the extending methods in \n * the scope of given package prefix.\n */\npublic class JooqClassifier implements SuspendableClassifier {\n    private static final String PKG_PREFIX = \"org/jooq\";\n    String[][] methodsArray = {\n        {\"java/util/Iterator\", \"hasNext\"},\n        {\"java/sql/Statement\", \".*\"},\n        {\"java/sql/Connection\", \".*\"},\n\n        {\"org/jooq/Context\", \"visit\", \"bindValue\"},\n        {\"org/jooq/Binding\", \"register\", \"get\", \"set\"},\n        {\"org/jooq/QueryPartInternal\", \"accept\", \"bind\"},\n        {\"org/jooq/BindContext\", \"bind\", \"bindValue\", \"bindValues\"},\n        {\"org/jooq/Query\", \"execute\"},\n        {\"org/jooq/ResultQuery\", \"getResult\", \"fetch.*\"},\n        {\"org/jooq/Cursor\", \"fetch.*\", \"hasNext\"},\n        {\"org/jooq/InsertResultStep\", \"fetch.*\"},\n\n        {\"org/jooq/impl/RecordOperation\", \"operate\"},\n\n        {\"org/jooq/impl/AbstractField\", \"accept\"},\n        {\"org/jooq/impl/AbstractQuery\", \"prepare\"},\n        {\"org/jooq/impl/AbstractContext\", \"visit0\"},\n        {\"org/jooq/impl/AbstractBindContext\", \"bindValue0\", \"bindInternal\"},\n        {\"org/jooq/impl/AbstractStoreQuery\", \"accept0\"},\n        {\"org/jooq/impl/AbstractDMLQuery\", \"accept0\"},\n        {\"org/jooq/impl/AbstractResultQuery\", \"getFields\"},\n\n        {\"org/jooq/impl/InsertQueryImpl\", \"toSQLInsert\"},\n        {\"org/jooq/impl/SelectQueryImpl\", \"toSQLReference0\", \"toSQLReferenceLimitDefault\"},\n        {\"org/jooq/impl/CursorImpl$CursorIterator\", \"fetch.*\"},\n        {\"org/jooq/impl/CursorImpl$CursorIterator\", \"hasNext\"},\n        {\"org/jooq/impl/CursorImpl$CursorIterator$CursorRecordInitialiser\", \"setValue\"},\n        {\"org/jooq/impl/CursorImpl$CursorResultSet\", \".*\"},\n        {\"org/jooq/impl/CursorImpl\", \"close\"},\n        {\"org/jooq/impl/RecordDelegate\", \"operate\"},\n        {\"org/jooq/impl/DSL\", \"using\"},\n\n        {\"org/jooq/DSLContext\", \"fetch.*\", \"execute.*\"},\n\n        {\"org/jooq/tools/jdbc/JDBCUtils\", \"dialect\", \"safeClose\"},\n        {\"org/jooq/impl/Utils\", \"safeClose\", \"consumeWarnings\", \"fetch.*\"},\n        {\"org/jooq/impl/MetaDataFieldProvider\", \"init\"},\n    };\n\n    @Override\n    public MethodDatabase.SuspendableType isSuspendable (\n        MethodDatabase db,\n        String sourceName, String sourceDebugInfo,\n        boolean isInterface, String className, String superClassName, String[] interfaces,\n        String methodName, String methodDesc, String methodSignature, String[] methodExceptions\n    ) {\n        // declares given methods as supers\n        for (String[] susExtendables : methodsArray) {\n            if (className.equals(susExtendables[0]))\n                for (int i = 1; i < susExtendables.length; i++) {\n                    if (methodName.matches(susExtendables[i])) {\n                        if (db.isVerbose())\n                            db.getLog().log(LogLevel.INFO, JooqClassifier.class.getName() + \": \" + className + \".\" + methodName + \" supersOrEqual \" + susExtendables[0] + \".\" + susExtendables[i]);\n                        return MethodDatabase.SuspendableType.SUSPENDABLE;\n                    }\n                }\n        }\n\n        // declares extending classes in jooq packacages as suspandables\n        if (!className.startsWith(PKG_PREFIX))\n            return null;\n        for (String[] susExtendables : methodsArray) {\n            if (SimpleSuspendableClassifier.extendsOrImplements(susExtendables[0], db, className, superClassName, interfaces))\n                for (int i = 1; i < susExtendables.length; i++) {\n                    if (methodName.matches(susExtendables[i])) {\n                        if (db.isVerbose())\n                            db.getLog().log(LogLevel.INFO, JooqClassifier.class.getName() + \": \" + className + \".\" + methodName + \" extends \" + susExtendables[0] + \".\" + susExtendables[i]);\n                        return MethodDatabase.SuspendableType.SUSPENDABLE;\n                    }\n                }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "comsat-jooq/src/main/resources/META-INF/services/co.paralleluniverse.fibers.instrument.SuspendableClassifier",
    "content": "co.paralleluniverse.fibers.jooq.JooqClassifier"
  },
  {
    "path": "comsat-jooq/src/test/java/co/paralleluniverse/fibers/jooq/JooqContextTest.java",
    "content": "package co.paralleluniverse.fibers.jooq;\n\n/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\nimport co.paralleluniverse.embedded.db.H2JdbcDatasource;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.jdbc.FiberDataSource;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.sql.Connection;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport javax.sql.DataSource;\nimport org.jooq.DSLContext;\nimport org.jooq.Record;\nimport org.jooq.RecordMapper;\nimport static org.jooq.impl.DSL.field;\nimport static org.jooq.impl.DSL.table;\nimport static org.jooq.impl.DSL.using;\nimport org.junit.After;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class JooqContextTest {\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {H2JdbcDatasource.class},});\n    }\n    private final Class<? extends DataSource> dsCls;\n    private Connection conn;\n    private DSLContext ctx;\n\n    public JooqContextTest(Class<? extends DataSource> cls) {\n        this.dsCls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        DataSource dataSource = dsCls.newInstance();\n        // snippet creation\n        this.conn = FiberDataSource.wrap(dataSource).getConnection();\n        this.ctx = using(conn);\n        // end of snippet\n        conn.createStatement().execute(\"create table something (id int primary key, name varchar(100))\");\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        conn.createStatement().execute(\"drop table something\");\n        conn.close();\n    }\n\n    @Test\n    public void testInsertSelect() throws IOException, InterruptedException, Exception {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                // snippet usage\n                for (int i = 0; i < 100; i++)\n                    ctx.insertInto(table(\"something\"), field(\"id\"), field(\"name\")).values(i, \"name\" + i).execute();\n                for (int i = 0; i < 50; i++) {\n                    Something something = ctx.select(field(\"id\"), field(\"name\")).from(table(\"something\")).where(field(\"id\", Integer.class).eq(i)).fetchOne().map(Something.mapper);\n                    assertEquals(\"name\" + i, something.name);\n                }\n                // end of snippet\n            }\n        }).start().join();\n    }\n\n    // snippet mapper\n    public static class Something {\n        public final int id;\n        public final String name;\n        public static RecordMapper<Record, Something> mapper = new RecordMapper<Record, Something>() {\n            @Override\n            public Something map(Record r) {\n                return new Something(r.getValue(field(\"id\", Integer.class)), r.getValue(field(\"name\", String.class)));\n            }\n        };\n\n        public Something(int id, String name) {\n            this.id = id;\n            this.name = name;\n        }\n    }\n    // end of snippet\n}\n"
  },
  {
    "path": "comsat-kafka/src/main/java/co/paralleluniverse/fibers/kafka/FiberKafkaProducer.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.kafka;\n\nimport co.paralleluniverse.strands.SettableFuture;\nimport org.apache.kafka.clients.producer.*;\nimport org.apache.kafka.common.Metric;\nimport org.apache.kafka.common.MetricName;\nimport org.apache.kafka.common.PartitionInfo;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\n\npublic class FiberKafkaProducer<K, V> implements Producer<K, V> {\n\n    private final Producer<K, V> producer;\n\n    public FiberKafkaProducer(Producer<K, V> producer) {\n        this.producer = producer;\n    }\n\n    @Override\n    public Future<RecordMetadata> send(ProducerRecord<K, V> record) {\n        return send(record, null);\n    }\n\n    @Override\n    public Future<RecordMetadata> send(ProducerRecord<K, V> record, Callback callback) {\n        final SettableFuture<RecordMetadata> future = new SettableFuture<>();\n        producer.send(record, new CallbackWrapper(future, callback));\n        return future;\n    }\n\n    @Override\n    public void flush() {\n        producer.flush();\n    }\n\n    @Override\n    public List<PartitionInfo> partitionsFor(String topic) {\n        return producer.partitionsFor(topic);\n    }\n\n    @Override\n    public Map<MetricName, ? extends Metric> metrics() {\n        return producer.metrics();\n    }\n\n    @Override\n    public void close() {\n        producer.close();\n    }\n\n    @Override\n    public void close(long timeout, TimeUnit unit) {\n        producer.close(timeout, unit);\n    }\n\n    private static class CallbackWrapper implements Callback {\n\n        private final SettableFuture<RecordMetadata> future;\n        private final Callback callback;\n\n        public CallbackWrapper(SettableFuture<RecordMetadata> future, Callback callback) {\n            this.future = future;\n            this.callback = callback;\n        }\n\n        @Override\n        public void onCompletion(RecordMetadata metadata, Exception exception) {\n            if (metadata != null) {\n                future.set(metadata);\n            } else {\n                future.setException(exception);\n            }\n            if (callback != null) {\n                callback.onCompletion(metadata, exception);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-kafka/src/test/java/co/paralleluniverse/fibers/kafka/FiberKafkaProducerTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.kafka;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport org.apache.kafka.clients.producer.Callback;\nimport org.apache.kafka.clients.producer.MockProducer;\nimport org.apache.kafka.clients.producer.ProducerRecord;\nimport org.apache.kafka.clients.producer.RecordMetadata;\nimport org.apache.kafka.common.serialization.ByteArraySerializer;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\npublic class FiberKafkaProducerTest {\n\n    private MockProducer<byte[], byte[]> mockProducer;\n    private FiberKafkaProducer<byte[], byte[]> fiberProducer;\n    private co.paralleluniverse.strands.concurrent.Phaser phaser;\n\n    @Before\n    public void setUp() {\n        mockProducer = new MockProducer<>(false, new ByteArraySerializer(), new ByteArraySerializer());\n        fiberProducer = new FiberKafkaProducer<>(mockProducer);\n        phaser = new co.paralleluniverse.strands.concurrent.Phaser(2);\n    }\n\n    @Test\n    public void testSuccessfulSendWithoutCallback() throws InterruptedException, TimeoutException, ExecutionException {\n        Fiber<Void> fiber = new Fiber<>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Future<RecordMetadata> f = fiberProducer.send(new ProducerRecord<>(\"Topic\", \"Key\".getBytes(), \"Value\".getBytes()));\n                Future<RecordMetadata> f2 = fiberProducer.send(new ProducerRecord<>(\"Topic\", \"Key\".getBytes(), \"Value\".getBytes()));\n                phaser.arrive();\n                try {\n                    RecordMetadata recordMetadata = f.get();\n\n                    assertEquals(\"Topic\", recordMetadata.topic());\n                    assertEquals(0, recordMetadata.offset());\n                    assertEquals(0, recordMetadata.partition());\n\n                    RecordMetadata recordMetadata2 = f2.get();\n\n                    assertEquals(\"Topic\", recordMetadata2.topic());\n                    assertEquals(1, recordMetadata2.offset());\n                    assertEquals(0, recordMetadata2.partition());\n                } catch (ExecutionException e) {\n                    fail();\n                }\n            }\n        });\n        fiber.start();\n\n        phaser.arriveAndAwaitAdvance();\n        mockProducer.completeNext();\n        mockProducer.completeNext();\n\n        fiber.join(5000, TimeUnit.MILLISECONDS);\n    }\n\n    @Test\n    public void testSuccessfulSendWithCallback() throws ExecutionException, InterruptedException, TimeoutException {\n        Fiber<Void> fiber = new Fiber<>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n\n                final AtomicReference<RecordMetadata> callbackMetadata = new AtomicReference<>(null);\n                final AtomicReference<RecordMetadata> callbackMetadata2 = new AtomicReference<>(null);\n\n                Future<RecordMetadata> f = fiberProducer.send(new ProducerRecord<>(\"Topic\", \"Key\".getBytes(), \"Value\".getBytes()),\n                        new Callback() {\n                            @Override\n                            public void onCompletion(RecordMetadata metadata, Exception exception) {\n                                callbackMetadata.set(metadata);\n                            }\n                        });\n                Future<RecordMetadata> f2 = fiberProducer.send(new ProducerRecord<>(\"Topic\", \"Key\".getBytes(), \"Value\".getBytes()),\n                        new Callback() {\n                            @Override\n                            public void onCompletion(RecordMetadata metadata, Exception exception) {\n                                callbackMetadata2.set(metadata);\n                            }\n                        });\n                phaser.arriveAndAwaitAdvance();\n\n                try {\n                    RecordMetadata recordMetadata = f.get();\n\n                    assertEquals(\"Topic\", recordMetadata.topic());\n                    assertEquals(0, recordMetadata.offset());\n                    assertEquals(0, recordMetadata.partition());\n\n                    RecordMetadata recordMetadata2 = f2.get();\n\n                    assertEquals(\"Topic\", recordMetadata2.topic());\n                    assertEquals(1, recordMetadata2.offset());\n                    assertEquals(0, recordMetadata2.partition());\n                } catch (ExecutionException e) {\n                    fail();\n                }\n\n                phaser.arriveAndAwaitAdvance();\n\n                assertEquals(\"Topic\", callbackMetadata.get().topic());\n                assertEquals(0, callbackMetadata.get().offset());\n                assertEquals(0, callbackMetadata.get().partition());\n\n                assertEquals(\"Topic\", callbackMetadata2.get().topic());\n                assertEquals(1, callbackMetadata2.get().offset());\n                assertEquals(0, callbackMetadata2.get().partition());\n            }\n        });\n        fiber.start();\n\n        phaser.arriveAndAwaitAdvance();\n        mockProducer.completeNext();\n        mockProducer.completeNext();\n        phaser.arrive();\n\n        fiber.join(5000, TimeUnit.MILLISECONDS);\n    }\n\n    @Test\n    public void testErrorSendWithoutCallback() throws ExecutionException, InterruptedException, TimeoutException {\n        final RuntimeException exception = new RuntimeException(\"Error\");\n\n        Fiber<Void> fiber = new Fiber<>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Future<RecordMetadata> f = fiberProducer.send(new ProducerRecord<>(\"Topic\", \"Key\".getBytes(), \"Value\".getBytes()));\n                phaser.arrive();\n                try {\n                    f.get();\n                    fail(\"Send should have failed.\");\n                } catch (ExecutionException e) {\n                    assertEquals(exception, e.getCause());\n                }\n            }\n        });\n        fiber.start();\n\n        phaser.arriveAndAwaitAdvance();\n        mockProducer.errorNext(exception);\n\n        fiber.join(5000, TimeUnit.MILLISECONDS);\n    }\n\n    @Test\n    public void testErrorSendWithCallback() throws ExecutionException, InterruptedException, TimeoutException {\n        final RuntimeException exception = new RuntimeException(\"Error\");\n        final AtomicReference<Exception> exceptionReference = new AtomicReference<>(null);\n\n        Fiber<Void> fiber = new Fiber<>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Future<RecordMetadata> f = fiberProducer.send(new ProducerRecord<>(\"Topic\", \"Key\".getBytes(), \"Value\".getBytes()),\n                        new Callback() {\n                            @Override\n                            public void onCompletion(RecordMetadata metadata, Exception exception) {\n                                exceptionReference.set(exception);\n                            }\n                        });\n\n                phaser.arriveAndAwaitAdvance();\n\n                try {\n                    f.get();\n                    fail(\"Send should have failed.\");\n                } catch (ExecutionException e) {\n                    assertEquals(exception, e.getCause());\n                }\n\n                phaser.arriveAndAwaitAdvance();\n                assertEquals(exception, exceptionReference.get());\n            }\n        });\n        fiber.start();\n\n        phaser.arriveAndAwaitAdvance();\n        mockProducer.errorNext(exception);\n        phaser.arrive();\n\n        fiber.join(5000, TimeUnit.MILLISECONDS);\n    }\n}\n"
  },
  {
    "path": "comsat-mongodb-allanbank/src/main/java/co/paralleluniverse/fibers/mongodb/FiberMongoCallback.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport co.paralleluniverse.fibers.FiberAsync;\nimport com.allanbank.mongodb.Callback;\nimport com.allanbank.mongodb.MongoDbException;\n\n/**\n * Base class for async-to-fiber-blocking Async Java Mongo Driver transformations\n * \n * @author circlespainter\n * @param <T>\n */\npublic abstract class FiberMongoCallback<T> extends FiberAsync<T, MongoDbException> implements Callback<T> {\n    @Override\n    public void callback(T success) {\n        asyncCompleted(success);\n    }\n\n    @Override\n    public void exception(Throwable failure) {\n        asyncFailed(failure);\n    }\n}\n"
  },
  {
    "path": "comsat-mongodb-allanbank/src/main/java/co/paralleluniverse/fibers/mongodb/FiberMongoClientImpl.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport com.allanbank.mongodb.MongoClient;\nimport com.allanbank.mongodb.MongoClientConfiguration;\nimport com.allanbank.mongodb.MongoDatabase;\nimport com.allanbank.mongodb.client.Client;\nimport com.allanbank.mongodb.client.ClientImpl;\nimport com.allanbank.mongodb.client.MongoClientImpl;\nimport com.allanbank.mongodb.client.SerialClientImpl;\n\n/**\n * @author circlespainter\n */\npublic class FiberMongoClientImpl extends MongoClientImpl {\n\n    public FiberMongoClientImpl(Client client) {\n        super(client);\n    }\n    \n    public FiberMongoClientImpl(MongoClientConfiguration mcc) {\n        super(mcc);\n    }\n    \n    @Override\n    public MongoDatabase getDatabase(String name) {\n        return new FiberMongoDatabaseImpl(this, getClient(), name);\n    }\n    \n    @Override\n    public MongoClient asSerializedClient() {\n        // TODO Make more robust\n        return new FiberMongoClientImpl(new SerialClientImpl((ClientImpl) getClient()));\n    }\n}\n"
  },
  {
    "path": "comsat-mongodb-allanbank/src/main/java/co/paralleluniverse/fibers/mongodb/FiberMongoCollectionImpl.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport com.allanbank.mongodb.Durability;\nimport com.allanbank.mongodb.ListenableFuture;\nimport com.allanbank.mongodb.MongoDatabase;\nimport com.allanbank.mongodb.MongoDbException;\nimport com.allanbank.mongodb.MongoIterator;\nimport com.allanbank.mongodb.ReadPreference;\nimport com.allanbank.mongodb.bson.Document;\nimport com.allanbank.mongodb.bson.DocumentAssignable;\nimport com.allanbank.mongodb.bson.Element;\nimport com.allanbank.mongodb.builder.Aggregate;\nimport com.allanbank.mongodb.builder.BatchedWrite;\nimport com.allanbank.mongodb.builder.Count;\nimport com.allanbank.mongodb.builder.Distinct;\nimport com.allanbank.mongodb.builder.Find;\nimport com.allanbank.mongodb.builder.FindAndModify;\nimport com.allanbank.mongodb.builder.GroupBy;\nimport com.allanbank.mongodb.builder.MapReduce;\nimport com.allanbank.mongodb.builder.ParallelScan;\nimport com.allanbank.mongodb.builder.Text;\nimport com.allanbank.mongodb.builder.TextResult;\nimport com.allanbank.mongodb.client.Client;\nimport com.allanbank.mongodb.client.SynchronousMongoCollectionImpl;\nimport java.util.Collection;\n\n/**\n * @author circlespainter\n * \n * TODO: new fiber-blocking APIs for now async-only operations (when added)\n */\npublic class FiberMongoCollectionImpl extends SynchronousMongoCollectionImpl {\n\n    public FiberMongoCollectionImpl(Client client, MongoDatabase md, String string) {\n        super(client, md, string);\n    }\n    \n    // Fiber-blocking API\n    \n    @Override\n    @Suspendable\n    public MongoIterator<Document> aggregate(final Aggregate.Builder command) throws MongoDbException {\n        MongoIterator<Document> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Document>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.aggregateAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Document> aggregate(final Aggregate command) throws MongoDbException {\n        MongoIterator<Document> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Document>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.aggregateAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long count() throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.countAsync(this);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long count(final Count query) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.countAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long count(final Count.Builder query) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.countAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long count(final DocumentAssignable query, final ReadPreference readPreference) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.countAsync(this, query, readPreference);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long count(final ReadPreference readPreference) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.countAsync(this, readPreference);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long delete(final DocumentAssignable query) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.deleteAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long delete(final DocumentAssignable query, final boolean singleDelete) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.deleteAsync(this, query, singleDelete);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long delete(final DocumentAssignable query, final boolean singleDelete, final Durability durability) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.deleteAsync(this, query, singleDelete, durability);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long delete(final DocumentAssignable query, final Durability durability) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.deleteAsync(this, query, durability);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Element> distinct(final Distinct.Builder command) throws MongoDbException {\n        MongoIterator<Element> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Element>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.distinctAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Element> distinct(final Distinct command) throws MongoDbException {\n        MongoIterator<Element> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Element>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.distinctAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n        @Override\n    @Suspendable\n    public Document explain(final Aggregate.Builder query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.explainAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document explain(final Aggregate query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.explainAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n    \n    @Override\n    @Suspendable\n    public Document explain(final DocumentAssignable query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.explainAsync(this, Find.builder().query(query));\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n    \n    @Override\n    @Suspendable\n    public Document explain(final Find.Builder query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.explainAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document explain(final Find query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.explainAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Document> find(final DocumentAssignable query) throws MongoDbException {\n        MongoIterator<Document> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Document>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.findAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document findAndModify(final FindAndModify.Builder query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.findAndModifyAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document findAndModify(final FindAndModify query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.findAndModifyAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n    \n    @Override\n    @Suspendable\n    public MongoIterator<Document> find(final Find.Builder query) throws MongoDbException {\n        MongoIterator<Document> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Document>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.findAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Document> find(final Find query) throws MongoDbException {\n        MongoIterator<Document> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Document>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.findAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document findOne(final DocumentAssignable query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.findOneAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document findOne(final Find.Builder query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.findOneAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document findOne(final Find query) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.findOneAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Element> groupBy(final GroupBy.Builder command) throws MongoDbException {\n        MongoIterator<Element> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Element>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.groupByAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Element> groupBy(final GroupBy command) throws MongoDbException {\n        MongoIterator<Element> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Element>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.groupByAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public int insert(final DocumentAssignable... documents) throws MongoDbException {\n        Integer res = null;\n        try {\n            res = new FiberMongoCallback<Integer>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.insertAsync(this, documents);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public int insert(final Durability durability, final DocumentAssignable[] documents) throws MongoDbException {\n        Integer res = null;\n        try {\n            res = new FiberMongoCallback<Integer>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.insertAsync(this, durability, documents);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public int insert(final boolean continueOnError, final DocumentAssignable... documents) throws MongoDbException {\n        Integer res = null;\n        try {\n            res = new FiberMongoCallback<Integer>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.insertAsync(this, continueOnError, documents);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public int insert(final boolean continueOnError, final Durability durability, final DocumentAssignable... documents) throws MongoDbException {\n        Integer res = null;\n        try {\n            res = new FiberMongoCallback<Integer>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.insertAsync(this, continueOnError, durability, documents);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Document> mapReduce(final MapReduce.Builder command) throws MongoDbException {\n        MongoIterator<Document> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Document>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.mapReduceAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public MongoIterator<Document> mapReduce(final MapReduce command) throws MongoDbException {\n        MongoIterator<Document> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<Document>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.mapReduceAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Collection<MongoIterator<Document>> parallelScan(final ParallelScan.Builder command) throws MongoDbException {\n        Collection<MongoIterator<Document>> res = null;\n        try {\n            res = new FiberMongoCallback<Collection<MongoIterator<Document>>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.parallelScanAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Collection<MongoIterator<Document>> parallelScan(final ParallelScan command) throws MongoDbException {\n        Collection<MongoIterator<Document>> res = null;\n        try {\n            res = new FiberMongoCallback<Collection<MongoIterator<Document>>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.parallelScanAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n    \n    @Override\n    @Suspendable\n    public int save(final DocumentAssignable query) throws MongoDbException {\n        Integer res = null;\n        try {\n            res = new FiberMongoCallback<Integer>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.saveAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public int save(final DocumentAssignable query, final Durability durability) throws MongoDbException {\n        Integer res = null;\n        try {\n            res = new FiberMongoCallback<Integer>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.saveAsync(this, query, durability);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    @Deprecated\n    public MongoIterator<TextResult> textSearch(final Text.Builder command) throws MongoDbException {\n        MongoIterator<TextResult> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<TextResult>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.textSearchAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    @Deprecated\n    public MongoIterator<TextResult> textSearch(final Text command) throws MongoDbException {\n        MongoIterator<TextResult> res = null;\n        try {\n            res = new FiberMongoCallback<MongoIterator<TextResult>>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.textSearchAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long update(final DocumentAssignable query, final DocumentAssignable update) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.updateAsync(this, query, update);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long update(final DocumentAssignable query, final DocumentAssignable update, final boolean multiUpdate, final boolean upsert) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.updateAsync(this, query, update, multiUpdate, upsert);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long update(final DocumentAssignable query, final DocumentAssignable update, final boolean multiUpdate, final boolean upsert, final Durability durability) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.updateAsync(this, query, update, multiUpdate, upsert, durability);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long update(final DocumentAssignable query, final DocumentAssignable update, final Durability durability) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.updateAsync(this, query, update, durability);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long write(final BatchedWrite query) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.writeAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public long write(final BatchedWrite.Builder query) throws MongoDbException {\n        Long res = null;\n        try {\n            res = new FiberMongoCallback<Long>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoCollectionImpl.super.writeAsync(this, query);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    \n    // Async w/fiber-blocking future API\n    \n    @Override\n    public ListenableFuture<MongoIterator<Document>> aggregateAsync(Aggregate.Builder command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Document>> future = new SettableListenableFuture<>();\n        aggregateAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Document>> aggregateAsync(Aggregate command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Document>> future = new SettableListenableFuture<>();\n        aggregateAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> countAsync() throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        countAsync(FiberMongoUtils.callbackSettingFuture(future));\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> countAsync(Count.Builder builder) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        countAsync(FiberMongoUtils.callbackSettingFuture(future), builder);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> countAsync(Count query) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        countAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n    \n    @Override\n    public ListenableFuture<Long> countAsync(DocumentAssignable query) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        countAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> countAsync(DocumentAssignable query, ReadPreference readPreference) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        countAsync(FiberMongoUtils.callbackSettingFuture(future), query, readPreference);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> countAsync(ReadPreference readPreference) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        countAsync(FiberMongoUtils.callbackSettingFuture(future), readPreference);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> deleteAsync(DocumentAssignable query) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        deleteAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> deleteAsync(DocumentAssignable query, boolean singleDelete) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        deleteAsync(FiberMongoUtils.callbackSettingFuture(future), query, singleDelete);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> deleteAsync(DocumentAssignable query, boolean singleDelete, Durability durability) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        deleteAsync(FiberMongoUtils.callbackSettingFuture(future), query, singleDelete, durability);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> deleteAsync(DocumentAssignable query, Durability durability) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        deleteAsync(FiberMongoUtils.callbackSettingFuture(future), query, durability);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Element>> distinctAsync(Distinct.Builder command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Element>> future = new SettableListenableFuture<>();\n        distinctAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Element>> distinctAsync(Distinct command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Element>> future = new SettableListenableFuture<>();\n        distinctAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> explainAsync(Aggregate.Builder query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        explainAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> explainAsync(Aggregate query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        explainAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n    \n    @Override\n    public ListenableFuture<Document> explainAsync(Find.Builder query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        explainAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> explainAsync(Find query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        explainAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Document>> findAsync(DocumentAssignable query) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Document>> future = new SettableListenableFuture<>();\n        findAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Document>> findAsync(Find.Builder query) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Document>> future = new SettableListenableFuture<>();\n        findAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Document>> findAsync(Find query) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Document>> future = new SettableListenableFuture<>();\n        findAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> findAndModifyAsync(FindAndModify query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        findAndModifyAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> findAndModifyAsync(FindAndModify.Builder query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        findAndModifyAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n    \n    @Override\n    public ListenableFuture<Document> findOneAsync(DocumentAssignable query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        findOneAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> findOneAsync(Find.Builder query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        findOneAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> findOneAsync(Find query) throws MongoDbException {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        findOneAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Element>> groupByAsync(GroupBy.Builder command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Element>> future = new SettableListenableFuture<>();\n        groupByAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Element>> groupByAsync(GroupBy command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Element>> future = new SettableListenableFuture<>();\n        groupByAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Integer> insertAsync(DocumentAssignable... documents) throws MongoDbException {\n        final SettableListenableFuture<Integer> future = new SettableListenableFuture<>();\n        insertAsync(FiberMongoUtils.callbackSettingFuture(future), documents);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Integer> insertAsync(Durability durability, DocumentAssignable... documents) throws MongoDbException {\n        final SettableListenableFuture<Integer> future = new SettableListenableFuture<>();\n        insertAsync(FiberMongoUtils.callbackSettingFuture(future), durability, documents);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Integer> insertAsync(boolean continueOnError, DocumentAssignable... documents) throws MongoDbException {\n        final SettableListenableFuture<Integer> future = new SettableListenableFuture<>();\n        insertAsync(FiberMongoUtils.callbackSettingFuture(future), continueOnError, documents);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Integer> insertAsync(boolean continueOnError, Durability durability, DocumentAssignable... documents) throws MongoDbException {\n        final SettableListenableFuture<Integer> future = new SettableListenableFuture<>();\n        insertAsync(FiberMongoUtils.callbackSettingFuture(future), continueOnError, durability, documents);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Document>> mapReduceAsync(MapReduce.Builder command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Document>> future = new SettableListenableFuture<>();\n        mapReduceAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<MongoIterator<Document>> mapReduceAsync(MapReduce command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<Document>> future = new SettableListenableFuture<>();\n        mapReduceAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n    \n    @Override\n    public ListenableFuture<Collection<MongoIterator<Document>>> parallelScanAsync(ParallelScan.Builder command) throws MongoDbException {\n        final SettableListenableFuture<Collection<MongoIterator<Document>>> future = new SettableListenableFuture<>();\n        parallelScanAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Collection<MongoIterator<Document>>> parallelScanAsync(ParallelScan command) throws MongoDbException {\n        final SettableListenableFuture<Collection<MongoIterator<Document>>> future = new SettableListenableFuture<>();\n        parallelScanAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Integer> saveAsync(DocumentAssignable query) throws MongoDbException {\n        final SettableListenableFuture<Integer> future = new SettableListenableFuture<>();\n        saveAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Integer> saveAsync(DocumentAssignable query, Durability durability) throws MongoDbException {\n        final SettableListenableFuture<Integer> future = new SettableListenableFuture<>();\n        saveAsync(FiberMongoUtils.callbackSettingFuture(future), query, durability);\n        return future;\n    }\n\n    @Deprecated\n    @Override\n    public ListenableFuture<MongoIterator<TextResult>> textSearchAsync(Text.Builder command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<TextResult>> future = new SettableListenableFuture<>();\n        textSearchAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Deprecated\n    @Override\n    public ListenableFuture<MongoIterator<TextResult>> textSearchAsync(Text command) throws MongoDbException {\n        final SettableListenableFuture<MongoIterator<TextResult>> future = new SettableListenableFuture<>();\n        textSearchAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> updateAsync(DocumentAssignable query, DocumentAssignable update) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        updateAsync(FiberMongoUtils.callbackSettingFuture(future), query, update);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> updateAsync(DocumentAssignable query, DocumentAssignable update, boolean multiUpdate, boolean upsert) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        updateAsync(FiberMongoUtils.callbackSettingFuture(future), query, update, multiUpdate, upsert);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> updateAsync(DocumentAssignable query, DocumentAssignable update, boolean multiUpdate, boolean upsert, Durability durability) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        updateAsync(FiberMongoUtils.callbackSettingFuture(future), query, update, multiUpdate, upsert, durability);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> updateAsync(DocumentAssignable query, DocumentAssignable update, Durability durability) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        updateAsync(FiberMongoUtils.callbackSettingFuture(future), query, update, durability);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> writeAsync(BatchedWrite.Builder builder) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        writeAsync(FiberMongoUtils.callbackSettingFuture(future), builder);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Long> writeAsync(BatchedWrite query) throws MongoDbException {\n        final SettableListenableFuture<Long> future = new SettableListenableFuture<>();\n        writeAsync(FiberMongoUtils.callbackSettingFuture(future), query);\n        return future;\n    }\n}"
  },
  {
    "path": "comsat-mongodb-allanbank/src/main/java/co/paralleluniverse/fibers/mongodb/FiberMongoDatabaseImpl.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport com.allanbank.mongodb.ListenableFuture;\nimport com.allanbank.mongodb.MongoClient;\nimport com.allanbank.mongodb.MongoCollection;\nimport com.allanbank.mongodb.MongoDbException;\nimport com.allanbank.mongodb.bson.Document;\nimport com.allanbank.mongodb.bson.DocumentAssignable;\nimport com.allanbank.mongodb.client.Client;\nimport com.allanbank.mongodb.client.MongoDatabaseImpl;\n\n/**\n * @author circlespainter\n * \n * TODO: new fiber-blocking APIs for now async-only operations\n */\npublic class FiberMongoDatabaseImpl extends MongoDatabaseImpl {\n\n    public FiberMongoDatabaseImpl(MongoClient mongoClient, Client client, String string) {\n        super(mongoClient, client, string);\n    }\n\n    @Override\n    public MongoCollection getCollection(String name) {\n        return new FiberMongoCollectionImpl(myClient, this, name);\n    }\n    \n    @Override\n    @Suspendable\n    public Document runCommand(final DocumentAssignable command) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoDatabaseImpl.super.runCommandAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document runCommand(final String command) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoDatabaseImpl.super.runCommandAsync(this, command);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document runCommand(final String command, final DocumentAssignable options) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoDatabaseImpl.super.runCommandAsync(this, command, options);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document runCommand(final String commandName, final int commandValue, final DocumentAssignable options) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoDatabaseImpl.super.runCommandAsync(this, commandName, commandValue, options);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n    @Override\n    @Suspendable\n    public Document runCommand(final String commandName, final String commandValue, final DocumentAssignable options) throws MongoDbException {\n        Document res = null;\n        try {\n            res = new FiberMongoCallback<Document>() {\n                @Override\n                protected void requestAsync() {\n                    FiberMongoDatabaseImpl.super.runCommandAsync(this, commandName, commandValue, options);\n                }\n            }.run();\n        } catch (SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(\"Should never happen\", ex);\n        }\n        return res;\n    }\n\n\n    // Async w/fiber-blocking future API\n    \n    @Override\n    public ListenableFuture<Document> runCommandAsync(DocumentAssignable command) {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        super.runCommandAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> runCommandAsync(String command) {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        super.runCommandAsync(FiberMongoUtils.callbackSettingFuture(future), command);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> runCommandAsync(String command, DocumentAssignable options) {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        super.runCommandAsync(FiberMongoUtils.callbackSettingFuture(future), command, options);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> runCommandAsync(String commandName, int commandValue, DocumentAssignable options) {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        super.runCommandAsync(FiberMongoUtils.callbackSettingFuture(future), commandName, commandValue, options);\n        return future;\n    }\n\n    @Override\n    public ListenableFuture<Document> runCommandAsync(String commandName, String commandValue, DocumentAssignable options) {\n        final SettableListenableFuture<Document> future = new SettableListenableFuture<>();\n        super.runCommandAsync(FiberMongoUtils.callbackSettingFuture(future), commandName, commandValue, options);\n        return future;\n    }\n}"
  },
  {
    "path": "comsat-mongodb-allanbank/src/main/java/co/paralleluniverse/fibers/mongodb/FiberMongoFactory.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport com.allanbank.mongodb.MongoClient;\nimport com.allanbank.mongodb.MongoClientConfiguration;\nimport com.allanbank.mongodb.MongoDbUri;\n\n/**\n *\n * @author circlespainter\n */\npublic class FiberMongoFactory {\n    \n    public static MongoClient createClient(MongoClientConfiguration mcc) {\n        return new FiberMongoClientImpl(mcc);\n    }\n\n    public static MongoClient createClient(MongoDbUri uri) {\n        return new FiberMongoClientImpl(new MongoClientConfiguration(uri));\n    }\n\n    public static MongoClient createClient(String uri) {\n        return new FiberMongoClientImpl(new MongoClientConfiguration(uri));\n    }\n}\n"
  },
  {
    "path": "comsat-mongodb-allanbank/src/main/java/co/paralleluniverse/fibers/mongodb/FiberMongoUtils.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport co.paralleluniverse.strands.SettableFuture;\nimport com.allanbank.mongodb.Callback;\n\n/**\n * Utility classes for callbacks (async-to-fiberblocking briding)\n * @author dev\n */\npublic class FiberMongoUtils {\n\n    /**\n     * Builds a new Async Java Mongo Driver callback that will set a future upon completion or failure\n     * @param <T>\n     * @param future\n     * @return\n     */\n    public static <T> Callback<T> callbackSettingFuture(final SettableFuture<T> future) {\n        return new Callback<T>() {\n\n            @Override\n            public void callback(T v) {\n                future.set(v);\n            }\n\n            @Override\n            public void exception(Throwable thrwbl) {\n                future.setException(thrwbl);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "comsat-mongodb-allanbank/src/main/java/co/paralleluniverse/fibers/mongodb/SettableListenableFuture.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport co.paralleluniverse.strands.SettableFuture;\nimport com.allanbank.mongodb.ListenableFuture;\nimport com.allanbank.mongodb.client.FutureCallback;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.RejectedExecutionException;\n\n/**\n * Adds ListenableFuture support to SettableFuture through a delegate\n * @author circlespainter\n */\npublic class SettableListenableFuture<V> extends SettableFuture<V> implements ListenableFuture<V> {\n    final private FutureCallback<V> delegate = new FutureCallback<>();\n\n    @Override\n    public boolean set(V value) {\n        boolean ret = super.set(value);\n        delegate.callback(value);\n        return ret;\n    }\n    \n    @Override\n    public boolean setException (Throwable exception) {\n        boolean ret = super.setException(exception);\n        delegate.exception(exception);\n        return ret;\n    }\n    \n    @Override\n    public void addListener(Runnable r, Executor exctr) throws RejectedExecutionException, IllegalArgumentException {\n        delegate.addListener(r, exctr);\n    }\n    \n}\n"
  },
  {
    "path": "comsat-mongodb-allanbank/src/main/resources/META-INF/suspendables",
    "content": "com.allanbank.mongodb.client.MongoClientImpl.listDatabaseNames\ncom.allanbank.mongodb.client.MongoClientImpl.listDatabases\ncom.allanbank.mongodb.client.MongoDatabaseImpl.drop\ncom.allanbank.mongodb.client.MongoDatabaseImpl.exists\ncom.allanbank.mongodb.client.MongoDatabaseImpl.createCappedCollection\ncom.allanbank.mongodb.client.MongoDatabaseImpl.createCollection\ncom.allanbank.mongodb.client.MongoDatabaseImpl.getProfilingStatus\ncom.allanbank.mongodb.client.MongoDatabaseImpl.listCollectionNames\ncom.allanbank.mongodb.client.MongoDatabaseImpl.listCollections\ncom.allanbank.mongodb.client.MongoDatabaseImpl.runAdminCommand\ncom.allanbank.mongodb.client.MongoDatabaseImpl.runCommand\ncom.allanbank.mongodb.client.MongoDatabaseImpl.setProfilingStatus\ncom.allanbank.mongodb.client.MongoDatabaseImpl.stats\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.createIndex\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.drop\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.dropIndex\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.exists\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.getDatabaseName\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.getName\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.isCapped\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.stats\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.updateOptions\ncom.allanbank.mongodb.client.SynchronousMongoCollectionImpl.validate"
  },
  {
    "path": "comsat-mongodb-allanbank/src/test/java/co/paralleluniverse/fibers/mongodb/AbstractTestFiberMongo.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport co.paralleluniverse.strands.channels.Channel;\nimport co.paralleluniverse.strands.channels.Channels;\nimport com.allanbank.mongodb.ListenableFuture;\nimport com.allanbank.mongodb.MongoClient;\nimport com.allanbank.mongodb.MongoDatabase;\nimport de.flapdoodle.embed.mongo.MongodExecutable;\nimport de.flapdoodle.embed.mongo.MongodProcess;\nimport de.flapdoodle.embed.mongo.MongodStarter;\nimport de.flapdoodle.embed.mongo.config.IMongodConfig;\nimport de.flapdoodle.embed.mongo.config.MongodConfigBuilder;\nimport de.flapdoodle.embed.mongo.config.Net;\nimport de.flapdoodle.embed.mongo.distribution.Version;\nimport de.flapdoodle.embed.process.runtime.Network;\nimport java.io.IOException;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport org.junit.AfterClass;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.BeforeClass;\n\n/**\n * @author circlespainter\n */\npublic abstract class AbstractTestFiberMongo {\n    private static MongodExecutable mongodExecutable;\n    private static MongoClient mongoClient;\n\n    protected static Executor executor;\n\n    protected AtomicBoolean listenerCalledFlag;\n    protected Runnable listenerCalledSetter;\n    protected Channel<AtomicBoolean> listenerCalledGoChannel;\n\n    protected MongoDatabase mongoDb;\n\n    protected <V> ListenableFuture<V> addListenerCalledFlagSetter(ListenableFuture<V> l) {\n        l.addListener(listenerCalledSetter, executor);\n        return l;\n    }\n    \n    protected void setUpTestBase() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                listenerCalledFlag = new AtomicBoolean(false);\n                listenerCalledGoChannel = Channels.newChannel(0);\n                listenerCalledSetter = new Runnable() { @Override public void run() {\n                    try {\n                        listenerCalledFlag.set(true);\n                        listenerCalledGoChannel.send(listenerCalledFlag);\n                    } catch (SuspendExecution | InterruptedException ex) {\n                        throw new AssertionError(\"This should never happen as we're using channels in threads\");\n                    }\n                }};\n                \n                mongoDb = mongoClient.getDatabase(\"test\");\n            }\n        }).start().join();\n    }\n    \n    protected void tearDownTestBase() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                listenerCalledSetter = null;\n                listenerCalledGoChannel = null;\n                listenerCalledFlag= null;\n\n                if (mongoDb != null) {\n                    mongoDb.drop();\n                    mongoDb = null;\n                }\n            }\n        }).start().join();\n    }\n\n    protected void assertListenerCalled() throws SuspendExecution, InterruptedException {\n        assertTrue(\"Listener called\", listenerCalledGoChannel.receive(30, TimeUnit.SECONDS).get());\n    }\n    \n    @BeforeClass\n    public static void setUpClass() throws IOException {\n        executor = Executors.newSingleThreadExecutor();\n\n        MongodStarter starter = MongodStarter.getDefaultInstance();\n\n        int port = 12345;\n        IMongodConfig mongodConfig = new MongodConfigBuilder()\n            .version(Version.Main.PRODUCTION)\n            .net(new Net(port, Network.localhostIsIPv6()))\n            .build();\n\n        try {\n            mongodExecutable = starter.prepare(mongodConfig);\n            MongodProcess mongod = mongodExecutable.start();\n            \n            mongoClient = FiberMongoFactory.createClient( \"mongodb://localhost:\" + port + \"/test?maxConnectionCount=10\" ).asSerializedClient();\n        } catch (IOException ioe) {\n            tearDownClass();\n        }\n    }\n\n    @AfterClass\n    public static void tearDownClass() throws IOException {\n        if (mongoClient != null) {\n            mongoClient.close();\n            mongoClient = null;\n        }\n        if (mongodExecutable != null) {\n            mongodExecutable.stop();\n            mongodExecutable = null;\n        }\n    }\n}"
  },
  {
    "path": "comsat-mongodb-allanbank/src/test/java/co/paralleluniverse/fibers/mongodb/FiberMongoCollTest.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport com.allanbank.mongodb.Durability;\nimport com.allanbank.mongodb.MongoCollection;\nimport com.allanbank.mongodb.MongoDbException;\nimport com.allanbank.mongodb.MongoIterator;\nimport com.allanbank.mongodb.bson.Document;\nimport com.allanbank.mongodb.bson.DocumentAssignable;\nimport com.allanbank.mongodb.bson.Element;\nimport static com.allanbank.mongodb.bson.builder.BuilderFactory.*;\nimport com.allanbank.mongodb.builder.Aggregate;\nimport com.allanbank.mongodb.builder.BatchedWrite;\nimport com.allanbank.mongodb.builder.Count;\nimport com.allanbank.mongodb.builder.Distinct;\nimport com.allanbank.mongodb.builder.Find;\nimport com.allanbank.mongodb.builder.FindAndModify;\nimport com.allanbank.mongodb.builder.GroupBy;\nimport com.allanbank.mongodb.builder.Index;\nimport com.allanbank.mongodb.builder.MapReduce;\nimport com.allanbank.mongodb.builder.ParallelScan;\nimport com.allanbank.mongodb.builder.Text;\nimport com.allanbank.mongodb.builder.TextResult;\nimport java.util.Collection;\nimport java.util.concurrent.ExecutionException;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\n\n/**\n * @author circlespainter\n * \n * TODO Missing tests:\n * \n * 1) Non-async suspendable methods (already declared in \"suspendables\"); anyway some are already used as part of test setup\n * 2) New fiber-blocking APIs for now async-only operations (when added, @see co.paralleluniverse.fibers.mongodb.FiberMongoCollectionImpl)\n */\npublic class FiberMongoCollTest extends AbstractTestFiberMongo {\n    private static final String COLL_NAME = \"test\";\n    \n    private static final Integer TEST_SET_SIZE = 2;\n\n    private static final String FIELD_INT_NAME = \"fieldInt\";\n    private static final String FIELD_TY_NAME = \"ty\";\n    private static final Integer FIELD_INT_FIRST_VALUE = 1;\n    private static final Integer TEST_SET_DOCS_COUNT_WITH_FIELD_INT_FIRST_VALUE = 1;\n\n    private static final Element ELEM_TY = e(FIELD_TY_NAME, \"test\");\n    private static final String TEXT_SEARCH_TERM = \"value\";\n    private static final String FIELD_STRING_NAME = \"fieldString\";\n    private static final Element ELEM_FIELD_STRING_1 = e(FIELD_STRING_NAME, TEXT_SEARCH_TERM + \" 1\");\n    private static final DocumentAssignable FIRST_TEST_ELEM = d(ELEM_TY, ELEM_FIELD_STRING_1, e(FIELD_INT_NAME, FIELD_INT_FIRST_VALUE));\n    private static final DocumentAssignable SECOND_TEST_ELEM = d(ELEM_TY, e(FIELD_STRING_NAME, TEXT_SEARCH_TERM + \" 2\"), e(FIELD_INT_NAME, 2));\n    \n    private MongoCollection mongoColl;\n    \n    private int insertTestSet() throws SuspendExecution, MongoDbException, IllegalArgumentException {\n        return mongoColl.insert(Durability.ACK, FIRST_TEST_ELEM, SECOND_TEST_ELEM);\n    }\n\n    private long deleteTestSet() throws SuspendExecution, MongoDbException, IllegalArgumentException {\n        return mongoColl.delete(d());\n    }\n    \n    @Before\n    public void setUpTest() throws ExecutionException, InterruptedException {\n        super.setUpTestBase();\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                mongoColl = mongoDb.getCollection(COLL_NAME);\n                mongoColl.createIndex(Index.text(FIELD_STRING_NAME));\n                insertTestSet();\n            }\n        }).start().join();\n    }\n    \n    @After\n    public void tearDownTest() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                deleteTestSet();\n\n                if (mongoColl != null) {\n                    mongoColl.drop();\n                    mongoColl = null;\n                }\n            }\n        }).start().join();\n        super.tearDownTestBase();\n    }\n\n    private static final String FIELD_COUNT_NAME = \"count\";\n    \n    private static String getAggregateSizeAsString(MongoIterator<Document> aggregate) {\n        return aggregate.next().get(FIELD_COUNT_NAME).getValueAsString();\n    }\n\n    private static final Aggregate.Builder AGGREGATE_QUERY =\n            Aggregate.builder()\n                .match(d(e(FIELD_INT_NAME, d(e(\"$gt\", 0), e(\"$lt\", 3)))))\n                .group(d(e(\"_id\", (String) null), e(FIELD_COUNT_NAME, d(e(\"$sum\", 1)))));\n        \n    @Test\n    public void testAggregateQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Document> aggregate = mongoColl.aggregate(AGGREGATE_QUERY.build());\n                assertEquals(TEST_SET_SIZE.toString(), getAggregateSizeAsString(aggregate));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testAggregateBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Document> aggregate = mongoColl.aggregate(AGGREGATE_QUERY);\n                assertEquals(TEST_SET_SIZE.toString(), getAggregateSizeAsString(aggregate));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testAggregateQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Document> aggregate = addListenerCalledFlagSetter(mongoColl.aggregateAsync(AGGREGATE_QUERY)).get();\n                    assertEquals(TEST_SET_SIZE.toString(), getAggregateSizeAsString(aggregate));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testAggregateBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Document> aggregate = addListenerCalledFlagSetter(mongoColl.aggregateAsync(AGGREGATE_QUERY)).get();\n                    assertEquals(TEST_SET_SIZE.toString(), getAggregateSizeAsString(aggregate));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testCount() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long res = mongoColl.count();\n                assertEquals((int) TEST_SET_SIZE, res);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testCountBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long res = mongoColl.count(Count.builder());\n                assertEquals((int) TEST_SET_SIZE, res);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testCountQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long res = mongoColl.count(Count.builder().build());\n                assertEquals((int) TEST_SET_SIZE, res);\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testCountQueryDocument() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long res = mongoColl.count();\n                assertEquals((int) TEST_SET_SIZE, res);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testCountFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long res = addListenerCalledFlagSetter(mongoColl.countAsync()).get();\n                    assertEquals((int) TEST_SET_SIZE, res);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testCountBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long res = addListenerCalledFlagSetter(mongoColl.countAsync(Count.builder())).get();\n                    assertEquals((int) TEST_SET_SIZE, res);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testCountQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long res = addListenerCalledFlagSetter(mongoColl.countAsync(Count.builder().build())).get();\n                    assertEquals((int) TEST_SET_SIZE, res);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testCountQueryDocumentFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long res = addListenerCalledFlagSetter(mongoColl.countAsync()).get();\n                    assertEquals((int) TEST_SET_SIZE, res);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static final DocumentAssignable DELETE_DOCUMENT = d(e(FIELD_INT_NAME, FIELD_INT_FIRST_VALUE));\n    private static final int DELETE_SIZE = TEST_SET_DOCS_COUNT_WITH_FIELD_INT_FIRST_VALUE;\n    \n    @Test\n    public void testDeleteQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long deleted = mongoColl.delete(DELETE_DOCUMENT);\n                assertEquals(DELETE_SIZE, deleted);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDeleteQuerySingle() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long deleted = mongoColl.delete(DELETE_DOCUMENT, true);\n                assertEquals(DELETE_SIZE, deleted);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDeleteQuerySingleDurable() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long deleted = mongoColl.delete(DELETE_DOCUMENT, true, Durability.ACK);\n                assertEquals(DELETE_SIZE, deleted);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDeleteQueryDurable() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long deleted = mongoColl.delete(DELETE_DOCUMENT, Durability.ACK);\n                assertEquals(DELETE_SIZE, deleted);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDeleteQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long deleted = addListenerCalledFlagSetter(mongoColl.deleteAsync(DELETE_DOCUMENT)).get();\n                    assertEquals(DELETE_SIZE, deleted);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDeleteQuerySingleFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long deleted = addListenerCalledFlagSetter(mongoColl.deleteAsync(DELETE_DOCUMENT, true)).get();\n                    assertEquals(DELETE_SIZE, deleted);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDeleteQuerySingleDurableFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long deleted = addListenerCalledFlagSetter(mongoColl.deleteAsync(DELETE_DOCUMENT, true, Durability.ACK)).get();\n                    assertEquals(DELETE_SIZE, deleted);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDeleteQueryDurableFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long deleted = addListenerCalledFlagSetter(mongoColl.deleteAsync(DELETE_DOCUMENT, Durability.ACK)).get();\n                    assertEquals(DELETE_SIZE, deleted);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static long getDistinctSize(MongoIterator<Element> distinct) throws IllegalArgumentException {\n        long res = 0;\n        while (distinct.hasNext()) { distinct.next(); res++; }\n        return res;\n    }\n\n    private static final Distinct.Builder DISTINCT_QUERY = Distinct.builder().key(FIELD_INT_NAME);\n        \n    @Test\n    public void testDistinctQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Element> distinct = mongoColl.distinct(DISTINCT_QUERY.build());\n                assertEquals((long) TEST_SET_SIZE, getDistinctSize(distinct));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDistinctBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Element> distinct = mongoColl.distinct(DISTINCT_QUERY);\n                assertEquals((long) TEST_SET_SIZE, getDistinctSize(distinct));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDistinctQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Element> distinct = addListenerCalledFlagSetter(mongoColl.distinctAsync(DISTINCT_QUERY.build())).get();\n                    assertEquals((long) TEST_SET_SIZE, getDistinctSize(distinct));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testDistinctBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Element> distinct = addListenerCalledFlagSetter(mongoColl.distinctAsync(DISTINCT_QUERY)).get();\n                    assertEquals((long) TEST_SET_SIZE, getDistinctSize(distinct));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static final String FIELD_AGGREGATE_RESULT_STAGES_NAME = \"stages\";\n    private static final String FIELD_AGGREGATE_RESULT_CURSOR_NAME = \"cursor\";\n\n    @Test\n    public void testExplainAggregateQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document explain = mongoColl.explain(AGGREGATE_QUERY.build());\n                assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_STAGES_NAME));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testExplainAggregateBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document explain = mongoColl.explain(AGGREGATE_QUERY);\n                assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_STAGES_NAME));\n            }\n        }).start().join();\n    }\n\n    private static final DocumentAssignable FIND_DOCUMENT = d(e(FIELD_INT_NAME, FIELD_INT_FIRST_VALUE));\n    \n    @Test\n    public void testExplainFindQueryDocument() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document explain = mongoColl.explain(FIND_DOCUMENT);\n                assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_CURSOR_NAME));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testExplainFindQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document explain = mongoColl.explain(Find.builder().query(FIND_DOCUMENT).build());\n                assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_CURSOR_NAME));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testExplainFindBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document explain = mongoColl.explain(Find.builder().query(FIND_DOCUMENT));\n                assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_CURSOR_NAME));\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testExplainAggregateQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document explain = addListenerCalledFlagSetter(mongoColl.explainAsync(AGGREGATE_QUERY.build())).get();\n                    assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_STAGES_NAME));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testExplainAggregateBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document explain = addListenerCalledFlagSetter(mongoColl.explainAsync(AGGREGATE_QUERY)).get();\n                    assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_STAGES_NAME));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testExplainFindQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document explain = addListenerCalledFlagSetter(mongoColl.explainAsync(Find.builder().query(FIND_DOCUMENT).build())).get();\n                    assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_CURSOR_NAME));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testExplainFindBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document explain = addListenerCalledFlagSetter(mongoColl.explainAsync(Find.builder().query(FIND_DOCUMENT))).get();\n                    assertNotNull(explain.get(FIELD_AGGREGATE_RESULT_CURSOR_NAME));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testFindQueryDocument() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Document> find = mongoColl.find(FIND_DOCUMENT);\n                assertTrue(find.hasNext());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Document> find = mongoColl.find(Find.builder().query(FIND_DOCUMENT).build());\n                assertTrue(find.hasNext());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Document> find = mongoColl.find(Find.builder().query(FIND_DOCUMENT));\n                assertTrue(find.hasNext());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Document> find = addListenerCalledFlagSetter(mongoColl.findAsync(Find.builder().query(FIND_DOCUMENT).build())).get();\n                    assertTrue(find.hasNext());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindQueryDocumentFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Document> find = addListenerCalledFlagSetter(mongoColl.findAsync(FIND_DOCUMENT)).get();\n                    assertTrue(find.hasNext());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Document> find = addListenerCalledFlagSetter(mongoColl.findAsync(Find.builder().query(FIND_DOCUMENT))).get();\n                    assertTrue(find.hasNext());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static final Integer UPDATE_VALUE = 10;\n    private static final Element UPDATE_ELEMENT = e(FIELD_INT_NAME, UPDATE_VALUE);\n    private static final DocumentAssignable UPDATE_DOCUMENT = d(UPDATE_ELEMENT);\n    \n    private static final FindAndModify.Builder FIND_AND_MODIFY_BUILDER =\n            FindAndModify.builder().query(FIND_DOCUMENT).setUpdate(UPDATE_DOCUMENT).setReturnNew(true);\n    \n    @Test\n    public void testFindAndModifyQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document findAndModify = mongoColl.findAndModify(FIND_AND_MODIFY_BUILDER.build());\n                assertEquals(UPDATE_VALUE.toString(), findAndModify.get(FIELD_INT_NAME).getValueAsString());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindAndModifyBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document findAndModify = mongoColl.findAndModify(FIND_AND_MODIFY_BUILDER);\n                assertEquals(UPDATE_VALUE.toString(), findAndModify.get(FIELD_INT_NAME).getValueAsString());\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testFindAndModifyQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document findAndModify = addListenerCalledFlagSetter(mongoColl.findAndModifyAsync(FIND_AND_MODIFY_BUILDER.build())).get();\n                    assertEquals(UPDATE_VALUE.toString(), findAndModify.get(FIELD_INT_NAME).getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindAndModifyBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document findAndModify = addListenerCalledFlagSetter(mongoColl.findAndModifyAsync(FIND_AND_MODIFY_BUILDER)).get();\n                    assertEquals(UPDATE_VALUE.toString(), findAndModify.get(FIELD_INT_NAME).getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindOneQueryDocument() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document find = mongoColl.findOne(FIND_DOCUMENT);\n                assertEquals(FIELD_INT_FIRST_VALUE.toString(), find.get(FIELD_INT_NAME).getValueAsString());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindOneQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document find = mongoColl.findOne(Find.builder().query(FIND_DOCUMENT).build());\n                assertEquals(FIELD_INT_FIRST_VALUE.toString(), find.get(FIELD_INT_NAME).getValueAsString());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindOneBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document find = mongoColl.findOne(Find.builder().query(FIND_DOCUMENT).build());\n                assertEquals(FIELD_INT_FIRST_VALUE.toString(), find.get(FIELD_INT_NAME).getValueAsString());\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testFindOneQueryDocumentFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document find = addListenerCalledFlagSetter(mongoColl.findOneAsync(FIND_DOCUMENT)).get();\n                    assertEquals(FIELD_INT_FIRST_VALUE.toString(), find.get(FIELD_INT_NAME).getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindOneQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document find = addListenerCalledFlagSetter(mongoColl.findOneAsync(Find.builder().query(FIND_DOCUMENT).build())).get();\n                    assertEquals(FIELD_INT_FIRST_VALUE.toString(), find.get(FIELD_INT_NAME).getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testFindOneBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document find = addListenerCalledFlagSetter(mongoColl.findOneAsync(Find.builder().query(FIND_DOCUMENT))).get();\n                    assertEquals(FIELD_INT_FIRST_VALUE.toString(), find.get(FIELD_INT_NAME).getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static final String FIELD_INT_SUM_NAME = \"fieldIntSum\";\n\n    private static final GroupBy.Builder GROUP_BY_BUILDER =\n            GroupBy.builder()\n                    .setInitialValue(d(e(FIELD_INT_SUM_NAME, 0)))\n                    .setKeyFunction(\"function(doc) { return { \" + FIELD_TY_NAME + \" : doc.\" + FIELD_TY_NAME + \" }; }\")\n                    .setReduceFunction(\"function(curr, result) { result.\" + FIELD_INT_SUM_NAME + \" += curr.\" + FIELD_INT_NAME + \"; }\");\n\n    private static final String FIELD_INT_SUM = \"3.0\";\n    \n    private static String getGroupByResultAsString(Element groupBy) {\n        return ((Document) groupBy.getValueAsObject()).get(FIELD_INT_SUM_NAME).getValueAsString();\n    }\n    \n    @Test\n    public void testGroupByQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Element> groupBy = mongoColl.groupBy(GROUP_BY_BUILDER.build());\n                assertEquals(FIELD_INT_SUM, getGroupByResultAsString(groupBy.next()));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testGroupByBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Element> groupBy = mongoColl.groupBy(GROUP_BY_BUILDER);\n                assertEquals(FIELD_INT_SUM, getGroupByResultAsString(groupBy.next()));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testGroupByQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Element> groupBy = addListenerCalledFlagSetter(mongoColl.groupByAsync(GROUP_BY_BUILDER.build())).get();\n                    assertEquals(FIELD_INT_SUM, getGroupByResultAsString(groupBy.next()));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testGroupByBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Element> groupBy = addListenerCalledFlagSetter(mongoColl.groupByAsync(GROUP_BY_BUILDER)).get();\n                    assertEquals(FIELD_INT_SUM, getGroupByResultAsString(groupBy.next()));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testInsert() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                deleteTestSet();\n                int inserted = mongoColl.insert(FIRST_TEST_ELEM, SECOND_TEST_ELEM);\n                assertEquals((int) TEST_SET_SIZE, inserted);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testInsertContinueOnError() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                deleteTestSet();\n                int inserted = mongoColl.insert(true, FIRST_TEST_ELEM, SECOND_TEST_ELEM);\n                assertEquals((int) TEST_SET_SIZE, inserted);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testInsertContinueOnErrorDurable() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                deleteTestSet();\n                int inserted = mongoColl.insert(true, Durability.ACK, FIRST_TEST_ELEM, SECOND_TEST_ELEM);\n                assertEquals((int) TEST_SET_SIZE, inserted);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testInsertDurable() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                deleteTestSet();\n                int inserted = mongoColl.insert(Durability.ACK, FIRST_TEST_ELEM, SECOND_TEST_ELEM);\n                assertEquals((int) TEST_SET_SIZE, inserted);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testInsertFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    deleteTestSet();\n                    int inserted = addListenerCalledFlagSetter(mongoColl.insertAsync(FIRST_TEST_ELEM, SECOND_TEST_ELEM)).get();\n                    assertEquals((int) TEST_SET_SIZE, inserted);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testInsertContinueOnErrorFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    deleteTestSet();\n                    int inserted = addListenerCalledFlagSetter(mongoColl.insertAsync(true, FIRST_TEST_ELEM, SECOND_TEST_ELEM)).get();\n                    assertEquals((int) TEST_SET_SIZE, inserted);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testInsertContinueOnErrorDurableFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    deleteTestSet();\n                    int inserted = addListenerCalledFlagSetter(mongoColl.insertAsync(true, Durability.ACK, FIRST_TEST_ELEM, SECOND_TEST_ELEM)).get();\n                    assertEquals((int) TEST_SET_SIZE, inserted);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testInsertDurableFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    deleteTestSet();\n                    int inserted = addListenerCalledFlagSetter(mongoColl.insertAsync(Durability.ACK, FIRST_TEST_ELEM, SECOND_TEST_ELEM)).get();\n                    assertEquals((int) TEST_SET_SIZE, inserted);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static String getMapReduceSizeAsString(MongoIterator<Document> mapReduce) {\n        Document res = (Document) mapReduce.next().get(\"value\").getValueAsObject();\n        return res.get(FIELD_INT_SUM_NAME).getValueAsString();\n    }\n\n    private static final MapReduce.Builder MAP_REDUCE_QUERY =\n        MapReduce.builder()\n            .map(\"function() { emit(\\\"\" + FIELD_INT_SUM_NAME + \"\\\", { \" + FIELD_INT_SUM_NAME + \" : this.\" + FIELD_INT_NAME + \" }); }\")\n            .reduce (\"function (key, values) {\\n\" +\n                     \"    var result = { \" + FIELD_INT_SUM_NAME + \" : 0 };\\n\" +\n                     \"    values.forEach(function (value) { result.\" + FIELD_INT_SUM_NAME + \" += value.\" + FIELD_INT_SUM_NAME + \"; });\\n\" +\n                     \"    return result;\\n\" +\n                     \"}\"\n            );\n        \n    @Test\n    public void testMapReduceQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Document> mapReduce = mongoColl.mapReduce(MAP_REDUCE_QUERY.build());\n                assertEquals(FIELD_INT_SUM, getMapReduceSizeAsString(mapReduce));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testMapReduceBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<Document> mapReduce = mongoColl.mapReduce(MAP_REDUCE_QUERY);\n                assertEquals(FIELD_INT_SUM, getMapReduceSizeAsString(mapReduce));\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testMapReduceQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Document> mapReduce = addListenerCalledFlagSetter(mongoColl.mapReduceAsync(MAP_REDUCE_QUERY)).get();\n                    assertEquals(FIELD_INT_SUM, getMapReduceSizeAsString(mapReduce));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testMapReduceBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<Document> mapReduce = addListenerCalledFlagSetter(mongoColl.mapReduceAsync(MAP_REDUCE_QUERY)).get();\n                    assertEquals(FIELD_INT_SUM, getMapReduceSizeAsString(mapReduce));\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static final int PARALLEL_SCAN_CONCURRENT_ITERATORS = 2;\n    private static final ParallelScan.Builder PARALLEL_SCAN_QUERY = ParallelScan.builder().setRequestedIteratorCount(PARALLEL_SCAN_CONCURRENT_ITERATORS);\n        \n    @Test\n    public void testParallelScanQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Collection<MongoIterator<Document>> parallelScan = mongoColl.parallelScan(PARALLEL_SCAN_QUERY.build());\n                assertEquals(1, parallelScan.size());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testParallelScanBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Collection<MongoIterator<Document>> parallelScan = mongoColl.parallelScan(PARALLEL_SCAN_QUERY);\n                assertEquals(1, parallelScan.size());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testParallelScanQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Collection<MongoIterator<Document>> parallelScan = addListenerCalledFlagSetter(mongoColl.parallelScanAsync(PARALLEL_SCAN_QUERY.build())).get();\n                    assertEquals(1, parallelScan.size());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testParallelScanBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Collection<MongoIterator<Document>> parallelScan = addListenerCalledFlagSetter(mongoColl.parallelScanAsync(PARALLEL_SCAN_QUERY)).get();\n                    assertEquals(1, parallelScan.size());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    \n    private static Document updatedDocument(Document docLoaded) {\n        return d(e(\"_id\", docLoaded.get(\"_id\")), ELEM_TY, ELEM_FIELD_STRING_1, UPDATE_ELEMENT).build();\n    }\n\n    \n    @Test\n    public void testSaveQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document docLoaded = mongoColl.findOne(FIND_DOCUMENT);\n                Document docChanged = updatedDocument(docLoaded);\n                int saved = mongoColl.save(docChanged);\n                assertEquals(1, saved); // TODO return value seems incompatible with API description, to be better understood\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testSaveQueryDurable() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document docLoaded = mongoColl.findOne(FIND_DOCUMENT);\n                Document docChanged = updatedDocument(docLoaded);\n                int saved = mongoColl.save(docChanged, Durability.ACK);\n                assertEquals(1, saved); // TODO return value seems incompatible with API description, to be better understood\n            }\n        }).start().join();\n    }  \n\n    @Test\n    public void testSaveQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document docLoaded = mongoColl.findOne(FIND_DOCUMENT);\n                    Document docChanged = updatedDocument(docLoaded);\n                    int saved = addListenerCalledFlagSetter(mongoColl.saveAsync(docChanged)).get();\n                    assertEquals(1, saved);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testSaveQueryDurableFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document docLoaded = mongoColl.findOne(FIND_DOCUMENT);\n                    Document docChanged = updatedDocument(docLoaded);\n                    int saved = addListenerCalledFlagSetter(mongoColl.saveAsync(docChanged, Durability.ACK)).get();\n                    assertEquals(1, saved); // TODO return value seems incompatible with API description, to be better understood\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static final Text.Builder TEXT_SEARCH_QUERY = Text.builder().searchTerm(TEXT_SEARCH_TERM);\n\n    @Test\n    @Deprecated\n    public void testTextSearchQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<TextResult> textResult = mongoColl.textSearch(TEXT_SEARCH_QUERY.build());\n                assertNotNull(textResult.hasNext());\n                textResult.next();\n                assertNotNull(textResult.hasNext()); // 2 results\n            }\n        }).start().join();\n    }\n\n    @Test\n    @Deprecated\n    public void testTextSearchBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                MongoIterator<TextResult> textResult = mongoColl.textSearch(TEXT_SEARCH_QUERY);\n                assertNotNull(textResult.hasNext());\n                textResult.next();\n                assertNotNull(textResult.hasNext()); // 2 results\n            }\n        }).start().join();\n    }\n\n    @Test\n    @Deprecated\n    public void testTextSearchQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<TextResult> textResult = addListenerCalledFlagSetter(mongoColl.textSearchAsync(TEXT_SEARCH_QUERY.build())).get();\n                    assertNotNull(textResult.hasNext());\n                    textResult.next();\n                    assertNotNull(textResult.hasNext()); // 2 results\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    @Deprecated\n    public void testTextSearchBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    MongoIterator<TextResult> textResult = addListenerCalledFlagSetter(mongoColl.textSearchAsync(TEXT_SEARCH_QUERY)).get();\n                    assertNotNull(textResult.hasNext());\n                    textResult.next();\n                    assertNotNull(textResult.hasNext()); // 2 results\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static final int UPDATE_SIZE = TEST_SET_DOCS_COUNT_WITH_FIELD_INT_FIRST_VALUE;\n    \n    @Test\n    public void testUpate() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long updated = mongoColl.update(FIND_DOCUMENT, UPDATE_DOCUMENT);\n                assertEquals(UPDATE_SIZE, updated);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testUpdateMultiUpsert() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long updated = mongoColl.update(FIND_DOCUMENT, UPDATE_DOCUMENT, false, true);\n                assertEquals(UPDATE_SIZE, updated);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testUpdateMultiUpsertDurability() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long updated = mongoColl.update(FIND_DOCUMENT, UPDATE_DOCUMENT, false, true, Durability.ACK);\n                assertEquals(UPDATE_SIZE, updated);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testUpdateDurability() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long updated = mongoColl.update(FIND_DOCUMENT, UPDATE_DOCUMENT, Durability.ACK);\n                assertEquals(UPDATE_SIZE, updated);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testUpdateFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long updated = addListenerCalledFlagSetter(mongoColl.updateAsync(FIND_DOCUMENT, UPDATE_DOCUMENT)).get();\n                    assertEquals(UPDATE_SIZE, updated);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testUpdateMultiUpsertFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long updated = addListenerCalledFlagSetter(mongoColl.updateAsync(FIND_DOCUMENT, UPDATE_DOCUMENT, false, true)).get();\n                    assertEquals(UPDATE_SIZE, updated);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testUpdateMultiUpsertDurabilityFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long updated = addListenerCalledFlagSetter(mongoColl.updateAsync(FIND_DOCUMENT, UPDATE_DOCUMENT, false, true, Durability.ACK)).get();\n                    assertEquals(UPDATE_SIZE, updated);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testUpdateDurabilityFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long updated = addListenerCalledFlagSetter(mongoColl.updateAsync(FIND_DOCUMENT, UPDATE_DOCUMENT, Durability.ACK)).get();\n                    assertEquals(UPDATE_SIZE, updated);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    private static final BatchedWrite.Builder BATCHED_WRITE_BUILDER = BatchedWrite.builder().update(FIND_DOCUMENT, UPDATE_DOCUMENT);\n    \n    @Test\n    public void testWriteQuery() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long written = mongoColl.write(BATCHED_WRITE_BUILDER.build());\n                assertEquals(UPDATE_SIZE, written);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testWriteBuilder() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                long written = mongoColl.write(BATCHED_WRITE_BUILDER);\n                assertEquals(UPDATE_SIZE, written);\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testWriteQueryFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long written = addListenerCalledFlagSetter(mongoColl.writeAsync(BATCHED_WRITE_BUILDER.build())).get();\n                    assertEquals(UPDATE_SIZE, written);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testWriteBuilderFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    long written = addListenerCalledFlagSetter(mongoColl.writeAsync(BATCHED_WRITE_BUILDER)).get();\n                    assertEquals(UPDATE_SIZE, written);\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    } \n}"
  },
  {
    "path": "comsat-mongodb-allanbank/src/test/java/co/paralleluniverse/fibers/mongodb/FiberMongoDbTest.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.mongodb;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport com.allanbank.mongodb.bson.Document;\nimport com.allanbank.mongodb.bson.builder.BuilderFactory;\nimport java.util.concurrent.ExecutionException;\nimport org.junit.After;\nimport static org.junit.Assert.*;\nimport org.junit.Before;\nimport org.junit.Test;\n\n/**\n * @author circlespainter\n * \n * TODO Missing tests:\n * \n * 1) Non-async suspendable methods (already declared in \"suspendables\"); anyway some are already used as part of test setup\n * 2) New fiber-blocking APIs for now async-only operations (when added, @see co.paralleluniverse.fibers.mongodb.FiberMongoDatabaseImpl)\n */\npublic class FiberMongoDbTest extends AbstractTestFiberMongo {\n    @Before\n    public void setUpTest() throws ExecutionException, InterruptedException {\n        super.setUpTestBase();\n    }\n    \n    @After\n    public void tearDownTest() throws ExecutionException, InterruptedException {\n        super.tearDownTestBase();\n    }\n    \n    @Test\n    public void testRunCommandDocument() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document res = mongoDb.runCommand (\n                    BuilderFactory.start()\n                        .add(\"ping\", 1)\n                );\n                assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testRunCommandString() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document res = mongoDb.runCommand(\"ping\");\n                assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testRunCommandOptions() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document res = mongoDb.runCommand(\"ping\", null);\n                assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testRunCommandNameIntValueOptions() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document res = mongoDb.runCommand(\"ping\", 1, null);\n                assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testRunCommandNameStringValueOptions() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                Document res = mongoDb.runCommand(\"ping\", \"1\", null);\n                assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testRunCommandDocumentFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document res = addListenerCalledFlagSetter(mongoDb.runCommandAsync(BuilderFactory.start().add(\"ping\", 1))).get();\n                    assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n    \n    @Test\n    public void testRunCommandStringFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document res = addListenerCalledFlagSetter(mongoDb.runCommandAsync(\"ping\")).get();\n                    assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testRunCommandOptionsFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document res = addListenerCalledFlagSetter(mongoDb.runCommandAsync(\"ping\", null)).get();\n                    assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testRunCommandNameIntValueOptionsFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document res = addListenerCalledFlagSetter(mongoDb.runCommandAsync(\"ping\", 1, null)).get();\n                    assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n\n    @Test\n    public void testRunCommandNameStringValueOptionsFuture() throws ExecutionException, InterruptedException {\n        new Fiber<Void>(new SuspendableRunnable() {\n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Document res = addListenerCalledFlagSetter(mongoDb.runCommandAsync(\"ping\", \"1\", null)).get();\n                    assertEquals(\"1.0\", res.get(\"ok\").getValueAsString());\n                    assertListenerCalled();\n                } catch (ExecutionException ex) {\n                    fail(ex.getLocalizedMessage());\n                }\n            }\n        }).start().join();\n    }\n}"
  },
  {
    "path": "comsat-okhttp/src/main/java/co/paralleluniverse/fibers/okhttp/FiberCall.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.okhttp;\n\nimport co.paralleluniverse.fibers.FiberAsync;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport com.squareup.okhttp.CallProxy;\nimport com.squareup.okhttp.Callback;\nimport com.squareup.okhttp.OkHttpClient;\nimport com.squareup.okhttp.Request;\nimport com.squareup.okhttp.Response;\nimport java.io.IOException;\nimport java.util.concurrent.ExecutionException;\n\n/**\n * Fiber-blocking OkHttp's {@link Call} implementation.\n *\n * @author circlespainter\n */\npublic class FiberCall extends CallProxy {\n\n    public FiberCall(final OkHttpClient client, final Request originalRequest) {\n        super(client, originalRequest);\n    }\n\n    @Override\n    @Suspendable\n    public Response execute() throws IOException {\n        try {\n            return new FiberAsyncCallback().run();\n        } catch (final SuspendExecution | InterruptedException ex) {\n            throw new AssertionError(ex);\n        }\n    }\n    \n    private class FiberAsyncCallback extends FiberAsync<Response, IOException> implements Callback {\n        @Override\n        protected void requestAsync() {\n            enqueue(this);\n        }\n\n        @Override\n        public void onFailure(final Request rqst, final IOException ioe) {\n            asyncFailed(ioe);\n        }\n\n        @Override\n        public void onResponse(final Response rspns) throws IOException {\n            asyncCompleted(rspns);\n        }\n\n        @Override\n        protected Response requestSync() throws IOException, InterruptedException, ExecutionException {\n            return FiberCall.super.execute();\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/main/java/co/paralleluniverse/fibers/okhttp/FiberOkHttpClient.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.okhttp;\n\nimport com.squareup.okhttp.Call;\nimport com.squareup.okhttp.OkHttpClient;\nimport com.squareup.okhttp.Request;\n\n/**\n * Fiber-blocking OkHttp's {@link OkHttpClient} implementation.\n *\n * @author circlespainter\n */\npublic class FiberOkHttpClient extends OkHttpClient {\n\n    @Override\n    public Call newCall(Request request) {\n        return new FiberCall(this, request);\n    }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/main/java/co/paralleluniverse/fibers/okhttp/FiberOkHttpUtil.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.okhttp;\n\nimport co.paralleluniverse.fibers.FiberUtil;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableCallable;\nimport com.squareup.okhttp.Call;\nimport com.squareup.okhttp.OkUrlFactory;\nimport com.squareup.okhttp.Request;\nimport com.squareup.okhttp.Response;\nimport com.squareup.okhttp.apache.OkApacheClient;\nimport java.io.IOException;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.methods.HttpRequestBase;\n\n/**\n *\n * @author circlespainter\n */\npublic class FiberOkHttpUtil {\n  public static Response executeInFiber(final FiberOkHttpClient client, final Request request) throws InterruptedException, IOException {\n    return FiberOkHttpUtil.executeInFiber(client.newCall(request));\n  }\n\n    public static Response executeInFiber(final Call call) throws InterruptedException, IOException {\n        return FiberUtil.runInFiberChecked (\n            new SuspendableCallable<Response>() {\n                @Override\n                public Response run() throws SuspendExecution, InterruptedException {\n                    try {\n                        return call.execute();\n                    } catch (IOException ex) {\n                        throw new RuntimeException(ex);\n                    }\n                }\n            }, IOException.class\n        );\n    }\n\n    public static HttpURLConnection openInFiber(final OkUrlFactory factory, final URL url) throws InterruptedException {\n        return FiberUtil.runInFiberRuntime (\n            new SuspendableCallable<HttpURLConnection>() {\n                @Override\n                public HttpURLConnection run() throws SuspendExecution, InterruptedException {\n                    return factory.open(url);\n                }\n            }\n        );\n    }\n\n    public static HttpResponse executeInFiber(final OkApacheClient client, final HttpRequestBase req) throws InterruptedException, IOException {\n        return FiberUtil.runInFiberChecked (\n            new SuspendableCallable<HttpResponse>() {\n                @Override\n                public HttpResponse run() throws SuspendExecution, InterruptedException {\n                    try {\n                        return client.execute(req);\n                    } catch (IOException ex) {\n                        throw new RuntimeException(ex);\n                    }\n                }\n           }, IOException.class\n        );\n    }\n\n    private FiberOkHttpUtil() {\n    }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/main/java/com/squareup/okhttp/CallProxy.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage com.squareup.okhttp;\n\n/**\n * Proxy to open up the {@link Call} protected (since version 2.4.0) constructor.\n *\n * @author circlespainter\n */\npublic class CallProxy extends Call {\n    public CallProxy(final OkHttpClient client, final Request originalRequest) {\n        super(client, originalRequest);\n    }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/main/resources/META-INF/suspendables",
    "content": "com.squareup.okhttp.apache.OkApacheClient.execute"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/InterceptorTest.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test;\n\nimport co.paralleluniverse.fibers.okhttp.test.utils.FiberOkHttpClientTestWrapper;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.RecordingCallback;\nimport com.squareup.okhttp.*;\nimport com.squareup.okhttp.mockwebserver.MockResponse;\nimport com.squareup.okhttp.mockwebserver.MockWebServer;\nimport com.squareup.okhttp.mockwebserver.RecordedRequest;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.SynchronousQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.ForwardingSink;\nimport okio.ForwardingSource;\nimport okio.GzipSink;\nimport okio.Okio;\nimport okio.Sink;\nimport okio.Source;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.fail;\n\npublic final class InterceptorTest {\n  @Rule public MockWebServer server = new MockWebServer();\n\n  private OkHttpClient client = new FiberOkHttpClientTestWrapper();\n  private RecordingCallback callback = new RecordingCallback();\n\n  @Test public void applicationInterceptorsCanShortCircuitResponses() throws Exception {\n    server.shutdown(); // Accept no connections.\n\n    Request request = new Request.Builder()\n        .url(\"https://localhost:1/\")\n        .build();\n\n    final Response interceptorResponse = new Response.Builder()\n        .request(request)\n        .protocol(Protocol.HTTP_1_1)\n        .code(200)\n        .message(\"Intercepted!\")\n        .body(ResponseBody.create(MediaType.parse(\"text/plain; charset=utf-8\"), \"abc\"))\n        .build();\n\n    client.interceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        return interceptorResponse;\n      }\n    });\n\n    Response response = client.newCall(request).execute();\n    assertSame(interceptorResponse, response);\n  }\n\n  @Ignore\n  @Test public void networkInterceptorsCannotShortCircuitResponses() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(500));\n\n    Interceptor interceptor = new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        return new Response.Builder()\n            .request(chain.request())\n            .protocol(Protocol.HTTP_1_1)\n            .code(200)\n            .message(\"Intercepted!\")\n            .body(ResponseBody.create(MediaType.parse(\"text/plain; charset=utf-8\"),\n  \"abc\"))\n            .build();\n      }\n    };\n    client.networkInterceptors().add(interceptor);\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (IllegalStateException expected) {\n      assertEquals(\"network interceptor \" + interceptor + \" must call proceed() exactly once\",\n          expected.getMessage());\n    }\n  }\n\n  @Ignore\n  @Test public void networkInterceptorsCannotCallProceedMultipleTimes() throws Exception {\n    server.enqueue(new MockResponse());\n    server.enqueue(new MockResponse());\n\n    Interceptor interceptor = new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        chain.proceed(chain.request());\n        return chain.proceed(chain.request());\n      }\n    };\n    client.networkInterceptors().add(interceptor);\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (IllegalStateException expected) {\n      assertEquals(\"network interceptor \" + interceptor + \" must call proceed() exactly once\",\n          expected.getMessage());\n    }\n  }\n\n  @Ignore\n  @Test public void networkInterceptorsCannotChangeServerAddress() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(500));\n\n    Interceptor interceptor = new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        Address address = chain.connection().getRoute().getAddress();\n        String sameHost = address.getUriHost();\n        int differentPort = address.getUriPort() + 1;\n        return chain.proceed(chain.request().newBuilder()\n            .url(HttpUrl.parse(\"http://\" + sameHost + \":\" + differentPort + \"/\"))\n            .build());\n      }\n    };\n    client.networkInterceptors().add(interceptor);\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (IllegalStateException expected) {\n      assertEquals(\"network interceptor \" + interceptor + \" must retain the same host and port\",\n          expected.getMessage());\n    }\n  }\n\n  @Test public void networkInterceptorsHaveConnectionAccess() throws Exception {\n    server.enqueue(new MockResponse());\n\n    client.networkInterceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        Connection connection = chain.connection();\n        assertNotNull(connection);\n        return chain.proceed(chain.request());\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request).execute();\n  }\n\n  @Test public void networkInterceptorsObserveNetworkHeaders() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(gzip(\"abcabcabc\"))\n        .addHeader(\"Content-Encoding: gzip\"));\n\n    client.networkInterceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        // The network request has everything: User-Agent, Host, Accept-Encoding.\n        Request networkRequest = chain.request();\n        assertNotNull(networkRequest.header(\"User-Agent\"));\n        assertEquals(server.getHostName() + \":\" + server.getPort(),\n            networkRequest.header(\"Host\"));\n        assertNotNull(networkRequest.header(\"Accept-Encoding\"));\n\n        // The network response also has everything, including the raw gzipped content.\n        Response networkResponse = chain.proceed(networkRequest);\n        assertEquals(\"gzip\", networkResponse.header(\"Content-Encoding\"));\n        return networkResponse;\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    // No extra headers in the application's request.\n    assertNull(request.header(\"User-Agent\"));\n    assertNull(request.header(\"Host\"));\n    assertNull(request.header(\"Accept-Encoding\"));\n\n    // No extra headers in the application's response.\n    Response response = client.newCall(request).execute();\n    assertNull(request.header(\"Content-Encoding\"));\n    assertEquals(\"abcabcabc\", response.body().string());\n  }\n\n  @Test public void networkInterceptorsCanChangeRequestMethodFromGetToPost() throws Exception {\n    server.enqueue(new MockResponse());\n\n    client.networkInterceptors().add(new Interceptor() {\n      @Override\n      public Response intercept(Chain chain) throws IOException {\n        Request originalRequest = chain.request();\n        MediaType mediaType = MediaType.parse(\"text/plain\");\n        RequestBody body = RequestBody.create(mediaType, \"abc\");\n        return chain.proceed(originalRequest.newBuilder()\n            .method(\"POST\", body)\n            .header(\"Content-Type\", mediaType.toString())\n            .header(\"Content-Length\", Long.toString(body.contentLength()))\n            .build());\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .get()\n        .build();\n\n    client.newCall(request).execute();\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"POST\", recordedRequest.getMethod());\n    assertEquals(\"abc\", recordedRequest.getBody().readUtf8());\n  }\n\n  @Test public void applicationInterceptorsRewriteRequestToServer() throws Exception {\n    rewriteRequestToServer(client.interceptors());\n  }\n\n  @Test public void networkInterceptorsRewriteRequestToServer() throws Exception {\n    rewriteRequestToServer(client.networkInterceptors());\n  }\n\n  private void rewriteRequestToServer(List<Interceptor> interceptors) throws Exception {\n    server.enqueue(new MockResponse());\n\n    interceptors.add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        Request originalRequest = chain.request();\n        return chain.proceed(originalRequest.newBuilder()\n            .method(\"POST\", uppercase(originalRequest.body()))\n            .addHeader(\"OkHttp-Intercepted\", \"yep\")\n            .build());\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .addHeader(\"Original-Header\", \"foo\")\n        .method(\"PUT\", RequestBody.create(MediaType.parse(\"text/plain\"), \"abc\"))\n        .build();\n\n    client.newCall(request).execute();\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"ABC\", recordedRequest.getBody().readUtf8());\n    assertEquals(\"foo\", recordedRequest.getHeader(\"Original-Header\"));\n    assertEquals(\"yep\", recordedRequest.getHeader(\"OkHttp-Intercepted\"));\n    assertEquals(\"POST\", recordedRequest.getMethod());\n  }\n\n  @Test public void applicationInterceptorsRewriteResponseFromServer() throws Exception {\n    rewriteResponseFromServer(client.interceptors());\n  }\n\n  @Test public void networkInterceptorsRewriteResponseFromServer() throws Exception {\n    rewriteResponseFromServer(client.networkInterceptors());\n  }\n\n  private void rewriteResponseFromServer(List<Interceptor> interceptors) throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Original-Header: foo\")\n        .setBody(\"abc\"));\n\n    interceptors.add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        Response originalResponse = chain.proceed(chain.request());\n        return originalResponse.newBuilder()\n            .body(uppercase(originalResponse.body()))\n            .addHeader(\"OkHttp-Intercepted\", \"yep\")\n            .build();\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    Response response = client.newCall(request).execute();\n    assertEquals(\"ABC\", response.body().string());\n    assertEquals(\"yep\", response.header(\"OkHttp-Intercepted\"));\n    assertEquals(\"foo\", response.header(\"Original-Header\"));\n  }\n\n  @Test public void multipleApplicationInterceptors() throws Exception {\n    multipleInterceptors(client.interceptors());\n  }\n\n  @Test public void multipleNetworkInterceptors() throws Exception {\n    multipleInterceptors(client.networkInterceptors());\n  }\n\n  private void multipleInterceptors(List<Interceptor> interceptors) throws Exception {\n    server.enqueue(new MockResponse());\n\n    interceptors.add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        Request originalRequest = chain.request();\n        Response originalResponse = chain.proceed(originalRequest.newBuilder()\n            .addHeader(\"Request-Interceptor\", \"Android\") // 1. Added first.\n            .build());\n        return originalResponse.newBuilder()\n            .addHeader(\"Response-Interceptor\", \"Donut\") // 4. Added last.\n            .build();\n      }\n    });\n    interceptors.add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        Request originalRequest = chain.request();\n        Response originalResponse = chain.proceed(originalRequest.newBuilder()\n            .addHeader(\"Request-Interceptor\", \"Bob\") // 2. Added second.\n            .build());\n        return originalResponse.newBuilder()\n            .addHeader(\"Response-Interceptor\", \"Cupcake\") // 3. Added third.\n            .build();\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    Response response = client.newCall(request).execute();\n    assertEquals(Arrays.asList(\"Cupcake\", \"Donut\"),\n        response.headers(\"Response-Interceptor\"));\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(Arrays.asList(\"Android\", \"Bob\"),\n        recordedRequest.getHeaders().values(\"Request-Interceptor\"));\n  }\n\n  @Test public void asyncApplicationInterceptors() throws Exception {\n    asyncInterceptors(client.interceptors());\n  }\n\n  @Test public void asyncNetworkInterceptors() throws Exception {\n    asyncInterceptors(client.networkInterceptors());\n  }\n\n  private void asyncInterceptors(List<Interceptor> interceptors) throws Exception {\n    server.enqueue(new MockResponse());\n\n    interceptors.add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        Response originalResponse = chain.proceed(chain.request());\n        return originalResponse.newBuilder()\n            .addHeader(\"OkHttp-Intercepted\", \"yep\")\n            .build();\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request).enqueue(callback);\n\n    callback.await(request.httpUrl())\n        .assertCode(200)\n        .assertHeader(\"OkHttp-Intercepted\", \"yep\");\n  }\n\n  @Test public void applicationInterceptorsCanMakeMultipleRequestsToServer() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"a\"));\n    server.enqueue(new MockResponse().setBody(\"b\"));\n\n    client.interceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        chain.proceed(chain.request());\n        return chain.proceed(chain.request());\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    Response response = client.newCall(request).execute();\n    assertEquals(response.body().string(), \"b\");\n  }\n\n  /** Make sure interceptors can interact with the OkHttp client. */\n  @Test public void interceptorMakesAnUnrelatedRequest() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"a\")); // Fetched by interceptor.\n    server.enqueue(new MockResponse().setBody(\"b\")); // Fetched directly.\n\n    client.interceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        if (chain.request().url().getPath().equals(\"/b\")) {\n          Request requestA = new Request.Builder()\n              .url(server.url(\"/a\"))\n              .build();\n          Response responseA = client.newCall(requestA).execute();\n          assertEquals(\"a\", responseA.body().string());\n        }\n\n        return chain.proceed(chain.request());\n      }\n    });\n\n    Request requestB = new Request.Builder()\n        .url(server.url(\"/b\"))\n        .build();\n    Response responseB = client.newCall(requestB).execute();\n    assertEquals(\"b\", responseB.body().string());\n  }\n\n  /** Make sure interceptors can interact with the OkHttp client asynchronously. */\n  @Test public void interceptorMakesAnUnrelatedAsyncRequest() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"a\")); // Fetched by interceptor.\n    server.enqueue(new MockResponse().setBody(\"b\")); // Fetched directly.\n\n    client.interceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        if (chain.request().url().getPath().equals(\"/b\")) {\n          Request requestA = new Request.Builder()\n              .url(server.url(\"/a\"))\n              .build();\n\n          try {\n            RecordingCallback callbackA = new RecordingCallback();\n            client.newCall(requestA).enqueue(callbackA);\n            callbackA.await(requestA.httpUrl()).assertBody(\"a\");\n          } catch (Exception e) {\n            throw new RuntimeException(e);\n          }\n        }\n\n        return chain.proceed(chain.request());\n      }\n    });\n\n    Request requestB = new Request.Builder()\n        .url(server.url(\"/b\"))\n        .build();\n    RecordingCallback callbackB = new RecordingCallback();\n    client.newCall(requestB).enqueue(callbackB);\n    callbackB.await(requestB.httpUrl()).assertBody(\"b\");\n  }\n\n  @Ignore @Test public void applicationkInterceptorThrowsRuntimeExceptionSynchronous() throws Exception {\n    interceptorThrowsRuntimeExceptionSynchronous(client.interceptors());\n  }\n\n  @Ignore @Test public void networkInterceptorThrowsRuntimeExceptionSynchronous() throws Exception {\n    interceptorThrowsRuntimeExceptionSynchronous(client.networkInterceptors());\n  }\n\n  /**\n   * When an interceptor throws an unexpected exception, synchronous callers can catch it and deal\n   * with it.\n   *\n   * TODO(jwilson): test that resources are not leaked when this happens.\n   */\n  private void interceptorThrowsRuntimeExceptionSynchronous(\n      List<Interceptor> interceptors) throws Exception {\n    interceptors.add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        throw new RuntimeException(\"boom!\");\n      }\n    });\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (RuntimeException expected) {\n      assertEquals(\"boom!\", expected.getMessage());\n    }\n  }\n\n  @Test public void networkInterceptorModifiedRequestIsReturned() throws IOException {\n    server.enqueue(new MockResponse());\n\n    Interceptor modifyHeaderInterceptor = new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        return chain.proceed(chain.request().newBuilder()\n          .header(\"User-Agent\", \"intercepted request\")\n          .build());\n      }\n    };\n\n    client.networkInterceptors().add(modifyHeaderInterceptor);\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"User-Agent\", \"user request\")\n        .build();\n\n    Response response = client.newCall(request).execute();\n    assertNotNull(response.request().header(\"User-Agent\"));\n    assertEquals(\"user request\", response.request().header(\"User-Agent\"));\n    assertEquals(\"intercepted request\", response.networkResponse().request().header(\"User-Agent\"));\n  }\n\n  @Test public void applicationInterceptorThrowsRuntimeExceptionAsynchronous() throws Exception {\n    interceptorThrowsRuntimeExceptionAsynchronous(client.interceptors());\n  }\n\n  @Test public void networkInterceptorThrowsRuntimeExceptionAsynchronous() throws Exception {\n    interceptorThrowsRuntimeExceptionAsynchronous(client.networkInterceptors());\n  }\n\n  /**\n   * When an interceptor throws an unexpected exception, asynchronous callers are left hanging. The\n   * exception goes to the uncaught exception handler.\n   *\n   * TODO(jwilson): test that resources are not leaked when this happens.\n   */\n  private void interceptorThrowsRuntimeExceptionAsynchronous(\n        List<Interceptor> interceptors) throws Exception {\n    interceptors.add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        throw new RuntimeException(\"boom!\");\n      }\n    });\n\n    ExceptionCatchingExecutor executor = new ExceptionCatchingExecutor();\n    client.setDispatcher(new Dispatcher(executor));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request).enqueue(callback);\n\n    assertEquals(\"boom!\", executor.takeException().getMessage());\n  }\n\n  @Ignore @Test public void applicationInterceptorReturnsNull() throws Exception {\n    server.enqueue(new MockResponse());\n\n    Interceptor interceptor = new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        chain.proceed(chain.request());\n        return null;\n      }\n    };\n    client.interceptors().add(interceptor);\n\n    ExceptionCatchingExecutor executor = new ExceptionCatchingExecutor();\n    client.setDispatcher(new Dispatcher(executor));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (NullPointerException expected) {\n      assertEquals(\"application interceptor \" + interceptor\n          + \" returned null\", expected.getMessage());\n    }\n  }\n\n  @Ignore @Test public void networkInterceptorReturnsNull() throws Exception {\n    server.enqueue(new MockResponse());\n\n    Interceptor interceptor = new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        chain.proceed(chain.request());\n        return null;\n      }\n    };\n    client.networkInterceptors().add(interceptor);\n\n    ExceptionCatchingExecutor executor = new ExceptionCatchingExecutor();\n    client.setDispatcher(new Dispatcher(executor));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (NullPointerException expected) {\n      assertEquals(\"network interceptor \" + interceptor + \" returned null\", expected.getMessage());\n    }\n  }\n\n  private RequestBody uppercase(final RequestBody original) {\n    return new RequestBody() {\n      @Override public MediaType contentType() {\n        return original.contentType();\n      }\n\n      @Override public long contentLength() throws IOException {\n        return original.contentLength();\n      }\n\n      @Override public void writeTo(BufferedSink sink) throws IOException {\n        Sink uppercase = uppercase(sink);\n        BufferedSink bufferedSink = Okio.buffer(uppercase);\n        original.writeTo(bufferedSink);\n        bufferedSink.emit();\n      }\n    };\n  }\n\n  private Sink uppercase(final BufferedSink original) {\n    return new ForwardingSink(original) {\n      @Override public void write(Buffer source, long byteCount) throws IOException {\n        original.writeUtf8(source.readUtf8(byteCount).toUpperCase(Locale.US));\n      }\n    };\n  }\n\n  static ResponseBody uppercase(ResponseBody original) throws IOException {\n    return ResponseBody.create(original.contentType(), original.contentLength(),\n        Okio.buffer(uppercase(original.source())));\n  }\n\n  private static Source uppercase(final Source original) {\n    return new ForwardingSource(original) {\n      @Override public long read(Buffer sink, long byteCount) throws IOException {\n        Buffer mixedCase = new Buffer();\n        long count = original.read(mixedCase, byteCount);\n        sink.writeUtf8(mixedCase.readUtf8().toUpperCase(Locale.US));\n        return count;\n      }\n    };\n  }\n\n  private Buffer gzip(String data) throws IOException {\n    Buffer result = new Buffer();\n    BufferedSink sink = Okio.buffer(new GzipSink(result));\n    sink.writeUtf8(data);\n    sink.close();\n    return result;\n  }\n\n  /** Catches exceptions that are otherwise headed for the uncaught exception handler. */\n  private static class ExceptionCatchingExecutor extends ThreadPoolExecutor {\n    private final BlockingQueue<Exception> exceptions = new LinkedBlockingQueue<>();\n\n    public ExceptionCatchingExecutor() {\n      super(1, 1, 0, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());\n    }\n\n    @Override public void execute(final Runnable runnable) {\n      super.execute(new Runnable() {\n        @Override public void run() {\n          try {\n            runnable.run();\n          } catch (Exception e) {\n            exceptions.add(e);\n          }\n        }\n      });\n    }\n\n    public Exception takeException() throws InterruptedException {\n      return exceptions.take();\n    }\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/apache/OkApacheClientTest.java",
    "content": "package co.paralleluniverse.fibers.okhttp.test.apache;\n\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.fibers.okhttp.FiberOkHttpClient;\nimport com.squareup.okhttp.apache.OkApacheClient;\nimport com.squareup.okhttp.mockwebserver.MockResponse;\nimport com.squareup.okhttp.mockwebserver.MockWebServer;\nimport com.squareup.okhttp.mockwebserver.RecordedRequest;\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URISyntaxException;\nimport java.util.zip.GZIPInputStream;\nimport okio.Buffer;\nimport okio.GzipSink;\nimport okio.Okio;\nimport org.apache.http.Header;\nimport org.apache.http.HttpEntity;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.client.methods.HttpPut;\nimport org.apache.http.entity.ByteArrayEntity;\nimport org.apache.http.entity.InputStreamEntity;\nimport org.apache.http.entity.StringEntity;\nimport org.apache.http.util.EntityUtils;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static com.squareup.okhttp.internal.Util.UTF_8;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\n\npublic class OkApacheClientTest {\n  private MockWebServer server;\n  private OkApacheTestWrapper client;\n\n  @Before public void setUp() throws IOException {\n    client = new OkApacheTestWrapper(new OkApacheClient(new FiberOkHttpClient()));\n    server = new MockWebServer();\n    server.start();\n  }\n\n  @After public void tearDown() throws IOException {\n    server.shutdown();\n  }\n\n  @Suspendable @Test public void success() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"Hello, World!\"));\n\n    HttpGet request = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response = client.execute(request);\n    String actual = EntityUtils.toString(response.getEntity());\n    assertEquals(\"Hello, World!\", actual);\n  }\n\n  @Suspendable @Test public void redirect() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(302).addHeader(\"Location\", \"/foo\"));\n    server.enqueue(new MockResponse().setBody(\"Hello, Redirect!\"));\n\n    HttpGet request = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response = client.execute(request);\n    String actual = EntityUtils.toString(response.getEntity(), UTF_8);\n    assertEquals(\"Hello, Redirect!\", actual);\n  }\n\n  @Suspendable @Test public void sessionExpired() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(422));\n\n    HttpGet request = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response = client.execute(request);\n    assertEquals(422, response.getStatusLine().getStatusCode());\n  }\n\n  @Suspendable @Test public void headers() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Foo\", \"Bar\"));\n    server.enqueue(new MockResponse().addHeader(\"Foo\", \"Bar\").addHeader(\"Foo\", \"Baz\"));\n\n    HttpGet request1 = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response1 = client.execute(request1);\n    Header[] headers1 = response1.getHeaders(\"Foo\");\n    assertEquals(1, headers1.length);\n    assertEquals(\"Bar\", headers1[0].getValue());\n\n    HttpGet request2 = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response2 = client.execute(request2);\n    Header[] headers2 = response2.getHeaders(\"Foo\");\n    assertEquals(2, headers2.length);\n    assertEquals(\"Bar\", headers2[0].getValue());\n    assertEquals(\"Baz\", headers2[1].getValue());\n  }\n\n  @Suspendable @Test public void postByteEntity() throws Exception {\n    server.enqueue(new MockResponse());\n\n    final HttpPost post = new HttpPost(server.getUrl(\"/\").toURI());\n    byte[] body = \"Hello, world!\".getBytes(UTF_8);\n    post.setEntity(new ByteArrayEntity(body));\n    client.execute(post);\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"Hello, world!\", request.getBody().readUtf8());\n    assertEquals(request.getHeader(\"Content-Length\"), \"13\");\n  }\n\n  @Suspendable @Test public void postInputStreamEntity() throws Exception {\n    server.enqueue(new MockResponse());\n\n    final HttpPost post = new HttpPost(server.getUrl(\"/\").toURI());\n    byte[] body = \"Hello, world!\".getBytes(UTF_8);\n    post.setEntity(new InputStreamEntity(new ByteArrayInputStream(body), body.length));\n    client.execute(post);\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"Hello, world!\", request.getBody().readUtf8());\n    assertEquals(request.getHeader(\"Content-Length\"), \"13\");\n  }\n  @Suspendable @Test public void postEmptyEntity() throws Exception {\n    server.enqueue(new MockResponse());\n    final HttpPost post = new HttpPost(server.getUrl(\"/\").toURI());\n    client.execute(post);\n    \n    RecordedRequest request = server.takeRequest();\n    assertEquals(0, request.getBodySize());\n    assertNotNull(request.getBody());\n  }\n  @Suspendable @Test public void putEmptyEntity() throws Exception {\n    server.enqueue(new MockResponse());\n    final HttpPut put = new HttpPut(server.getUrl(\"/\").toURI());\n    client.execute(put);\n    \n    RecordedRequest request = server.takeRequest();\n    assertEquals(0, request.getBodySize());\n    assertNotNull(request.getBody());\n  }\n\n  @Suspendable @Test public void postOverrideContentType() throws Exception {\n    server.enqueue(new MockResponse());\n\n    HttpPost httpPost = new HttpPost();\n    httpPost.setURI(server.getUrl(\"/\").toURI());\n    httpPost.addHeader(\"Content-Type\", \"application/xml\");\n    httpPost.setEntity(new StringEntity(\"<yo/>\"));\n    client.execute(httpPost);\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(request.getHeader(\"Content-Type\"), \"application/xml\");\n  }\n\n  @Suspendable @Test public void contentType() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"<html><body><h1>Hello, World!</h1></body></html>\")\n        .setHeader(\"Content-Type\", \"text/html\"));\n    server.enqueue(new MockResponse().setBody(\"{\\\"Message\\\": { \\\"text\\\": \\\"Hello, World!\\\" } }\")\n        .setHeader(\"Content-Type\", \"application/json\"));\n    server.enqueue(new MockResponse().setBody(\"Hello, World!\"));\n\n    HttpGet request1 = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response1 = client.execute(request1);\n    Header[] headers1 = response1.getHeaders(\"Content-Type\");\n    assertEquals(1, headers1.length);\n    assertEquals(\"text/html\", headers1[0].getValue());\n    assertNotNull(response1.getEntity().getContentType());\n    assertEquals(\"text/html\", response1.getEntity().getContentType().getValue());\n\n    HttpGet request2 = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response2 = client.execute(request2);\n    Header[] headers2 = response2.getHeaders(\"Content-Type\");\n    assertEquals(1, headers2.length);\n    assertEquals(\"application/json\", headers2[0].getValue());\n    assertNotNull(response2.getEntity().getContentType());\n    assertEquals(\"application/json\", response2.getEntity().getContentType().getValue());\n\n    HttpGet request3 = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response3 = client.execute(request3);\n    Header[] headers3 = response3.getHeaders(\"Content-Type\");\n    assertEquals(0, headers3.length);\n    assertNull(response3.getEntity().getContentType());\n  }\n\n  @Suspendable @Test public void contentTypeIsCaseInsensitive() throws URISyntaxException, IOException, InterruptedException {\n    server.enqueue(new MockResponse().setBody(\"{\\\"Message\\\": { \\\"text\\\": \\\"Hello, World!\\\" } }\")\n        .setHeader(\"cONTENT-tYPE\", \"application/json\"));\n\n    HttpGet request = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response = client.execute(request);\n    assertEquals(\"application/json\", response.getEntity().getContentType().getValue());\n  }\n\n  @Suspendable @Test public void contentEncoding() throws Exception {\n    String text = \"{\\\"Message\\\": { \\\"text\\\": \\\"Hello, World!\\\" } }\";\n    server.enqueue(new MockResponse().setBody(gzip(text))\n        .setHeader(\"Content-Encoding\", \"gzip\"));\n\n    HttpGet request = new HttpGet(server.getUrl(\"/\").toURI());\n    request.setHeader(\"Accept-encoding\", \"gzip\"); // Not transparent gzip.\n    HttpResponse response = client.execute(request);\n    HttpEntity entity = response.getEntity();\n\n    Header[] encodingHeaders = response.getHeaders(\"Content-Encoding\");\n    assertEquals(1, encodingHeaders.length);\n    assertEquals(\"gzip\", encodingHeaders[0].getValue());\n    assertNotNull(entity.getContentEncoding());\n    assertEquals(\"gzip\", entity.getContentEncoding().getValue());\n\n    assertEquals(text, gunzip(entity));\n  }\n\n  @Suspendable @Test public void jsonGzipResponse() throws Exception {\n    String text = \"{\\\"Message\\\": { \\\"text\\\": \\\"Hello, World!\\\" } }\";\n    server.enqueue(new MockResponse().setBody(gzip(text))\n        .setHeader(\"Content-Encoding\", \"gzip\")\n        .setHeader(\"Content-Type\", \"application/json\"));\n\n    HttpGet request1 = new HttpGet(server.getUrl(\"/\").toURI());\n    request1.setHeader(\"Accept-encoding\", \"gzip\"); // Not transparent gzip.\n\n    HttpResponse response = client.execute(request1);\n    HttpEntity entity = response.getEntity();\n\n    Header[] encodingHeaders = response.getHeaders(\"Content-Encoding\");\n    assertEquals(1, encodingHeaders.length);\n    assertEquals(\"gzip\", encodingHeaders[0].getValue());\n    assertNotNull(entity.getContentEncoding());\n    assertEquals(\"gzip\", entity.getContentEncoding().getValue());\n\n    Header[] typeHeaders = response.getHeaders(\"Content-Type\");\n    assertEquals(1, typeHeaders.length);\n    assertEquals(\"application/json\", typeHeaders[0].getValue());\n    assertNotNull(entity.getContentType());\n    assertEquals(\"application/json\", entity.getContentType().getValue());\n\n    assertEquals(text, gunzip(entity));\n  }\n\n  @Suspendable @Test public void jsonTransparentGzipResponse() throws Exception {\n    String text = \"{\\\"Message\\\": { \\\"text\\\": \\\"Hello, World!\\\" } }\";\n    server.enqueue(new MockResponse().setBody(gzip(text))\n        .setHeader(\"Content-Encoding\", \"gzip\")\n        .setHeader(\"Content-Type\", \"application/json\"));\n\n    HttpGet request = new HttpGet(server.getUrl(\"/\").toURI());\n    HttpResponse response = client.execute(request);\n    HttpEntity entity = response.getEntity();\n\n    // Expecting transparent gzip response by not adding header \"Accept-encoding: gzip\"\n    Header[] encodingHeaders = response.getHeaders(\"Content-Encoding\");\n    assertEquals(0, encodingHeaders.length);\n    assertNull(entity.getContentEncoding());\n\n    // Content length should be absent.\n    Header[] lengthHeaders = response.getHeaders(\"Content-Length\");\n    assertEquals(0, lengthHeaders.length);\n    assertEquals(-1, entity.getContentLength());\n\n    Header[] typeHeaders = response.getHeaders(\"Content-Type\");\n    assertEquals(1, typeHeaders.length);\n    assertEquals(\"application/json\", typeHeaders[0].getValue());\n    assertNotNull(entity.getContentType());\n    assertEquals(\"application/json\", entity.getContentType().getValue());\n\n    assertEquals(text, EntityUtils.toString(entity, UTF_8));\n  }\n\n  private static Buffer gzip(String body) throws IOException {\n    Buffer buffer = new Buffer();\n    Okio.buffer(new GzipSink(buffer)).writeUtf8(body).close();\n    return buffer;\n  }\n\n  private static String gunzip(HttpEntity body) throws IOException {\n    InputStream in = new GZIPInputStream(body.getContent());\n    Buffer buffer = new Buffer();\n    byte[] temp = new byte[1024];\n    int read;\n    while ((read = in.read(temp)) != -1) {\n      buffer.write(temp, 0, read);\n    }\n    return buffer.readUtf8();\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/apache/OkApacheTestWrapper.java",
    "content": "package co.paralleluniverse.fibers.okhttp.test.apache;\n\nimport co.paralleluniverse.fibers.okhttp.FiberOkHttpUtil;\nimport com.squareup.okhttp.apache.OkApacheClient;\nimport org.apache.http.HttpResponse;\nimport org.apache.http.client.methods.HttpRequestBase;\n\nimport java.io.IOException;\n\npublic final class OkApacheTestWrapper {\n    private OkApacheClient underlying;\n\n    public OkApacheTestWrapper(OkApacheClient underlying) {\n        this.underlying = underlying;\n    }\n\n    public HttpResponse execute(HttpRequestBase request) throws IOException, InterruptedException {\n        return FiberOkHttpUtil.executeInFiber(underlying, request);\n    }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/FiberCallTestWrapper.java",
    "content": "package co.paralleluniverse.fibers.okhttp.test.utils;\n\nimport co.paralleluniverse.fibers.okhttp.FiberCall;\nimport co.paralleluniverse.fibers.okhttp.FiberOkHttpClient;\nimport co.paralleluniverse.fibers.okhttp.FiberOkHttpUtil;\nimport com.squareup.okhttp.Call;\nimport com.squareup.okhttp.Callback;\nimport com.squareup.okhttp.Request;\nimport com.squareup.okhttp.Response;\n\nimport java.io.IOException;\n\npublic final class FiberCallTestWrapper extends FiberCall {\n    private final Call underlying;\n\n    public FiberCallTestWrapper(FiberOkHttpClient client, Call call, Request request) {\n        super(client, request);\n        this.underlying = call;\n    }\n\n    @Override\n    public Response execute() throws IOException {\n        try {\n            return FiberOkHttpUtil.executeInFiber(underlying);\n        } catch (final InterruptedException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    @Override\n    public void enqueue(Callback responseCallback) {\n        underlying.enqueue(responseCallback);\n    }\n\n    @Override\n    public void cancel() {\n        underlying.cancel();\n    }\n\n    @Override\n    public boolean isCanceled() {\n        return underlying.isCanceled();\n    }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/FiberOkHttpClientTestWrapper.java",
    "content": "package co.paralleluniverse.fibers.okhttp.test.utils;\n\nimport co.paralleluniverse.fibers.okhttp.FiberOkHttpClient;\nimport com.squareup.okhttp.Call;\nimport com.squareup.okhttp.Request;\n\nfinal public class FiberOkHttpClientTestWrapper extends FiberOkHttpClient {\n    @Override\n    public Call newCall(Request request) {\n        return new FiberCallTestWrapper(this, super.newCall(request), request);\n    }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/DelegatingSSLSocket.java",
    "content": "/*\n * Copyright 2014 Square Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.net.InetAddress;\nimport java.net.SocketAddress;\nimport java.net.SocketException;\nimport java.nio.channels.SocketChannel;\nimport javax.net.ssl.HandshakeCompletedListener;\nimport javax.net.ssl.SSLParameters;\nimport javax.net.ssl.SSLSession;\nimport javax.net.ssl.SSLSocket;\n\n/**\n * An {@link javax.net.ssl.SSLSocket} that delegates all calls.\n */\npublic abstract class DelegatingSSLSocket extends SSLSocket {\n  protected final SSLSocket delegate;\n\n  public DelegatingSSLSocket(SSLSocket delegate) {\n    this.delegate = delegate;\n  }\n\n  @Override public void shutdownInput() throws IOException {\n    delegate.shutdownInput();\n  }\n\n  @Override public void shutdownOutput() throws IOException {\n    delegate.shutdownOutput();\n  }\n\n  @Override public String[] getSupportedCipherSuites() {\n    return delegate.getSupportedCipherSuites();\n  }\n\n  @Override public String[] getEnabledCipherSuites() {\n    return delegate.getEnabledCipherSuites();\n  }\n\n  @Override public void setEnabledCipherSuites(String[] suites) {\n    delegate.setEnabledCipherSuites(suites);\n  }\n\n  @Override public String[] getSupportedProtocols() {\n    return delegate.getSupportedProtocols();\n  }\n\n  @Override public String[] getEnabledProtocols() {\n    return delegate.getEnabledProtocols();\n  }\n\n  @Override public void setEnabledProtocols(String[] protocols) {\n    delegate.setEnabledProtocols(protocols);\n  }\n\n  @Override public SSLSession getSession() {\n    return delegate.getSession();\n  }\n\n  @Override public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {\n    delegate.addHandshakeCompletedListener(listener);\n  }\n\n  @Override public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {\n    delegate.removeHandshakeCompletedListener(listener);\n  }\n\n  @Override public void startHandshake() throws IOException {\n    delegate.startHandshake();\n  }\n\n  @Override public void setUseClientMode(boolean mode) {\n    delegate.setUseClientMode(mode);\n  }\n\n  @Override public boolean getUseClientMode() {\n    return delegate.getUseClientMode();\n  }\n\n  @Override public void setNeedClientAuth(boolean need) {\n    delegate.setNeedClientAuth(need);\n  }\n\n  @Override public void setWantClientAuth(boolean want) {\n    delegate.setWantClientAuth(want);\n  }\n\n  @Override public boolean getNeedClientAuth() {\n    return delegate.getNeedClientAuth();\n  }\n\n  @Override public boolean getWantClientAuth() {\n    return delegate.getWantClientAuth();\n  }\n\n  @Override public void setEnableSessionCreation(boolean flag) {\n    delegate.setEnableSessionCreation(flag);\n  }\n\n  @Override public boolean getEnableSessionCreation() {\n    return delegate.getEnableSessionCreation();\n  }\n\n  @Override public SSLParameters getSSLParameters() {\n    return delegate.getSSLParameters();\n  }\n\n  @Override public void setSSLParameters(SSLParameters p) {\n    delegate.setSSLParameters(p);\n  }\n\n  @Override public void close() throws IOException {\n    delegate.close();\n  }\n\n  @Override public InetAddress getInetAddress() {\n    return delegate.getInetAddress();\n  }\n\n  @Override public InputStream getInputStream() throws IOException {\n    return delegate.getInputStream();\n  }\n\n  @Override public boolean getKeepAlive() throws SocketException {\n    return delegate.getKeepAlive();\n  }\n\n  @Override public InetAddress getLocalAddress() {\n    return delegate.getLocalAddress();\n  }\n\n  @Override public int getLocalPort() {\n    return delegate.getLocalPort();\n  }\n\n  @Override public OutputStream getOutputStream() throws IOException {\n    return delegate.getOutputStream();\n  }\n\n  @Override public int getPort() {\n    return delegate.getPort();\n  }\n\n  @Override public int getSoLinger() throws SocketException {\n    return delegate.getSoLinger();\n  }\n\n  @Override public int getReceiveBufferSize() throws SocketException {\n    return delegate.getReceiveBufferSize();\n  }\n\n  @Override public int getSendBufferSize() throws SocketException {\n    return delegate.getSendBufferSize();\n  }\n\n  @Override public int getSoTimeout() throws SocketException {\n    return delegate.getSoTimeout();\n  }\n\n  @Override public boolean getTcpNoDelay() throws SocketException {\n    return delegate.getTcpNoDelay();\n  }\n\n  @Override public void setKeepAlive(boolean keepAlive) throws SocketException {\n    delegate.setKeepAlive(keepAlive);\n  }\n\n  @Override public void setSendBufferSize(int size) throws SocketException {\n    delegate.setSendBufferSize(size);\n  }\n\n  @Override public void setReceiveBufferSize(int size) throws SocketException {\n    delegate.setReceiveBufferSize(size);\n  }\n\n  @Override public void setSoLinger(boolean on, int timeout) throws SocketException {\n    delegate.setSoLinger(on, timeout);\n  }\n\n  @Override public void setSoTimeout(int timeout) throws SocketException {\n    delegate.setSoTimeout(timeout);\n  }\n\n  @Override public void setTcpNoDelay(boolean on) throws SocketException {\n    delegate.setTcpNoDelay(on);\n  }\n\n  @Override public String toString() {\n    return delegate.toString();\n  }\n\n  @Override public SocketAddress getLocalSocketAddress() {\n    return delegate.getLocalSocketAddress();\n  }\n\n  @Override public SocketAddress getRemoteSocketAddress() {\n    return delegate.getRemoteSocketAddress();\n  }\n\n  @Override public boolean isBound() {\n    return delegate.isBound();\n  }\n\n  @Override public boolean isConnected() {\n    return delegate.isConnected();\n  }\n\n  @Override public boolean isClosed() {\n    return delegate.isClosed();\n  }\n\n  @Override public void bind(SocketAddress localAddr) throws IOException {\n    delegate.bind(localAddr);\n  }\n\n  @Override public void connect(SocketAddress remoteAddr) throws IOException {\n    delegate.connect(remoteAddr);\n  }\n\n  @Override public void connect(SocketAddress remoteAddr, int timeout) throws IOException {\n    delegate.connect(remoteAddr, timeout);\n  }\n\n  @Override public boolean isInputShutdown() {\n    return delegate.isInputShutdown();\n  }\n\n  @Override public boolean isOutputShutdown() {\n    return delegate.isOutputShutdown();\n  }\n\n  @Override public void setReuseAddress(boolean reuse) throws SocketException {\n    delegate.setReuseAddress(reuse);\n  }\n\n  @Override public boolean getReuseAddress() throws SocketException {\n    return delegate.getReuseAddress();\n  }\n\n  @Override public void setOOBInline(boolean oobinline) throws SocketException {\n    delegate.setOOBInline(oobinline);\n  }\n\n  @Override public boolean getOOBInline() throws SocketException {\n    return delegate.getOOBInline();\n  }\n\n  @Override public void setTrafficClass(int value) throws SocketException {\n    delegate.setTrafficClass(value);\n  }\n\n  @Override public int getTrafficClass() throws SocketException {\n    return delegate.getTrafficClass();\n  }\n\n  @Override public void sendUrgentData(int value) throws IOException {\n    delegate.sendUrgentData(value);\n  }\n\n  @Override public SocketChannel getChannel() {\n    return delegate.getChannel();\n  }\n\n  @Override public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {\n    delegate.setPerformancePreferences(connectionTime, latency, bandwidth);\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/DelegatingSSLSocketFactory.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.Socket;\nimport java.net.UnknownHostException;\nimport javax.net.ssl.SSLSocket;\nimport javax.net.ssl.SSLSocketFactory;\n\n/**\n * A {@link SSLSocketFactory} that delegates calls. Sockets can be configured after\n * creation by overriding {@link #configureSocket(javax.net.ssl.SSLSocket)}.\n */\npublic class DelegatingSSLSocketFactory extends SSLSocketFactory {\n\n  private final SSLSocketFactory delegate;\n\n  public DelegatingSSLSocketFactory(SSLSocketFactory delegate) {\n    this.delegate = delegate;\n  }\n\n  @Override\n  public SSLSocket createSocket() throws IOException {\n    SSLSocket sslSocket = (SSLSocket) delegate.createSocket();\n    return configureSocket(sslSocket);\n  }\n\n  @Override\n  public SSLSocket createSocket(String host, int port) throws IOException, UnknownHostException {\n    SSLSocket sslSocket = (SSLSocket) delegate.createSocket(host, port);\n    return configureSocket(sslSocket);\n  }\n\n  @Override\n  public SSLSocket createSocket(String host, int port, InetAddress localAddress, int localPort)\n      throws IOException, UnknownHostException {\n    SSLSocket sslSocket = (SSLSocket) delegate.createSocket(host, port, localAddress, localPort);\n    return configureSocket(sslSocket);\n  }\n\n  @Override\n  public SSLSocket createSocket(InetAddress host, int port) throws IOException {\n    SSLSocket sslSocket = (SSLSocket) delegate.createSocket(host, port);\n    return configureSocket(sslSocket);\n  }\n\n  @Override\n  public SSLSocket createSocket(InetAddress host, int port, InetAddress localAddress, int localPort)\n      throws IOException {\n    SSLSocket sslSocket = (SSLSocket) delegate.createSocket(host, port, localAddress, localPort);\n    return configureSocket(sslSocket);\n  }\n\n  @Override\n  public String[] getDefaultCipherSuites() {\n    return delegate.getDefaultCipherSuites();\n  }\n\n  @Override\n  public String[] getSupportedCipherSuites() {\n    return delegate.getSupportedCipherSuites();\n  }\n\n  @Override\n  public SSLSocket createSocket(Socket socket, String host, int port, boolean autoClose)\n      throws IOException {\n    SSLSocket sslSocket = (SSLSocket) delegate.createSocket(socket, host, port, autoClose);\n    return configureSocket(sslSocket);\n  }\n\n  protected SSLSocket configureSocket(SSLSocket sslSocket) throws IOException {\n    // No-op by default.\n    return sslSocket;\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/DelegatingServerSocketFactory.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.ServerSocket;\nimport javax.net.ServerSocketFactory;\n\n/**\n * A {@link ServerSocketFactory} that delegates calls. Sockets can be configured after creation by\n * overriding {@link #configureServerSocket(java.net.ServerSocket)}.\n */\npublic class DelegatingServerSocketFactory extends ServerSocketFactory {\n\n  private final ServerSocketFactory delegate;\n\n  public DelegatingServerSocketFactory(ServerSocketFactory delegate) {\n    this.delegate = delegate;\n  }\n\n  @Override\n  public ServerSocket createServerSocket() throws IOException {\n    ServerSocket serverSocket = delegate.createServerSocket();\n    return configureServerSocket(serverSocket);\n  }\n\n  @Override\n  public ServerSocket createServerSocket(int port) throws IOException {\n    ServerSocket serverSocket = delegate.createServerSocket(port);\n    return configureServerSocket(serverSocket);\n  }\n\n  @Override\n  public ServerSocket createServerSocket(int port, int backlog) throws IOException {\n    ServerSocket serverSocket = delegate.createServerSocket(port, backlog);\n    return configureServerSocket(serverSocket);\n  }\n\n  @Override\n  public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress)\n      throws IOException {\n    ServerSocket serverSocket = delegate.createServerSocket(port, backlog, ifAddress);\n    return configureServerSocket(serverSocket);\n  }\n\n  protected ServerSocket configureServerSocket(ServerSocket serverSocket) throws IOException {\n    // No-op by default.\n    return serverSocket;\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/DelegatingSocketFactory.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.Socket;\nimport java.net.UnknownHostException;\nimport javax.net.SocketFactory;\n\n/**\n * A {@link SocketFactory} that delegates calls. Sockets can be configured after creation by\n * overriding {@link #configureSocket(java.net.Socket)}.\n */\npublic class DelegatingSocketFactory extends SocketFactory {\n\n  private final SocketFactory delegate;\n\n  public DelegatingSocketFactory(SocketFactory delegate) {\n    this.delegate = delegate;\n  }\n\n  @Override\n  public Socket createSocket() throws IOException {\n    Socket socket = delegate.createSocket();\n    return configureSocket(socket);\n  }\n\n  @Override\n  public Socket createSocket(String host, int port) throws IOException, UnknownHostException {\n    Socket socket = delegate.createSocket(host, port);\n    return configureSocket(socket);\n  }\n\n  @Override\n  public Socket createSocket(String host, int port, InetAddress localAddress, int localPort)\n      throws IOException, UnknownHostException {\n    Socket socket = delegate.createSocket(host, port, localAddress, localPort);\n    return configureSocket(socket);\n  }\n\n  @Override\n  public Socket createSocket(InetAddress host, int port) throws IOException {\n    Socket socket = delegate.createSocket(host, port);\n    return configureSocket(socket);\n  }\n\n  @Override\n  public Socket createSocket(InetAddress host, int port, InetAddress localAddress, int localPort)\n      throws IOException {\n    Socket socket = delegate.createSocket(host, port, localAddress, localPort);\n    return configureSocket(socket);\n  }\n\n  protected Socket configureSocket(Socket socket) throws IOException {\n    // No-op by default.\n    return socket;\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/DoubleInetAddressDns.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport com.squareup.okhttp.Dns;\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * A network that always resolves two IP addresses per host. Use this when testing route selection\n * fallbacks to guarantee that a fallback address is available.\n */\npublic class DoubleInetAddressDns implements Dns {\n  @Override public List<InetAddress> lookup(String hostname) throws UnknownHostException {\n    List<InetAddress> addresses = Dns.SYSTEM.lookup(hostname);\n    return Arrays.asList(addresses.get(0), addresses.get(0));\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/FallbackTestClientSocketFactory.java",
    "content": "/*\n * Copyright 2014 Square Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.DelegatingSSLSocket;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.DelegatingSSLSocketFactory;\n\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.Socket;\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.net.ssl.SSLSocket;\nimport javax.net.ssl.SSLSocketFactory;\n\n/**\n * An SSLSocketFactory that delegates calls. Sockets created by the delegate are wrapped with ones\n * that will not accept the {@link #TLS_FALLBACK_SCSV} cipher, thus bypassing server-side fallback\n * checks on platforms that support it. Unfortunately this wrapping will disable any\n * reflection-based calls to SSLSocket from Platform.\n */\npublic class FallbackTestClientSocketFactory extends DelegatingSSLSocketFactory {\n  /**\n   * The cipher suite used during TLS connection fallback to indicate a fallback.\n   * See https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00\n   */\n  public static final String TLS_FALLBACK_SCSV = \"TLS_FALLBACK_SCSV\";\n\n  public FallbackTestClientSocketFactory(SSLSocketFactory delegate) {\n    super(delegate);\n  }\n\n  @Override protected SSLSocket configureSocket(SSLSocket sslSocket) throws IOException {\n    return new TlsFallbackScsvDisabledSSLSocket(sslSocket);\n  }\n\n  private static class TlsFallbackScsvDisabledSSLSocket extends DelegatingSSLSocket {\n\n    public TlsFallbackScsvDisabledSSLSocket(SSLSocket socket) {\n      super(socket);\n    }\n\n    @Override public void setEnabledCipherSuites(String[] suites) {\n      List<String> enabledCipherSuites = new ArrayList<String>(suites.length);\n      for (String suite : suites) {\n        if (!suite.equals(TLS_FALLBACK_SCSV)) {\n          enabledCipherSuites.add(suite);\n        }\n      }\n      delegate.setEnabledCipherSuites(\n          enabledCipherSuites.toArray(new String[enabledCipherSuites.size()]));\n    }\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/RecordedResponse.java",
    "content": "/*\n * Copyright (C) 2013 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport com.squareup.okhttp.Handshake;\nimport com.squareup.okhttp.Request;\nimport com.squareup.okhttp.Response;\nimport com.squareup.okhttp.ws.WebSocket;\nimport java.io.IOException;\nimport java.net.URL;\nimport java.util.Arrays;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * A received response or failure recorded by the response recorder.\n */\npublic final class RecordedResponse {\n  public final Request request;\n  public final Response response;\n  public final WebSocket webSocket;\n  public final String body;\n  public final IOException failure;\n\n  public RecordedResponse(Request request, Response response, WebSocket webSocket, String body,\n      IOException failure) {\n    this.request = request;\n    this.response = response;\n    this.webSocket = webSocket;\n    this.body = body;\n    this.failure = failure;\n  }\n\n  public RecordedResponse assertRequestUrl(URL url) {\n    assertEquals(url, request.url());\n    return this;\n  }\n\n  public RecordedResponse assertRequestMethod(String method) {\n    assertEquals(method, request.method());\n    return this;\n  }\n\n  public RecordedResponse assertRequestHeader(String name, String... values) {\n    assertEquals(Arrays.asList(values), request.headers(name));\n    return this;\n  }\n\n  public RecordedResponse assertCode(int expectedCode) {\n    assertEquals(expectedCode, response.code());\n    return this;\n  }\n\n  public RecordedResponse assertSuccessful() {\n    assertTrue(response.isSuccessful());\n    return this;\n  }\n\n  public RecordedResponse assertNotSuccessful() {\n    assertFalse(response.isSuccessful());\n    return this;\n  }\n\n  public RecordedResponse assertHeader(String name, String... values) {\n    assertEquals(Arrays.asList(values), response.headers(name));\n    return this;\n  }\n\n  public RecordedResponse assertBody(String expectedBody) {\n    assertEquals(expectedBody, body);\n    return this;\n  }\n\n  public RecordedResponse assertHandshake() {\n    Handshake handshake = response.handshake();\n    assertNotNull(handshake.cipherSuite());\n    assertNotNull(handshake.peerPrincipal());\n    assertEquals(1, handshake.peerCertificates().size());\n    assertNull(handshake.localPrincipal());\n    assertEquals(0, handshake.localCertificates().size());\n    return this;\n  }\n\n  /**\n   * Asserts that the current response was redirected and returns the prior\n   * response.\n   */\n  public RecordedResponse priorResponse() {\n    Response priorResponse = response.priorResponse();\n    assertNotNull(priorResponse);\n    assertNull(priorResponse.body());\n    return new RecordedResponse(priorResponse.request(), priorResponse, null, null, null);\n  }\n\n  /**\n   * Asserts that the current response used the network and returns the network\n   * response.\n   */\n  public RecordedResponse networkResponse() {\n    Response networkResponse = response.networkResponse();\n    assertNotNull(networkResponse);\n    assertNull(networkResponse.body());\n    return new RecordedResponse(networkResponse.request(), networkResponse, null, null, null);\n  }\n\n  /** Asserts that the current response didn't use the network. */\n  public RecordedResponse assertNoNetworkResponse() {\n    assertNull(response.networkResponse());\n    return this;\n  }\n\n  /** Asserts that the current response didn't use the cache. */\n  public RecordedResponse assertNoCacheResponse() {\n    assertNull(response.cacheResponse());\n    return this;\n  }\n\n  /**\n   * Asserts that the current response used the cache and returns the cache\n   * response.\n   */\n  public RecordedResponse cacheResponse() {\n    Response cacheResponse = response.cacheResponse();\n    assertNotNull(cacheResponse);\n    assertNull(cacheResponse.body());\n    return new RecordedResponse(cacheResponse.request(), cacheResponse, null, null, null);\n  }\n\n  public void assertFailure(String... messages) {\n    assertNotNull(failure);\n    assertTrue(failure.getMessage(), Arrays.asList(messages).contains(failure.getMessage()));\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/RecordingAuthenticator.java",
    "content": "/*\n * Copyright (C) 2013 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport java.net.Authenticator;\nimport java.net.PasswordAuthentication;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class RecordingAuthenticator extends Authenticator {\n  /** base64(\"username:password\") */\n  public static final String BASE_64_CREDENTIALS = \"dXNlcm5hbWU6cGFzc3dvcmQ=\";\n\n  public final List<String> calls = new ArrayList<>();\n  public final PasswordAuthentication authentication;\n\n  public RecordingAuthenticator(PasswordAuthentication authentication) {\n    this.authentication = authentication;\n  }\n\n  public RecordingAuthenticator() {\n    this(new PasswordAuthentication(\"username\", \"password\".toCharArray()));\n  }\n\n  @Override protected PasswordAuthentication getPasswordAuthentication() {\n    this.calls.add(\"host=\" + getRequestingHost()\n        + \" port=\" + getRequestingPort()\n        + \" site=\" + getRequestingSite().getHostName()\n        + \" url=\" + getRequestingURL()\n        + \" type=\" + getRequestorType()\n        + \" prompt=\" + getRequestingPrompt()\n        + \" protocol=\" + getRequestingProtocol()\n        + \" scheme=\" + getRequestingScheme());\n    return authentication;\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/RecordingCallback.java",
    "content": "/*\n * Copyright (C) 2013 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport com.squareup.okhttp.Callback;\nimport com.squareup.okhttp.HttpUrl;\nimport com.squareup.okhttp.Request;\nimport com.squareup.okhttp.Response;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Records received HTTP responses so they can be later retrieved by tests.\n */\npublic class RecordingCallback implements Callback {\n  public static final long TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10);\n\n  private final List<RecordedResponse> responses = new ArrayList<>();\n\n  @Override public synchronized void onFailure(Request request, IOException e) {\n    responses.add(new RecordedResponse(request, null, null, null, e));\n    notifyAll();\n  }\n\n  @Override public synchronized void onResponse(Response response) throws IOException {\n    String body = response.body().string();\n    responses.add(new RecordedResponse(response.request(), response, null, body, null));\n    notifyAll();\n  }\n\n  /**\n   * Returns the recorded response triggered by {@code request}. Throws if the\n   * response isn't enqueued before the timeout.\n   */\n  public synchronized RecordedResponse await(HttpUrl url) throws Exception {\n    long timeoutMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) + TIMEOUT_MILLIS;\n    while (true) {\n      for (Iterator<RecordedResponse> i = responses.iterator(); i.hasNext(); ) {\n        RecordedResponse recordedResponse = i.next();\n        if (recordedResponse.request.httpUrl().equals(url)) {\n          i.remove();\n          return recordedResponse;\n        }\n      }\n\n      long nowMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());\n      if (nowMillis >= timeoutMillis) break;\n      wait(timeoutMillis - nowMillis);\n    }\n\n    throw new AssertionError(\"Timed out waiting for response to \" + url);\n  }\n\n  public synchronized void assertNoResponse(HttpUrl url) throws Exception {\n    for (RecordedResponse recordedResponse : responses) {\n      if (recordedResponse.request.httpUrl().equals(url)) {\n        throw new AssertionError(\"Expected no response for \" + url);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/RecordingOkAuthenticator.java",
    "content": "/*\n * Copyright (C) 2013 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport com.squareup.okhttp.Authenticator;\nimport com.squareup.okhttp.Request;\nimport com.squareup.okhttp.Response;\nimport java.net.Proxy;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic final class RecordingOkAuthenticator implements Authenticator {\n  public final List<Response> responses = new ArrayList<>();\n  public final List<Proxy> proxies = new ArrayList<>();\n  public final String credential;\n\n  public RecordingOkAuthenticator(String credential) {\n    this.credential = credential;\n  }\n\n  public Response onlyResponse() {\n    if (responses.size() != 1) throw new IllegalStateException();\n    return responses.get(0);\n  }\n\n  public Proxy onlyProxy() {\n    if (proxies.size() != 1) throw new IllegalStateException();\n    return proxies.get(0);\n  }\n\n  @Override public Request authenticate(Proxy proxy, Response response) {\n    responses.add(response);\n    proxies.add(proxy);\n    return response.request().newBuilder()\n        .addHeader(\"Authorization\", credential)\n        .build();\n  }\n\n  @Override public Request authenticateProxy(Proxy proxy, Response response) {\n    responses.add(response);\n    proxies.add(proxy);\n    return response.request().newBuilder()\n        .addHeader(\"Proxy-Authorization\", credential)\n        .build();\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/SingleInetAddressDns.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport com.squareup.okhttp.Dns;\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * A network that resolves only one IP address per host. Use this when testing\n * route selection fallbacks to prevent the host machine's various IP addresses\n * from interfering.\n */\npublic class SingleInetAddressDns implements Dns {\n  @Override public List<InetAddress> lookup(String hostname) throws UnknownHostException {\n    List<InetAddress> addresses = Dns.SYSTEM.lookup(hostname);\n    return Collections.singletonList(addresses.get(0));\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/SocksProxy.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport com.squareup.okhttp.internal.NamedRunnable;\nimport com.squareup.okhttp.internal.Util;\nimport java.io.IOException;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.ProtocolException;\nimport java.net.Proxy;\nimport java.net.ServerSocket;\nimport java.net.Socket;\nimport java.net.SocketException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.logging.Level;\nimport java.util.logging.Logger;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.BufferedSource;\nimport okio.Okio;\n\n/**\n * A limited implementation of SOCKS Protocol Version 5, intended to be similar to MockWebServer.\n * See <a href=\"https://www.ietf.org/rfc/rfc1928.txt\">RFC 1928</a>.\n */\npublic final class SocksProxy {\n  private static final int VERSION_5 = 5;\n  private static final int METHOD_NONE = 0xff;\n  private static final int METHOD_NO_AUTHENTICATION_REQUIRED = 0;\n  private static final int ADDRESS_TYPE_IPV4 = 1;\n  private static final int ADDRESS_TYPE_DOMAIN_NAME = 3;\n  private static final int COMMAND_CONNECT = 1;\n  private static final int REPLY_SUCCEEDED = 0;\n\n  private static final Logger logger = Logger.getLogger(SocksProxy.class.getName());\n\n  private final ExecutorService executor = Executors.newCachedThreadPool(\n      Util.threadFactory(\"SocksProxy\", false));\n\n  private ServerSocket serverSocket;\n  private AtomicInteger connectionCount = new AtomicInteger();\n\n  public void play() throws IOException {\n    serverSocket = new ServerSocket(0);\n    executor.execute(new NamedRunnable(\"SocksProxy %s\", serverSocket.getLocalPort()) {\n      @Override protected void execute() {\n        try {\n          while (true) {\n            Socket socket = serverSocket.accept();\n            connectionCount.incrementAndGet();\n            service(socket);\n          }\n        } catch (SocketException e) {\n          logger.info(name + \" done accepting connections: \" + e.getMessage());\n        } catch (IOException e) {\n          logger.log(Level.WARNING, name + \" failed unexpectedly\", e);\n        }\n      }\n    });\n  }\n\n  public Proxy proxy() {\n    return new Proxy(Proxy.Type.SOCKS, InetSocketAddress.createUnresolved(\n        \"localhost\", serverSocket.getLocalPort()));\n  }\n\n  public int connectionCount() {\n    return connectionCount.get();\n  }\n\n  public void shutdown() throws Exception {\n    serverSocket.close();\n    executor.shutdown();\n    if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {\n      throw new IOException(\"Gave up waiting for executor to shut down\");\n    }\n  }\n\n  private void service(final Socket from) {\n    executor.execute(new NamedRunnable(\"SocksProxy %s\", from.getRemoteSocketAddress()) {\n      @Override protected void execute() {\n        try {\n          BufferedSource fromSource = Okio.buffer(Okio.source(from));\n          BufferedSink fromSink = Okio.buffer(Okio.sink(from));\n          hello(fromSource, fromSink);\n          acceptCommand(from.getInetAddress(), fromSource, fromSink);\n        } catch (IOException e) {\n          logger.log(Level.WARNING, name + \" failed\", e);\n          Util.closeQuietly(from);\n        }\n      }\n    });\n  }\n\n  private void hello(BufferedSource fromSource, BufferedSink fromSink) throws IOException {\n    int version = fromSource.readByte() & 0xff;\n    int methodCount = fromSource.readByte() & 0xff;\n    int selectedMethod = METHOD_NONE;\n\n    if (version != VERSION_5) {\n      throw new ProtocolException(\"unsupported version: \" + version);\n    }\n\n    for (int i = 0; i < methodCount; i++) {\n      int candidateMethod = fromSource.readByte() & 0xff;\n      if (candidateMethod == METHOD_NO_AUTHENTICATION_REQUIRED) {\n        selectedMethod = candidateMethod;\n      }\n    }\n\n    switch (selectedMethod) {\n      case METHOD_NO_AUTHENTICATION_REQUIRED:\n        fromSink.writeByte(VERSION_5);\n        fromSink.writeByte(selectedMethod);\n        fromSink.emit();\n        break;\n\n      default:\n        throw new ProtocolException(\"unsupported method: \" + selectedMethod);\n    }\n  }\n\n  private void acceptCommand(InetAddress fromAddress, BufferedSource fromSource,\n      BufferedSink fromSink) throws IOException {\n    // Read the command.\n    int version = fromSource.readByte() & 0xff;\n    if (version != VERSION_5) throw new ProtocolException(\"unexpected version: \" + version);\n    int command = fromSource.readByte() & 0xff;\n    int reserved = fromSource.readByte() & 0xff;\n    if (reserved != 0) throw new ProtocolException(\"unexpected reserved: \" + reserved);\n\n    int addressType = fromSource.readByte() & 0xff;\n    InetAddress toAddress;\n    switch (addressType) {\n      case ADDRESS_TYPE_IPV4:\n        toAddress = InetAddress.getByAddress(fromSource.readByteArray(4L));\n        break;\n\n      case ADDRESS_TYPE_DOMAIN_NAME:\n        int domainNameLength = fromSource.readByte() & 0xff;\n        String domainName = fromSource.readUtf8(domainNameLength);\n        toAddress = InetAddress.getByName(domainName);\n        break;\n\n      default:\n        throw new ProtocolException(\"unsupported address type: \" + addressType);\n    }\n\n    int port = fromSource.readShort() & 0xffff;\n\n    switch (command) {\n      case COMMAND_CONNECT:\n        Socket toSocket = new Socket(toAddress, port);\n        byte[] localAddress = toSocket.getLocalAddress().getAddress();\n        if (localAddress.length != 4) {\n          throw new ProtocolException(\"unexpected address: \" + toSocket.getLocalAddress());\n        }\n\n        // Write the reply.\n        fromSink.writeByte(VERSION_5);\n        fromSink.writeByte(REPLY_SUCCEEDED);\n        fromSink.writeByte(0);\n        fromSink.writeByte(ADDRESS_TYPE_IPV4);\n        fromSink.write(localAddress);\n        fromSink.writeShort(toSocket.getLocalPort());\n        fromSink.emit();\n\n        logger.log(Level.INFO, \"SocksProxy connected \" + fromAddress + \" to \" + toAddress);\n\n        // Copy sources to sinks in both directions.\n        BufferedSource toSource = Okio.buffer(Okio.source(toSocket));\n        BufferedSink toSink = Okio.buffer(Okio.sink(toSocket));\n        transfer(fromAddress, toAddress, fromSource, toSink);\n        transfer(fromAddress, toAddress, toSource, fromSink);\n        break;\n\n      default:\n        throw new ProtocolException(\"unexpected command: \" + command);\n    }\n  }\n\n  private void transfer(final InetAddress fromAddress, final InetAddress toAddress,\n      final BufferedSource source, final BufferedSink sink) {\n    executor.execute(new NamedRunnable(\"SocksProxy %s to %s\", fromAddress, toAddress) {\n      @Override protected void execute() {\n        Buffer buffer = new Buffer();\n        try {\n          while (true) {\n            long byteCount = source.read(buffer, 2048L);\n            if (byteCount == -1L) break;\n            sink.write(buffer, byteCount);\n            sink.emit();\n          }\n        } catch (SocketException e) {\n          logger.info(name + \" done: \" + e.getMessage());\n        } catch (IOException e) {\n          logger.log(Level.WARNING, name + \" failed\", e);\n        }\n\n        try {\n          source.close();\n        } catch (IOException e) {\n          logger.log(Level.WARNING, name + \" failed\", e);\n        }\n\n        try {\n          sink.close();\n        } catch (IOException e) {\n          logger.log(Level.WARNING, name + \" failed\", e);\n        }\n      }\n    });\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/SocksProxyTest.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport com.squareup.okhttp.OkHttpClient;\nimport com.squareup.okhttp.Request;\nimport com.squareup.okhttp.Response;\nimport com.squareup.okhttp.mockwebserver.MockResponse;\nimport com.squareup.okhttp.mockwebserver.MockWebServer;\nimport java.io.IOException;\nimport java.net.Proxy;\nimport java.net.ProxySelector;\nimport java.net.SocketAddress;\nimport java.net.URI;\nimport java.util.Collections;\nimport java.util.List;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\n\npublic final class SocksProxyTest {\n  private final SocksProxy socksProxy = new SocksProxy();\n  private final MockWebServer server = new MockWebServer();\n\n  @Before public void setUp() throws Exception {\n    server.start();\n    socksProxy.play();\n  }\n\n  @After public void tearDown() throws Exception {\n    server.shutdown();\n    socksProxy.shutdown();\n  }\n\n  @Test public void proxy() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n\n    OkHttpClient client = new OkHttpClient()\n        .setProxy(socksProxy.proxy());\n\n    Request request1 = new Request.Builder().url(server.url(\"/\")).build();\n    Response response1 = client.newCall(request1).execute();\n    assertEquals(\"abc\", response1.body().string());\n\n    Request request2 = new Request.Builder().url(server.url(\"/\")).build();\n    Response response2 = client.newCall(request2).execute();\n    assertEquals(\"def\", response2.body().string());\n\n    // The HTTP calls should share a single connection.\n    assertEquals(1, socksProxy.connectionCount());\n  }\n\n  @Test public void proxySelector() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    ProxySelector proxySelector = new ProxySelector() {\n      @Override public List<Proxy> select(URI uri) {\n        return Collections.singletonList(socksProxy.proxy());\n      }\n\n      @Override public void connectFailed(URI uri, SocketAddress socketAddress, IOException e) {\n        throw new AssertionError();\n      }\n    };\n\n    OkHttpClient client = new OkHttpClient()\n        .setProxySelector(proxySelector);\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"abc\", response.body().string());\n\n    assertEquals(1, socksProxy.connectionCount());\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/TestLogHandler.java",
    "content": "/*\n * Copyright (C) 2014 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.logging.Handler;\nimport java.util.logging.LogRecord;\n\n/**\n * A log handler that records which log messages were published so that a calling test can make\n * assertions about them.\n */\npublic final class TestLogHandler extends Handler {\n  private final List<String> logs = new ArrayList<>();\n\n  @Override public synchronized void publish(LogRecord logRecord) {\n    logs.add(logRecord.getLevel() + \": \" + logRecord.getMessage());\n    notifyAll();\n  }\n\n  @Override public void flush() {\n  }\n\n  @Override public void close() throws SecurityException {\n  }\n\n  public synchronized String take() throws InterruptedException {\n    while (logs.isEmpty()) {\n      wait();\n    }\n    return logs.remove(0);\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/http/FakeDns.java",
    "content": "/*\n * Copyright (C) 2012 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original.http;\n\nimport com.squareup.okhttp.Dns;\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static org.junit.Assert.assertEquals;\n\npublic final class FakeDns implements Dns {\n  private List<String> requestedHosts = new ArrayList<>();\n  private List<InetAddress> addresses = Collections.emptyList();\n\n  /** Sets the addresses to be returned by this fake DNS service. */\n  public FakeDns addresses(List<InetAddress> addresses) {\n    this.addresses = new ArrayList<>(addresses);\n    return this;\n  }\n\n  /** Sets the service to throw when a hostname is requested. */\n  public FakeDns unknownHost() {\n    this.addresses = Collections.emptyList();\n    return this;\n  }\n\n  public InetAddress address(int index) {\n    return addresses.get(index);\n  }\n\n  @Override public List<InetAddress> lookup(String hostname) throws UnknownHostException {\n    requestedHosts.add(hostname);\n    if (addresses.isEmpty()) throw new UnknownHostException();\n    return addresses;\n  }\n\n  public void assertRequests(String... expectedHosts) {\n    assertEquals(Arrays.asList(expectedHosts), requestedHosts);\n    requestedHosts.clear();\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/io/InMemoryFileSystem.java",
    "content": "/*\n * Copyright (C) 2015 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original.io;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.IdentityHashMap;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport com.squareup.okhttp.internal.io.FileSystem;\nimport okio.Buffer;\nimport okio.ForwardingSink;\nimport okio.ForwardingSource;\nimport okio.Sink;\nimport okio.Source;\nimport org.junit.rules.TestRule;\nimport org.junit.runner.Description;\nimport org.junit.runners.model.Statement;\n\n/** A simple file system where all files are held in memory. Not safe for concurrent use. */\npublic final class InMemoryFileSystem implements FileSystem, TestRule {\n  private final Map<File, Buffer> files = new LinkedHashMap<>();\n  private final Map<Source, File> openSources = new IdentityHashMap<>();\n  private final Map<Sink, File> openSinks = new IdentityHashMap<>();\n\n  @Override public Statement apply(final Statement base, Description description) {\n    return new Statement() {\n      @Override public void evaluate() throws Throwable {\n        base.evaluate();\n        ensureResourcesClosed();\n      }\n    };\n  }\n\n  public void ensureResourcesClosed() {\n    List<String> openResources = new ArrayList<>();\n    for (File file : openSources.values()) {\n      openResources.add(\"Source for \" + file);\n    }\n    for (File file : openSinks.values()) {\n      openResources.add(\"Sink for \" + file);\n    }\n    if (!openResources.isEmpty()) {\n      StringBuilder builder = new StringBuilder(\"Resources acquired but not closed:\");\n      for (String resource : openResources) {\n        builder.append(\"\\n * \").append(resource);\n      }\n      throw new IllegalStateException(builder.toString());\n    }\n  }\n\n  @Override public Source source(File file) throws FileNotFoundException {\n    Buffer result = files.get(file);\n    if (result == null) throw new FileNotFoundException();\n\n    final Source source = result.clone();\n    openSources.put(source, file);\n\n    return new ForwardingSource(source) {\n      @Override public void close() throws IOException {\n        openSources.remove(source);\n        super.close();\n      }\n    };\n  }\n\n  @Override public Sink sink(File file) throws FileNotFoundException {\n    return sink(file, false);\n  }\n\n  @Override public Sink appendingSink(File file) throws FileNotFoundException {\n    return sink(file, true);\n  }\n\n  private Sink sink(File file, boolean appending) {\n    Buffer result = null;\n    if (appending) {\n      result = files.get(file);\n    }\n    if (result == null) {\n      result = new Buffer();\n    }\n    files.put(file, result);\n\n    final Sink sink = result;\n    openSinks.put(sink, file);\n\n    return new ForwardingSink(sink) {\n      @Override public void close() throws IOException {\n        openSinks.remove(sink);\n        super.close();\n      }\n    };\n  }\n\n  @Override public void delete(File file) throws IOException {\n    files.remove(file);\n  }\n\n  @Override public boolean exists(File file) throws IOException {\n    return files.containsKey(file);\n  }\n\n  @Override public long size(File file) {\n    Buffer buffer = files.get(file);\n    return buffer != null ? buffer.size() : 0L;\n  }\n\n  @Override public void rename(File from, File to) throws IOException {\n    Buffer buffer = files.remove(from);\n    if (buffer == null) throw new FileNotFoundException();\n    files.put(to, buffer);\n  }\n\n  @Override public void deleteContents(File directory) throws IOException {\n    String prefix = directory.toString() + \"/\";\n    for (Iterator<File> i = files.keySet().iterator(); i.hasNext(); ) {\n      File file = i.next();\n      if (file.toString().startsWith(prefix)) i.remove();\n    }\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/co/paralleluniverse/fibers/okhttp/test/utils/original/testing/RecordingHostnameVerifier.java",
    "content": "/*\n * Copyright (C) 2013 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage co.paralleluniverse.fibers.okhttp.test.utils.original.testing;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.SSLSession;\n\npublic final class RecordingHostnameVerifier implements HostnameVerifier {\n  public final List<String> calls = new ArrayList<>();\n\n  public boolean verify(String hostname, SSLSession session) {\n    calls.add(\"verify \" + hostname);\n    return true;\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/com/squareup/okhttp/CacheTest.java",
    "content": "/*\n * Copyright (C) 2011 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.squareup.okhttp;\n\nimport co.paralleluniverse.fibers.okhttp.test.utils.FiberOkHttpClientTestWrapper;\nimport com.squareup.okhttp.internal.Internal;\nimport com.squareup.okhttp.internal.SslContextBuilder;\nimport com.squareup.okhttp.internal.Util;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.io.InMemoryFileSystem;\nimport com.squareup.okhttp.mockwebserver.MockResponse;\nimport com.squareup.okhttp.mockwebserver.MockWebServer;\nimport com.squareup.okhttp.mockwebserver.RecordedRequest;\nimport java.io.File;\nimport java.io.IOException;\nimport java.net.CookieHandler;\nimport java.net.CookieManager;\nimport java.net.HttpCookie;\nimport java.net.HttpURLConnection;\nimport java.net.ResponseCache;\nimport java.security.Principal;\nimport java.security.cert.Certificate;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.NoSuchElementException;\nimport java.util.TimeZone;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicReference;\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLSession;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.BufferedSource;\nimport okio.GzipSink;\nimport okio.Okio;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\n\nimport static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_END;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/** Test caching with {@link OkUrlFactory}. */\npublic final class CacheTest {\n  private static final HostnameVerifier NULL_HOSTNAME_VERIFIER = new HostnameVerifier() {\n    @Override public boolean verify(String s, SSLSession sslSession) {\n      return true;\n    }\n  };\n\n  @Rule public MockWebServer server = new MockWebServer();\n  @Rule public MockWebServer server2 = new MockWebServer();\n  @Rule public InMemoryFileSystem fileSystem = new InMemoryFileSystem();\n\n  private final SSLContext sslContext = SslContextBuilder.localhost();\n  private final OkHttpClient client = new FiberOkHttpClientTestWrapper();\n  private Cache cache;\n  private final CookieManager cookieManager = new CookieManager();\n\n  @Before public void setUp() throws Exception {\n    server.setProtocolNegotiationEnabled(false);\n    cache = new Cache(new File(\"/cache/\"), Integer.MAX_VALUE, fileSystem);\n    client.setCache(cache);\n    CookieHandler.setDefault(cookieManager);\n  }\n\n  @After public void tearDown() throws Exception {\n    ResponseCache.setDefault(null);\n    CookieHandler.setDefault(null);\n    cache.delete();\n  }\n\n  /**\n   * Test that response caching is consistent with the RI and the spec.\n   * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4\n   */\n  @Test public void responseCachingByResponseCode() throws Exception {\n    // Test each documented HTTP/1.1 code, plus the first unused value in each range.\n    // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html\n\n    // We can't test 100 because it's not really a response.\n    // assertCached(false, 100);\n    assertCached(false, 101);\n    assertCached(false, 102);\n    assertCached(true,  200);\n    assertCached(false, 201);\n    assertCached(false, 202);\n    assertCached(true,  203);\n    assertCached(true,  204);\n    assertCached(false, 205);\n    assertCached(false, 206); //Electing to not cache partial responses\n    assertCached(false, 207);\n    assertCached(true,  300);\n    assertCached(true,  301);\n    assertCached(true,  302);\n    assertCached(false, 303);\n    assertCached(false, 304);\n    assertCached(false, 305);\n    assertCached(false, 306);\n    assertCached(true,  307);\n    assertCached(true,  308);\n    assertCached(false, 400);\n    assertCached(false, 401);\n    assertCached(false, 402);\n    assertCached(false, 403);\n    assertCached(true,  404);\n    assertCached(true,  405);\n    assertCached(false, 406);\n    assertCached(false, 408);\n    assertCached(false, 409);\n    // the HTTP spec permits caching 410s, but the RI doesn't.\n    assertCached(true,  410);\n    assertCached(false, 411);\n    assertCached(false, 412);\n    assertCached(false, 413);\n    assertCached(true,  414);\n    assertCached(false, 415);\n    assertCached(false, 416);\n    assertCached(false, 417);\n    assertCached(false, 418);\n\n    assertCached(false, 500);\n    assertCached(true,  501);\n    assertCached(false, 502);\n    assertCached(false, 503);\n    assertCached(false, 504);\n    assertCached(false, 505);\n    assertCached(false, 506);\n  }\n\n  private void assertCached(boolean shouldPut, int responseCode) throws Exception {\n    server = new MockWebServer();\n    MockResponse mockResponse = new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setResponseCode(responseCode)\n        .setBody(\"ABCDE\")\n        .addHeader(\"WWW-Authenticate: challenge\");\n    if (responseCode == HttpURLConnection.HTTP_PROXY_AUTH) {\n      mockResponse.addHeader(\"Proxy-Authenticate: Basic realm=\\\"protected area\\\"\");\n    } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {\n      mockResponse.addHeader(\"WWW-Authenticate: Basic realm=\\\"protected area\\\"\");\n    } else if (responseCode == HttpURLConnection.HTTP_NO_CONTENT\n        || responseCode == HttpURLConnection.HTTP_RESET) {\n      mockResponse.setBody(\"\"); // We forbid bodies for 204 and 205.\n    }\n    server.enqueue(mockResponse);\n    server.start();\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(responseCode, response.code());\n\n    // Exhaust the content stream.\n    response.body().string();\n\n    Response cached = cache.get(request);\n    if (shouldPut) {\n      assertNotNull(Integer.toString(responseCode), cached);\n      cached.body().close();\n    } else {\n      assertNull(Integer.toString(responseCode), cached);\n    }\n    server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers\n  }\n\n  @Test public void responseCachingAndInputStreamSkipWithFixedLength() throws IOException {\n    testResponseCaching(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void responseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException {\n    testResponseCaching(TransferKind.CHUNKED);\n  }\n\n  @Test public void responseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException {\n    testResponseCaching(TransferKind.END_OF_STREAM);\n  }\n\n  /**\n   * Skipping bytes in the input stream caused ResponseCache corruption.\n   * http://code.google.com/p/android/issues/detail?id=8175\n   */\n  private void testResponseCaching(TransferKind transferKind) throws IOException {\n    MockResponse mockResponse = new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setStatus(\"HTTP/1.1 200 Fantastic\");\n    transferKind.setBody(mockResponse, \"I love puppies but hate spiders\", 1);\n    server.enqueue(mockResponse);\n\n    // Make sure that calling skip() doesn't omit bytes from the cache.\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    Response response1 = client.newCall(request).execute();\n\n    BufferedSource in1 = response1.body().source();\n    assertEquals(\"I love \", in1.readUtf8(\"I love \".length()));\n    in1.skip(\"puppies but hate \".length());\n    assertEquals(\"spiders\", in1.readUtf8(\"spiders\".length()));\n    assertTrue(in1.exhausted());\n    in1.close();\n    assertEquals(1, cache.getWriteSuccessCount());\n    assertEquals(0, cache.getWriteAbortCount());\n\n    Response response2 = client.newCall(request).execute();\n    BufferedSource in2 = response2.body().source();\n    assertEquals(\"I love puppies but hate spiders\",\n        in2.readUtf8(\"I love puppies but hate spiders\".length()));\n    assertEquals(200, response2.code());\n    assertEquals(\"Fantastic\", response2.message());\n\n    assertTrue(in2.exhausted());\n    in2.close();\n    assertEquals(1, cache.getWriteSuccessCount());\n    assertEquals(0, cache.getWriteAbortCount());\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getHitCount());\n  }\n\n  @Test public void secureResponseCaching() throws IOException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setBody(\"ABC\"));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    Response response1 = client.newCall(request).execute();\n    BufferedSource in = response1.body().source();\n    assertEquals(\"ABC\", in.readUtf8());\n\n    // OpenJDK 6 fails on this line, complaining that the connection isn't open yet\n    String suite = response1.handshake().cipherSuite();\n    List<Certificate> localCerts = response1.handshake().localCertificates();\n    List<Certificate> serverCerts = response1.handshake().peerCertificates();\n    Principal peerPrincipal = response1.handshake().peerPrincipal();\n    Principal localPrincipal = response1.handshake().localPrincipal();\n\n    Response response2 = client.newCall(request).execute(); // Cached!\n    assertEquals(\"ABC\", response2.body().string());\n\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(1, cache.getHitCount());\n\n    assertEquals(suite, response2.handshake().cipherSuite());\n    assertEquals(localCerts, response2.handshake().localCertificates());\n    assertEquals(serverCerts, response2.handshake().peerCertificates());\n    assertEquals(peerPrincipal, response2.handshake().peerPrincipal());\n    assertEquals(localPrincipal, response2.handshake().localPrincipal());\n  }\n\n  @Test public void responseCachingAndRedirects() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)\n        .addHeader(\"Location: /foo\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setBody(\"ABC\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"DEF\"));\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    Response response1 = client.newCall(request).execute();\n    assertEquals(\"ABC\", response1.body().string());\n\n    Response response2 = client.newCall(request).execute(); // Cached!\n    assertEquals(\"ABC\", response2.body().string());\n\n    assertEquals(4, cache.getRequestCount()); // 2 requests + 2 redirects\n    assertEquals(2, cache.getNetworkCount());\n    assertEquals(2, cache.getHitCount());\n  }\n\n  @Test public void redirectToCachedResult() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"ABC\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)\n        .addHeader(\"Location: /foo\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"DEF\"));\n\n    Request request1 = new Request.Builder().url(server.url(\"/foo\")).build();\n    Response response1 = client.newCall(request1).execute();\n    assertEquals(\"ABC\", response1.body().string());\n    RecordedRequest recordedRequest1 = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", recordedRequest1.getRequestLine());\n    assertEquals(0, recordedRequest1.getSequenceNumber());\n\n    Request request2 = new Request.Builder().url(server.url(\"/bar\")).build();\n    Response response2 = client.newCall(request2).execute();\n    assertEquals(\"ABC\", response2.body().string());\n    RecordedRequest recordedRequest2 = server.takeRequest();\n    assertEquals(\"GET /bar HTTP/1.1\", recordedRequest2.getRequestLine());\n    assertEquals(1, recordedRequest2.getSequenceNumber());\n\n    // an unrelated request should reuse the pooled connection\n    Request request3 = new Request.Builder().url(server.url(\"/baz\")).build();\n    Response response3 = client.newCall(request3).execute();\n    assertEquals(\"DEF\", response3.body().string());\n    RecordedRequest recordedRequest3 = server.takeRequest();\n    assertEquals(\"GET /baz HTTP/1.1\", recordedRequest3.getRequestLine());\n    assertEquals(2, recordedRequest3.getSequenceNumber());\n  }\n\n  @Test public void secureResponseCachingAndRedirects() throws IOException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)\n        .addHeader(\"Location: /foo\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setBody(\"ABC\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"DEF\"));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n\n    Response response1 = get(server.url(\"/\"));\n    assertEquals(\"ABC\", response1.body().string());\n    assertNotNull(response1.handshake().cipherSuite());\n\n    // Cached!\n    Response response2 = get(server.url(\"/\"));\n    assertEquals(\"ABC\", response2.body().string());\n    assertNotNull(response2.handshake().cipherSuite());\n\n    assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4\n    assertEquals(2, cache.getHitCount());\n    assertEquals(response1.handshake().cipherSuite(), response2.handshake().cipherSuite());\n  }\n\n  /**\n   * We've had bugs where caching and cross-protocol redirects yield class\n   * cast exceptions internal to the cache because we incorrectly assumed that\n   * HttpsURLConnection was always HTTPS and HttpURLConnection was always HTTP;\n   * in practice redirects mean that each can do either.\n   *\n   * https://github.com/square/okhttp/issues/214\n   */\n  @Test public void secureResponseCachingAndProtocolRedirects() throws IOException {\n    server2.useHttps(sslContext.getSocketFactory(), false);\n    server2.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setBody(\"ABC\"));\n    server2.enqueue(new MockResponse()\n        .setBody(\"DEF\"));\n\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)\n        .addHeader(\"Location: \" + server2.url(\"/\")));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n\n    Response response1 = get(server.url(\"/\"));\n    assertEquals(\"ABC\", response1.body().string());\n\n    // Cached!\n    Response response2 = get(server.url(\"/\"));\n    assertEquals(\"ABC\", response2.body().string());\n\n    assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4\n    assertEquals(2, cache.getHitCount());\n  }\n\n  @Test public void foundCachedWithExpiresHeader() throws Exception {\n    temporaryRedirectCachedWithCachingHeader(302, \"Expires\", formatDate(1, TimeUnit.HOURS));\n  }\n\n  @Test public void foundCachedWithCacheControlHeader() throws Exception {\n    temporaryRedirectCachedWithCachingHeader(302, \"Cache-Control\", \"max-age=60\");\n  }\n\n  @Test public void temporaryRedirectCachedWithExpiresHeader() throws Exception {\n    temporaryRedirectCachedWithCachingHeader(307, \"Expires\", formatDate(1, TimeUnit.HOURS));\n  }\n\n  @Test public void temporaryRedirectCachedWithCacheControlHeader() throws Exception {\n    temporaryRedirectCachedWithCachingHeader(307, \"Cache-Control\", \"max-age=60\");\n  }\n\n  @Test public void foundNotCachedWithoutCacheHeader() throws Exception {\n    temporaryRedirectNotCachedWithoutCachingHeader(302);\n  }\n\n  @Test public void temporaryRedirectNotCachedWithoutCacheHeader() throws Exception {\n    temporaryRedirectNotCachedWithoutCachingHeader(307);\n  }\n\n  private void temporaryRedirectCachedWithCachingHeader(\n      int responseCode, String headerName, String headerValue) throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(responseCode)\n        .addHeader(headerName, headerValue)\n        .addHeader(\"Location\", \"/a\"));\n    server.enqueue(new MockResponse()\n        .addHeader(headerName, headerValue)\n        .setBody(\"a\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"b\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"c\"));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"a\", get(url).body().string());\n    assertEquals(\"a\", get(url).body().string());\n  }\n\n  private void temporaryRedirectNotCachedWithoutCachingHeader(int responseCode) throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(responseCode)\n        .addHeader(\"Location\", \"/a\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"a\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"b\"));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"a\", get(url).body().string());\n    assertEquals(\"b\", get(url).body().string());\n  }\n\n  @Test public void serverDisconnectsPrematurelyWithContentLengthHeader() throws IOException {\n    testServerPrematureDisconnect(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void serverDisconnectsPrematurelyWithChunkedEncoding() throws IOException {\n    testServerPrematureDisconnect(TransferKind.CHUNKED);\n  }\n\n  @Test public void serverDisconnectsPrematurelyWithNoLengthHeaders() throws IOException {\n    // Intentionally empty. This case doesn't make sense because there's no\n    // such thing as a premature disconnect when the disconnect itself\n    // indicates the end of the data stream.\n  }\n\n  private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException {\n    MockResponse mockResponse = new MockResponse();\n    transferKind.setBody(mockResponse, \"ABCDE\\nFGHIJKLMNOPQRSTUVWXYZ\", 16);\n    server.enqueue(truncateViolently(mockResponse, 16));\n    server.enqueue(new MockResponse()\n        .setBody(\"Request #2\"));\n\n    BufferedSource bodySource = get(server.url(\"/\")).body().source();\n    assertEquals(\"ABCDE\", bodySource.readUtf8Line());\n    try {\n      bodySource.readUtf8Line();\n      fail(\"This implementation silently ignored a truncated HTTP body.\");\n    } catch (IOException expected) {\n    } finally {\n      bodySource.close();\n    }\n\n    assertEquals(1, cache.getWriteAbortCount());\n    assertEquals(0, cache.getWriteSuccessCount());\n    Response response = get(server.url(\"/\"));\n    assertEquals(\"Request #2\", response.body().string());\n    assertEquals(1, cache.getWriteAbortCount());\n    assertEquals(1, cache.getWriteSuccessCount());\n  }\n\n  @Test public void clientPrematureDisconnectWithContentLengthHeader() throws IOException {\n    testClientPrematureDisconnect(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void clientPrematureDisconnectWithChunkedEncoding() throws IOException {\n    testClientPrematureDisconnect(TransferKind.CHUNKED);\n  }\n\n  @Test public void clientPrematureDisconnectWithNoLengthHeaders() throws IOException {\n    testClientPrematureDisconnect(TransferKind.END_OF_STREAM);\n  }\n\n  private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException {\n    // Setting a low transfer speed ensures that stream discarding will time out.\n    MockResponse mockResponse = new MockResponse()\n        .throttleBody(6, 1, TimeUnit.SECONDS);\n    transferKind.setBody(mockResponse, \"ABCDE\\nFGHIJKLMNOPQRSTUVWXYZ\", 1024);\n    server.enqueue(mockResponse);\n    server.enqueue(new MockResponse()\n        .setBody(\"Request #2\"));\n\n    Response response1 = get(server.url(\"/\"));\n    BufferedSource in = response1.body().source();\n    assertEquals(\"ABCDE\", in.readUtf8(5));\n    in.close();\n    try {\n      in.readByte();\n      fail(\"Expected an IllegalStateException because the source is closed.\");\n    } catch (IllegalStateException expected) {\n    }\n\n    assertEquals(1, cache.getWriteAbortCount());\n    assertEquals(0, cache.getWriteSuccessCount());\n    Response response2 = get(server.url(\"/\"));\n    assertEquals(\"Request #2\", response2.body().string());\n    assertEquals(1, cache.getWriteAbortCount());\n    assertEquals(1, cache.getWriteSuccessCount());\n  }\n\n  @Test public void defaultExpirationDateFullyCachedForLessThan24Hours() throws Exception {\n    //      last modified: 105 seconds ago\n    //             served:   5 seconds ago\n    //   default lifetime: (105 - 5) / 10 = 10 seconds\n    //            expires:  10 seconds from served date = 5 seconds from now\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-105, TimeUnit.SECONDS))\n        .addHeader(\"Date: \" + formatDate(-5, TimeUnit.SECONDS))\n        .setBody(\"A\"));\n\n    HttpUrl url = server.url(\"/\");\n    Response response1 = get(url);\n    assertEquals(\"A\", response1.body().string());\n\n    Response response2 = get(url);\n    assertEquals(\"A\", response2.body().string());\n    assertNull(response2.header(\"Warning\"));\n  }\n\n  @Test public void defaultExpirationDateConditionallyCached() throws Exception {\n    //      last modified: 115 seconds ago\n    //             served:  15 seconds ago\n    //   default lifetime: (115 - 15) / 10 = 10 seconds\n    //            expires:  10 seconds from served date = 5 seconds ago\n    String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + lastModifiedDate)\n        .addHeader(\"Date: \" + formatDate(-15, TimeUnit.SECONDS)));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void defaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception {\n    //      last modified: 105 days ago\n    //             served:   5 days ago\n    //   default lifetime: (105 - 5) / 10 = 10 days\n    //            expires:  10 days from served date = 5 days from now\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-105, TimeUnit.DAYS))\n        .addHeader(\"Date: \" + formatDate(-5, TimeUnit.DAYS))\n        .setBody(\"A\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    Response response = get(server.url(\"/\"));\n    assertEquals(\"A\", response.body().string());\n    assertEquals(\"113 HttpURLConnection \\\"Heuristic expiration\\\"\", response.header(\"Warning\"));\n  }\n\n  @Test public void noDefaultExpirationForUrlsWithQueryString() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-105, TimeUnit.SECONDS))\n        .addHeader(\"Date: \" + formatDate(-5, TimeUnit.SECONDS))\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\").newBuilder().addQueryParameter(\"foo\", \"bar\").build();\n    assertEquals(\"A\", get(url).body().string());\n    assertEquals(\"B\", get(url).body().string());\n  }\n\n  @Test public void expirationDateInThePastWithLastModifiedHeader() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + lastModifiedDate)\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void expirationDateInThePastWithNoLastModifiedHeader() throws Exception {\n    assertNotCached(new MockResponse()\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n  }\n\n  @Test public void expirationDateInTheFuture() throws Exception {\n    assertFullyCached(new MockResponse()\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n  }\n\n  @Test public void maxAgePreferredWithMaxAgeAndExpires() throws Exception {\n    assertFullyCached(new MockResponse()\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()\n        .addHeader(\"Date: \" + formatDate(-120, TimeUnit.SECONDS))\n        .addHeader(\"Last-Modified: \" + lastModifiedDate)\n        .addHeader(\"Cache-Control: max-age=60\"));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void maxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception {\n    // Chrome interprets max-age relative to the local clock. Both our cache\n    // and Firefox both use the earlier of the local and server's clock.\n    assertNotCached(new MockResponse()\n        .addHeader(\"Date: \" + formatDate(-120, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeInTheFutureWithDateHeader() throws Exception {\n    assertFullyCached(new MockResponse()\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeInTheFutureWithNoDateHeader() throws Exception {\n    assertFullyCached(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeWithLastModifiedButNoServedDate() throws Exception {\n    assertFullyCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-120, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception {\n    assertFullyCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-120, TimeUnit.SECONDS))\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgePreferredOverLowerSharedMaxAge() throws Exception {\n    assertFullyCached(new MockResponse()\n        .addHeader(\"Date: \" + formatDate(-2, TimeUnit.MINUTES))\n        .addHeader(\"Cache-Control: s-maxage=60\")\n        .addHeader(\"Cache-Control: max-age=180\"));\n  }\n\n  @Test public void maxAgePreferredOverHigherMaxAge() throws Exception {\n    assertNotCached(new MockResponse()\n        .addHeader(\"Date: \" + formatDate(-2, TimeUnit.MINUTES))\n        .addHeader(\"Cache-Control: s-maxage=180\")\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void requestMethodOptionsIsNotCached() throws Exception {\n    testRequestMethod(\"OPTIONS\", false);\n  }\n\n  @Test public void requestMethodGetIsCached() throws Exception {\n    testRequestMethod(\"GET\", true);\n  }\n\n  @Test public void requestMethodHeadIsNotCached() throws Exception {\n    // We could support this but choose not to for implementation simplicity\n    testRequestMethod(\"HEAD\", false);\n  }\n\n  @Test public void requestMethodPostIsNotCached() throws Exception {\n    // We could support this but choose not to for implementation simplicity\n    testRequestMethod(\"POST\", false);\n  }\n\n  @Test public void requestMethodPutIsNotCached() throws Exception {\n    testRequestMethod(\"PUT\", false);\n  }\n\n  @Test public void requestMethodDeleteIsNotCached() throws Exception {\n    testRequestMethod(\"DELETE\", false);\n  }\n\n  @Test public void requestMethodTraceIsNotCached() throws Exception {\n    testRequestMethod(\"TRACE\", false);\n  }\n\n  private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception {\n    // 1. seed the cache (potentially)\n    // 2. expect a cache hit or miss\n    server.enqueue(new MockResponse()\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .addHeader(\"X-Response-ID: 1\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"X-Response-ID: 2\"));\n\n    HttpUrl url = server.url(\"/\");\n\n    Request request = new Request.Builder()\n        .url(url)\n        .method(requestMethod, requestBodyOrNull(requestMethod))\n        .build();\n    Response response1 = client.newCall(request).execute();\n    response1.body().close();\n    assertEquals(\"1\", response1.header(\"X-Response-ID\"));\n\n    Response response2 = get(url);\n    response2.body().close();\n    if (expectCached) {\n      assertEquals(\"1\", response2.header(\"X-Response-ID\"));\n    } else {\n      assertEquals(\"2\", response2.header(\"X-Response-ID\"));\n    }\n  }\n\n  private RequestBody requestBodyOrNull(String requestMethod) {\n    return (requestMethod.equals(\"POST\") || requestMethod.equals(\"PUT\"))\n          ? RequestBody.create(MediaType.parse(\"text/plain\"), \"foo\")\n          : null;\n  }\n\n  @Test public void postInvalidatesCache() throws Exception {\n    testMethodInvalidates(\"POST\");\n  }\n\n  @Test public void putInvalidatesCache() throws Exception {\n    testMethodInvalidates(\"PUT\");\n  }\n\n  @Test public void deleteMethodInvalidatesCache() throws Exception {\n    testMethodInvalidates(\"DELETE\");\n  }\n\n  private void testMethodInvalidates(String requestMethod) throws Exception {\n    // 1. seed the cache\n    // 2. invalidate it\n    // 3. expect a cache miss\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"C\"));\n\n    HttpUrl url = server.url(\"/\");\n\n    assertEquals(\"A\", get(url).body().string());\n\n    Request request = new Request.Builder()\n        .url(url)\n        .method(requestMethod, requestBodyOrNull(requestMethod))\n        .build();\n    Response invalidate = client.newCall(request).execute();\n    assertEquals(\"B\", invalidate.body().string());\n\n    assertEquals(\"C\", get(url).body().string());\n  }\n\n  @Test public void postInvalidatesCacheWithUncacheableResponse() throws Exception {\n    // 1. seed the cache\n    // 2. invalidate it with uncacheable response\n    // 3. expect a cache miss\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\")\n        .setResponseCode(500));\n    server.enqueue(new MockResponse()\n        .setBody(\"C\"));\n\n    HttpUrl url = server.url(\"/\");\n\n    assertEquals(\"A\", get(url).body().string());\n\n    Request request = new Request.Builder()\n        .url(url)\n        .method(\"POST\", requestBodyOrNull(\"POST\"))\n        .build();\n    Response invalidate = client.newCall(request).execute();\n    assertEquals(\"B\", invalidate.body().string());\n\n    assertEquals(\"C\", get(url).body().string());\n  }\n\n  @Test public void etag() throws Exception {\n    RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()\n        .addHeader(\"ETag: v1\"));\n    assertEquals(\"v1\", conditionalRequest.getHeader(\"If-None-Match\"));\n  }\n\n  /** If both If-Modified-Since and If-None-Match conditions apply, send only If-None-Match. */\n  @Test public void etagAndExpirationDateInThePast() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()\n        .addHeader(\"ETag: v1\")\n        .addHeader(\"Last-Modified: \" + lastModifiedDate)\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n    assertEquals(\"v1\", conditionalRequest.getHeader(\"If-None-Match\"));\n    assertNull(conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void etagAndExpirationDateInTheFuture() throws Exception {\n    assertFullyCached(new MockResponse()\n        .addHeader(\"ETag: v1\")\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n  }\n\n  @Test public void cacheControlNoCache() throws Exception {\n    assertNotCached(new MockResponse()\n        .addHeader(\"Cache-Control: no-cache\"));\n  }\n\n  @Test public void cacheControlNoCacheAndExpirationDateInTheFuture() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + lastModifiedDate)\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: no-cache\"));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void pragmaNoCache() throws Exception {\n    assertNotCached(new MockResponse()\n        .addHeader(\"Pragma: no-cache\"));\n  }\n\n  @Test public void pragmaNoCacheAndExpirationDateInTheFuture() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + lastModifiedDate)\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .addHeader(\"Pragma: no-cache\"));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void cacheControlNoStore() throws Exception {\n    assertNotCached(new MockResponse()\n        .addHeader(\"Cache-Control: no-store\"));\n  }\n\n  @Test public void cacheControlNoStoreAndExpirationDateInTheFuture() throws Exception {\n    assertNotCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: no-store\"));\n  }\n\n  @Test public void partialRangeResponsesDoNotCorruptCache() throws Exception {\n    // 1. request a range\n    // 2. request a full document, expecting a cache miss\n    server.enqueue(new MockResponse()\n        .setBody(\"AA\")\n        .setResponseCode(HttpURLConnection.HTTP_PARTIAL)\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .addHeader(\"Content-Range: bytes 1000-1001/2000\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"BB\"));\n\n    HttpUrl url = server.url(\"/\");\n\n    Request request = new Request.Builder()\n        .url(url)\n        .header(\"Range\", \"bytes=1000-1001\")\n        .build();\n    Response range = client.newCall(request).execute();\n    assertEquals(\"AA\", range.body().string());\n\n    assertEquals(\"BB\", get(url).body().string());\n  }\n\n  @Test public void serverReturnsDocumentOlderThanCache() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\")\n        .addHeader(\"Last-Modified: \" + formatDate(-4, TimeUnit.HOURS)));\n\n    HttpUrl url = server.url(\"/\");\n\n    assertEquals(\"A\", get(url).body().string());\n    assertEquals(\"A\", get(url).body().string());\n  }\n\n  @Test public void clientSideNoStore() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"B\"));\n\n    Request request1 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .cacheControl(new CacheControl.Builder().noStore().build())\n        .build();\n    Response response1 = client.newCall(request1).execute();\n    assertEquals(\"A\", response1.body().string());\n\n    Request request2 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    Response response2 = client.newCall(request2).execute();\n    assertEquals(\"B\", response2.body().string());\n  }\n\n  @Test public void nonIdentityEncodingAndConditionalCache() throws Exception {\n    assertNonIdentityEncodingCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n  }\n\n  @Test public void nonIdentityEncodingAndFullCache() throws Exception {\n    assertNonIdentityEncodingCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n  }\n\n  private void assertNonIdentityEncodingCached(MockResponse response) throws Exception {\n    server.enqueue(response\n        .setBody(gzip(\"ABCABCABC\"))\n        .addHeader(\"Content-Encoding: gzip\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    // At least three request/response pairs are required because after the first request is cached\n    // a different execution path might be taken. Thus modifications to the cache applied during\n    // the second request might not be visible until another request is performed.\n    assertEquals(\"ABCABCABC\", get(server.url(\"/\")).body().string());\n    assertEquals(\"ABCABCABC\", get(server.url(\"/\")).body().string());\n    assertEquals(\"ABCABCABC\", get(server.url(\"/\")).body().string());\n  }\n\n  @Test public void notModifiedSpecifiesEncoding() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(gzip(\"ABCABCABC\"))\n        .addHeader(\"Content-Encoding: gzip\")\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)\n        .addHeader(\"Content-Encoding: gzip\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"DEFDEFDEF\"));\n\n    assertEquals(\"ABCABCABC\", get(server.url(\"/\")).body().string());\n    assertEquals(\"ABCABCABC\", get(server.url(\"/\")).body().string());\n    assertEquals(\"DEFDEFDEF\", get(server.url(\"/\")).body().string());\n  }\n\n  /** https://github.com/square/okhttp/issues/947 */\n  @Test public void gzipAndVaryOnAcceptEncoding() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(gzip(\"ABCABCABC\"))\n        .addHeader(\"Content-Encoding: gzip\")\n        .addHeader(\"Vary: Accept-Encoding\")\n        .addHeader(\"Cache-Control: max-age=60\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"FAIL\"));\n\n    assertEquals(\"ABCABCABC\", get(server.url(\"/\")).body().string());\n    assertEquals(\"ABCABCABC\", get(server.url(\"/\")).body().string());\n  }\n\n  @Test public void conditionalCacheHitIsNotDoublePooled() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"ETag: v1\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .clearHeaders()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    ConnectionPool pool = ConnectionPool.getDefault();\n    pool.evictAll();\n    client.setConnectionPool(pool);\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(1, client.getConnectionPool().getConnectionCount());\n  }\n\n  @Test public void expiresDateBeforeModifiedDate() throws Exception {\n    assertConditionallyCached(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(-2, TimeUnit.HOURS)));\n  }\n\n  @Test public void requestMaxAge() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Date: \" + formatDate(-1, TimeUnit.MINUTES))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"max-age=30\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"B\", response.body().string());\n  }\n\n  @Test public void requestMinFresh() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"min-fresh=120\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"B\", response.body().string());\n  }\n\n  @Test public void requestMaxStale() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=120\")\n        .addHeader(\"Date: \" + formatDate(-4, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"max-stale=180\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"A\", response.body().string());\n    assertEquals(\"110 HttpURLConnection \\\"Response is stale\\\"\", response.header(\"Warning\"));\n  }\n\n  @Test public void requestMaxStaleDirectiveWithNoValue() throws IOException {\n    // Add a stale response to the cache.\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=120\")\n        .addHeader(\"Date: \" + formatDate(-4, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n\n    // With max-stale, we'll return that stale response.\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"max-stale\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"A\", response.body().string());\n    assertEquals(\"110 HttpURLConnection \\\"Response is stale\\\"\", response.header(\"Warning\"));\n  }\n\n  @Test public void requestMaxStaleNotHonoredWithMustRevalidate() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=120, must-revalidate\")\n        .addHeader(\"Date: \" + formatDate(-4, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"max-stale=180\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"B\", response.body().string());\n  }\n\n  @Test public void requestOnlyIfCachedWithNoResponseCached() throws IOException {\n    // (no responses enqueued)\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"only-if-cached\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertTrue(response.body().source().exhausted());\n    assertEquals(504, response.code());\n    assertEquals(1, cache.getRequestCount());\n    assertEquals(0, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n  }\n\n  @Test public void requestOnlyIfCachedWithFullResponseCached() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"only-if-cached\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"A\", response.body().string());\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(1, cache.getHitCount());\n  }\n\n  @Test public void requestOnlyIfCachedWithConditionalResponseCached() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(-1, TimeUnit.MINUTES)));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"only-if-cached\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertTrue(response.body().source().exhausted());\n    assertEquals(504, response.code());\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n  }\n\n  @Test public void requestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"only-if-cached\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertTrue(response.body().source().exhausted());\n    assertEquals(504, response.code());\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n  }\n\n  @Test public void requestCacheControlNoCache() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-120, TimeUnit.SECONDS))\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n    Request request = new Request.Builder()\n        .url(url)\n        .header(\"Cache-Control\", \"no-cache\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"B\", response.body().string());\n  }\n\n  @Test public void requestPragmaNoCache() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-120, TimeUnit.SECONDS))\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n    Request request = new Request.Builder()\n        .url(url)\n        .header(\"Pragma\", \"no-cache\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"B\", response.body().string());\n  }\n\n  @Test public void clientSuppliedIfModifiedSinceWithCachedResult() throws Exception {\n    MockResponse response = new MockResponse()\n        .addHeader(\"ETag: v3\")\n        .addHeader(\"Cache-Control: max-age=0\");\n    String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS);\n    RecordedRequest request =\n        assertClientSuppliedCondition(response, \"If-Modified-Since\", ifModifiedSinceDate);\n    assertEquals(ifModifiedSinceDate, request.getHeader(\"If-Modified-Since\"));\n    assertNull(request.getHeader(\"If-None-Match\"));\n  }\n\n  @Test public void clientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception {\n    String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES);\n    MockResponse response = new MockResponse()\n        .addHeader(\"Last-Modified: \" + lastModifiedDate)\n        .addHeader(\"Date: \" + formatDate(-2, TimeUnit.MINUTES))\n        .addHeader(\"Cache-Control: max-age=0\");\n    RecordedRequest request = assertClientSuppliedCondition(response, \"If-None-Match\", \"v1\");\n    assertEquals(\"v1\", request.getHeader(\"If-None-Match\"));\n    assertNull(request.getHeader(\"If-Modified-Since\"));\n  }\n\n  private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName,\n      String conditionValue) throws Exception {\n    server.enqueue(seed.setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n\n    Request request = new Request.Builder()\n        .url(url)\n        .header(conditionName, conditionValue)\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, response.code());\n    assertEquals(\"\", response.body().string());\n\n    server.takeRequest(); // seed\n    return server.takeRequest();\n  }\n\n  /**\n   * For Last-Modified and Date headers, we should echo the date back in the\n   * exact format we were served.\n   */\n  @Test public void retainServedDateFormat() throws Exception {\n    // Serve a response with a non-standard date format that OkHttp supports.\n    Date lastModifiedDate = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(-1));\n    Date servedDate = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(-2));\n    DateFormat dateFormat = new SimpleDateFormat(\"EEE dd-MMM-yyyy HH:mm:ss z\", Locale.US);\n    dateFormat.setTimeZone(TimeZone.getTimeZone(\"EDT\"));\n    String lastModifiedString = dateFormat.format(lastModifiedDate);\n    String servedString = dateFormat.format(servedDate);\n\n    // This response should be conditionally cached.\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + lastModifiedString)\n        .addHeader(\"Expires: \" + servedString)\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n\n    // The first request has no conditions.\n    RecordedRequest request1 = server.takeRequest();\n    assertNull(request1.getHeader(\"If-Modified-Since\"));\n\n    // The 2nd request uses the server's date format.\n    RecordedRequest request2 = server.takeRequest();\n    assertEquals(lastModifiedString, request2.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void clientSuppliedConditionWithoutCachedResult() throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"If-Modified-Since\", formatDate(-24, TimeUnit.HOURS))\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, response.code());\n    assertEquals(\"\", response.body().string());\n  }\n\n  @Test public void authorizationRequestFullyCached() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    Request request = new Request.Builder()\n        .url(url)\n        .header(\"Authorization\", \"password\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"A\", response.body().string());\n    assertEquals(\"A\", get(url).body().string());\n  }\n\n  @Test public void contentLocationDoesNotPopulateCache() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Content-Location: /bar\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/foo\")).body().string());\n    assertEquals(\"B\", get(server.url(\"/bar\")).body().string());\n  }\n\n  @Test public void connectionIsReturnedToPoolAfterConditionalSuccess() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/a\")).body().string());\n    assertEquals(\"A\", get(server.url(\"/a\")).body().string());\n    assertEquals(\"B\", get(server.url(\"/b\")).body().string());\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n    assertEquals(2, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void statisticsConditionalCacheMiss() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"C\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(1, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n    assertEquals(\"B\", get(server.url(\"/\")).body().string());\n    assertEquals(\"C\", get(server.url(\"/\")).body().string());\n    assertEquals(3, cache.getRequestCount());\n    assertEquals(3, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n  }\n\n  @Test public void statisticsConditionalCacheHit() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(1, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(3, cache.getRequestCount());\n    assertEquals(3, cache.getNetworkCount());\n    assertEquals(2, cache.getHitCount());\n  }\n\n  @Test public void statisticsFullCacheHit() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"A\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(1, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(3, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(2, cache.getHitCount());\n  }\n\n  @Test public void varyMatchesChangedRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    Request frRequest = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"fr-CA\")\n        .build();\n    Response frResponse = client.newCall(frRequest).execute();\n    assertEquals(\"A\", frResponse.body().string());\n\n    Request enRequest = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"en-US\")\n        .build();\n    Response enResponse = client.newCall(enRequest).execute();\n    assertEquals(\"B\", enResponse.body().string());\n  }\n\n  @Test public void varyMatchesUnchangedRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    Request request = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"fr-CA\")\n        .build();\n    Response response1 = client.newCall(request).execute();\n    assertEquals(\"A\", response1.body().string());\n    Request request1 = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"fr-CA\")\n        .build();\n    Response response2 = client.newCall(request1).execute();\n    assertEquals(\"A\", response2.body().string());\n  }\n\n  @Test public void varyMatchesAbsentRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Foo\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n  }\n\n  @Test public void varyMatchesAddedRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Foo\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    Request request = new Request.Builder()\n        .url(server.url(\"/\")).header(\"Foo\", \"bar\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"B\", response.body().string());\n  }\n\n  @Test public void varyMatchesRemovedRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Foo\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\")).header(\"Foo\", \"bar\")\n        .build();\n    Response fooresponse = client.newCall(request).execute();\n    assertEquals(\"A\", fooresponse.body().string());\n    assertEquals(\"B\", get(server.url(\"/\")).body().string());\n  }\n\n  @Test public void varyFieldsAreCaseInsensitive() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: ACCEPT-LANGUAGE\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    Request request = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"fr-CA\")\n        .build();\n    Response response1 = client.newCall(request).execute();\n    assertEquals(\"A\", response1.body().string());\n    Request request1 = new Request.Builder()\n        .url(url)\n        .header(\"accept-language\", \"fr-CA\")\n        .build();\n    Response response2 = client.newCall(request1).execute();\n    assertEquals(\"A\", response2.body().string());\n  }\n\n  @Test public void varyMultipleFieldsWithMatch() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language, Accept-Charset\")\n        .addHeader(\"Vary: Accept-Encoding\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    Request request = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"fr-CA\")\n        .header(\"Accept-Charset\", \"UTF-8\")\n        .header(\"Accept-Encoding\", \"identity\")\n        .build();\n    Response response1 = client.newCall(request).execute();\n    assertEquals(\"A\", response1.body().string());\n    Request request1 = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"fr-CA\")\n        .header(\"Accept-Charset\", \"UTF-8\")\n        .header(\"Accept-Encoding\", \"identity\")\n        .build();\n    Response response2 = client.newCall(request1).execute();\n    assertEquals(\"A\", response2.body().string());\n  }\n\n  @Test public void varyMultipleFieldsWithNoMatch() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language, Accept-Charset\")\n        .addHeader(\"Vary: Accept-Encoding\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    Request frRequest = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"fr-CA\")\n        .header(\"Accept-Charset\", \"UTF-8\")\n        .header(\"Accept-Encoding\", \"identity\")\n        .build();\n    Response frResponse = client.newCall(frRequest).execute();\n    assertEquals(\"A\", frResponse.body().string());\n    Request enRequest = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"en-CA\")\n        .header(\"Accept-Charset\", \"UTF-8\")\n        .header(\"Accept-Encoding\", \"identity\")\n        .build();\n    Response enResponse = client.newCall(enRequest).execute();\n    assertEquals(\"B\", enResponse.body().string());\n  }\n\n  @Test public void varyMultipleFieldValuesWithMatch() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    Request request1 = new Request.Builder()\n        .url(url)\n        .addHeader(\"Accept-Language\", \"fr-CA, fr-FR\")\n        .addHeader(\"Accept-Language\", \"en-US\")\n        .build();\n    Response response1 = client.newCall(request1).execute();\n    assertEquals(\"A\", response1.body().string());\n\n    Request request2 = new Request.Builder()\n        .url(url)\n        .addHeader(\"Accept-Language\", \"fr-CA, fr-FR\")\n        .addHeader(\"Accept-Language\", \"en-US\")\n        .build();\n    Response response2 = client.newCall(request2).execute();\n    assertEquals(\"A\", response2.body().string());\n  }\n\n  @Test public void varyMultipleFieldValuesWithNoMatch() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    Request request1 = new Request.Builder()\n        .url(url)\n        .addHeader(\"Accept-Language\", \"fr-CA, fr-FR\")\n        .addHeader(\"Accept-Language\", \"en-US\")\n        .build();\n    Response response1 = client.newCall(request1).execute();\n    assertEquals(\"A\", response1.body().string());\n\n    Request request2 = new Request.Builder()\n        .url(url)\n        .addHeader(\"Accept-Language\", \"fr-CA\")\n        .addHeader(\"Accept-Language\", \"en-US\")\n        .build();\n    Response response2 = client.newCall(request2).execute();\n    assertEquals(\"B\", response2.body().string());\n  }\n\n  @Test public void varyAsterisk() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: *\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    assertEquals(\"B\", get(server.url(\"/\")).body().string());\n  }\n\n  @Test public void varyAndHttps() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n\n    HttpUrl url = server.url(\"/\");\n    Request request1 = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"en-US\")\n        .build();\n    Response response1 = client.newCall(request1).execute();\n    assertEquals(\"A\", response1.body().string());\n\n    Request request2 = new Request.Builder()\n        .url(url)\n        .header(\"Accept-Language\", \"en-US\")\n        .build();\n    Response response2 = client.newCall(request2).execute();\n    assertEquals(\"A\", response2.body().string());\n  }\n\n  @Test public void cachePlusCookies() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Set-Cookie: a=FIRST; domain=\" + server.getCookieDomain() + \";\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Set-Cookie: a=SECOND; domain=\" + server.getCookieDomain() + \";\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n    assertCookies(url, \"a=FIRST\");\n    assertEquals(\"A\", get(url).body().string());\n    assertCookies(url, \"a=SECOND\");\n  }\n\n  @Test public void getHeadersReturnsNetworkEndToEndHeaders() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Allow: GET, HEAD\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Allow: GET, HEAD, PUT\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    Response response1 = get(server.url(\"/\"));\n    assertEquals(\"A\", response1.body().string());\n    assertEquals(\"GET, HEAD\", response1.header(\"Allow\"));\n\n    Response response2 = get(server.url(\"/\"));\n    assertEquals(\"A\", response2.body().string());\n    assertEquals(\"GET, HEAD, PUT\", response2.header(\"Allow\"));\n  }\n\n  @Test public void getHeadersReturnsCachedHopByHopHeaders() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Transfer-Encoding: identity\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Transfer-Encoding: none\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    Response response1 = get(server.url(\"/\"));\n    assertEquals(\"A\", response1.body().string());\n    assertEquals(\"identity\", response1.header(\"Transfer-Encoding\"));\n\n    Response response2 = get(server.url(\"/\"));\n    assertEquals(\"A\", response2.body().string());\n    assertEquals(\"identity\", response2.header(\"Transfer-Encoding\"));\n  }\n\n  @Test public void getHeadersDeletesCached100LevelWarnings() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Warning: 199 test danger\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    Response response1 = get(server.url(\"/\"));\n    assertEquals(\"A\", response1.body().string());\n    assertEquals(\"199 test danger\", response1.header(\"Warning\"));\n\n    Response response2 = get(server.url(\"/\"));\n    assertEquals(\"A\", response2.body().string());\n    assertEquals(null, response2.header(\"Warning\"));\n  }\n\n  @Test public void getHeadersRetainsCached200LevelWarnings() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Warning: 299 test danger\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    Response response1 = get(server.url(\"/\"));\n    assertEquals(\"A\", response1.body().string());\n    assertEquals(\"299 test danger\", response1.header(\"Warning\"));\n\n    Response response2 = get(server.url(\"/\"));\n    assertEquals(\"A\", response2.body().string());\n    assertEquals(\"299 test danger\", response2.header(\"Warning\"));\n  }\n\n  public void assertCookies(HttpUrl url, String... expectedCookies) throws Exception {\n    List<String> actualCookies = new ArrayList<>();\n    for (HttpCookie cookie : cookieManager.getCookieStore().get(url.uri())) {\n      actualCookies.add(cookie.toString());\n    }\n    assertEquals(Arrays.asList(expectedCookies), actualCookies);\n  }\n\n  @Test public void doNotCachePartialResponse() throws Exception  {\n    assertNotCached(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_PARTIAL)\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.HOURS))\n        .addHeader(\"Content-Range: bytes 100-100/200\")\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void conditionalHitUpdatesCache() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(0, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Allow: GET, HEAD\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    // cache miss; seed the cache\n    Response response1 = get(server.url(\"/a\"));\n    assertEquals(\"A\", response1.body().string());\n    assertEquals(null, response1.header(\"Allow\"));\n\n    // conditional cache hit; update the cache\n    Response response2 = get(server.url(\"/a\"));\n    assertEquals(HttpURLConnection.HTTP_OK, response2.code());\n    assertEquals(\"A\", response2.body().string());\n    assertEquals(\"GET, HEAD\", response2.header(\"Allow\"));\n\n    // full cache hit\n    Response response3 = get(server.url(\"/a\"));\n    assertEquals(\"A\", response3.body().string());\n    assertEquals(\"GET, HEAD\", response3.header(\"Allow\"));\n\n    assertEquals(2, server.getRequestCount());\n  }\n\n  @Test public void responseSourceHeaderCached() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    Request request = new Request.Builder()\n        .url(server.url(\"/\")).header(\"Cache-Control\", \"only-if-cached\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"A\", response.body().string());\n  }\n\n  @Test public void responseSourceHeaderConditionalCacheFetched() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(-31, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    Response response = get(server.url(\"/\"));\n    assertEquals(\"B\", response.body().string());\n  }\n\n  @Test public void responseSourceHeaderConditionalCacheNotFetched() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=0\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse()\n        .setResponseCode(304));\n\n    assertEquals(\"A\", get(server.url(\"/\")).body().string());\n    Response response = get(server.url(\"/\"));\n    assertEquals(\"A\", response.body().string());\n  }\n\n  @Test public void responseSourceHeaderFetched() throws IOException {\n    server.enqueue(new MockResponse()\n        .setBody(\"A\"));\n\n    Response response = get(server.url(\"/\"));\n    assertEquals(\"A\", response.body().string());\n  }\n\n  @Test public void emptyResponseHeaderNameFromCacheIsLenient() throws Exception {\n    Headers.Builder headers = new Headers.Builder()\n        .add(\"Cache-Control: max-age=120\");\n    Internal.instance.addLenient(headers, \": A\");\n    server.enqueue(new MockResponse()\n        .setHeaders(headers.build())\n        .setBody(\"body\"));\n\n    Response response = get(server.url(\"/\"));\n    assertEquals(\"A\", response.header(\"\"));\n    assertEquals(\"body\", response.body().string());\n  }\n\n  /**\n   * Old implementations of OkHttp's response cache wrote header fields like\n   * \":status: 200 OK\". This broke our cached response parser because it split\n   * on the first colon. This regression test exists to help us read these old\n   * bad cache entries.\n   *\n   * https://github.com/square/okhttp/issues/227\n   */\n  @Test public void testGoldenCacheResponse() throws Exception {\n    cache.close();\n    server.enqueue(new MockResponse()\n        .clearHeaders()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    HttpUrl url = server.url(\"/\");\n    String urlKey = Util.md5Hex(url.toString());\n    String entryMetadata = \"\"\n        + \"\" + url + \"\\n\"\n        + \"GET\\n\"\n        + \"0\\n\"\n        + \"HTTP/1.1 200 OK\\n\"\n        + \"7\\n\"\n        + \":status: 200 OK\\n\"\n        + \":version: HTTP/1.1\\n\"\n        + \"etag: foo\\n\"\n        + \"content-length: 3\\n\"\n        + \"OkHttp-Received-Millis: \" + System.currentTimeMillis() + \"\\n\"\n        + \"X-Android-Response-Source: NETWORK 200\\n\"\n        + \"OkHttp-Sent-Millis: \" + System.currentTimeMillis() + \"\\n\"\n        + \"\\n\"\n        + \"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\\n\"\n        + \"1\\n\"\n        + \"MIIBpDCCAQ2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDEw1qd2lsc29uLmxvY2FsMB4XDTEzMDgy\"\n        + \"OTA1MDE1OVoXDTEzMDgzMDA1MDE1OVowGDEWMBQGA1UEAxMNandpbHNvbi5sb2NhbDCBnzANBgkqhkiG9w0BAQEF\"\n        + \"AAOBjQAwgYkCgYEAlFW+rGo/YikCcRghOyKkJanmVmJSce/p2/jH1QvNIFKizZdh8AKNwojt3ywRWaDULA/RlCUc\"\n        + \"ltF3HGNsCyjQI/+Lf40x7JpxXF8oim1E6EtDoYtGWAseelawus3IQ13nmo6nWzfyCA55KhAWf4VipelEy8DjcuFK\"\n        + \"v6L0xwXnI0ECAwEAATANBgkqhkiG9w0BAQsFAAOBgQAuluNyPo1HksU3+Mr/PyRQIQS4BI7pRXN8mcejXmqyscdP\"\n        + \"7S6J21FBFeRR8/XNjVOp4HT9uSc2hrRtTEHEZCmpyoxixbnM706ikTmC7SN/GgM+SmcoJ1ipJcNcl8N0X6zym4dm\"\n        + \"yFfXKHu2PkTo7QFdpOJFvP3lIigcSZXozfmEDg==\\n\"\n        + \"-1\\n\";\n    String entryBody = \"abc\";\n    String journalBody = \"\"\n        + \"libcore.io.DiskLruCache\\n\"\n        + \"1\\n\"\n        + \"201105\\n\"\n        + \"2\\n\"\n        + \"\\n\"\n        + \"CLEAN \" + urlKey + \" \" + entryMetadata.length() + \" \" + entryBody.length() + \"\\n\";\n    writeFile(cache.getDirectory(), urlKey + \".0\", entryMetadata);\n    writeFile(cache.getDirectory(), urlKey + \".1\", entryBody);\n    writeFile(cache.getDirectory(), \"journal\", journalBody);\n    cache = new Cache(cache.getDirectory(), Integer.MAX_VALUE, fileSystem);\n    client.setCache(cache);\n\n    Response response = get(url);\n    assertEquals(entryBody, response.body().string());\n    assertEquals(\"3\", response.header(\"Content-Length\"));\n    assertEquals(\"foo\", response.header(\"etag\"));\n  }\n\n  @Test public void evictAll() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n    client.getCache().evictAll();\n    assertEquals(0, client.getCache().getSize());\n    assertEquals(\"B\", get(url).body().string());\n  }\n\n  @Test public void networkInterceptorInvokedForConditionalGet() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"ETag: v1\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    // Seed the cache.\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n\n    final AtomicReference<String> ifNoneMatch = new AtomicReference<>();\n    client.networkInterceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        ifNoneMatch.compareAndSet(null, chain.request().header(\"If-None-Match\"));\n        return chain.proceed(chain.request());\n      }\n    });\n\n    // Confirm the value is cached and intercepted.\n    assertEquals(\"A\", get(url).body().string());\n    assertEquals(\"v1\", ifNoneMatch.get());\n  }\n\n  @Test public void networkInterceptorNotInvokedForFullyCached() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"A\"));\n\n    // Seed the cache.\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n\n    // Confirm the interceptor isn't exercised.\n    client.networkInterceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        throw new AssertionError();\n      }\n    });\n    assertEquals(\"A\", get(url).body().string());\n  }\n\n  @Test public void iterateCache() throws Exception {\n    // Put some responses in the cache.\n    server.enqueue(new MockResponse()\n        .setBody(\"a\"));\n    HttpUrl urlA = server.url(\"/a\");\n    assertEquals(\"a\", get(urlA).body().string());\n\n    server.enqueue(new MockResponse()\n        .setBody(\"b\"));\n    HttpUrl urlB = server.url(\"/b\");\n    assertEquals(\"b\", get(urlB).body().string());\n\n    server.enqueue(new MockResponse()\n        .setBody(\"c\"));\n    HttpUrl urlC = server.url(\"/c\");\n    assertEquals(\"c\", get(urlC).body().string());\n\n    // Confirm the iterator returns those responses...\n    Iterator<String> i = cache.urls();\n    assertTrue(i.hasNext());\n    assertEquals(urlA.toString(), i.next());\n    assertTrue(i.hasNext());\n    assertEquals(urlB.toString(), i.next());\n    assertTrue(i.hasNext());\n    assertEquals(urlC.toString(), i.next());\n\n    // ... and nothing else.\n    assertFalse(i.hasNext());\n    try {\n      i.next();\n      fail();\n    } catch (NoSuchElementException expected) {\n    }\n  }\n\n  @Test public void iteratorRemoveFromCache() throws Exception {\n    // Put a response in the cache.\n    server.enqueue(new MockResponse()\n        .addHeader(\"Cache-Control: max-age=60\")\n        .setBody(\"a\"));\n    HttpUrl url = server.url(\"/a\");\n    assertEquals(\"a\", get(url).body().string());\n\n    // Remove it with iteration.\n    Iterator<String> i = cache.urls();\n    assertEquals(url.toString(), i.next());\n    i.remove();\n\n    // Confirm that subsequent requests suffer a cache miss.\n    server.enqueue(new MockResponse()\n        .setBody(\"b\"));\n    assertEquals(\"b\", get(url).body().string());\n  }\n\n  @Test public void iteratorRemoveWithoutNextThrows() throws Exception {\n    // Put a response in the cache.\n    server.enqueue(new MockResponse()\n        .setBody(\"a\"));\n    HttpUrl url = server.url(\"/a\");\n    assertEquals(\"a\", get(url).body().string());\n\n    Iterator<String> i = cache.urls();\n    assertTrue(i.hasNext());\n    try {\n      i.remove();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void iteratorRemoveOncePerCallToNext() throws Exception {\n    // Put a response in the cache.\n    server.enqueue(new MockResponse()\n        .setBody(\"a\"));\n    HttpUrl url = server.url(\"/a\");\n    assertEquals(\"a\", get(url).body().string());\n\n    Iterator<String> i = cache.urls();\n    assertEquals(url.toString(), i.next());\n    i.remove();\n\n    // Too many calls to remove().\n    try {\n      i.remove();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void elementEvictedBetweenHasNextAndNext() throws Exception {\n    // Put a response in the cache.\n    server.enqueue(new MockResponse()\n        .setBody(\"a\"));\n    HttpUrl url = server.url(\"/a\");\n    assertEquals(\"a\", get(url).body().string());\n\n    // The URL will remain available if hasNext() returned true...\n    Iterator<String> i = cache.urls();\n    assertTrue(i.hasNext());\n\n    // ...so even when we evict the element, we still get something back.\n    cache.evictAll();\n    assertEquals(url.toString(), i.next());\n\n    // Remove does nothing. But most importantly, it doesn't throw!\n    i.remove();\n  }\n\n  @Test public void elementEvictedBeforeHasNextIsOmitted() throws Exception {\n    // Put a response in the cache.\n    server.enqueue(new MockResponse()\n        .setBody(\"a\"));\n    HttpUrl url = server.url(\"/a\");\n    assertEquals(\"a\", get(url).body().string());\n\n    Iterator<String> i = cache.urls();\n    cache.evictAll();\n\n    // The URL was evicted before hasNext() made any promises.\n    assertFalse(i.hasNext());\n    try {\n      i.next();\n      fail();\n    } catch (NoSuchElementException expected) {\n    }\n  }\n\n  /** Test https://github.com/square/okhttp/issues/1712. */\n  @Test public void conditionalMissUpdatesCache() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"ETag: v1\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse()\n        .addHeader(\"ETag: v2\")\n        .setBody(\"B\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n    assertEquals(\"A\", get(url).body().string());\n    assertEquals(\"B\", get(url).body().string());\n    assertEquals(\"B\", get(url).body().string());\n\n    assertEquals(null, server.takeRequest().getHeader(\"If-None-Match\"));\n    assertEquals(\"v1\", server.takeRequest().getHeader(\"If-None-Match\"));\n    assertEquals(\"v1\", server.takeRequest().getHeader(\"If-None-Match\"));\n    assertEquals(\"v2\", server.takeRequest().getHeader(\"If-None-Match\"));\n  }\n\n  private Response get(HttpUrl url) throws IOException {\n    Request request = new Request.Builder()\n        .url(url)\n        .build();\n    return client.newCall(request).execute();\n  }\n\n\n  private void writeFile(File directory, String file, String content) throws IOException {\n    BufferedSink sink = Okio.buffer(fileSystem.sink(new File(directory, file)));\n    sink.writeUtf8(content);\n    sink.close();\n  }\n\n  /**\n   * @param delta the offset from the current date to use. Negative\n   * values yield dates in the past; positive values yield dates in the\n   * future.\n   */\n  private String formatDate(long delta, TimeUnit timeUnit) {\n    return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta)));\n  }\n\n  private String formatDate(Date date) {\n    DateFormat rfc1123 = new SimpleDateFormat(\"EEE, dd MMM yyyy HH:mm:ss zzz\", Locale.US);\n    rfc1123.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n    return rfc1123.format(date);\n  }\n\n  private void assertNotCached(MockResponse response) throws Exception {\n    server.enqueue(response.setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n    assertEquals(\"B\", get(url).body().string());\n  }\n\n  /** @return the request with the conditional get headers. */\n  private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception {\n    // scenario 1: condition succeeds\n    server.enqueue(response.setBody(\"A\").setStatus(\"HTTP/1.1 200 A-OK\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    // scenario 2: condition fails\n    server.enqueue(response.setBody(\"B\")\n        .setStatus(\"HTTP/1.1 200 B-OK\"));\n    server.enqueue(new MockResponse()\n        .setStatus(\"HTTP/1.1 200 C-OK\")\n        .setBody(\"C\"));\n\n    HttpUrl valid = server.url(\"/valid\");\n    Response response1 = get(valid);\n    assertEquals(\"A\", response1.body().string());\n    assertEquals(HttpURLConnection.HTTP_OK, response1.code());\n    assertEquals(\"A-OK\", response1.message());\n    Response response2 = get(valid);\n    assertEquals(\"A\", response2.body().string());\n    assertEquals(HttpURLConnection.HTTP_OK, response2.code());\n    assertEquals(\"A-OK\", response2.message());\n\n    HttpUrl invalid = server.url(\"/invalid\");\n    Response response3 = get(invalid);\n    assertEquals(\"B\", response3.body().string());\n    assertEquals(HttpURLConnection.HTTP_OK, response3.code());\n    assertEquals(\"B-OK\", response3.message());\n    Response response4 = get(invalid);\n    assertEquals(\"C\", response4.body().string());\n    assertEquals(HttpURLConnection.HTTP_OK, response4.code());\n    assertEquals(\"C-OK\", response4.message());\n\n    server.takeRequest(); // regular get\n    return server.takeRequest(); // conditional get\n  }\n\n  private void assertFullyCached(MockResponse response) throws Exception {\n    server.enqueue(response.setBody(\"A\"));\n    server.enqueue(response.setBody(\"B\"));\n\n    HttpUrl url = server.url(\"/\");\n    assertEquals(\"A\", get(url).body().string());\n    assertEquals(\"A\", get(url).body().string());\n  }\n\n  /**\n   * Shortens the body of {@code response} but not the corresponding headers.\n   * Only useful to test how clients respond to the premature conclusion of\n   * the HTTP body.\n   */\n  private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) {\n    response.setSocketPolicy(DISCONNECT_AT_END);\n    Headers headers = response.getHeaders();\n    Buffer truncatedBody = new Buffer();\n    truncatedBody.write(response.getBody(), numBytesToKeep);\n    response.setBody(truncatedBody);\n    response.setHeaders(headers);\n    return response;\n  }\n\n  enum TransferKind {\n    CHUNKED() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize)\n          throws IOException {\n        response.setChunkedBody(content, chunkSize);\n      }\n    },\n    FIXED_LENGTH() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize) {\n        response.setBody(content);\n      }\n    },\n    END_OF_STREAM() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize) {\n        response.setBody(content);\n        response.setSocketPolicy(DISCONNECT_AT_END);\n        response.removeHeader(\"Content-Length\");\n      }\n    };\n\n    abstract void setBody(MockResponse response, Buffer content, int chunkSize) throws IOException;\n\n    void setBody(MockResponse response, String content, int chunkSize) throws IOException {\n      setBody(response, new Buffer().writeUtf8(content), chunkSize);\n    }\n  }\n\n  /** Returns a gzipped copy of {@code bytes}. */\n  public Buffer gzip(String data) throws IOException {\n    Buffer result = new Buffer();\n    BufferedSink sink = Okio.buffer(new GzipSink(result));\n    sink.writeUtf8(data);\n    sink.close();\n    return result;\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/com/squareup/okhttp/CallTest.java",
    "content": "/*\n * Copyright (C) 2013 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.squareup.okhttp;\n\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.DelegatingSSLSocketFactory;\nimport co.paralleluniverse.fibers.okhttp.test.utils.FiberOkHttpClientTestWrapper;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.*;\nimport com.squareup.okhttp.internal.SslContextBuilder;\nimport com.squareup.okhttp.internal.Util;\nimport com.squareup.okhttp.internal.Version;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.http.FakeDns;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.io.InMemoryFileSystem;\nimport com.squareup.okhttp.mockwebserver.Dispatcher;\nimport com.squareup.okhttp.mockwebserver.MockResponse;\nimport com.squareup.okhttp.mockwebserver.MockWebServer;\nimport com.squareup.okhttp.mockwebserver.RecordedRequest;\nimport com.squareup.okhttp.mockwebserver.SocketPolicy;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.testing.RecordingHostnameVerifier;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InterruptedIOException;\nimport java.net.CookieManager;\nimport java.net.HttpCookie;\nimport java.net.HttpURLConnection;\nimport java.net.InetAddress;\nimport java.net.InetSocketAddress;\nimport java.net.ProtocolException;\nimport java.net.ServerSocket;\nimport java.net.UnknownServiceException;\nimport java.security.cert.Certificate;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.SynchronousQueue;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicReference;\nimport javax.net.ServerSocketFactory;\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLHandshakeException;\nimport javax.net.ssl.SSLPeerUnverifiedException;\nimport javax.net.ssl.SSLProtocolException;\nimport javax.net.ssl.SSLSocket;\nimport javax.net.ssl.SSLSocketFactory;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.BufferedSource;\nimport okio.GzipSink;\nimport okio.Okio;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.TestRule;\nimport org.junit.rules.Timeout;\n\nimport static com.squareup.okhttp.internal.Internal.logger;\nimport static java.net.CookiePolicy.ACCEPT_ORIGINAL_SERVER;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotSame;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\npublic final class CallTest {\n  @Rule public final TestRule timeout = new Timeout(30_000);\n  @Rule public final MockWebServer server = new MockWebServer();\n  @Rule public final MockWebServer server2 = new MockWebServer();\n  @Rule public final InMemoryFileSystem fileSystem = new InMemoryFileSystem();\n\n  private SSLContext sslContext = SslContextBuilder.localhost();\n  private OkHttpClient client = new FiberOkHttpClientTestWrapper();\n  private RecordingCallback callback = new RecordingCallback();\n  private TestLogHandler logHandler = new TestLogHandler();\n  private Cache cache = new Cache(new File(\"/cache/\"), Integer.MAX_VALUE, fileSystem);\n  private ServerSocket nullServer;\n\n  @Before public void setUp() throws Exception {\n    logger.addHandler(logHandler);\n  }\n\n  @After public void tearDown() throws Exception {\n    cache.delete();\n    Util.closeQuietly(nullServer);\n    logger.removeHandler(logHandler);\n  }\n\n  @Test public void get() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\").addHeader(\"Content-Type: text/plain\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"User-Agent\", \"SyncApiTest\")\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertSuccessful()\n        .assertHeader(\"Content-Type\", \"text/plain\")\n        .assertBody(\"abc\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"GET\", recordedRequest.getMethod());\n    assertEquals(\"SyncApiTest\", recordedRequest.getHeader(\"User-Agent\"));\n    assertEquals(0, recordedRequest.getBody().size());\n    assertNull(recordedRequest.getHeader(\"Content-Length\"));\n  }\n\n  @Test public void buildRequestUsingHttpUrl() throws Exception {\n    server.enqueue(new MockResponse());\n\n    HttpUrl httpUrl = server.url(\"/\");\n    Request request = new Request.Builder()\n        .url(httpUrl)\n        .build();\n    assertEquals(httpUrl, request.httpUrl());\n\n    executeSynchronously(request).assertSuccessful();\n  }\n\n  @Test public void invalidScheme() throws Exception {\n    Request.Builder requestBuilder = new Request.Builder();\n    try {\n      requestBuilder.url(\"ftp://hostname/path\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertEquals(expected.getMessage(), \"unexpected url: ftp://hostname/path\");\n    }\n  }\n\n  @Test public void invalidPort() throws Exception {\n    Request.Builder requestBuilder = new Request.Builder();\n    try {\n      requestBuilder.url(\"http://localhost:65536/\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n      assertEquals(expected.getMessage(), \"unexpected url: http://localhost:65536/\");\n    }\n  }\n\n  @Test public void getReturns500() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(500));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(500)\n        .assertNotSuccessful();\n  }\n\n  @Test public void get_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    get();\n  }\n\n  @Test public void get_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    get();\n  }\n\n  @Test public void repeatedHeaderNames() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"B\", \"123\")\n        .addHeader(\"B\", \"234\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .addHeader(\"A\", \"345\")\n        .addHeader(\"A\", \"456\")\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertHeader(\"B\", \"123\", \"234\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(Arrays.asList(\"345\", \"456\"), recordedRequest.getHeaders().values(\"A\"));\n  }\n\n  @Test public void repeatedHeaderNames_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    repeatedHeaderNames();\n  }\n\n  @Test public void repeatedHeaderNames_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    repeatedHeaderNames();\n  }\n\n  @Test public void getWithRequestBody() throws Exception {\n    server.enqueue(new MockResponse());\n\n    try {\n      new Request.Builder().method(\"GET\", RequestBody.create(MediaType.parse(\"text/plain\"), \"abc\"));\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void head() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Content-Type: text/plain\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .head()\n        .header(\"User-Agent\", \"SyncApiTest\")\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertHeader(\"Content-Type\", \"text/plain\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"HEAD\", recordedRequest.getMethod());\n    assertEquals(\"SyncApiTest\", recordedRequest.getHeader(\"User-Agent\"));\n    assertEquals(0, recordedRequest.getBody().size());\n    assertNull(recordedRequest.getHeader(\"Content-Length\"));\n  }\n\n  @Test public void head_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    head();\n  }\n\n  @Test public void head_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    head();\n  }\n\n  @Test public void post() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .post(RequestBody.create(MediaType.parse(\"text/plain\"), \"def\"))\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertBody(\"abc\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"POST\", recordedRequest.getMethod());\n    assertEquals(\"def\", recordedRequest.getBody().readUtf8());\n    assertEquals(\"3\", recordedRequest.getHeader(\"Content-Length\"));\n    assertEquals(\"text/plain; charset=utf-8\", recordedRequest.getHeader(\"Content-Type\"));\n  }\n\n  @Test public void post_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    post();\n  }\n\n  @Test public void post_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    post();\n  }\n\n  @Test public void postZeroLength() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .method(\"POST\", RequestBody.create(null, new byte[0]))\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertBody(\"abc\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"POST\", recordedRequest.getMethod());\n    assertEquals(0, recordedRequest.getBody().size());\n    assertEquals(\"0\", recordedRequest.getHeader(\"Content-Length\"));\n    assertEquals(null, recordedRequest.getHeader(\"Content-Type\"));\n  }\n\n  @Test public void postZeroLength_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    postZeroLength();\n  }\n\n  @Test public void postZerolength_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    postZeroLength();\n  }\n\n  @Test public void postBodyRetransmittedAfterAuthorizationFail() throws Exception {\n    postBodyRetransmittedAfterAuthorizationFail(\"abc\");\n  }\n\n  @Test public void postBodyRetransmittedAfterAuthorizationFail_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    postBodyRetransmittedAfterAuthorizationFail(\"abc\");\n  }\n\n  @Test public void postBodyRetransmittedAfterAuthorizationFail_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    postBodyRetransmittedAfterAuthorizationFail(\"abc\");\n  }\n\n  /** Don't explode when resending an empty post. https://github.com/square/okhttp/issues/1131 */\n  @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail() throws Exception {\n    postBodyRetransmittedAfterAuthorizationFail(\"\");\n  }\n\n  @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    postBodyRetransmittedAfterAuthorizationFail(\"\");\n  }\n\n  @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    postBodyRetransmittedAfterAuthorizationFail(\"\");\n  }\n\n  private void postBodyRetransmittedAfterAuthorizationFail(String body) throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(401));\n    server.enqueue(new MockResponse());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .method(\"POST\", RequestBody.create(null, body))\n        .build();\n\n    String credential = Credentials.basic(\"jesse\", \"secret\");\n    client.setAuthenticator(new RecordingOkAuthenticator(credential));\n\n    Response response = client.newCall(request).execute();\n    assertEquals(200, response.code());\n\n    RecordedRequest recordedRequest1 = server.takeRequest();\n    assertEquals(\"POST\", recordedRequest1.getMethod());\n    assertEquals(body, recordedRequest1.getBody().readUtf8());\n    assertNull(recordedRequest1.getHeader(\"Authorization\"));\n\n    RecordedRequest recordedRequest2 = server.takeRequest();\n    assertEquals(\"POST\", recordedRequest2.getMethod());\n    assertEquals(body, recordedRequest2.getBody().readUtf8());\n    assertEquals(credential, recordedRequest2.getHeader(\"Authorization\"));\n  }\n\n  @Test public void attemptAuthorization20Times() throws Exception {\n    for (int i = 0; i < 20; i++) {\n      server.enqueue(new MockResponse().setResponseCode(401));\n    }\n    server.enqueue(new MockResponse().setBody(\"Success!\"));\n\n    String credential = Credentials.basic(\"jesse\", \"secret\");\n    client.setAuthenticator(new RecordingOkAuthenticator(credential));\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertBody(\"Success!\");\n  }\n\n  @Test public void doesNotAttemptAuthorization21Times() throws Exception {\n    for (int i = 0; i < 21; i++) {\n      server.enqueue(new MockResponse().setResponseCode(401));\n    }\n\n    String credential = Credentials.basic(\"jesse\", \"secret\");\n    client.setAuthenticator(new RecordingOkAuthenticator(credential));\n\n    try {\n      client.newCall(new Request.Builder().url(server.url(\"/0\")).build()).execute();\n      fail();\n    } catch (IOException expected) {\n      assertEquals(\"Too many follow-up requests: 21\", expected.getMessage());\n    }\n  }\n\n  @Test public void delete() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .delete()\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertBody(\"abc\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"DELETE\", recordedRequest.getMethod());\n    assertEquals(0, recordedRequest.getBody().size());\n    assertEquals(\"0\", recordedRequest.getHeader(\"Content-Length\"));\n    assertEquals(null, recordedRequest.getHeader(\"Content-Type\"));\n  }\n\n  @Test public void delete_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    delete();\n  }\n\n  @Test public void delete_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    delete();\n  }\n\n  @Test public void deleteWithRequestBody() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .method(\"DELETE\", RequestBody.create(MediaType.parse(\"text/plain\"), \"def\"))\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertBody(\"abc\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"DELETE\", recordedRequest.getMethod());\n    assertEquals(\"def\", recordedRequest.getBody().readUtf8());\n  }\n\n  @Test public void put() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .put(RequestBody.create(MediaType.parse(\"text/plain\"), \"def\"))\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertBody(\"abc\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"PUT\", recordedRequest.getMethod());\n    assertEquals(\"def\", recordedRequest.getBody().readUtf8());\n    assertEquals(\"3\", recordedRequest.getHeader(\"Content-Length\"));\n    assertEquals(\"text/plain; charset=utf-8\", recordedRequest.getHeader(\"Content-Type\"));\n  }\n\n  @Test public void put_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    put();\n  }\n\n  @Test public void put_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    put();\n  }\n\n  @Test public void patch() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .patch(RequestBody.create(MediaType.parse(\"text/plain\"), \"def\"))\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertBody(\"abc\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"PATCH\", recordedRequest.getMethod());\n    assertEquals(\"def\", recordedRequest.getBody().readUtf8());\n    assertEquals(\"3\", recordedRequest.getHeader(\"Content-Length\"));\n    assertEquals(\"text/plain; charset=utf-8\", recordedRequest.getHeader(\"Content-Type\"));\n  }\n\n  @Test public void patch_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    patch();\n  }\n\n  @Test public void patch_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    patch();\n  }\n\n  @Test public void unspecifiedRequestBodyContentTypeDoesNotGetDefault() throws Exception {\n    server.enqueue(new MockResponse());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .method(\"POST\", RequestBody.create(null, \"abc\"))\n        .build();\n\n    executeSynchronously(request).assertCode(200);\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(null, recordedRequest.getHeader(\"Content-Type\"));\n    assertEquals(\"3\", recordedRequest.getHeader(\"Content-Length\"));\n    assertEquals(\"abc\", recordedRequest.getBody().readUtf8());\n  }\n\n  @Test public void illegalToExecuteTwice() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(\"abc\")\n        .addHeader(\"Content-Type: text/plain\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"User-Agent\", \"SyncApiTest\")\n        .build();\n\n    Call call = client.newCall(request);\n    call.execute();\n\n    try {\n      call.execute();\n      fail();\n    } catch (IllegalStateException e){\n      assertEquals(\"Already Executed\", e.getMessage());\n    }\n\n    try {\n      call.enqueue(callback);\n      fail();\n    } catch (IllegalStateException e){\n      assertEquals(\"Already Executed\", e.getMessage());\n    }\n\n    assertEquals(\"SyncApiTest\", server.takeRequest().getHeader(\"User-Agent\"));\n  }\n\n  @Test public void illegalToExecuteTwice_Async() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(\"abc\")\n        .addHeader(\"Content-Type: text/plain\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"User-Agent\", \"SyncApiTest\")\n        .build();\n\n    Call call = client.newCall(request);\n    call.enqueue(callback);\n\n    try {\n      call.execute();\n      fail();\n    } catch (IllegalStateException e){\n      assertEquals(\"Already Executed\", e.getMessage());\n    }\n\n    try {\n      call.enqueue(callback);\n      fail();\n    } catch (IllegalStateException e){\n      assertEquals(\"Already Executed\", e.getMessage());\n    }\n\n    assertEquals(\"SyncApiTest\", server.takeRequest().getHeader(\"User-Agent\"));\n  }\n\n  @Test public void get_Async() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(\"abc\")\n        .addHeader(\"Content-Type: text/plain\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"User-Agent\", \"AsyncApiTest\")\n        .build();\n    client.newCall(request).enqueue(callback);\n\n    callback.await(request.httpUrl())\n        .assertCode(200)\n        .assertHeader(\"Content-Type\", \"text/plain\")\n        .assertBody(\"abc\");\n\n    assertEquals(\"AsyncApiTest\", server.takeRequest().getHeader(\"User-Agent\"));\n  }\n\n  @Test public void exceptionThrownByOnResponseIsRedactedAndLogged() throws Exception {\n    server.enqueue(new MockResponse());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/secret\"))\n        .build();\n\n    client.newCall(request).enqueue(new Callback() {\n      @Override public void onFailure(Request request, IOException e) {\n        fail();\n      }\n\n      @Override public void onResponse(Response response) throws IOException {\n        throw new IOException(\"a\");\n      }\n    });\n\n    assertEquals(\"INFO: Callback failure for call to \" + server.url(\"/\") + \"...\",\n        logHandler.take());\n  }\n\n  @Test public void connectionPooling() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n    server.enqueue(new MockResponse().setBody(\"ghi\"));\n\n    executeSynchronously(new Request.Builder().url(server.url(\"/a\")).build())\n        .assertBody(\"abc\");\n\n    executeSynchronously(new Request.Builder().url(server.url(\"/b\")).build())\n        .assertBody(\"def\");\n\n    executeSynchronously(new Request.Builder().url(server.url(\"/c\")).build())\n        .assertBody(\"ghi\");\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n    assertEquals(2, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void connectionPooling_Async() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n    server.enqueue(new MockResponse().setBody(\"ghi\"));\n\n    client.newCall(new Request.Builder().url(server.url(\"/a\")).build()).enqueue(callback);\n    callback.await(server.url(\"/a\")).assertBody(\"abc\");\n\n    client.newCall(new Request.Builder().url(server.url(\"/b\")).build()).enqueue(callback);\n    callback.await(server.url(\"/b\")).assertBody(\"def\");\n\n    client.newCall(new Request.Builder().url(server.url(\"/c\")).build()).enqueue(callback);\n    callback.await(server.url(\"/c\")).assertBody(\"ghi\");\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n    assertEquals(2, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void connectionReuseWhenResponseBodyConsumed_Async() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n\n    Request request = new Request.Builder().url(server.url(\"/a\")).build();\n    client.newCall(request).enqueue(new Callback() {\n      @Override public void onFailure(Request request, IOException e) {\n        throw new AssertionError();\n      }\n\n      @Override public void onResponse(Response response) throws IOException {\n        InputStream bytes = response.body().byteStream();\n        assertEquals('a', bytes.read());\n        assertEquals('b', bytes.read());\n        assertEquals('c', bytes.read());\n\n        // This request will share a connection with 'A' cause it's all done.\n        client.newCall(new Request.Builder().url(server.url(\"/b\")).build()).enqueue(callback);\n      }\n    });\n\n    callback.await(server.url(\"/b\")).assertCode(200).assertBody(\"def\");\n    assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection.\n    assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reuse!\n  }\n\n  @Test public void timeoutsUpdatedOnReusedConnections() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setBody(\"def\").throttleBody(1, 750, TimeUnit.MILLISECONDS));\n\n    // First request: time out after 1000ms.\n    client.setReadTimeout(1000, TimeUnit.MILLISECONDS);\n    executeSynchronously(new Request.Builder().url(server.url(\"/a\")).build()).assertBody(\"abc\");\n\n    // Second request: time out after 250ms.\n    client.setReadTimeout(250, TimeUnit.MILLISECONDS);\n    Request request = new Request.Builder().url(server.url(\"/b\")).build();\n    Response response = client.newCall(request).execute();\n    BufferedSource bodySource = response.body().source();\n    assertEquals('d', bodySource.readByte());\n\n    // The second byte of this request will be delayed by 750ms so we should time out after 250ms.\n    long startNanos = System.nanoTime();\n    try {\n      bodySource.readByte();\n      fail();\n    } catch (IOException expected) {\n      // Timed out as expected.\n      long elapsedNanos = System.nanoTime() - startNanos;\n      long elapsedMillis = TimeUnit.NANOSECONDS.toMillis(elapsedNanos);\n      assertTrue(String.format(\"Timed out: %sms\", elapsedMillis), elapsedMillis < 500);\n    }\n  }\n\n  // https://github.com/square/okhttp/issues/442\n  @Test public void timeoutsNotRetried() throws Exception {\n    server.enqueue(new MockResponse()\n        .setSocketPolicy(SocketPolicy.NO_RESPONSE));\n    server.enqueue(new MockResponse()\n        .setBody(\"unreachable!\"));\n\n    client.setDns(new DoubleInetAddressDns());\n    client.setReadTimeout(100, TimeUnit.MILLISECONDS);\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    try {\n      // If this succeeds, too many requests were made.\n      client.newCall(request).execute();\n      fail();\n    } catch (InterruptedIOException expected) {\n    }\n  }\n\n  // https://github.com/square/okhttp/issues/1801\n  @Test public void asyncCallEngineInitialized() throws Exception {\n    OkHttpClient c = new OkHttpClient();\n    c.interceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        throw new IOException();\n      }\n    });\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    c.newCall(request).enqueue(callback);\n    RecordedResponse response = callback.await(request.httpUrl());\n    assertEquals(request, response.request);\n  }\n\n  @Test public void reusedSinksGetIndependentTimeoutInstances() throws Exception {\n    server.enqueue(new MockResponse());\n    server.enqueue(new MockResponse());\n\n    // Call 1: set a deadline on the request body.\n    RequestBody requestBody1 = new RequestBody() {\n      @Override public MediaType contentType() {\n        return MediaType.parse(\"text/plain\");\n      }\n      @Override public void writeTo(BufferedSink sink) throws IOException {\n        sink.writeUtf8(\"abc\");\n        sink.timeout().deadline(5, TimeUnit.SECONDS);\n      }\n    };\n    Request request1 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .method(\"POST\", requestBody1)\n        .build();\n    Response response1 = client.newCall(request1).execute();\n    assertEquals(200, response1.code());\n\n    // Call 2: check for the absence of a deadline on the request body.\n    RequestBody requestBody2 = new RequestBody() {\n      @Override public MediaType contentType() {\n        return MediaType.parse(\"text/plain\");\n      }\n      @Override public void writeTo(BufferedSink sink) throws IOException {\n        assertFalse(sink.timeout().hasDeadline());\n        sink.writeUtf8(\"def\");\n      }\n    };\n    Request request2 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .method(\"POST\", requestBody2)\n        .build();\n    Response response2 = client.newCall(request2).execute();\n    assertEquals(200, response2.code());\n\n    // Use sequence numbers to confirm the connection was pooled.\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void reusedSourcesGetIndependentTimeoutInstances() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n\n    // Call 1: set a deadline on the response body.\n    Request request1 = new Request.Builder().url(server.url(\"/\")).build();\n    Response response1 = client.newCall(request1).execute();\n    BufferedSource body1 = response1.body().source();\n    assertEquals(\"abc\", body1.readUtf8());\n    body1.timeout().deadline(5, TimeUnit.SECONDS);\n\n    // Call 2: check for the absence of a deadline on the request body.\n    Request request2 = new Request.Builder().url(server.url(\"/\")).build();\n    Response response2 = client.newCall(request2).execute();\n    BufferedSource body2 = response2.body().source();\n    assertEquals(\"def\", body2.readUtf8());\n    assertFalse(body2.timeout().hasDeadline());\n\n    // Use sequence numbers to confirm the connection was pooled.\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void tls() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse()\n        .setBody(\"abc\")\n        .addHeader(\"Content-Type: text/plain\"));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n\n    executeSynchronously(new Request.Builder().url(server.url(\"/\")).build())\n        .assertHandshake();\n  }\n\n  @Test public void tls_Async() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse()\n        .setBody(\"abc\")\n        .addHeader(\"Content-Type: text/plain\"));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request).enqueue(callback);\n\n    callback.await(request.httpUrl()).assertHandshake();\n  }\n\n  @Test public void recoverWhenRetryOnConnectionFailureIsTrue() throws Exception {\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_START));\n    server.enqueue(new MockResponse().setBody(\"retry success\"));\n\n    client.setDns(new DoubleInetAddressDns());\n    assertTrue(client.getRetryOnConnectionFailure());\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"retry success\", response.body().string());\n  }\n\n  @Test public void noRecoverWhenRetryOnConnectionFailureIsFalse() throws Exception {\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_START));\n    server.enqueue(new MockResponse().setBody(\"unreachable!\"));\n\n    client.setDns(new DoubleInetAddressDns());\n    client.setRetryOnConnectionFailure(false);\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    try {\n      // If this succeeds, too many requests were made.\n      client.newCall(request).execute();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void recoverFromTlsHandshakeFailure() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    suppressTlsFallbackScsv(client);\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n    client.setDns(new SingleInetAddressDns());\n\n    executeSynchronously(new Request.Builder().url(server.url(\"/\")).build())\n        .assertBody(\"abc\");\n  }\n\n  @Test public void recoverFromTlsHandshakeFailure_tlsFallbackScsvEnabled() throws Exception {\n    final String tlsFallbackScsv = \"TLS_FALLBACK_SCSV\";\n    List<String> supportedCiphers =\n        Arrays.asList(sslContext.getSocketFactory().getSupportedCipherSuites());\n    if (!supportedCiphers.contains(tlsFallbackScsv)) {\n      // This only works if the client socket supports TLS_FALLBACK_SCSV.\n      return;\n    }\n\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));\n\n    RecordingSSLSocketFactory clientSocketFactory =\n        new RecordingSSLSocketFactory(sslContext.getSocketFactory());\n    client.setSslSocketFactory(clientSocketFactory);\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n    client.setDns(new SingleInetAddressDns());\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (SSLHandshakeException expected) {\n    }\n\n    List<SSLSocket> clientSockets = clientSocketFactory.getSocketsCreated();\n    SSLSocket firstSocket = clientSockets.get(0);\n    assertFalse(Arrays.asList(firstSocket.getEnabledCipherSuites()).contains(tlsFallbackScsv));\n    SSLSocket secondSocket = clientSockets.get(1);\n    assertTrue(Arrays.asList(secondSocket.getEnabledCipherSuites()).contains(tlsFallbackScsv));\n  }\n\n  @Test public void recoverFromTlsHandshakeFailure_Async() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    suppressTlsFallbackScsv(client);\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request).enqueue(callback);\n\n    callback.await(request.httpUrl()).assertBody(\"abc\");\n  }\n\n  @Test public void noRecoveryFromTlsHandshakeFailureWhenTlsFallbackIsDisabled() throws Exception {\n    client.setConnectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT));\n\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));\n\n    suppressTlsFallbackScsv(client);\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n    client.setDns(new SingleInetAddressDns());\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (SSLProtocolException expected) {\n      // RI response to the FAIL_HANDSHAKE\n    } catch (SSLHandshakeException expected) {\n      // Android's response to the FAIL_HANDSHAKE\n    }\n  }\n\n  @Test public void cleartextCallsFailWhenCleartextIsDisabled() throws Exception {\n    // Configure the client with only TLS configurations. No cleartext!\n    client.setConnectionSpecs(\n        Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS));\n\n    server.enqueue(new MockResponse());\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (UnknownServiceException expected) {\n      assertTrue(expected.getMessage().contains(\"CLEARTEXT communication not supported\"));\n    }\n  }\n\n  @Test public void setFollowSslRedirectsFalse() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setResponseCode(301).addHeader(\"Location: http://square.com\"));\n\n    client.setFollowSslRedirects(false);\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    Response response = client.newCall(request).execute();\n    assertEquals(301, response.code());\n  }\n\n  @Test public void matchingPinnedCertificate() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse());\n    server.enqueue(new MockResponse());\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n\n    // Make a first request without certificate pinning. Use it to collect certificates to pin.\n    Request request1 = new Request.Builder().url(server.url(\"/\")).build();\n    Response response1 = client.newCall(request1).execute();\n    CertificatePinner.Builder certificatePinnerBuilder = new CertificatePinner.Builder();\n    for (Certificate certificate : response1.handshake().peerCertificates()) {\n      certificatePinnerBuilder.add(server.getHostName(), CertificatePinner.pin(certificate));\n    }\n\n    // Make another request with certificate pinning. It should complete normally.\n    client.setCertificatePinner(certificatePinnerBuilder.build());\n    Request request2 = new Request.Builder().url(server.url(\"/\")).build();\n    Response response2 = client.newCall(request2).execute();\n    assertNotSame(response2.handshake(), response1.handshake());\n  }\n\n  @Test public void unmatchingPinnedCertificate() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse());\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n\n    // Pin publicobject.com's cert.\n    client.setCertificatePinner(new CertificatePinner.Builder()\n        .add(server.getHostName(), \"sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=\")\n        .build());\n\n    // When we pin the wrong certificate, connectivity fails.\n    Request request = new Request.Builder().url(server.url(\"/\")).build();\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (SSLPeerUnverifiedException expected) {\n      assertTrue(expected.getMessage().startsWith(\"Certificate pinning failure!\"));\n    }\n  }\n\n  @Test public void post_Async() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .post(RequestBody.create(MediaType.parse(\"text/plain\"), \"def\"))\n        .build();\n    client.newCall(request).enqueue(callback);\n\n    callback.await(request.httpUrl())\n        .assertCode(200)\n        .assertBody(\"abc\");\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertEquals(\"def\", recordedRequest.getBody().readUtf8());\n    assertEquals(\"3\", recordedRequest.getHeader(\"Content-Length\"));\n    assertEquals(\"text/plain; charset=utf-8\", recordedRequest.getHeader(\"Content-Type\"));\n  }\n\n  @Test public void postBodyRetransmittedOnFailureRecovery() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AFTER_REQUEST));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n\n    // Seed the connection pool so we have something that can fail.\n    Request request1 = new Request.Builder().url(server.url(\"/\")).build();\n    Response response1 = client.newCall(request1).execute();\n    assertEquals(\"abc\", response1.body().string());\n\n    Request request2 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .post(RequestBody.create(MediaType.parse(\"text/plain\"), \"body!\"))\n        .build();\n    Response response2 = client.newCall(request2).execute();\n    assertEquals(\"def\", response2.body().string());\n\n    RecordedRequest get = server.takeRequest();\n    assertEquals(0, get.getSequenceNumber());\n\n    RecordedRequest post1 = server.takeRequest();\n    assertEquals(\"body!\", post1.getBody().readUtf8());\n    assertEquals(1, post1.getSequenceNumber());\n\n    RecordedRequest post2 = server.takeRequest();\n    assertEquals(\"body!\", post2.getBody().readUtf8());\n    assertEquals(0, post2.getSequenceNumber());\n  }\n\n  @Test public void cacheHit() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"ETag: v1\")\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Charset\")\n        .setBody(\"A\"));\n\n    client.setCache(cache);\n\n    // Store a response in the cache.\n    HttpUrl url = server.url(\"/\");\n    Request cacheStoreRequest = new Request.Builder()\n        .url(url)\n        .addHeader(\"Accept-Language\", \"fr-CA\")\n        .addHeader(\"Accept-Charset\", \"UTF-8\")\n        .build();\n    executeSynchronously(cacheStoreRequest)\n        .assertCode(200)\n        .assertBody(\"A\");\n    assertNull(server.takeRequest().getHeader(\"If-None-Match\"));\n\n    // Hit that stored response.\n    Request cacheHitRequest = new Request.Builder()\n        .url(url)\n        .addHeader(\"Accept-Language\", \"en-US\") // Different, but Vary says it doesn't matter.\n        .addHeader(\"Accept-Charset\", \"UTF-8\")\n        .build();\n    RecordedResponse cacheHit = executeSynchronously(cacheHitRequest);\n\n    // Check the merged response. The request is the application's original request.\n    cacheHit.assertCode(200)\n        .assertBody(\"A\")\n        .assertHeader(\"ETag\", \"v1\")\n        .assertRequestUrl(cacheStoreRequest.url())\n        .assertRequestHeader(\"Accept-Language\", \"en-US\")\n        .assertRequestHeader(\"Accept-Charset\", \"UTF-8\");\n\n    // Check the cached response. Its request contains only the saved Vary headers.\n    cacheHit.cacheResponse()\n        .assertCode(200)\n        .assertHeader(\"ETag\", \"v1\")\n        .assertRequestMethod(\"GET\")\n        .assertRequestUrl(cacheStoreRequest.url())\n        .assertRequestHeader(\"Accept-Language\")\n        .assertRequestHeader(\"Accept-Charset\", \"UTF-8\");\n\n    cacheHit.assertNoNetworkResponse();\n  }\n\n  @Test public void conditionalCacheHit() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"ETag: v1\")\n        .addHeader(\"Vary: Accept-Charset\")\n        .addHeader(\"Donut: a\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().clearHeaders()\n        .addHeader(\"Donut: b\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    client.setCache(cache);\n\n    // Store a response in the cache.\n    HttpUrl url = server.url(\"/\");\n    Request cacheStoreRequest = new Request.Builder()\n        .url(url)\n        .addHeader(\"Accept-Language\", \"fr-CA\")\n        .addHeader(\"Accept-Charset\", \"UTF-8\")\n        .build();\n    executeSynchronously(cacheStoreRequest)\n        .assertCode(200)\n        .assertHeader(\"Donut\", \"a\")\n        .assertBody(\"A\");\n    assertNull(server.takeRequest().getHeader(\"If-None-Match\"));\n\n    // Hit that stored response.\n    Request cacheHitRequest = new Request.Builder()\n        .url(url)\n        .addHeader(\"Accept-Language\", \"en-US\") // Different, but Vary says it doesn't matter.\n        .addHeader(\"Accept-Charset\", \"UTF-8\")\n        .build();\n    RecordedResponse cacheHit = executeSynchronously(cacheHitRequest);\n    assertEquals(\"v1\", server.takeRequest().getHeader(\"If-None-Match\"));\n\n    // Check the merged response. The request is the application's original request.\n    cacheHit.assertCode(200)\n        .assertBody(\"A\")\n        .assertHeader(\"Donut\", \"b\")\n        .assertRequestUrl(cacheStoreRequest.url())\n        .assertRequestHeader(\"Accept-Language\", \"en-US\")\n        .assertRequestHeader(\"Accept-Charset\", \"UTF-8\")\n        .assertRequestHeader(\"If-None-Match\"); // No If-None-Match on the user's request.\n\n    // Check the cached response. Its request contains only the saved Vary headers.\n    cacheHit.cacheResponse()\n        .assertCode(200)\n        .assertHeader(\"Donut\", \"a\")\n        .assertHeader(\"ETag\", \"v1\")\n        .assertRequestUrl(cacheStoreRequest.url())\n        .assertRequestHeader(\"Accept-Language\") // No Vary on Accept-Language.\n        .assertRequestHeader(\"Accept-Charset\", \"UTF-8\") // Because of Vary on Accept-Charset.\n        .assertRequestHeader(\"If-None-Match\"); // This wasn't present in the original request.\n\n    // Check the network response. It has the caller's request, plus some caching headers.\n    cacheHit.networkResponse()\n        .assertCode(304)\n        .assertHeader(\"Donut\", \"b\")\n        .assertRequestHeader(\"Accept-Language\", \"en-US\")\n        .assertRequestHeader(\"Accept-Charset\", \"UTF-8\")\n        .assertRequestHeader(\"If-None-Match\", \"v1\"); // If-None-Match in the validation request.\n  }\n\n  @Test public void conditionalCacheHit_Async() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\").addHeader(\"ETag: v1\"));\n    server.enqueue(new MockResponse()\n        .clearHeaders()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    client.setCache(cache);\n\n    Request request1 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request1).enqueue(callback);\n    callback.await(request1.httpUrl()).assertCode(200).assertBody(\"A\");\n    assertNull(server.takeRequest().getHeader(\"If-None-Match\"));\n\n    Request request2 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request2).enqueue(callback);\n    callback.await(request2.httpUrl()).assertCode(200).assertBody(\"A\");\n    assertEquals(\"v1\", server.takeRequest().getHeader(\"If-None-Match\"));\n  }\n\n  @Test public void conditionalCacheMiss() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"ETag: v1\")\n        .addHeader(\"Vary: Accept-Charset\")\n        .addHeader(\"Donut: a\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Donut: b\")\n        .setBody(\"B\"));\n\n    client.setCache(cache);\n\n    Request cacheStoreRequest = new Request.Builder()\n        .url(server.url(\"/\"))\n        .addHeader(\"Accept-Language\", \"fr-CA\")\n        .addHeader(\"Accept-Charset\", \"UTF-8\")\n        .build();\n    executeSynchronously(cacheStoreRequest)\n        .assertCode(200)\n        .assertBody(\"A\");\n    assertNull(server.takeRequest().getHeader(\"If-None-Match\"));\n\n    Request cacheMissRequest = new Request.Builder()\n        .url(server.url(\"/\"))\n        .addHeader(\"Accept-Language\", \"en-US\") // Different, but Vary says it doesn't matter.\n        .addHeader(\"Accept-Charset\", \"UTF-8\")\n        .build();\n    RecordedResponse cacheHit = executeSynchronously(cacheMissRequest);\n    assertEquals(\"v1\", server.takeRequest().getHeader(\"If-None-Match\"));\n\n    // Check the user response. It has the application's original request.\n    cacheHit.assertCode(200)\n        .assertBody(\"B\")\n        .assertHeader(\"Donut\", \"b\")\n        .assertRequestUrl(cacheStoreRequest.url());\n\n    // Check the cache response. Even though it's a miss, we used the cache.\n    cacheHit.cacheResponse()\n        .assertCode(200)\n        .assertHeader(\"Donut\", \"a\")\n        .assertHeader(\"ETag\", \"v1\")\n        .assertRequestUrl(cacheStoreRequest.url());\n\n    // Check the network response. It has the network request, plus caching headers.\n    cacheHit.networkResponse()\n        .assertCode(200)\n        .assertHeader(\"Donut\", \"b\")\n        .assertRequestHeader(\"If-None-Match\", \"v1\")  // If-None-Match in the validation request.\n        .assertRequestUrl(cacheStoreRequest.url());\n  }\n\n  @Test public void conditionalCacheMiss_Async() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\").addHeader(\"ETag: v1\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    client.setCache(cache);\n\n    Request request1 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request1).enqueue(callback);\n    callback.await(request1.httpUrl()).assertCode(200).assertBody(\"A\");\n    assertNull(server.takeRequest().getHeader(\"If-None-Match\"));\n\n    Request request2 = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n    client.newCall(request2).enqueue(callback);\n    callback.await(request2.httpUrl()).assertCode(200).assertBody(\"B\");\n    assertEquals(\"v1\", server.takeRequest().getHeader(\"If-None-Match\"));\n  }\n\n  @Test public void onlyIfCachedReturns504WhenNotCached() throws Exception {\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Cache-Control\", \"only-if-cached\")\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(504)\n        .assertBody(\"\")\n        .assertNoNetworkResponse()\n        .assertNoCacheResponse();\n  }\n\n  @Test public void redirect() throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(301)\n        .addHeader(\"Location: /b\")\n        .addHeader(\"Test\", \"Redirect from /a to /b\")\n        .setBody(\"/a has moved!\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(302)\n        .addHeader(\"Location: /c\")\n        .addHeader(\"Test\", \"Redirect from /b to /c\")\n        .setBody(\"/b has moved!\"));\n    server.enqueue(new MockResponse().setBody(\"C\"));\n\n    executeSynchronously(new Request.Builder().url(server.url(\"/a\")).build())\n        .assertCode(200)\n        .assertBody(\"C\")\n        .priorResponse()\n        .assertCode(302)\n        .assertHeader(\"Test\", \"Redirect from /b to /c\")\n        .priorResponse()\n        .assertCode(301)\n        .assertHeader(\"Test\", \"Redirect from /a to /b\");\n\n    assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection.\n    assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reused.\n    assertEquals(2, server.takeRequest().getSequenceNumber()); // Connection reused again!\n  }\n\n  @Test public void postRedirectsToGet() throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: /page2\")\n        .setBody(\"This page has moved!\"));\n    server.enqueue(new MockResponse().setBody(\"Page 2\"));\n\n    Response response = client.newCall(new Request.Builder()\n        .url(server.url(\"/page1\"))\n        .post(RequestBody.create(MediaType.parse(\"text/plain\"), \"Request Body\"))\n        .build()).execute();\n    assertEquals(\"Page 2\", response.body().string());\n\n    RecordedRequest page1 = server.takeRequest();\n    assertEquals(\"POST /page1 HTTP/1.1\", page1.getRequestLine());\n    assertEquals(\"Request Body\", page1.getBody().readUtf8());\n\n    RecordedRequest page2 = server.takeRequest();\n    assertEquals(\"GET /page2 HTTP/1.1\", page2.getRequestLine());\n  }\n\n  @Test public void redirectsDoNotIncludeTooManyCookies() throws Exception {\n    server2.enqueue(new MockResponse().setBody(\"Page 2\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: \" + server2.url(\"/\")));\n\n    CookieManager cookieManager = new CookieManager(null, ACCEPT_ORIGINAL_SERVER);\n    HttpCookie cookie = new HttpCookie(\"c\", \"cookie\");\n    cookie.setDomain(server.getCookieDomain());\n    cookie.setPath(\"/\");\n    String portList = Integer.toString(server.getPort());\n    cookie.setPortlist(portList);\n    cookieManager.getCookieStore().add(server.url(\"/\").uri(), cookie);\n    client.setCookieHandler(cookieManager);\n\n    Response response = client.newCall(new Request.Builder()\n        .url(server.url(\"/page1\"))\n        .build()).execute();\n    assertEquals(\"Page 2\", response.body().string());\n\n    RecordedRequest request1 = server.takeRequest();\n    assertEquals(\"$Version=\\\"1\\\"; c=\\\"cookie\\\";$Path=\\\"/\\\";$Domain=\\\"\"\n        + server.getCookieDomain()\n        + \"\\\";$Port=\\\"\"\n        + portList\n        + \"\\\"\", request1.getHeader(\"Cookie\"));\n\n    RecordedRequest request2 = server2.takeRequest();\n    assertNull(request2.getHeader(\"Cookie\"));\n  }\n\n  @Test public void redirectsDoNotIncludeTooManyAuthHeaders() throws Exception {\n    server2.enqueue(new MockResponse().setBody(\"Page 2\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(401));\n    server.enqueue(new MockResponse()\n        .setResponseCode(302)\n        .addHeader(\"Location: \" + server2.url(\"/b\")));\n\n    client.setAuthenticator(new RecordingOkAuthenticator(Credentials.basic(\"jesse\", \"secret\")));\n\n    Request request = new Request.Builder().url(server.url(\"/a\")).build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"Page 2\", response.body().string());\n\n    RecordedRequest redirectRequest = server2.takeRequest();\n    assertNull(redirectRequest.getHeader(\"Authorization\"));\n    assertEquals(\"/b\", redirectRequest.getPath());\n  }\n\n  @Test public void redirect_Async() throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(301)\n        .addHeader(\"Location: /b\")\n        .addHeader(\"Test\", \"Redirect from /a to /b\")\n        .setBody(\"/a has moved!\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(302)\n        .addHeader(\"Location: /c\")\n        .addHeader(\"Test\", \"Redirect from /b to /c\")\n        .setBody(\"/b has moved!\"));\n    server.enqueue(new MockResponse().setBody(\"C\"));\n\n    Request request = new Request.Builder().url(server.url(\"/a\")).build();\n    client.newCall(request).enqueue(callback);\n\n    callback.await(server.url(\"/c\"))\n        .assertCode(200)\n        .assertBody(\"C\")\n        .priorResponse()\n        .assertCode(302)\n        .assertHeader(\"Test\", \"Redirect from /b to /c\")\n        .priorResponse()\n        .assertCode(301)\n        .assertHeader(\"Test\", \"Redirect from /a to /b\");\n\n    assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection.\n    assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reused.\n    assertEquals(2, server.takeRequest().getSequenceNumber()); // Connection reused again!\n  }\n\n  @Test public void follow20Redirects() throws Exception {\n    for (int i = 0; i < 20; i++) {\n      server.enqueue(new MockResponse()\n          .setResponseCode(301)\n          .addHeader(\"Location: /\" + (i + 1))\n          .setBody(\"Redirecting to /\" + (i + 1)));\n    }\n    server.enqueue(new MockResponse().setBody(\"Success!\"));\n\n    executeSynchronously(new Request.Builder().url(server.url(\"/0\")).build())\n        .assertCode(200)\n        .assertBody(\"Success!\");\n  }\n\n  @Test public void follow20Redirects_Async() throws Exception {\n    for (int i = 0; i < 20; i++) {\n      server.enqueue(new MockResponse()\n          .setResponseCode(301)\n          .addHeader(\"Location: /\" + (i + 1))\n          .setBody(\"Redirecting to /\" + (i + 1)));\n    }\n    server.enqueue(new MockResponse().setBody(\"Success!\"));\n\n    Request request = new Request.Builder().url(server.url(\"/0\")).build();\n    client.newCall(request).enqueue(callback);\n    callback.await(server.url(\"/20\"))\n        .assertCode(200)\n        .assertBody(\"Success!\");\n  }\n\n  @Test public void doesNotFollow21Redirects() throws Exception {\n    for (int i = 0; i < 21; i++) {\n      server.enqueue(new MockResponse()\n          .setResponseCode(301)\n          .addHeader(\"Location: /\" + (i + 1))\n          .setBody(\"Redirecting to /\" + (i + 1)));\n    }\n\n    try {\n      client.newCall(new Request.Builder().url(server.url(\"/0\")).build()).execute();\n      fail();\n    } catch (IOException expected) {\n      assertEquals(\"Too many follow-up requests: 21\", expected.getMessage());\n    }\n  }\n\n  @Test public void doesNotFollow21Redirects_Async() throws Exception {\n    for (int i = 0; i < 21; i++) {\n      server.enqueue(new MockResponse()\n          .setResponseCode(301)\n          .addHeader(\"Location: /\" + (i + 1))\n          .setBody(\"Redirecting to /\" + (i + 1)));\n    }\n\n    Request request = new Request.Builder().url(server.url(\"/0\")).build();\n    client.newCall(request).enqueue(callback);\n    callback.await(server.url(\"/20\")).assertFailure(\"Too many follow-up requests: 21\");\n  }\n\n  @Test public void http204WithBodyDisallowed() throws IOException {\n    server.enqueue(new MockResponse()\n        .setResponseCode(204)\n        .setBody(\"I'm not even supposed to be here today.\"));\n\n    try {\n      executeSynchronously(new Request.Builder().url(server.url(\"/\")).build());\n      fail();\n    } catch (ProtocolException e) {\n      assertEquals(\"HTTP 204 had non-zero Content-Length: 39\", e.getMessage());\n    }\n  }\n\n  @Test public void http205WithBodyDisallowed() throws IOException {\n    server.enqueue(new MockResponse()\n        .setResponseCode(205)\n        .setBody(\"I'm not even supposed to be here today.\"));\n\n    try {\n      executeSynchronously(new Request.Builder().url(server.url(\"/\")).build());\n      fail();\n    } catch (ProtocolException e) {\n      assertEquals(\"HTTP 205 had non-zero Content-Length: 39\", e.getMessage());\n    }\n  }\n\n  @Test public void canceledBeforeExecute() throws Exception {\n    Call call = client.newCall(new Request.Builder().url(server.url(\"/a\")).build());\n    call.cancel();\n\n    try {\n      call.execute();\n      fail();\n    } catch (IOException expected) {\n    }\n    assertEquals(0, server.getRequestCount());\n  }\n\n  @Test public void cancelDuringHttpConnect() throws Exception {\n    cancelDuringConnect(\"http\");\n  }\n\n  @Test public void cancelDuringHttpsConnect() throws Exception {\n    cancelDuringConnect(\"https\");\n  }\n\n  /** Cancel a call that's waiting for connect to complete. */\n  private void cancelDuringConnect(String scheme) throws Exception {\n    InetSocketAddress socketAddress = startNullServer();\n\n    HttpUrl url = new HttpUrl.Builder()\n        .scheme(scheme)\n        .host(socketAddress.getHostName())\n        .port(socketAddress.getPort())\n        .build();\n\n    long cancelDelayMillis = 300L;\n    Call call = client.newCall(new Request.Builder().url(url).build());\n    cancelLater(call, cancelDelayMillis);\n\n    long startNanos = System.nanoTime();\n    try {\n      call.execute();\n      fail();\n    } catch (IOException expected) {\n    }\n    long elapsedNanos = System.nanoTime() - startNanos;\n    assertEquals(cancelDelayMillis, TimeUnit.NANOSECONDS.toMillis(elapsedNanos), 100f);\n  }\n\n  private InetSocketAddress startNullServer() throws IOException {\n    InetSocketAddress address = new InetSocketAddress(InetAddress.getByName(\"localhost\"), 0);\n    nullServer = ServerSocketFactory.getDefault().createServerSocket();\n    nullServer.bind(address);\n    return new InetSocketAddress(address.getAddress(), nullServer.getLocalPort());\n  }\n\n  @Test public void cancelTagImmediatelyAfterEnqueue() throws Exception {\n    server.enqueue(new MockResponse());\n    Call call = client.newCall(new Request.Builder()\n        .url(server.url(\"/a\"))\n        .tag(\"request\")\n        .build());\n    call.enqueue(callback);\n    client.cancel(\"request\");\n    callback.await(server.url(\"/a\")).assertFailure(\"Canceled\");\n  }\n\n  @Test public void cancelBeforeBodyIsRead() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"def\").throttleBody(1, 750, TimeUnit.MILLISECONDS));\n\n    final Call call = client.newCall(new Request.Builder().url(server.url(\"/a\")).build());\n    ExecutorService executor = Executors.newSingleThreadExecutor();\n    Future<Response> result = executor.submit(new Callable<Response>() {\n      @Override public Response call() throws Exception {\n        return call.execute();\n      }\n    });\n\n    Thread.sleep(100); // wait for it to go in flight.\n\n    call.cancel();\n    try {\n      result.get().body().bytes();\n      fail();\n    } catch (IOException expected) {\n    }\n    assertEquals(1, server.getRequestCount());\n  }\n\n  @Test public void cancelInFlightBeforeResponseReadThrowsIOE() throws Exception {\n    server.setDispatcher(new Dispatcher() {\n      @Override public MockResponse dispatch(RecordedRequest request) {\n        client.cancel(\"request\");\n        return new MockResponse().setBody(\"A\");\n      }\n    });\n\n    Request request = new Request.Builder().url(server.url(\"/a\")).tag(\"request\").build();\n    try {\n      client.newCall(request).execute();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void cancelInFlightBeforeResponseReadThrowsIOE_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    cancelInFlightBeforeResponseReadThrowsIOE();\n  }\n\n  @Test public void cancelInFlightBeforeResponseReadThrowsIOE_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    cancelInFlightBeforeResponseReadThrowsIOE();\n  }\n\n  /**\n   * This test puts a request in front of one that is to be canceled, so that it is canceled before\n   * I/O takes place.\n   */\n  @Test public void canceledBeforeIOSignalsOnFailure() throws Exception {\n    client.getDispatcher().setMaxRequests(1); // Force requests to be executed serially.\n    server.setDispatcher(new Dispatcher() {\n      char nextResponse = 'A';\n\n      @Override public MockResponse dispatch(RecordedRequest request) {\n        client.cancel(\"request B\");\n        return new MockResponse().setBody(Character.toString(nextResponse++));\n      }\n    });\n\n    Request requestA = new Request.Builder().url(server.url(\"/a\")).tag(\"request A\").build();\n    client.newCall(requestA).enqueue(callback);\n    assertEquals(\"/a\", server.takeRequest().getPath());\n\n    Request requestB = new Request.Builder().url(server.url(\"/b\")).tag(\"request B\").build();\n    client.newCall(requestB).enqueue(callback);\n\n    callback.await(requestA.httpUrl()).assertBody(\"A\");\n    // At this point we know the callback is ready, and that it will receive a cancel failure.\n    callback.await(requestB.httpUrl()).assertFailure(\"Canceled\");\n  }\n\n  @Test public void canceledBeforeIOSignalsOnFailure_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    canceledBeforeIOSignalsOnFailure();\n  }\n\n  @Test public void canceledBeforeIOSignalsOnFailure_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    canceledBeforeIOSignalsOnFailure();\n  }\n\n  @Test public void canceledBeforeResponseReadSignalsOnFailure() throws Exception {\n    Request requestA = new Request.Builder().url(server.url(\"/a\")).tag(\"request A\").build();\n    final Call call = client.newCall(requestA);\n    server.setDispatcher(new Dispatcher() {\n      @Override public MockResponse dispatch(RecordedRequest request) {\n        call.cancel();\n        return new MockResponse().setBody(\"A\");\n      }\n    });\n\n    call.enqueue(callback);\n    assertEquals(\"/a\", server.takeRequest().getPath());\n\n    callback.await(requestA.httpUrl()).assertFailure(\"Canceled\", \"stream was reset: CANCEL\",\n        \"Socket closed\");\n  }\n\n  @Test public void canceledBeforeResponseReadSignalsOnFailure_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    canceledBeforeResponseReadSignalsOnFailure();\n  }\n\n  @Test public void canceledBeforeResponseReadSignalsOnFailure_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    canceledBeforeResponseReadSignalsOnFailure();\n  }\n\n  /**\n   * There's a race condition where the cancel may apply after the stream has already been\n   * processed.\n   */\n  @Test public void canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    final CountDownLatch latch = new CountDownLatch(1);\n    final AtomicReference<String> bodyRef = new AtomicReference<>();\n    final AtomicBoolean failureRef = new AtomicBoolean();\n\n    Request request = new Request.Builder().url(server.url(\"/a\")).tag(\"request A\").build();\n    final Call call = client.newCall(request);\n    call.enqueue(new Callback() {\n      @Override public void onFailure(Request request, IOException e) {\n        failureRef.set(true);\n        latch.countDown();\n      }\n\n      @Override public void onResponse(Response response) throws IOException {\n        call.cancel();\n        try {\n          bodyRef.set(response.body().string());\n        } catch (IOException e) { // It is ok if this broke the stream.\n          bodyRef.set(\"A\");\n          throw e; // We expect to not loop into onFailure in this case.\n        } finally {\n          latch.countDown();\n        }\n      }\n    });\n\n    latch.await();\n    assertEquals(\"A\", bodyRef.get());\n    assertFalse(failureRef.get());\n  }\n\n  @Test public void canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce_HTTP_2()\n      throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce();\n  }\n\n  @Test public void canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce_SPDY_3()\n      throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    canceledAfterResponseIsDeliveredBreaksStreamButSignalsOnce();\n  }\n\n  @Test public void cancelWithInterceptor() throws Exception {\n    client.interceptors().add(new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        chain.proceed(chain.request());\n        throw new AssertionError(); // We expect an exception.\n      }\n    });\n\n    Call call = client.newCall(new Request.Builder().url(server.url(\"/a\")).build());\n    call.cancel();\n\n    try {\n      call.execute();\n      fail();\n    } catch (IOException expected) {\n    }\n    assertEquals(0, server.getRequestCount());\n  }\n\n  @Test public void gzip() throws Exception {\n    Buffer gzippedBody = gzip(\"abcabcabc\");\n    String bodySize = Long.toString(gzippedBody.size());\n\n    server.enqueue(new MockResponse()\n        .setBody(gzippedBody)\n        .addHeader(\"Content-Encoding: gzip\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    // Confirm that the user request doesn't have Accept-Encoding, and the user\n    // response doesn't have a Content-Encoding or Content-Length.\n    RecordedResponse userResponse = executeSynchronously(request);\n    userResponse.assertCode(200)\n        .assertRequestHeader(\"Accept-Encoding\")\n        .assertHeader(\"Content-Encoding\")\n        .assertHeader(\"Content-Length\")\n        .assertBody(\"abcabcabc\");\n\n    // But the network request doesn't lie. OkHttp used gzip for this call.\n    userResponse.networkResponse()\n        .assertHeader(\"Content-Encoding\", \"gzip\")\n        .assertHeader(\"Content-Length\", bodySize)\n        .assertRequestHeader(\"Accept-Encoding\", \"gzip\");\n  }\n\n  @Test public void asyncResponseCanBeConsumedLater() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"User-Agent\", \"SyncApiTest\")\n        .build();\n\n    final BlockingQueue<Response> responseRef = new SynchronousQueue<>();\n    client.newCall(request).enqueue(new Callback() {\n      @Override public void onFailure(Request request, IOException e) {\n        throw new AssertionError();\n      }\n\n      @Override public void onResponse(Response response) throws IOException {\n        try {\n          responseRef.put(response);\n        } catch (InterruptedException e) {\n          throw new AssertionError();\n        }\n      }\n    });\n\n    Response response = responseRef.take();\n    assertEquals(200, response.code());\n    assertEquals(\"abc\", response.body().string());\n\n    // Make another request just to confirm that that connection can be reused...\n    executeSynchronously(new Request.Builder().url(server.url(\"/\")).build()).assertBody(\"def\");\n    assertEquals(0, server.takeRequest().getSequenceNumber()); // New connection.\n    assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection reused.\n\n    // ... even before we close the response body!\n    response.body().close();\n  }\n\n  @Test public void userAgentIsIncludedByDefault() throws Exception {\n    server.enqueue(new MockResponse());\n\n    executeSynchronously(new Request.Builder().url(server.url(\"/\")).build());\n\n    RecordedRequest recordedRequest = server.takeRequest();\n    assertTrue(recordedRequest.getHeader(\"User-Agent\")\n        .matches(Version.userAgent()));\n  }\n\n  @Test public void setFollowRedirectsFalse() throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(302)\n        .addHeader(\"Location: /b\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    client.setFollowRedirects(false);\n    RecordedResponse recordedResponse = executeSynchronously(\n        new Request.Builder().url(server.url(\"/a\")).build());\n\n    recordedResponse\n        .assertBody(\"A\")\n        .assertCode(302);\n  }\n\n  @Test public void expect100ContinueNonEmptyRequestBody() throws Exception {\n    server.enqueue(new MockResponse());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Expect\", \"100-continue\")\n        .post(RequestBody.create(MediaType.parse(\"text/plain\"), \"abc\"))\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertSuccessful();\n\n    assertEquals(\"abc\", server.takeRequest().getBody().readUtf8());\n  }\n\n  @Test public void expect100ContinueEmptyRequestBody() throws Exception {\n    server.enqueue(new MockResponse());\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .header(\"Expect\", \"100-continue\")\n        .post(RequestBody.create(MediaType.parse(\"text/plain\"), \"\"))\n        .build();\n\n    executeSynchronously(request)\n        .assertCode(200)\n        .assertSuccessful();\n  }\n\n  /** We forbid non-ASCII characters in outgoing request headers, but accept UTF-8. */\n  @Test public void responseHeaderParsingIsLenient() throws Exception {\n    Headers headers = new Headers.Builder()\n        .add(\"Content-Length\", \"0\")\n        .addLenient(\"a\\tb: c\\u007fd\")\n        .addLenient(\": ef\")\n        .addLenient(\"\\ud83c\\udf69: \\u2615\\ufe0f\")\n        .build();\n    server.enqueue(new MockResponse().setHeaders(headers));\n\n    Request request = new Request.Builder()\n        .url(server.url(\"/\"))\n        .build();\n\n    executeSynchronously(request)\n        .assertHeader(\"a\\tb\", \"c\\u007fd\")\n        .assertHeader(\"\\ud83c\\udf69\", \"\\u2615\\ufe0f\")\n        .assertHeader(\"\", \"ef\");\n  }\n\n  @Test public void customDns() throws Exception {\n    // Configure a DNS that returns our MockWebServer for every hostname.\n    FakeDns dns = new FakeDns();\n    dns.addresses(Dns.SYSTEM.lookup(server.url(\"/\").host()));\n    client.setDns(dns);\n\n    server.enqueue(new MockResponse());\n    Request request = new Request.Builder()\n        .url(server.url(\"/\").newBuilder().host(\"android.com\").build())\n        .build();\n    executeSynchronously(request).assertCode(200);\n\n    dns.assertRequests(\"android.com\");\n  }\n\n  /** We had a bug where failed HTTP/2 calls could break the entire connection. */\n  @Ignore // TODO(jwilson): fix HttpEngine connection cleanups.\n  @Test public void failingCallsDoNotInterfereWithConnection() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n\n    server.enqueue(new MockResponse().setBody(\"Response 1\"));\n    server.enqueue(new MockResponse().setBody(\"Response 2\"));\n\n    RequestBody requestBody = new RequestBody() {\n      @Override public MediaType contentType() {\n        return null;\n      }\n\n      @Override public void writeTo(BufferedSink sink) throws IOException {\n        sink.writeUtf8(\"abc\");\n        sink.flush();\n\n        makeFailingCall();\n\n        sink.writeUtf8(\"def\");\n        sink.flush();\n      }\n    };\n    Call call = client.newCall(new Request.Builder()\n        .url(server.url(\"/\"))\n        .post(requestBody)\n        .build());\n    assertEquals(\"Response 1\", call.execute().body().string());\n  }\n\n  /** Test which headers are sent unencrypted to the HTTP proxy. */\n  @Test public void proxyConnectOmitsApplicationHeaders() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), true);\n    server.enqueue(new MockResponse()\n        .setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END)\n        .clearHeaders());\n    server.enqueue(new MockResponse()\n        .setBody(\"encrypted response from the origin server\"));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setProxy(server.toProxyAddress());\n    RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();\n    client.setHostnameVerifier(hostnameVerifier);\n\n    Request request = new Request.Builder()\n        .url(\"https://android.com/foo\")\n        .header(\"Private\", \"Secret\")\n        .header(\"User-Agent\", \"App 1.0\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"encrypted response from the origin server\", response.body().string());\n\n    RecordedRequest connect = server.takeRequest();\n    assertNull(connect.getHeader(\"Private\"));\n    assertEquals(Version.userAgent(), connect.getHeader(\"User-Agent\"));\n    assertEquals(\"Keep-Alive\", connect.getHeader(\"Proxy-Connection\"));\n    assertEquals(\"android.com\", connect.getHeader(\"Host\"));\n\n    RecordedRequest get = server.takeRequest();\n    assertEquals(\"Secret\", get.getHeader(\"Private\"));\n    assertEquals(\"App 1.0\", get.getHeader(\"User-Agent\"));\n\n    assertEquals(Arrays.asList(\"verify android.com\"), hostnameVerifier.calls);\n  }\n\n  /** Respond to a proxy authorization challenge. */\n  @Test public void proxyAuthenticateOnConnect() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), true);\n    server.enqueue(new MockResponse()\n        .setResponseCode(407)\n        .addHeader(\"Proxy-Authenticate: Basic realm=\\\"localhost\\\"\"));\n    server.enqueue(new MockResponse()\n        .setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END)\n        .clearHeaders());\n    server.enqueue(new MockResponse()\n        .setBody(\"response body\"));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setProxy(server.toProxyAddress());\n    client.setAuthenticator(new RecordingOkAuthenticator(\"password\"));\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n\n    Request request = new Request.Builder()\n        .url(\"https://android.com/foo\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"response body\", response.body().string());\n\n    RecordedRequest connect1 = server.takeRequest();\n    assertEquals(\"CONNECT android.com:443 HTTP/1.1\", connect1.getRequestLine());\n    assertNull(connect1.getHeader(\"Proxy-Authorization\"));\n\n    RecordedRequest connect2 = server.takeRequest();\n    assertEquals(\"CONNECT android.com:443 HTTP/1.1\", connect2.getRequestLine());\n    assertEquals(\"password\", connect2.getHeader(\"Proxy-Authorization\"));\n\n    RecordedRequest get = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", get.getRequestLine());\n    assertNull(get.getHeader(\"Proxy-Authorization\"));\n  }\n\n  /**\n   * Confirm that we don't send the Proxy-Authorization header from the request to the proxy server.\n   * We used to have that behavior but it is problematic because unrelated requests end up sharing\n   * credentials. Worse, that approach leaks proxy credentials to the origin server.\n   */\n  @Test public void noProactiveProxyAuthorization() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), true);\n    server.enqueue(new MockResponse()\n        .setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END)\n        .clearHeaders());\n    server.enqueue(new MockResponse()\n        .setBody(\"response body\"));\n\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setProxy(server.toProxyAddress());\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n\n    Request request = new Request.Builder()\n        .url(\"https://android.com/foo\")\n        .header(\"Proxy-Authorization\", \"password\")\n        .build();\n    Response response = client.newCall(request).execute();\n    assertEquals(\"response body\", response.body().string());\n\n    RecordedRequest connect = server.takeRequest();\n    assertNull(connect.getHeader(\"Proxy-Authorization\"));\n\n    RecordedRequest get = server.takeRequest();\n    assertEquals(\"password\", get.getHeader(\"Proxy-Authorization\"));\n  }\n\n  private void makeFailingCall() {\n    RequestBody requestBody = new RequestBody() {\n      @Override public MediaType contentType() {\n        return null;\n      }\n\n      @Override public long contentLength() throws IOException {\n        return 1;\n      }\n\n      @Override public void writeTo(BufferedSink sink) throws IOException {\n        throw new IOException(\"write body fail!\");\n      }\n    };\n    Call call = client.newCall(new Request.Builder()\n        .url(server.url(\"/\"))\n        .post(requestBody)\n        .build());\n    try {\n      call.execute();\n      fail();\n    } catch (IOException expected) {\n      assertEquals(\"write body fail!\", expected.getMessage());\n    }\n  }\n\n  private RecordedResponse executeSynchronously(Request request) throws IOException {\n    Response response = client.newCall(request).execute();\n    return new RecordedResponse(request, response, null, response.body().string(), null);\n  }\n\n  /**\n   * Tests that use this will fail unless boot classpath is set. Ex. {@code\n   * -Xbootclasspath/p:/tmp/alpn-boot-8.0.0.v20140317}\n   */\n  private void enableProtocol(Protocol protocol) {\n    client.setSslSocketFactory(sslContext.getSocketFactory());\n    client.setHostnameVerifier(new RecordingHostnameVerifier());\n    client.setProtocols(Arrays.asList(protocol, Protocol.HTTP_1_1));\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.setProtocols(client.getProtocols());\n  }\n\n  private Buffer gzip(String data) throws IOException {\n    Buffer result = new Buffer();\n    BufferedSink sink = Okio.buffer(new GzipSink(result));\n    sink.writeUtf8(data);\n    sink.close();\n    return result;\n  }\n\n  private void cancelLater(final Call call, final long delay) {\n    new Thread(\"canceler\") {\n      @Override public void run() {\n        try {\n          Thread.sleep(delay);\n        } catch (InterruptedException e) {\n          throw new AssertionError();\n        }\n        call.cancel();\n      }\n    }.start();\n  }\n\n  private static class RecordingSSLSocketFactory extends DelegatingSSLSocketFactory {\n\n    private List<SSLSocket> socketsCreated = new ArrayList<>();\n\n    public RecordingSSLSocketFactory(SSLSocketFactory delegate) {\n      super(delegate);\n    }\n\n    @Override\n    protected SSLSocket configureSocket(SSLSocket sslSocket) throws IOException {\n      socketsCreated.add(sslSocket);\n      return sslSocket;\n    }\n\n    public List<SSLSocket> getSocketsCreated() {\n      return socketsCreated;\n    }\n  }\n\n  /**\n   * Used during tests that involve TLS connection fallback attempts. OkHttp includes the\n   * TLS_FALLBACK_SCSV cipher on fallback connections. See\n   * {@link com.squareup.okhttp.FallbackTestClientSocketFactory} for details.\n   */\n  private void suppressTlsFallbackScsv(OkHttpClient client) {\n    FallbackTestClientSocketFactory clientSocketFactory =\n        new FallbackTestClientSocketFactory(sslContext.getSocketFactory());\n    client.setSslSocketFactory(clientSocketFactory);\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/com/squareup/okhttp/DispatcherTest.java",
    "content": "package com.squareup.okhttp;\n\nimport co.paralleluniverse.fibers.okhttp.test.utils.FiberOkHttpClientTestWrapper;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.RecordingCallback;\nimport com.squareup.okhttp.Call.AsyncCall;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.AbstractExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\npublic final class DispatcherTest {\n  RecordingExecutor executor = new RecordingExecutor();\n  RecordingCallback callback = new RecordingCallback();\n  Dispatcher dispatcher = new Dispatcher(executor);\n  OkHttpClient client = new FiberOkHttpClientTestWrapper().setDispatcher(dispatcher);\n\n  @Before public void setUp() throws Exception {\n    dispatcher.setMaxRequests(20);\n    dispatcher.setMaxRequestsPerHost(10);\n  }\n\n  @Test public void maxRequestsZero() throws Exception {\n    try {\n      dispatcher.setMaxRequests(0);\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void maxPerHostZero() throws Exception {\n    try {\n      dispatcher.setMaxRequestsPerHost(0);\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void enqueuedJobsRunImmediately() throws Exception {\n    client.newCall(newRequest(\"http://a/1\")).enqueue(callback);\n    executor.assertJobs(\"http://a/1\");\n  }\n\n  @Test public void maxRequestsEnforced() throws Exception {\n    dispatcher.setMaxRequests(3);\n    client.newCall(newRequest(\"http://a/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/2\")).enqueue(callback);\n    client.newCall(newRequest(\"http://b/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://b/2\")).enqueue(callback);\n    executor.assertJobs(\"http://a/1\", \"http://a/2\", \"http://b/1\");\n  }\n\n  @Test public void maxPerHostEnforced() throws Exception {\n    dispatcher.setMaxRequestsPerHost(2);\n    client.newCall(newRequest(\"http://a/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/2\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/3\")).enqueue(callback);\n    executor.assertJobs(\"http://a/1\", \"http://a/2\");\n  }\n\n  @Test public void increasingMaxRequestsPromotesJobsImmediately() throws Exception {\n    dispatcher.setMaxRequests(2);\n    client.newCall(newRequest(\"http://a/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://b/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://c/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/2\")).enqueue(callback);\n    client.newCall(newRequest(\"http://b/2\")).enqueue(callback);\n    dispatcher.setMaxRequests(4);\n    executor.assertJobs(\"http://a/1\", \"http://b/1\", \"http://c/1\", \"http://a/2\");\n  }\n\n  @Test public void increasingMaxPerHostPromotesJobsImmediately() throws Exception {\n    dispatcher.setMaxRequestsPerHost(2);\n    client.newCall(newRequest(\"http://a/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/2\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/3\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/4\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/5\")).enqueue(callback);\n    dispatcher.setMaxRequestsPerHost(4);\n    executor.assertJobs(\"http://a/1\", \"http://a/2\", \"http://a/3\", \"http://a/4\");\n  }\n\n  @Test public void oldJobFinishesNewJobCanRunDifferentHost() throws Exception {\n    dispatcher.setMaxRequests(1);\n    client.newCall(newRequest(\"http://a/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://b/1\")).enqueue(callback);\n    executor.finishJob(\"http://a/1\");\n    executor.assertJobs(\"http://b/1\");\n  }\n\n  @Test public void oldJobFinishesNewJobWithSameHostStarts() throws Exception {\n    dispatcher.setMaxRequests(2);\n    dispatcher.setMaxRequestsPerHost(1);\n    client.newCall(newRequest(\"http://a/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://b/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://b/2\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/2\")).enqueue(callback);\n    executor.finishJob(\"http://a/1\");\n    executor.assertJobs(\"http://b/1\", \"http://a/2\");\n  }\n\n  @Test public void oldJobFinishesNewJobCantRunDueToHostLimit() throws Exception {\n    dispatcher.setMaxRequestsPerHost(1);\n    client.newCall(newRequest(\"http://a/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://b/1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/2\")).enqueue(callback);\n    executor.finishJob(\"http://b/1\");\n    executor.assertJobs(\"http://a/1\");\n  }\n\n  @Test public void cancelingRunningJobTakesNoEffectUntilJobFinishes() throws Exception {\n    dispatcher.setMaxRequests(1);\n    client.newCall(newRequest(\"http://a/1\", \"tag1\")).enqueue(callback);\n    client.newCall(newRequest(\"http://a/2\")).enqueue(callback);\n    dispatcher.cancel(\"tag1\");\n    executor.assertJobs(\"http://a/1\");\n    executor.finishJob(\"http://a/1\");\n    executor.assertJobs(\"http://a/2\");\n  }\n\n  class RecordingExecutor extends AbstractExecutorService {\n    private List<AsyncCall> calls = new ArrayList<>();\n\n    @Override public void execute(Runnable command) {\n      calls.add((AsyncCall) command);\n    }\n\n    public void assertJobs(String... expectedUrls) {\n      List<String> actualUrls = new ArrayList<>();\n      for (AsyncCall call : calls) {\n        actualUrls.add(call.request().urlString());\n      }\n      assertEquals(Arrays.asList(expectedUrls), actualUrls);\n    }\n\n    public void finishJob(String url) {\n      for (Iterator<AsyncCall> i = calls.iterator(); i.hasNext(); ) {\n        AsyncCall call = i.next();\n        if (call.request().urlString().equals(url)) {\n          i.remove();\n          dispatcher.finished(call);\n          return;\n        }\n      }\n      throw new AssertionError(\"No such job: \" + url);\n    }\n\n    @Override public void shutdown() {\n      throw new UnsupportedOperationException();\n    }\n\n    @Override public List<Runnable> shutdownNow() {\n      throw new UnsupportedOperationException();\n    }\n\n    @Override public boolean isShutdown() {\n      throw new UnsupportedOperationException();\n    }\n\n    @Override public boolean isTerminated() {\n      throw new UnsupportedOperationException();\n    }\n\n    @Override public boolean awaitTermination(long timeout, TimeUnit unit)\n        throws InterruptedException {\n      throw new UnsupportedOperationException();\n    }\n  }\n\n  private Request newRequest(String url) {\n    return new Request.Builder().url(url).build();\n  }\n\n  private Request newRequest(String url, String tag) {\n    return new Request.Builder().url(url).tag(tag).build();\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/com/squareup/okhttp/OkUrlFactoryTest.java",
    "content": "package com.squareup.okhttp;\n\nimport co.paralleluniverse.fibers.okhttp.test.utils.FiberOkHttpClientTestWrapper;\nimport com.squareup.okhttp.internal.Platform;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.io.InMemoryFileSystem;\nimport com.squareup.okhttp.mockwebserver.MockResponse;\nimport com.squareup.okhttp.mockwebserver.MockWebServer;\nimport java.io.File;\nimport java.io.IOException;\nimport java.net.HttpURLConnection;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Locale;\nimport java.util.TimeZone;\nimport java.util.concurrent.TimeUnit;\nimport okio.BufferedSource;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\n\nimport static java.nio.charset.StandardCharsets.US_ASCII;\nimport static okio.Okio.buffer;\nimport static okio.Okio.source;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.fail;\n\npublic class OkUrlFactoryTest {\n  @Rule public MockWebServer server = new MockWebServer();\n  @Rule public InMemoryFileSystem fileSystem = new InMemoryFileSystem();\n\n  private OkUrlFactory factory;\n  private Cache cache;\n\n  @Before public void setUp() throws IOException {\n    OkHttpClient client = new FiberOkHttpClientTestWrapper();\n    cache = new Cache(new File(\"/cache/\"), 10 * 1024 * 1024, fileSystem);\n    client.setCache(cache);\n    factory = new OkUrlFactory(client);\n  }\n\n  @After public void tearDown() throws IOException {\n    cache.delete();\n  }\n\n  /**\n   * Response code 407 should only come from proxy servers. Android's client\n   * throws if it is sent by an origin server.\n   */\n  @Test public void originServerSends407() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(407));\n\n    HttpURLConnection conn = factory.open(server.getUrl(\"/\"));\n    try {\n      conn.getResponseCode();\n      fail();\n    } catch (IOException ignored) {\n    }\n  }\n\n  @Test public void networkResponseSourceHeader() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"Isla Sorna\"));\n\n    HttpURLConnection connection = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection, \"NETWORK 200\");\n    assertResponseBody(connection, \"Isla Sorna\");\n  }\n\n  @Test public void networkFailureResponseSourceHeader() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(404));\n\n    HttpURLConnection connection = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection, \"NETWORK 404\");\n    connection.getErrorStream().close();\n  }\n\n  @Test public void conditionalCacheHitResponseSourceHeaders() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(0, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"Isla Nublar\"));\n    server.enqueue(new MockResponse().setResponseCode(304));\n\n    HttpURLConnection connection1 = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection1, \"NETWORK 200\");\n    assertResponseBody(connection1, \"Isla Nublar\");\n\n    HttpURLConnection connection2 = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection2, \"CONDITIONAL_CACHE 304\");\n    assertResponseBody(connection2, \"Isla Nublar\");\n  }\n\n  @Test public void conditionalCacheMissResponseSourceHeaders() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(0, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"Isla Nublar\"));\n    server.enqueue(new MockResponse().setBody(\"Isla Sorna\"));\n\n    HttpURLConnection connection1 = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection1, \"NETWORK 200\");\n    assertResponseBody(connection1, \"Isla Nublar\");\n\n    HttpURLConnection connection2 = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection2, \"CONDITIONAL_CACHE 200\");\n    assertResponseBody(connection2, \"Isla Sorna\");\n  }\n\n  @Test public void cacheResponseSourceHeaders() throws Exception {\n    server.enqueue(new MockResponse()\n        .addHeader(\"Expires: \" + formatDate(2, TimeUnit.HOURS))\n        .setBody(\"Isla Nublar\"));\n\n    HttpURLConnection connection1 = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection1, \"NETWORK 200\");\n    assertResponseBody(connection1, \"Isla Nublar\");\n\n    HttpURLConnection connection2 = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection2, \"CACHE 200\");\n    assertResponseBody(connection2, \"Isla Nublar\");\n  }\n\n  @Test public void noneResponseSourceHeaders() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"Isla Nublar\"));\n\n    HttpURLConnection connection1 = factory.open(server.getUrl(\"/\"));\n    assertResponseHeader(connection1, \"NETWORK 200\");\n    assertResponseBody(connection1, \"Isla Nublar\");\n\n    HttpURLConnection connection2 = factory.open(server.getUrl(\"/\"));\n    connection2.setRequestProperty(\"Cache-Control\", \"only-if-cached\");\n    assertResponseHeader(connection2, \"NONE\");\n  }\n\n  @Test\n  public void setInstanceFollowRedirectsFalse() throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(302)\n        .addHeader(\"Location: /b\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"B\"));\n\n    HttpURLConnection connection = factory.open(server.getUrl(\"/a\"));\n    connection.setInstanceFollowRedirects(false);\n    assertResponseBody(connection, \"A\");\n    assertResponseCode(connection, 302);\n  }\n\n  private void assertResponseBody(HttpURLConnection connection, String expected) throws Exception {\n    BufferedSource source = buffer(source(connection.getInputStream()));\n    String actual = source.readString(US_ASCII);\n    source.close();\n    assertEquals(expected, actual);\n  }\n\n  private void assertResponseHeader(HttpURLConnection connection, String expected) {\n    final String headerFieldPrefix = Platform.get().getPrefix();\n    assertEquals(expected, connection.getHeaderField(headerFieldPrefix + \"-Response-Source\"));\n  }\n\n  private void assertResponseCode(HttpURLConnection connection, int expected) throws IOException {\n    assertEquals(expected, connection.getResponseCode());\n  }\n\n  private static String formatDate(long delta, TimeUnit timeUnit) {\n    return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta)));\n  }\n\n  private static String formatDate(Date date) {\n    DateFormat rfc1123 = new SimpleDateFormat(\"EEE, dd MMM yyyy HH:mm:ss zzz\", Locale.US);\n    rfc1123.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n    return rfc1123.format(date);\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/com/squareup/okhttp/README.md",
    "content": "Unfortunately these tests can't be moved as they use package-local functionality.\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/com/squareup/okhttp/URLConnectionTest.java",
    "content": "/*\n * Copyright (C) 2009 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.squareup.okhttp;\n\nimport co.paralleluniverse.fibers.okhttp.test.utils.FiberOkHttpClientTestWrapper;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.*;\nimport com.squareup.okhttp.internal.Internal;\nimport com.squareup.okhttp.internal.SslContextBuilder;\nimport com.squareup.okhttp.internal.Util;\nimport com.squareup.okhttp.internal.Version;\nimport com.squareup.okhttp.mockwebserver.MockResponse;\nimport com.squareup.okhttp.mockwebserver.MockWebServer;\nimport com.squareup.okhttp.mockwebserver.RecordedRequest;\nimport com.squareup.okhttp.mockwebserver.SocketPolicy;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.testing.RecordingHostnameVerifier;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.net.Authenticator;\nimport java.net.ConnectException;\nimport java.net.HttpRetryException;\nimport java.net.HttpURLConnection;\nimport java.net.InetAddress;\nimport java.net.ProtocolException;\nimport java.net.Proxy;\nimport java.net.ProxySelector;\nimport java.net.ServerSocket;\nimport java.net.Socket;\nimport java.net.SocketAddress;\nimport java.net.SocketTimeoutException;\nimport java.net.URI;\nimport java.net.URL;\nimport java.net.URLConnection;\nimport java.net.UnknownHostException;\nimport java.security.cert.CertificateException;\nimport java.security.cert.X509Certificate;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Random;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\nimport java.util.zip.GZIPInputStream;\nimport javax.net.ServerSocketFactory;\nimport javax.net.SocketFactory;\nimport javax.net.ssl.HttpsURLConnection;\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLException;\nimport javax.net.ssl.SSLHandshakeException;\nimport javax.net.ssl.SSLSocketFactory;\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.X509TrustManager;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.GzipSink;\nimport okio.Okio;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Ignore;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.TemporaryFolder;\n\nimport static com.squareup.okhttp.internal.Util.UTF_8;\nimport static com.squareup.okhttp.internal.http.OkHeaders.SELECTED_PROTOCOL;\nimport static com.squareup.okhttp.internal.http.StatusLine.HTTP_PERM_REDIRECT;\nimport static com.squareup.okhttp.internal.http.StatusLine.HTTP_TEMP_REDIRECT;\nimport static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_END;\nimport static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_START;\nimport static com.squareup.okhttp.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END;\nimport static com.squareup.okhttp.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;\nimport static java.util.concurrent.TimeUnit.MILLISECONDS;\nimport static java.util.concurrent.TimeUnit.NANOSECONDS;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/** Android's URLConnectionTest. */\npublic final class URLConnectionTest {\n  @Rule public final MockWebServer server = new MockWebServer();\n  @Rule public final MockWebServer server2 = new MockWebServer();\n  @Rule public final TemporaryFolder tempDir = new TemporaryFolder();\n\n  private SSLContext sslContext = SslContextBuilder.localhost();\n  private OkUrlFactory client;\n  private HttpURLConnection connection;\n  private Cache cache;\n\n  @Before public void setUp() throws Exception {\n    server.setProtocolNegotiationEnabled(false);\n    client = new OkUrlFactory(new FiberOkHttpClientTestWrapper());\n  }\n\n  @After public void tearDown() throws Exception {\n    Authenticator.setDefault(null);\n    System.clearProperty(\"proxyHost\");\n    System.clearProperty(\"proxyPort\");\n    System.clearProperty(\"http.agent\");\n    System.clearProperty(\"http.proxyHost\");\n    System.clearProperty(\"http.proxyPort\");\n    System.clearProperty(\"https.proxyHost\");\n    System.clearProperty(\"https.proxyPort\");\n    if (cache != null) {\n      cache.delete();\n    }\n  }\n\n  @Test public void requestHeaders() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse());\n\n    connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"D\", \"e\");\n    connection.addRequestProperty(\"D\", \"f\");\n    assertEquals(\"f\", connection.getRequestProperty(\"D\"));\n    assertEquals(\"f\", connection.getRequestProperty(\"d\"));\n    Map<String, List<String>> requestHeaders = connection.getRequestProperties();\n    assertEquals(newSet(\"e\", \"f\"), new LinkedHashSet<>(requestHeaders.get(\"D\")));\n    assertEquals(newSet(\"e\", \"f\"), new LinkedHashSet<>(requestHeaders.get(\"d\")));\n    try {\n      requestHeaders.put(\"G\", Arrays.asList(\"h\"));\n      fail(\"Modified an unmodifiable view.\");\n    } catch (UnsupportedOperationException expected) {\n    }\n    try {\n      requestHeaders.get(\"D\").add(\"i\");\n      fail(\"Modified an unmodifiable view.\");\n    } catch (UnsupportedOperationException expected) {\n    }\n    try {\n      connection.setRequestProperty(null, \"j\");\n      fail();\n    } catch (NullPointerException expected) {\n    }\n    try {\n      connection.addRequestProperty(null, \"k\");\n      fail();\n    } catch (NullPointerException expected) {\n    }\n    connection.setRequestProperty(\"NullValue\", null);\n    assertNull(connection.getRequestProperty(\"NullValue\"));\n    connection.addRequestProperty(\"AnotherNullValue\", null);\n    assertNull(connection.getRequestProperty(\"AnotherNullValue\"));\n\n    connection.getResponseCode();\n    RecordedRequest request = server.takeRequest();\n    assertEquals(Arrays.asList(\"e\", \"f\"), request.getHeaders().values(\"D\"));\n    assertNull(request.getHeader(\"NullValue\"));\n    assertNull(request.getHeader(\"AnotherNullValue\"));\n    assertNull(request.getHeader(\"G\"));\n    assertNull(request.getHeader(\"null\"));\n\n    try {\n      connection.addRequestProperty(\"N\", \"o\");\n      fail(\"Set header after connect\");\n    } catch (IllegalStateException expected) {\n    }\n    try {\n      connection.setRequestProperty(\"P\", \"q\");\n      fail(\"Set header after connect\");\n    } catch (IllegalStateException expected) {\n    }\n    try {\n      connection.getRequestProperties();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void getRequestPropertyReturnsLastValue() throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"A\", \"value1\");\n    connection.addRequestProperty(\"A\", \"value2\");\n    assertEquals(\"value2\", connection.getRequestProperty(\"A\"));\n  }\n\n  @Test public void responseHeaders() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse().setStatus(\"HTTP/1.0 200 Fantastic\")\n        .addHeader(\"A: c\")\n        .addHeader(\"B: d\")\n        .addHeader(\"A: e\")\n        .setChunkedBody(\"ABCDE\\nFGHIJ\\nKLMNO\\nPQR\", 8));\n\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(200, connection.getResponseCode());\n    assertEquals(\"Fantastic\", connection.getResponseMessage());\n    assertEquals(\"HTTP/1.0 200 Fantastic\", connection.getHeaderField(null));\n    Map<String, List<String>> responseHeaders = connection.getHeaderFields();\n    assertEquals(Arrays.asList(\"HTTP/1.0 200 Fantastic\"), responseHeaders.get(null));\n    assertEquals(newSet(\"c\", \"e\"), new LinkedHashSet<>(responseHeaders.get(\"A\")));\n    assertEquals(newSet(\"c\", \"e\"), new LinkedHashSet<>(responseHeaders.get(\"a\")));\n    try {\n      responseHeaders.put(\"N\", Arrays.asList(\"o\"));\n      fail(\"Modified an unmodifiable view.\");\n    } catch (UnsupportedOperationException expected) {\n    }\n    try {\n      responseHeaders.get(\"A\").add(\"f\");\n      fail(\"Modified an unmodifiable view.\");\n    } catch (UnsupportedOperationException expected) {\n    }\n    assertEquals(\"A\", connection.getHeaderFieldKey(0));\n    assertEquals(\"c\", connection.getHeaderField(0));\n    assertEquals(\"B\", connection.getHeaderFieldKey(1));\n    assertEquals(\"d\", connection.getHeaderField(1));\n    assertEquals(\"A\", connection.getHeaderFieldKey(2));\n    assertEquals(\"e\", connection.getHeaderField(2));\n  }\n\n  @Test public void serverSendsInvalidResponseHeaders() throws Exception {\n    server.enqueue(new MockResponse().setStatus(\"HTP/1.1 200 OK\"));\n\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getResponseCode();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void serverSendsInvalidCodeTooLarge() throws Exception {\n    server.enqueue(new MockResponse().setStatus(\"HTTP/1.1 2147483648 OK\"));\n\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getResponseCode();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void serverSendsInvalidCodeNotANumber() throws Exception {\n    server.enqueue(new MockResponse().setStatus(\"HTTP/1.1 00a OK\"));\n\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getResponseCode();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void serverSendsUnnecessaryWhitespace() throws Exception {\n    server.enqueue(new MockResponse().setStatus(\" HTTP/1.1 2147483648 OK\"));\n\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getResponseCode();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void connectRetriesUntilConnectedOrFailed() throws Exception {\n    URL url = server.getUrl(\"/foo\");\n    server.shutdown();\n\n    connection = client.open(url);\n    try {\n      connection.connect();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void requestBodySurvivesRetriesWithFixedLength() throws Exception {\n    testRequestBodySurvivesRetries(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void requestBodySurvivesRetriesWithChunkedStreaming() throws Exception {\n    testRequestBodySurvivesRetries(TransferKind.CHUNKED);\n  }\n\n  @Test public void requestBodySurvivesRetriesWithBufferedBody() throws Exception {\n    testRequestBodySurvivesRetries(TransferKind.END_OF_STREAM);\n  }\n\n  private void testRequestBodySurvivesRetries(TransferKind transferKind) throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    // Use a misconfigured proxy to guarantee that the request is retried.\n    FakeProxySelector proxySelector = new FakeProxySelector();\n    proxySelector.proxies.add(server2.toProxyAddress());\n    client.client().setProxySelector(proxySelector);\n    server2.shutdown();\n\n    connection = client.open(server.getUrl(\"/def\"));\n    connection.setDoOutput(true);\n    transferKind.setForRequest(connection, 4);\n    connection.getOutputStream().write(\"body\".getBytes(\"UTF-8\"));\n    assertContent(\"abc\", connection);\n\n    assertEquals(\"body\", server.takeRequest().getBody().readUtf8());\n  }\n\n  @Test public void getErrorStreamOnSuccessfulRequest() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertNull(connection.getErrorStream());\n  }\n\n  @Test public void getErrorStreamOnUnsuccessfulRequest() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(404).setBody(\"A\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection.getErrorStream(), Integer.MAX_VALUE));\n  }\n\n  // Check that if we don't read to the end of a response, the next request on the\n  // recycled connection doesn't get the unread tail of the first request's response.\n  // http://code.google.com/p/android/issues/detail?id=2939\n  @Test public void bug2939() throws Exception {\n    MockResponse response = new MockResponse().setChunkedBody(\"ABCDE\\nFGHIJ\\nKLMNO\\nPQR\", 8);\n\n    server.enqueue(response);\n    server.enqueue(response);\n\n    assertContent(\"ABCDE\", client.open(server.getUrl(\"/\")), 5);\n    assertContent(\"ABCDE\", client.open(server.getUrl(\"/\")), 5);\n  }\n\n  // Check that we recognize a few basic mime types by extension.\n  // http://code.google.com/p/android/issues/detail?id=10100\n  @Test public void bug10100() throws Exception {\n    assertEquals(\"image/jpeg\", URLConnection.guessContentTypeFromName(\"someFile.jpg\"));\n    assertEquals(\"application/pdf\", URLConnection.guessContentTypeFromName(\"stuff.pdf\"));\n  }\n\n  @Test public void connectionsArePooled() throws Exception {\n    MockResponse response = new MockResponse().setBody(\"ABCDEFGHIJKLMNOPQR\");\n\n    server.enqueue(response);\n    server.enqueue(response);\n    server.enqueue(response);\n\n    assertContent(\"ABCDEFGHIJKLMNOPQR\", client.open(server.getUrl(\"/foo\")));\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertContent(\"ABCDEFGHIJKLMNOPQR\", client.open(server.getUrl(\"/bar?baz=quux\")));\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n    assertContent(\"ABCDEFGHIJKLMNOPQR\", client.open(server.getUrl(\"/z\")));\n    assertEquals(2, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void chunkedConnectionsArePooled() throws Exception {\n    MockResponse response = new MockResponse().setChunkedBody(\"ABCDEFGHIJKLMNOPQR\", 5);\n\n    server.enqueue(response);\n    server.enqueue(response);\n    server.enqueue(response);\n\n    assertContent(\"ABCDEFGHIJKLMNOPQR\", client.open(server.getUrl(\"/foo\")));\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertContent(\"ABCDEFGHIJKLMNOPQR\", client.open(server.getUrl(\"/bar?baz=quux\")));\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n    assertContent(\"ABCDEFGHIJKLMNOPQR\", client.open(server.getUrl(\"/z\")));\n    assertEquals(2, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void serverClosesSocket() throws Exception {\n    testServerClosesOutput(DISCONNECT_AT_END);\n  }\n\n  @Test public void serverShutdownInput() throws Exception {\n    testServerClosesOutput(SHUTDOWN_INPUT_AT_END);\n  }\n\n  @Test public void serverShutdownOutput() throws Exception {\n    testServerClosesOutput(SHUTDOWN_OUTPUT_AT_END);\n  }\n\n  @Test public void invalidHost() throws Exception {\n    // Note that 1234.1.1.1 is an invalid host in a URI, but URL isn't as strict.\n    URL url = new URL(\"http://1234.1.1.1/index.html\");\n    HttpURLConnection connection = client.open(url);\n    try {\n      connection.connect();\n      fail();\n    } catch (UnknownHostException expected) {\n    }\n  }\n\n  private void testServerClosesOutput(SocketPolicy socketPolicy) throws Exception {\n    server.enqueue(new MockResponse().setBody(\"This connection won't pool properly\")\n        .setSocketPolicy(socketPolicy));\n    MockResponse responseAfter = new MockResponse().setBody(\"This comes after a busted connection\");\n    server.enqueue(responseAfter);\n    server.enqueue(responseAfter); // Enqueue 2x because the broken connection may be reused.\n\n    HttpURLConnection connection1 = client.open(server.getUrl(\"/a\"));\n    connection1.setReadTimeout(100);\n    assertContent(\"This connection won't pool properly\", connection1);\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    HttpURLConnection connection2 = client.open(server.getUrl(\"/b\"));\n    connection2.setReadTimeout(100);\n    assertContent(\"This comes after a busted connection\", connection2);\n\n    // Check that a fresh connection was created, either immediately or after attempting reuse.\n    RecordedRequest requestAfter = server.takeRequest();\n    if (server.getRequestCount() == 3) {\n      requestAfter = server.takeRequest(); // The failure consumed a response.\n    }\n    // sequence number 0 means the HTTP socket connection was not reused\n    assertEquals(0, requestAfter.getSequenceNumber());\n  }\n\n  enum WriteKind {BYTE_BY_BYTE, SMALL_BUFFERS, LARGE_BUFFERS}\n\n  @Test public void chunkedUpload_byteByByte() throws Exception {\n    doUpload(TransferKind.CHUNKED, WriteKind.BYTE_BY_BYTE);\n  }\n\n  @Test public void chunkedUpload_smallBuffers() throws Exception {\n    doUpload(TransferKind.CHUNKED, WriteKind.SMALL_BUFFERS);\n  }\n\n  @Test public void chunkedUpload_largeBuffers() throws Exception {\n    doUpload(TransferKind.CHUNKED, WriteKind.LARGE_BUFFERS);\n  }\n\n  @Test public void fixedLengthUpload_byteByByte() throws Exception {\n    doUpload(TransferKind.FIXED_LENGTH, WriteKind.BYTE_BY_BYTE);\n  }\n\n  @Test public void fixedLengthUpload_smallBuffers() throws Exception {\n    doUpload(TransferKind.FIXED_LENGTH, WriteKind.SMALL_BUFFERS);\n  }\n\n  @Test public void fixedLengthUpload_largeBuffers() throws Exception {\n    doUpload(TransferKind.FIXED_LENGTH, WriteKind.LARGE_BUFFERS);\n  }\n\n  private void doUpload(TransferKind uploadKind, WriteKind writeKind) throws Exception {\n    int n = 512 * 1024;\n    server.setBodyLimit(0);\n    server.enqueue(new MockResponse());\n\n    HttpURLConnection conn = client.open(server.getUrl(\"/\"));\n    conn.setDoOutput(true);\n    conn.setRequestMethod(\"POST\");\n    if (uploadKind == TransferKind.CHUNKED) {\n      conn.setChunkedStreamingMode(-1);\n    } else {\n      conn.setFixedLengthStreamingMode(n);\n    }\n    OutputStream out = conn.getOutputStream();\n    if (writeKind == WriteKind.BYTE_BY_BYTE) {\n      for (int i = 0; i < n; ++i) {\n        out.write('x');\n      }\n    } else {\n      byte[] buf = new byte[writeKind == WriteKind.SMALL_BUFFERS ? 256 : 64 * 1024];\n      Arrays.fill(buf, (byte) 'x');\n      for (int i = 0; i < n; i += buf.length) {\n        out.write(buf, 0, Math.min(buf.length, n - i));\n      }\n    }\n    out.close();\n    assertEquals(200, conn.getResponseCode());\n    RecordedRequest request = server.takeRequest();\n    assertEquals(n, request.getBodySize());\n    if (uploadKind == TransferKind.CHUNKED) {\n      assertTrue(request.getChunkSizes().size() > 0);\n    } else {\n      assertTrue(request.getChunkSizes().isEmpty());\n    }\n  }\n\n  @Test public void getResponseCodeNoResponseBody() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"abc: def\"));\n\n    URL url = server.getUrl(\"/\");\n    HttpURLConnection conn = client.open(url);\n    conn.setDoInput(false);\n    assertEquals(\"def\", conn.getHeaderField(\"abc\"));\n    assertEquals(200, conn.getResponseCode());\n    try {\n      conn.getInputStream();\n      fail();\n    } catch (ProtocolException expected) {\n    }\n  }\n\n  @Test public void connectViaHttps() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setBody(\"this response comes via HTTPS\"));\n\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = client.open(server.getUrl(\"/foo\"));\n\n    assertContent(\"this response comes via HTTPS\", connection);\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", request.getRequestLine());\n  }\n\n  @Test public void inspectHandshakeThroughoutRequestLifecycle() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse());\n\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n\n    HttpsURLConnection httpsConnection = (HttpsURLConnection) client.open(server.getUrl(\"/foo\"));\n\n    // Prior to calling connect(), getting the cipher suite is forbidden.\n    try {\n      httpsConnection.getCipherSuite();\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n\n    // Calling connect establishes a handshake...\n    httpsConnection.connect();\n    assertNotNull(httpsConnection.getCipherSuite());\n\n    // ...which remains after we read the response body...\n    assertContent(\"\", httpsConnection);\n    assertNotNull(httpsConnection.getCipherSuite());\n\n    // ...and after we disconnect.\n    httpsConnection.disconnect();\n    assertNotNull(httpsConnection.getCipherSuite());\n  }\n\n  @Test public void connectViaHttpsReusingConnections() throws IOException, InterruptedException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setBody(\"this response comes via HTTPS\"));\n    server.enqueue(new MockResponse().setBody(\"another response via HTTPS\"));\n\n    // The pool will only reuse sockets if the SSL socket factories are the same.\n    SSLSocketFactory clientSocketFactory = sslContext.getSocketFactory();\n    RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();\n\n    client.client().setSslSocketFactory(clientSocketFactory);\n    client.client().setHostnameVerifier(hostnameVerifier);\n    connection = client.open(server.getUrl(\"/\"));\n    assertContent(\"this response comes via HTTPS\", connection);\n\n    connection = client.open(server.getUrl(\"/\"));\n    assertContent(\"another response via HTTPS\", connection);\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void connectViaHttpsReusingConnectionsDifferentFactories()\n      throws IOException, InterruptedException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setBody(\"this response comes via HTTPS\"));\n    server.enqueue(new MockResponse().setBody(\"another response via HTTPS\"));\n\n    // install a custom SSL socket factory so the server can be authorized\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    HttpURLConnection connection1 = client.open(server.getUrl(\"/\"));\n    assertContent(\"this response comes via HTTPS\", connection1);\n\n    client.client().setSslSocketFactory(null);\n    HttpURLConnection connection2 = client.open(server.getUrl(\"/\"));\n    try {\n      readAscii(connection2.getInputStream(), Integer.MAX_VALUE);\n      fail(\"without an SSL socket factory, the connection should fail\");\n    } catch (SSLException expected) {\n    }\n  }\n\n  @Test public void connectViaHttpsWithSSLFallback() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));\n    server.enqueue(new MockResponse().setBody(\"this response comes via SSL\"));\n\n    suppressTlsFallbackScsv(client.client());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = client.open(server.getUrl(\"/foo\"));\n\n    assertContent(\"this response comes via SSL\", connection);\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", request.getRequestLine());\n    assertEquals(TlsVersion.TLS_1_0, request.getTlsVersion());\n  }\n\n  @Test public void connectViaHttpsWithSSLFallbackFailuresRecorded() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.FAIL_HANDSHAKE));\n\n    suppressTlsFallbackScsv(client.client());\n    client.client().setDns(new SingleInetAddressDns());\n\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = client.open(server.getUrl(\"/foo\"));\n\n    try {\n      connection.getResponseCode();\n      fail();\n    } catch (IOException expected) {\n      assertEquals(1, expected.getSuppressed().length);\n    }\n  }\n\n  /**\n   * When a pooled connection fails, don't blame the route. Otherwise pooled\n   * connection failures can cause unnecessary SSL fallbacks.\n   *\n   * https://github.com/square/okhttp/issues/515\n   */\n  @Test public void sslFallbackNotUsedWhenRecycledConnectionFails() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse()\n        .setBody(\"abc\")\n        .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n\n    suppressTlsFallbackScsv(client.client());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n\n    assertContent(\"abc\", client.open(server.getUrl(\"/\")));\n    assertContent(\"def\", client.open(server.getUrl(\"/\")));\n\n    Set<TlsVersion> tlsVersions =\n        EnumSet.of(TlsVersion.TLS_1_0, TlsVersion.TLS_1_2); // v1.2 on OpenJDK 8.\n\n    RecordedRequest request1 = server.takeRequest();\n    assertTrue(tlsVersions.contains(request1.getTlsVersion()));\n\n    RecordedRequest request2 = server.takeRequest();\n    assertTrue(tlsVersions.contains(request2.getTlsVersion()));\n  }\n\n  /**\n   * Verify that we don't retry connections on certificate verification errors.\n   *\n   * http://code.google.com/p/android/issues/detail?id=13178\n   */\n  @Test public void connectViaHttpsToUntrustedServer() throws IOException, InterruptedException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse()); // unused\n\n    connection = client.open(server.getUrl(\"/foo\"));\n    try {\n      connection.getInputStream();\n      fail();\n    } catch (SSLHandshakeException expected) {\n      assertTrue(expected.getCause() instanceof CertificateException);\n    }\n    assertEquals(0, server.getRequestCount());\n  }\n\n  @Test public void connectViaProxyUsingProxyArg() throws Exception {\n    testConnectViaProxy(ProxyConfig.CREATE_ARG);\n  }\n\n  @Test public void connectViaProxyUsingProxySystemProperty() throws Exception {\n    testConnectViaProxy(ProxyConfig.PROXY_SYSTEM_PROPERTY);\n  }\n\n  @Test public void connectViaProxyUsingHttpProxySystemProperty() throws Exception {\n    testConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY);\n  }\n\n  private void testConnectViaProxy(ProxyConfig proxyConfig) throws Exception {\n    MockResponse mockResponse = new MockResponse().setBody(\"this response comes via a proxy\");\n    server.enqueue(mockResponse);\n\n    URL url = new URL(\"http://android.com/foo\");\n    connection = proxyConfig.connect(server, client, url);\n    assertContent(\"this response comes via a proxy\", connection);\n    assertTrue(connection.usingProxy());\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"GET http://android.com/foo HTTP/1.1\", request.getRequestLine());\n    assertEquals(\"android.com\", request.getHeader(\"Host\"));\n  }\n\n  @Test public void contentDisagreesWithContentLengthHeaderBodyTooLong() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"abc\\r\\nYOU SHOULD NOT SEE THIS\")\n        .clearHeaders()\n        .addHeader(\"Content-Length: 3\"));\n    assertContent(\"abc\", client.open(server.getUrl(\"/\")));\n  }\n\n  @Test public void contentDisagreesWithContentLengthHeaderBodyTooShort() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"abc\")\n        .setHeader(\"Content-Length\", \"5\")\n        .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END));\n    try {\n      readAscii(client.open(server.getUrl(\"/\")).getInputStream(), 5);\n      fail();\n    } catch (ProtocolException expected) {\n    }\n  }\n\n  public void testConnectViaSocketFactory(boolean useHttps) throws IOException {\n    SocketFactory uselessSocketFactory = new SocketFactory() {\n      public Socket createSocket() { throw new IllegalArgumentException(\"useless\"); }\n      public Socket createSocket(InetAddress host, int port) { return null; }\n      public Socket createSocket(InetAddress address, int port, InetAddress localAddress,\n          int localPort) { return null; }\n      public Socket createSocket(String host, int port) { return null; }\n      public Socket createSocket(String host, int port, InetAddress localHost, int localPort) {\n        return null;\n      }\n    };\n\n    if (useHttps) {\n      server.useHttps(sslContext.getSocketFactory(), false);\n      client.client().setSslSocketFactory(sslContext.getSocketFactory());\n      client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    }\n\n    server.enqueue(new MockResponse().setStatus(\"HTTP/1.1 200 OK\"));\n\n    client.client().setSocketFactory(uselessSocketFactory);\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getResponseCode();\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n\n    client.client().setSocketFactory(SocketFactory.getDefault());\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(200, connection.getResponseCode());\n  }\n\n  @Test public void connectHttpViaSocketFactory() throws Exception {\n    testConnectViaSocketFactory(false);\n  }\n\n  @Test public void connectHttpsViaSocketFactory() throws Exception {\n    testConnectViaSocketFactory(true);\n  }\n\n  @Test public void contentDisagreesWithChunkedHeaderBodyTooLong() throws IOException {\n    MockResponse mockResponse = new MockResponse();\n    mockResponse.setChunkedBody(\"abc\", 3);\n    Buffer buffer = mockResponse.getBody();\n    buffer.writeUtf8(\"\\r\\nYOU SHOULD NOT SEE THIS\");\n    mockResponse.setBody(buffer);\n    mockResponse.clearHeaders();\n    mockResponse.addHeader(\"Transfer-encoding: chunked\");\n\n    server.enqueue(mockResponse);\n\n    assertContent(\"abc\", client.open(server.getUrl(\"/\")));\n  }\n\n  @Test public void contentDisagreesWithChunkedHeaderBodyTooShort() throws IOException {\n    MockResponse mockResponse = new MockResponse();\n    mockResponse.setChunkedBody(\"abcde\", 5);\n\n    Buffer truncatedBody = new Buffer();\n    Buffer fullBody = mockResponse.getBody();\n    truncatedBody.write(fullBody, fullBody.indexOf((byte) 'e'));\n    mockResponse.setBody(truncatedBody);\n\n    mockResponse.clearHeaders();\n    mockResponse.addHeader(\"Transfer-encoding: chunked\");\n    mockResponse.setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);\n\n    server.enqueue(mockResponse);\n\n    try {\n      readAscii(client.open(server.getUrl(\"/\")).getInputStream(), 5);\n      fail();\n    } catch (ProtocolException expected) {\n    }\n  }\n\n  @Test public void connectViaHttpProxyToHttpsUsingProxyArgWithNoProxy() throws Exception {\n    testConnectViaDirectProxyToHttps(ProxyConfig.NO_PROXY);\n  }\n\n  @Test public void connectViaHttpProxyToHttpsUsingHttpProxySystemProperty() throws Exception {\n    // https should not use http proxy\n    testConnectViaDirectProxyToHttps(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY);\n  }\n\n  private void testConnectViaDirectProxyToHttps(ProxyConfig proxyConfig) throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setBody(\"this response comes via HTTPS\"));\n\n    URL url = server.getUrl(\"/foo\");\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = proxyConfig.connect(server, client, url);\n\n    assertContent(\"this response comes via HTTPS\", connection);\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", request.getRequestLine());\n  }\n\n  @Test public void connectViaHttpProxyToHttpsUsingProxyArg() throws Exception {\n    testConnectViaHttpProxyToHttps(ProxyConfig.CREATE_ARG);\n  }\n\n  /**\n   * We weren't honoring all of the appropriate proxy system properties when\n   * connecting via HTTPS. http://b/3097518\n   */\n  @Test public void connectViaHttpProxyToHttpsUsingProxySystemProperty() throws Exception {\n    testConnectViaHttpProxyToHttps(ProxyConfig.PROXY_SYSTEM_PROPERTY);\n  }\n\n  @Test public void connectViaHttpProxyToHttpsUsingHttpsProxySystemProperty() throws Exception {\n    testConnectViaHttpProxyToHttps(ProxyConfig.HTTPS_PROXY_SYSTEM_PROPERTY);\n  }\n\n  /**\n   * We were verifying the wrong hostname when connecting to an HTTPS site\n   * through a proxy. http://b/3097277\n   */\n  private void testConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception {\n    RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();\n\n    server.useHttps(sslContext.getSocketFactory(), true);\n    server.enqueue(\n        new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders());\n    server.enqueue(new MockResponse().setBody(\"this response comes via a secure proxy\"));\n\n    URL url = new URL(\"https://android.com/foo\");\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(hostnameVerifier);\n    connection = proxyConfig.connect(server, client, url);\n\n    assertContent(\"this response comes via a secure proxy\", connection);\n\n    RecordedRequest connect = server.takeRequest();\n    assertEquals(\"Connect line failure on proxy\", \"CONNECT android.com:443 HTTP/1.1\",\n        connect.getRequestLine());\n    assertEquals(\"android.com\", connect.getHeader(\"Host\"));\n\n    RecordedRequest get = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", get.getRequestLine());\n    assertEquals(\"android.com\", get.getHeader(\"Host\"));\n    assertEquals(Arrays.asList(\"verify android.com\"), hostnameVerifier.calls);\n  }\n\n  /** Tolerate bad https proxy response when using HttpResponseCache. Android bug 6754912. */\n  @Test public void connectViaHttpProxyToHttpsUsingBadProxyAndHttpResponseCache() throws Exception {\n    initResponseCache();\n\n    server.useHttps(sslContext.getSocketFactory(), true);\n    // The inclusion of a body in the response to a CONNECT is key to reproducing b/6754912.\n    MockResponse badProxyResponse = new MockResponse()\n        .setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END)\n        .setBody(\"bogus proxy connect response content\");\n    server.enqueue(badProxyResponse);\n    server.enqueue(new MockResponse().setBody(\"response\"));\n\n    // Configure a single IP address for the host and a single configuration, so we only need one\n    // failure to fail permanently.\n    client.client().setDns(new SingleInetAddressDns());\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setConnectionSpecs(Util.immutableList(ConnectionSpec.MODERN_TLS));\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    client.client().setProxy(server.toProxyAddress());\n\n    URL url = new URL(\"https://android.com/foo\");\n    connection = client.open(url);\n    assertContent(\"response\", connection);\n\n    RecordedRequest connect = server.takeRequest();\n    assertEquals(\"CONNECT android.com:443 HTTP/1.1\", connect.getRequestLine());\n    assertEquals(\"android.com\", connect.getHeader(\"Host\"));\n  }\n\n  private void initResponseCache() throws IOException {\n    cache = new Cache(tempDir.getRoot(), Integer.MAX_VALUE);\n    client.client().setCache(cache);\n  }\n\n  /** Test which headers are sent unencrypted to the HTTP proxy. */\n  @Test public void proxyConnectIncludesProxyHeadersOnly()\n      throws IOException, InterruptedException {\n    RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();\n\n    server.useHttps(sslContext.getSocketFactory(), true);\n    server.enqueue(\n        new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders());\n    server.enqueue(new MockResponse().setBody(\"encrypted response from the origin server\"));\n\n    client.client().setProxy(server.toProxyAddress());\n\n    URL url = new URL(\"https://android.com/foo\");\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(hostnameVerifier);\n    connection = client.open(url);\n    connection.addRequestProperty(\"Private\", \"Secret\");\n    connection.addRequestProperty(\"Proxy-Authorization\", \"bar\");\n    connection.addRequestProperty(\"User-Agent\", \"baz\");\n    assertContent(\"encrypted response from the origin server\", connection);\n\n    RecordedRequest connect = server.takeRequest();\n    assertNull(connect.getHeader(\"Private\"));\n    assertNull(connect.getHeader(\"Proxy-Authorization\"));\n    assertEquals(Version.userAgent(), connect.getHeader(\"User-Agent\"));\n    assertEquals(\"android.com\", connect.getHeader(\"Host\"));\n    assertEquals(\"Keep-Alive\", connect.getHeader(\"Proxy-Connection\"));\n\n    RecordedRequest get = server.takeRequest();\n    assertEquals(\"Secret\", get.getHeader(\"Private\"));\n    assertEquals(Arrays.asList(\"verify android.com\"), hostnameVerifier.calls);\n  }\n\n  @Test public void proxyAuthenticateOnConnect() throws Exception {\n    Authenticator.setDefault(new RecordingAuthenticator());\n    server.useHttps(sslContext.getSocketFactory(), true);\n    server.enqueue(new MockResponse().setResponseCode(407)\n        .addHeader(\"Proxy-Authenticate: Basic realm=\\\"localhost\\\"\"));\n    server.enqueue(\n        new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders());\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    client.client().setProxy(server.toProxyAddress());\n\n    URL url = new URL(\"https://android.com/foo\");\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = client.open(url);\n    assertContent(\"A\", connection);\n\n    RecordedRequest connect1 = server.takeRequest();\n    assertEquals(\"CONNECT android.com:443 HTTP/1.1\", connect1.getRequestLine());\n    assertNull(connect1.getHeader(\"Proxy-Authorization\"));\n\n    RecordedRequest connect2 = server.takeRequest();\n    assertEquals(\"CONNECT android.com:443 HTTP/1.1\", connect2.getRequestLine());\n    assertEquals(\"Basic \" + RecordingAuthenticator.BASE_64_CREDENTIALS,\n        connect2.getHeader(\"Proxy-Authorization\"));\n\n    RecordedRequest get = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", get.getRequestLine());\n    assertNull(get.getHeader(\"Proxy-Authorization\"));\n  }\n\n  // Don't disconnect after building a tunnel with CONNECT\n  // http://code.google.com/p/android/issues/detail?id=37221\n  @Test public void proxyWithConnectionClose() throws IOException {\n    server.useHttps(sslContext.getSocketFactory(), true);\n    server.enqueue(\n        new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders());\n    server.enqueue(new MockResponse().setBody(\"this response comes via a proxy\"));\n\n    client.client().setProxy(server.toProxyAddress());\n\n    URL url = new URL(\"https://android.com/foo\");\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = client.open(url);\n    connection.setRequestProperty(\"Connection\", \"close\");\n\n    assertContent(\"this response comes via a proxy\", connection);\n  }\n\n  @Test public void proxyWithConnectionReuse() throws IOException {\n    SSLSocketFactory socketFactory = sslContext.getSocketFactory();\n    RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();\n\n    server.useHttps(socketFactory, true);\n    server.enqueue(\n        new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END).clearHeaders());\n    server.enqueue(new MockResponse().setBody(\"response 1\"));\n    server.enqueue(new MockResponse().setBody(\"response 2\"));\n\n    client.client().setProxy(server.toProxyAddress());\n\n    URL url = new URL(\"https://android.com/foo\");\n    client.client().setSslSocketFactory(socketFactory);\n    client.client().setHostnameVerifier(hostnameVerifier);\n    assertContent(\"response 1\", client.open(url));\n    assertContent(\"response 2\", client.open(url));\n  }\n\n  @Test public void disconnectedConnection() throws IOException {\n    server.enqueue(new MockResponse()\n        .throttleBody(2, 100, TimeUnit.MILLISECONDS)\n        .setBody(\"ABCD\"));\n\n    connection = client.open(server.getUrl(\"/\"));\n    InputStream in = connection.getInputStream();\n    assertEquals('A', (char) in.read());\n    connection.disconnect();\n    try {\n      // Reading 'B' may succeed if it's buffered.\n      in.read();\n\n      // But 'C' shouldn't be buffered (the response is throttled) and this should fail.\n      in.read();\n      fail(\"Expected a connection closed exception\");\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void disconnectBeforeConnect() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    connection = client.open(server.getUrl(\"/\"));\n    connection.disconnect();\n    assertContent(\"A\", connection);\n    assertEquals(200, connection.getResponseCode());\n  }\n\n  @SuppressWarnings(\"deprecation\") @Test public void defaultRequestProperty() throws Exception {\n    URLConnection.setDefaultRequestProperty(\"X-testSetDefaultRequestProperty\", \"A\");\n    assertNull(URLConnection.getDefaultRequestProperty(\"X-setDefaultRequestProperty\"));\n  }\n\n  /**\n   * Reads {@code count} characters from the stream. If the stream is\n   * exhausted before {@code count} characters can be read, the remaining\n   * characters are returned and the stream is closed.\n   */\n  private String readAscii(InputStream in, int count) throws IOException {\n    StringBuilder result = new StringBuilder();\n    for (int i = 0; i < count; i++) {\n      int value = in.read();\n      if (value == -1) {\n        in.close();\n        break;\n      }\n      result.append((char) value);\n    }\n    return result.toString();\n  }\n\n  @Test public void markAndResetWithContentLengthHeader() throws IOException {\n    testMarkAndReset(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void markAndResetWithChunkedEncoding() throws IOException {\n    testMarkAndReset(TransferKind.CHUNKED);\n  }\n\n  @Test public void markAndResetWithNoLengthHeaders() throws IOException {\n    testMarkAndReset(TransferKind.END_OF_STREAM);\n  }\n\n  private void testMarkAndReset(TransferKind transferKind) throws IOException {\n    MockResponse response = new MockResponse();\n    transferKind.setBody(response, \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", 1024);\n    server.enqueue(response);\n    server.enqueue(response);\n\n    InputStream in = client.open(server.getUrl(\"/\")).getInputStream();\n    assertFalse(\"This implementation claims to support mark().\", in.markSupported());\n    in.mark(5);\n    assertEquals(\"ABCDE\", readAscii(in, 5));\n    try {\n      in.reset();\n      fail();\n    } catch (IOException expected) {\n    }\n    assertEquals(\"FGHIJKLMNOPQRSTUVWXYZ\", readAscii(in, Integer.MAX_VALUE));\n    assertContent(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", client.open(server.getUrl(\"/\")));\n  }\n\n  /**\n   * We've had a bug where we forget the HTTP response when we see response\n   * code 401. This causes a new HTTP request to be issued for every call into\n   * the URLConnection.\n   */\n  @Test public void unauthorizedResponseHandling() throws IOException {\n    MockResponse response = new MockResponse().addHeader(\"WWW-Authenticate: challenge\")\n        .setResponseCode(401) // UNAUTHORIZED\n        .setBody(\"Unauthorized\");\n    server.enqueue(response);\n    server.enqueue(response);\n    server.enqueue(response);\n\n    URL url = server.getUrl(\"/\");\n    HttpURLConnection conn = client.open(url);\n\n    assertEquals(401, conn.getResponseCode());\n    assertEquals(401, conn.getResponseCode());\n    assertEquals(401, conn.getResponseCode());\n    assertEquals(1, server.getRequestCount());\n  }\n\n  @Test public void nonHexChunkSize() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"5\\r\\nABCDE\\r\\nG\\r\\nFGHIJKLMNOPQRSTU\\r\\n0\\r\\n\\r\\n\")\n        .clearHeaders()\n        .addHeader(\"Transfer-encoding: chunked\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    try {\n      readAscii(connection.getInputStream(), Integer.MAX_VALUE);\n      fail();\n    } catch (IOException e) {\n    }\n  }\n\n  @Test public void malformedChunkSize() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"5:x\\r\\nABCDE\\r\\n0\\r\\n\\r\\n\")\n        .clearHeaders()\n        .addHeader(\"Transfer-encoding: chunked\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    try {\n      readAscii(connection.getInputStream(), Integer.MAX_VALUE);\n      fail();\n    } catch (IOException e) {\n    }\n  }\n\n  @Test public void extensionAfterChunkSize() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"5;x\\r\\nABCDE\\r\\n0\\r\\n\\r\\n\")\n        .clearHeaders()\n        .addHeader(\"Transfer-encoding: chunked\"));\n\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    assertContent(\"ABCDE\", connection);\n  }\n\n  @Test public void missingChunkBody() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"5\")\n        .clearHeaders()\n        .addHeader(\"Transfer-encoding: chunked\")\n        .setSocketPolicy(DISCONNECT_AT_END));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    try {\n      readAscii(connection.getInputStream(), Integer.MAX_VALUE);\n      fail();\n    } catch (IOException e) {\n    }\n  }\n\n  /**\n   * This test checks whether connections are gzipped by default. This\n   * behavior in not required by the API, so a failure of this test does not\n   * imply a bug in the implementation.\n   */\n  @Test public void gzipEncodingEnabledByDefault() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse()\n        .setBody(gzip(\"ABCABCABC\"))\n        .addHeader(\"Content-Encoding: gzip\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"ABCABCABC\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n    assertNull(connection.getContentEncoding());\n    assertEquals(-1, connection.getContentLength());\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"gzip\", request.getHeader(\"Accept-Encoding\"));\n  }\n\n  @Test public void clientConfiguredGzipContentEncoding() throws Exception {\n    Buffer bodyBytes = gzip(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n    server.enqueue(new MockResponse()\n        .setBody(bodyBytes)\n        .addHeader(\"Content-Encoding: gzip\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Accept-Encoding\", \"gzip\");\n    InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream());\n    assertEquals(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", readAscii(gunzippedIn, Integer.MAX_VALUE));\n    assertEquals(bodyBytes.size(), connection.getContentLength());\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"gzip\", request.getHeader(\"Accept-Encoding\"));\n  }\n\n  @Test public void gzipAndConnectionReuseWithFixedLength() throws Exception {\n    testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.FIXED_LENGTH, false);\n  }\n\n  @Test public void gzipAndConnectionReuseWithChunkedEncoding() throws Exception {\n    testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.CHUNKED, false);\n  }\n\n  @Test public void gzipAndConnectionReuseWithFixedLengthAndTls() throws Exception {\n    testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.FIXED_LENGTH, true);\n  }\n\n  @Test public void gzipAndConnectionReuseWithChunkedEncodingAndTls() throws Exception {\n    testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.CHUNKED, true);\n  }\n\n  @Test public void clientConfiguredCustomContentEncoding() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"ABCDE\").addHeader(\"Content-Encoding: custom\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Accept-Encoding\", \"custom\");\n    assertEquals(\"ABCDE\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"custom\", request.getHeader(\"Accept-Encoding\"));\n  }\n\n  /**\n   * Test a bug where gzip input streams weren't exhausting the input stream,\n   * which corrupted the request that followed or prevented connection reuse.\n   * http://code.google.com/p/android/issues/detail?id=7059\n   * http://code.google.com/p/android/issues/detail?id=38817\n   */\n  private void testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind transferKind,\n      boolean tls) throws Exception {\n    if (tls) {\n      SSLSocketFactory socketFactory = sslContext.getSocketFactory();\n      RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();\n      server.useHttps(socketFactory, false);\n      client.client().setSslSocketFactory(socketFactory);\n      client.client().setHostnameVerifier(hostnameVerifier);\n    }\n\n    MockResponse responseOne = new MockResponse();\n    responseOne.addHeader(\"Content-Encoding: gzip\");\n    transferKind.setBody(responseOne, gzip(\"one (gzipped)\"), 5);\n    server.enqueue(responseOne);\n    MockResponse responseTwo = new MockResponse();\n    transferKind.setBody(responseTwo, \"two (identity)\", 5);\n    server.enqueue(responseTwo);\n\n    HttpURLConnection connection1 = client.open(server.getUrl(\"/\"));\n    connection1.addRequestProperty(\"Accept-Encoding\", \"gzip\");\n    InputStream gunzippedIn = new GZIPInputStream(connection1.getInputStream());\n    assertEquals(\"one (gzipped)\", readAscii(gunzippedIn, Integer.MAX_VALUE));\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n\n    HttpURLConnection connection2 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"two (identity)\", readAscii(connection2.getInputStream(), Integer.MAX_VALUE));\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void transparentGzipWorksAfterExceptionRecovery() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(\"a\")\n        .setSocketPolicy(SHUTDOWN_INPUT_AT_END));\n    server.enqueue(new MockResponse()\n        .addHeader(\"Content-Encoding: gzip\")\n        .setBody(gzip(\"b\")));\n\n    // Seed the pool with a bad connection.\n    assertContent(\"a\", client.open(server.getUrl(\"/\")));\n\n    // This connection will need to be recovered. When it is, transparent gzip should still work!\n    assertContent(\"b\", client.open(server.getUrl(\"/\")));\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(0, server.takeRequest().getSequenceNumber()); // Connection is not pooled.\n  }\n\n  @Test public void endOfStreamResponseIsNotPooled() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(\"{}\")\n        .clearHeaders()\n        .setSocketPolicy(DISCONNECT_AT_END));\n\n    ConnectionPool pool = ConnectionPool.getDefault();\n    pool.evictAll();\n    client.client().setConnectionPool(pool);\n\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    assertContent(\"{}\", connection);\n    assertEquals(0, client.client().getConnectionPool().getConnectionCount());\n  }\n\n  @Test public void earlyDisconnectDoesntHarmPoolingWithChunkedEncoding() throws Exception {\n    testEarlyDisconnectDoesntHarmPooling(TransferKind.CHUNKED);\n  }\n\n  @Test public void earlyDisconnectDoesntHarmPoolingWithFixedLengthEncoding() throws Exception {\n    testEarlyDisconnectDoesntHarmPooling(TransferKind.FIXED_LENGTH);\n  }\n\n  private void testEarlyDisconnectDoesntHarmPooling(TransferKind transferKind) throws Exception {\n    MockResponse response1 = new MockResponse();\n    transferKind.setBody(response1, \"ABCDEFGHIJK\", 1024);\n    server.enqueue(response1);\n\n    MockResponse response2 = new MockResponse();\n    transferKind.setBody(response2, \"LMNOPQRSTUV\", 1024);\n    server.enqueue(response2);\n\n    HttpURLConnection connection1 = client.open(server.getUrl(\"/\"));\n    InputStream in1 = connection1.getInputStream();\n    assertEquals(\"ABCDE\", readAscii(in1, 5));\n    in1.close();\n    connection1.disconnect();\n\n    HttpURLConnection connection2 = client.open(server.getUrl(\"/\"));\n    InputStream in2 = connection2.getInputStream();\n    assertEquals(\"LMNOP\", readAscii(in2, 5));\n    in2.close();\n    connection2.disconnect();\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(1, server.takeRequest().getSequenceNumber()); // Connection is pooled!\n  }\n\n  @Test public void streamDiscardingIsTimely() throws Exception {\n    // This response takes at least a full second to serve: 10,000 bytes served 100 bytes at a time.\n    server.enqueue(new MockResponse()\n        .setBody(new Buffer().write(new byte[10000]))\n        .throttleBody(100, 10, MILLISECONDS));\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    long startNanos = System.nanoTime();\n    URLConnection connection1 = client.open(server.getUrl(\"/\"));\n    InputStream in = connection1.getInputStream();\n    in.close();\n    long elapsedNanos = System.nanoTime() - startNanos;\n    long elapsedMillis = NANOSECONDS.toMillis(elapsedNanos);\n\n    // If we're working correctly, this should be greater than 100ms, but less than double that.\n    // Previously we had a bug where we would download the entire response body as long as no\n    // individual read took longer than 100ms.\n    assertTrue(String.format(\"Time to close: %sms\", elapsedMillis), elapsedMillis < 500);\n\n    // Do another request to confirm that the discarded connection was not pooled.\n    assertContent(\"A\", client.open(server.getUrl(\"/\")));\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(0, server.takeRequest().getSequenceNumber()); // Connection is not pooled.\n  }\n\n  @Test public void setChunkedStreamingMode() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse());\n\n    String body = \"ABCDEFGHIJKLMNOPQ\";\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setChunkedStreamingMode(0); // OkHttp does not honor specific chunk sizes.\n    connection.setDoOutput(true);\n    OutputStream outputStream = connection.getOutputStream();\n    outputStream.write(body.getBytes(\"US-ASCII\"));\n    assertEquals(200, connection.getResponseCode());\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(body, request.getBody().readUtf8());\n    assertEquals(Arrays.asList(body.length()), request.getChunkSizes());\n  }\n\n  @Test public void authenticateWithFixedLengthStreaming() throws Exception {\n    testAuthenticateWithStreamingPost(StreamingMode.FIXED_LENGTH);\n  }\n\n  @Test public void authenticateWithChunkedStreaming() throws Exception {\n    testAuthenticateWithStreamingPost(StreamingMode.CHUNKED);\n  }\n\n  private void testAuthenticateWithStreamingPost(StreamingMode streamingMode) throws Exception {\n    MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401)\n        .addHeader(\"WWW-Authenticate: Basic realm=\\\"protected area\\\"\")\n        .setBody(\"Please authenticate.\");\n    server.enqueue(pleaseAuthenticate);\n\n    Authenticator.setDefault(new RecordingAuthenticator());\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    byte[] requestBody = { 'A', 'B', 'C', 'D' };\n    if (streamingMode == StreamingMode.FIXED_LENGTH) {\n      connection.setFixedLengthStreamingMode(requestBody.length);\n    } else if (streamingMode == StreamingMode.CHUNKED) {\n      connection.setChunkedStreamingMode(0);\n    }\n    OutputStream outputStream = connection.getOutputStream();\n    outputStream.write(requestBody);\n    outputStream.close();\n    try {\n      connection.getInputStream();\n      fail();\n    } catch (HttpRetryException expected) {\n    }\n\n    // no authorization header for the request...\n    RecordedRequest request = server.takeRequest();\n    assertNull(request.getHeader(\"Authorization\"));\n    assertEquals(\"ABCD\", request.getBody().readUtf8());\n  }\n\n  @Test public void postBodyRetransmittedAfterAuthorizationFail() throws Exception {\n    postBodyRetransmittedAfterAuthorizationFail(\"abc\");\n  }\n\n  @Test public void postBodyRetransmittedAfterAuthorizationFail_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    postBodyRetransmittedAfterAuthorizationFail(\"abc\");\n  }\n\n  @Test public void postBodyRetransmittedAfterAuthorizationFail_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    postBodyRetransmittedAfterAuthorizationFail(\"abc\");\n  }\n\n  /** Don't explode when resending an empty post. https://github.com/square/okhttp/issues/1131 */\n  @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail() throws Exception {\n    postBodyRetransmittedAfterAuthorizationFail(\"\");\n  }\n\n  @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    postBodyRetransmittedAfterAuthorizationFail(\"\");\n  }\n\n  @Test public void postEmptyBodyRetransmittedAfterAuthorizationFail_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    postBodyRetransmittedAfterAuthorizationFail(\"\");\n  }\n\n  private void postBodyRetransmittedAfterAuthorizationFail(String body) throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(401));\n    server.enqueue(new MockResponse());\n\n    String credential = Credentials.basic(\"jesse\", \"secret\");\n    client.client().setAuthenticator(new RecordingOkAuthenticator(credential));\n\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    OutputStream outputStream = connection.getOutputStream();\n    outputStream.write(body.getBytes(\"UTF-8\"));\n    outputStream.close();\n    assertEquals(200, connection.getResponseCode());\n\n    RecordedRequest recordedRequest1 = server.takeRequest();\n    assertEquals(\"POST\", recordedRequest1.getMethod());\n    assertEquals(body, recordedRequest1.getBody().readUtf8());\n    assertNull(recordedRequest1.getHeader(\"Authorization\"));\n\n    RecordedRequest recordedRequest2 = server.takeRequest();\n    assertEquals(\"POST\", recordedRequest2.getMethod());\n    assertEquals(body, recordedRequest2.getBody().readUtf8());\n    assertEquals(credential, recordedRequest2.getHeader(\"Authorization\"));\n  }\n\n  @Test public void nonStandardAuthenticationScheme() throws Exception {\n    List<String> calls = authCallsForHeader(\"WWW-Authenticate: Foo\");\n    assertEquals(Collections.<String>emptyList(), calls);\n  }\n\n  @Test public void nonStandardAuthenticationSchemeWithRealm() throws Exception {\n    List<String> calls = authCallsForHeader(\"WWW-Authenticate: Foo realm=\\\"Bar\\\"\");\n    assertEquals(0, calls.size());\n  }\n\n  // Digest auth is currently unsupported. Test that digest requests should fail reasonably.\n  // http://code.google.com/p/android/issues/detail?id=11140\n  @Test public void digestAuthentication() throws Exception {\n    List<String> calls = authCallsForHeader(\"WWW-Authenticate: Digest \"\n        + \"realm=\\\"testrealm@host.com\\\", qop=\\\"auth,auth-int\\\", \"\n        + \"nonce=\\\"dcd98b7102dd2f0e8b11d0f600bfb0c093\\\", \"\n        + \"opaque=\\\"5ccc069c403ebaf9f0171e9517f40e41\\\"\");\n    assertEquals(0, calls.size());\n  }\n\n  @Test public void allAttributesSetInServerAuthenticationCallbacks() throws Exception {\n    List<String> calls = authCallsForHeader(\"WWW-Authenticate: Basic realm=\\\"Bar\\\"\");\n    assertEquals(1, calls.size());\n    URL url = server.getUrl(\"/\");\n    String call = calls.get(0);\n    assertTrue(call, call.contains(\"host=\" + url.getHost()));\n    assertTrue(call, call.contains(\"port=\" + url.getPort()));\n    assertTrue(call, call.contains(\"site=\" + url.getHost()));\n    assertTrue(call, call.contains(\"url=\" + url));\n    assertTrue(call, call.contains(\"type=\" + Authenticator.RequestorType.SERVER));\n    assertTrue(call, call.contains(\"prompt=Bar\"));\n    assertTrue(call, call.contains(\"protocol=http\"));\n    assertTrue(call, call.toLowerCase().contains(\"scheme=basic\")); // lowercase for the RI.\n  }\n\n  @Test public void allAttributesSetInProxyAuthenticationCallbacks() throws Exception {\n    List<String> calls = authCallsForHeader(\"Proxy-Authenticate: Basic realm=\\\"Bar\\\"\");\n    assertEquals(1, calls.size());\n    URL url = server.getUrl(\"/\");\n    String call = calls.get(0);\n    assertTrue(call, call.contains(\"host=\" + url.getHost()));\n    assertTrue(call, call.contains(\"port=\" + url.getPort()));\n    assertTrue(call, call.contains(\"site=\" + url.getHost()));\n    assertTrue(call, call.contains(\"url=http://android.com\"));\n    assertTrue(call, call.contains(\"type=\" + Authenticator.RequestorType.PROXY));\n    assertTrue(call, call.contains(\"prompt=Bar\"));\n    assertTrue(call, call.contains(\"protocol=http\"));\n    assertTrue(call, call.toLowerCase().contains(\"scheme=basic\")); // lowercase for the RI.\n  }\n\n  private List<String> authCallsForHeader(String authHeader) throws IOException {\n    boolean proxy = authHeader.startsWith(\"Proxy-\");\n    int responseCode = proxy ? 407 : 401;\n    RecordingAuthenticator authenticator = new RecordingAuthenticator(null);\n    Authenticator.setDefault(authenticator);\n    MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(responseCode)\n        .addHeader(authHeader)\n        .setBody(\"Please authenticate.\");\n    server.enqueue(pleaseAuthenticate);\n\n    if (proxy) {\n      client.client().setProxy(server.toProxyAddress());\n      connection = client.open(new URL(\"http://android.com\"));\n    } else {\n      connection = client.open(server.getUrl(\"/\"));\n    }\n    assertEquals(responseCode, connection.getResponseCode());\n    return authenticator.calls;\n  }\n\n  @Test public void setValidRequestMethod() throws Exception {\n    assertValidRequestMethod(\"GET\");\n    assertValidRequestMethod(\"DELETE\");\n    assertValidRequestMethod(\"HEAD\");\n    assertValidRequestMethod(\"OPTIONS\");\n    assertValidRequestMethod(\"POST\");\n    assertValidRequestMethod(\"PUT\");\n    assertValidRequestMethod(\"TRACE\");\n    assertValidRequestMethod(\"PATCH\");\n  }\n\n  private void assertValidRequestMethod(String requestMethod) throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setRequestMethod(requestMethod);\n    assertEquals(requestMethod, connection.getRequestMethod());\n  }\n\n  @Test public void setInvalidRequestMethodLowercase() throws Exception {\n    assertInvalidRequestMethod(\"get\");\n  }\n\n  @Test public void setInvalidRequestMethodConnect() throws Exception {\n    assertInvalidRequestMethod(\"CONNECT\");\n  }\n\n  private void assertInvalidRequestMethod(String requestMethod) throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.setRequestMethod(requestMethod);\n      fail();\n    } catch (ProtocolException expected) {\n    }\n  }\n\n  @Test public void shoutcast() throws Exception {\n    server.enqueue(new MockResponse().setStatus(\"ICY 200 OK\")\n        // .addHeader(\"HTTP/1.0 200 OK\")\n        .addHeader(\"Accept-Ranges: none\")\n        .addHeader(\"Content-Type: audio/mpeg\")\n        .addHeader(\"icy-br:128\")\n        .addHeader(\"ice-audio-info: bitrate=128;samplerate=44100;channels=2\")\n        .addHeader(\"icy-br:128\")\n        .addHeader(\"icy-description:Rock\")\n        .addHeader(\"icy-genre:riders\")\n        .addHeader(\"icy-name:A2RRock\")\n        .addHeader(\"icy-pub:1\")\n        .addHeader(\"icy-url:http://www.A2Rradio.com\")\n        .addHeader(\"Server: Icecast 2.3.3-kh8\")\n        .addHeader(\"Cache-Control: no-cache\")\n        .addHeader(\"Pragma: no-cache\")\n        .addHeader(\"Expires: Mon, 26 Jul 1997 05:00:00 GMT\")\n        .addHeader(\"icy-metaint:16000\")\n        .setBody(\"mp3 data\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(200, connection.getResponseCode());\n    assertEquals(\"OK\", connection.getResponseMessage());\n    assertContent(\"mp3 data\", connection);\n  }\n\n  @Test public void cannotSetNegativeFixedLengthStreamingMode() throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.setFixedLengthStreamingMode(-2);\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void canSetNegativeChunkedStreamingMode() throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setChunkedStreamingMode(-2);\n  }\n\n  @Test public void cannotSetFixedLengthStreamingModeAfterConnect() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n    try {\n      connection.setFixedLengthStreamingMode(1);\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void cannotSetChunkedStreamingModeAfterConnect() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n    try {\n      connection.setChunkedStreamingMode(1);\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void cannotSetFixedLengthStreamingModeAfterChunkedStreamingMode() throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setChunkedStreamingMode(1);\n    try {\n      connection.setFixedLengthStreamingMode(1);\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void cannotSetChunkedStreamingModeAfterFixedLengthStreamingMode() throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setFixedLengthStreamingMode(1);\n    try {\n      connection.setChunkedStreamingMode(1);\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void secureFixedLengthStreaming() throws Exception {\n    testSecureStreamingPost(StreamingMode.FIXED_LENGTH);\n  }\n\n  @Test public void secureChunkedStreaming() throws Exception {\n    testSecureStreamingPost(StreamingMode.CHUNKED);\n  }\n\n  /**\n   * Users have reported problems using HTTPS with streaming request bodies.\n   * http://code.google.com/p/android/issues/detail?id=12860\n   */\n  private void testSecureStreamingPost(StreamingMode streamingMode) throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setBody(\"Success!\"));\n\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    byte[] requestBody = { 'A', 'B', 'C', 'D' };\n    if (streamingMode == StreamingMode.FIXED_LENGTH) {\n      connection.setFixedLengthStreamingMode(requestBody.length);\n    } else if (streamingMode == StreamingMode.CHUNKED) {\n      connection.setChunkedStreamingMode(0);\n    }\n    OutputStream outputStream = connection.getOutputStream();\n    outputStream.write(requestBody);\n    outputStream.close();\n    assertEquals(\"Success!\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"POST / HTTP/1.1\", request.getRequestLine());\n    if (streamingMode == StreamingMode.FIXED_LENGTH) {\n      assertEquals(Collections.<Integer>emptyList(), request.getChunkSizes());\n    } else if (streamingMode == StreamingMode.CHUNKED) {\n      assertEquals(Arrays.asList(4), request.getChunkSizes());\n    }\n    assertEquals(\"ABCD\", request.getBody().readUtf8());\n  }\n\n  enum StreamingMode {\n    FIXED_LENGTH, CHUNKED\n  }\n\n  @Test public void authenticateWithPost() throws Exception {\n    MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401)\n        .addHeader(\"WWW-Authenticate: Basic realm=\\\"protected area\\\"\")\n        .setBody(\"Please authenticate.\");\n    // fail auth three times...\n    server.enqueue(pleaseAuthenticate);\n    server.enqueue(pleaseAuthenticate);\n    server.enqueue(pleaseAuthenticate);\n    // ...then succeed the fourth time\n    server.enqueue(new MockResponse().setBody(\"Successful auth!\"));\n\n    Authenticator.setDefault(new RecordingAuthenticator());\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    byte[] requestBody = { 'A', 'B', 'C', 'D' };\n    OutputStream outputStream = connection.getOutputStream();\n    outputStream.write(requestBody);\n    outputStream.close();\n    assertEquals(\"Successful auth!\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    // no authorization header for the first request...\n    RecordedRequest request = server.takeRequest();\n    assertNull(request.getHeader(\"Authorization\"));\n\n    // ...but the three requests that follow include an authorization header\n    for (int i = 0; i < 3; i++) {\n      request = server.takeRequest();\n      assertEquals(\"POST / HTTP/1.1\", request.getRequestLine());\n      assertEquals(\"Basic \" + RecordingAuthenticator.BASE_64_CREDENTIALS,\n          request.getHeader(\"Authorization\"));\n      assertEquals(\"ABCD\", request.getBody().readUtf8());\n    }\n  }\n\n  @Test public void authenticateWithGet() throws Exception {\n    MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401)\n        .addHeader(\"WWW-Authenticate: Basic realm=\\\"protected area\\\"\")\n        .setBody(\"Please authenticate.\");\n    // fail auth three times...\n    server.enqueue(pleaseAuthenticate);\n    server.enqueue(pleaseAuthenticate);\n    server.enqueue(pleaseAuthenticate);\n    // ...then succeed the fourth time\n    server.enqueue(new MockResponse().setBody(\"Successful auth!\"));\n\n    Authenticator.setDefault(new RecordingAuthenticator());\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"Successful auth!\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    // no authorization header for the first request...\n    RecordedRequest request = server.takeRequest();\n    assertNull(request.getHeader(\"Authorization\"));\n\n    // ...but the three requests that follow requests include an authorization header\n    for (int i = 0; i < 3; i++) {\n      request = server.takeRequest();\n      assertEquals(\"GET / HTTP/1.1\", request.getRequestLine());\n      assertEquals(\"Basic \" + RecordingAuthenticator.BASE_64_CREDENTIALS,\n          request.getHeader(\"Authorization\"));\n    }\n  }\n\n  /** https://code.google.com/p/android/issues/detail?id=74026 */\n  @Test public void authenticateWithGetAndTransparentGzip() throws Exception {\n    MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401)\n        .addHeader(\"WWW-Authenticate: Basic realm=\\\"protected area\\\"\")\n        .setBody(\"Please authenticate.\");\n    // fail auth three times...\n    server.enqueue(pleaseAuthenticate);\n    server.enqueue(pleaseAuthenticate);\n    server.enqueue(pleaseAuthenticate);\n    // ...then succeed the fourth time\n    MockResponse successfulResponse = new MockResponse()\n        .addHeader(\"Content-Encoding\", \"gzip\")\n        .setBody(gzip(\"Successful auth!\"));\n    server.enqueue(successfulResponse);\n\n    Authenticator.setDefault(new RecordingAuthenticator());\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"Successful auth!\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    // no authorization header for the first request...\n    RecordedRequest request = server.takeRequest();\n    assertNull(request.getHeader(\"Authorization\"));\n\n    // ...but the three requests that follow requests include an authorization header\n    for (int i = 0; i < 3; i++) {\n      request = server.takeRequest();\n      assertEquals(\"GET / HTTP/1.1\", request.getRequestLine());\n      assertEquals(\"Basic \" + RecordingAuthenticator.BASE_64_CREDENTIALS,\n          request.getHeader(\"Authorization\"));\n    }\n  }\n\n  /** https://github.com/square/okhttp/issues/342 */\n  @Test public void authenticateRealmUppercase() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(401)\n        .addHeader(\"wWw-aUtHeNtIcAtE: bAsIc rEaLm=\\\"pRoTeCtEd aReA\\\"\")\n        .setBody(\"Please authenticate.\"));\n    server.enqueue(new MockResponse().setBody(\"Successful auth!\"));\n\n    Authenticator.setDefault(new RecordingAuthenticator());\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"Successful auth!\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n  }\n\n  @Test public void redirectedWithChunkedEncoding() throws Exception {\n    testRedirected(TransferKind.CHUNKED, true);\n  }\n\n  @Test public void redirectedWithContentLengthHeader() throws Exception {\n    testRedirected(TransferKind.FIXED_LENGTH, true);\n  }\n\n  @Test public void redirectedWithNoLengthHeaders() throws Exception {\n    testRedirected(TransferKind.END_OF_STREAM, false);\n  }\n\n  private void testRedirected(TransferKind transferKind, boolean reuse) throws Exception {\n    MockResponse response = new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: /foo\");\n    transferKind.setBody(response, \"This page has moved!\", 10);\n    server.enqueue(response);\n    server.enqueue(new MockResponse().setBody(\"This is the new location!\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"This is the new location!\",\n        readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    RecordedRequest first = server.takeRequest();\n    assertEquals(\"GET / HTTP/1.1\", first.getRequestLine());\n    RecordedRequest retry = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", retry.getRequestLine());\n    if (reuse) {\n      assertEquals(\"Expected connection reuse\", 1, retry.getSequenceNumber());\n    }\n  }\n\n  @Test public void redirectedOnHttps() throws IOException, InterruptedException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: /foo\")\n        .setBody(\"This page has moved!\"));\n    server.enqueue(new MockResponse().setBody(\"This is the new location!\"));\n\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"This is the new location!\",\n        readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    RecordedRequest first = server.takeRequest();\n    assertEquals(\"GET / HTTP/1.1\", first.getRequestLine());\n    RecordedRequest retry = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", retry.getRequestLine());\n    assertEquals(\"Expected connection reuse\", 1, retry.getSequenceNumber());\n  }\n\n  @Test public void notRedirectedFromHttpsToHttp() throws IOException, InterruptedException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: http://anyhost/foo\")\n        .setBody(\"This page has moved!\"));\n\n    client.client().setFollowSslRedirects(false);\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"This page has moved!\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n  }\n\n  @Test public void notRedirectedFromHttpToHttps() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: https://anyhost/foo\")\n        .setBody(\"This page has moved!\"));\n\n    client.client().setFollowSslRedirects(false);\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"This page has moved!\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n  }\n\n  @Test public void redirectedFromHttpsToHttpFollowingProtocolRedirects() throws Exception {\n    server2.enqueue(new MockResponse().setBody(\"This is insecure HTTP!\"));\n\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: \" + server2.getUrl(\"/\"))\n        .setBody(\"This page has moved!\"));\n\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    client.client().setFollowSslRedirects(true);\n    HttpsURLConnection connection = (HttpsURLConnection) client.open(server.getUrl(\"/\"));\n    assertContent(\"This is insecure HTTP!\", connection);\n    assertNull(connection.getCipherSuite());\n    assertNull(connection.getLocalCertificates());\n    assertNull(connection.getServerCertificates());\n    assertNull(connection.getPeerPrincipal());\n    assertNull(connection.getLocalPrincipal());\n  }\n\n  @Test public void redirectedFromHttpToHttpsFollowingProtocolRedirects() throws Exception {\n    server2.useHttps(sslContext.getSocketFactory(), false);\n    server2.enqueue(new MockResponse().setBody(\"This is secure HTTPS!\"));\n\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: \" + server2.getUrl(\"/\"))\n        .setBody(\"This page has moved!\"));\n\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    client.client().setFollowSslRedirects(true);\n    connection = client.open(server.getUrl(\"/\"));\n    assertContent(\"This is secure HTTPS!\", connection);\n    assertFalse(connection instanceof HttpsURLConnection);\n  }\n\n  @Test public void redirectToAnotherOriginServer() throws Exception {\n    redirectToAnotherOriginServer(false);\n  }\n\n  @Test public void redirectToAnotherOriginServerWithHttps() throws Exception {\n    redirectToAnotherOriginServer(true);\n  }\n\n  private void redirectToAnotherOriginServer(boolean https) throws Exception {\n    if (https) {\n      server.useHttps(sslContext.getSocketFactory(), false);\n      server2.useHttps(sslContext.getSocketFactory(), false);\n      server2.setProtocolNegotiationEnabled(false);\n      client.client().setSslSocketFactory(sslContext.getSocketFactory());\n      client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    }\n\n    server2.enqueue(new MockResponse().setBody(\"This is the 2nd server!\"));\n    server2.enqueue(new MockResponse().setBody(\"This is the 2nd server, again!\"));\n\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: \" + server2.getUrl(\"/\").toString())\n        .setBody(\"This page has moved!\"));\n    server.enqueue(new MockResponse().setBody(\"This is the first server again!\"));\n\n    connection = client.open(server.getUrl(\"/\"));\n    assertContent(\"This is the 2nd server!\", connection);\n    assertEquals(server2.getUrl(\"/\"), connection.getURL());\n\n    // make sure the first server was careful to recycle the connection\n    assertContent(\"This is the first server again!\", client.open(server.getUrl(\"/\")));\n    assertContent(\"This is the 2nd server, again!\", client.open(server2.getUrl(\"/\")));\n\n    String server1Host = server.getHostName() + \":\" + server.getPort();\n    String server2Host = server2.getHostName() + \":\" + server2.getPort();\n    assertEquals(server1Host, server.takeRequest().getHeader(\"Host\"));\n    assertEquals(server2Host, server2.takeRequest().getHeader(\"Host\"));\n    assertEquals(\"Expected connection reuse\", 1, server.takeRequest().getSequenceNumber());\n    assertEquals(\"Expected connection reuse\", 1, server2.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void redirectWithProxySelector() throws Exception {\n    final List<URI> proxySelectionRequests = new ArrayList<URI>();\n    client.client().setProxySelector(new ProxySelector() {\n      @Override public List<Proxy> select(URI uri) {\n        proxySelectionRequests.add(uri);\n        MockWebServer proxyServer = (uri.getPort() == server.getPort())\n            ? server\n            : server2;\n        return Arrays.asList(proxyServer.toProxyAddress());\n      }\n\n      @Override public void connectFailed(URI uri, SocketAddress address, IOException failure) {\n        throw new AssertionError();\n      }\n    });\n\n    server2.enqueue(new MockResponse().setBody(\"This is the 2nd server!\"));\n\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: \" + server2.getUrl(\"/b\").toString())\n        .setBody(\"This page has moved!\"));\n\n    assertContent(\"This is the 2nd server!\", client.open(server.getUrl(\"/a\")));\n\n    assertEquals(Arrays.asList(server.getUrl(\"/a\").toURI(), server2.getUrl(\"/b\").toURI()),\n        proxySelectionRequests);\n  }\n\n  @Test public void redirectWithAuthentication() throws Exception {\n    server2.enqueue(new MockResponse().setBody(\"Page 2\"));\n\n    server.enqueue(new MockResponse().setResponseCode(401));\n    server.enqueue(new MockResponse().setResponseCode(302)\n        .addHeader(\"Location: \" + server2.getUrl(\"/b\")));\n\n    client.client().setAuthenticator(\n        new RecordingOkAuthenticator(Credentials.basic(\"jesse\", \"secret\")));\n    assertContent(\"Page 2\", client.open(server.getUrl(\"/a\")));\n\n    RecordedRequest redirectRequest = server2.takeRequest();\n    assertNull(redirectRequest.getHeader(\"Authorization\"));\n    assertEquals(\"/b\", redirectRequest.getPath());\n  }\n\n  @Test public void response300MultipleChoiceWithPost() throws Exception {\n    // Chrome doesn't follow the redirect, but Firefox and the RI both do\n    testResponseRedirectedWithPost(HttpURLConnection.HTTP_MULT_CHOICE, TransferKind.END_OF_STREAM);\n  }\n\n  @Test public void response301MovedPermanentlyWithPost() throws Exception {\n    testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_PERM, TransferKind.END_OF_STREAM);\n  }\n\n  @Test public void response302MovedTemporarilyWithPost() throws Exception {\n    testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_TEMP, TransferKind.END_OF_STREAM);\n  }\n\n  @Test public void response303SeeOtherWithPost() throws Exception {\n    testResponseRedirectedWithPost(HttpURLConnection.HTTP_SEE_OTHER, TransferKind.END_OF_STREAM);\n  }\n\n  @Test public void postRedirectToGetWithChunkedRequest() throws Exception {\n    testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_TEMP, TransferKind.CHUNKED);\n  }\n\n  @Test public void postRedirectToGetWithStreamedRequest() throws Exception {\n    testResponseRedirectedWithPost(HttpURLConnection.HTTP_MOVED_TEMP, TransferKind.FIXED_LENGTH);\n  }\n\n  private void testResponseRedirectedWithPost(int redirectCode, TransferKind transferKind)\n      throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(redirectCode)\n        .addHeader(\"Location: /page2\")\n        .setBody(\"This page has moved!\"));\n    server.enqueue(new MockResponse().setBody(\"Page 2\"));\n\n    connection = client.open(server.getUrl(\"/page1\"));\n    connection.setDoOutput(true);\n    transferKind.setForRequest(connection, 4);\n    byte[] requestBody = { 'A', 'B', 'C', 'D' };\n    OutputStream outputStream = connection.getOutputStream();\n    outputStream.write(requestBody);\n    outputStream.close();\n    assertEquals(\"Page 2\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n    assertTrue(connection.getDoOutput());\n\n    RecordedRequest page1 = server.takeRequest();\n    assertEquals(\"POST /page1 HTTP/1.1\", page1.getRequestLine());\n    assertEquals(\"ABCD\", page1.getBody().readUtf8());\n\n    RecordedRequest page2 = server.takeRequest();\n    assertEquals(\"GET /page2 HTTP/1.1\", page2.getRequestLine());\n  }\n\n  @Test public void redirectedPostStripsRequestBodyHeaders() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: /page2\"));\n    server.enqueue(new MockResponse().setBody(\"Page 2\"));\n\n    connection = client.open(server.getUrl(\"/page1\"));\n    connection.setDoOutput(true);\n    connection.addRequestProperty(\"Content-Length\", \"4\");\n    connection.addRequestProperty(\"Content-Type\", \"text/plain; charset=utf-8\");\n    connection.addRequestProperty(\"Transfer-Encoding\", \"identity\");\n    OutputStream outputStream = connection.getOutputStream();\n    outputStream.write(\"ABCD\".getBytes(\"UTF-8\"));\n    outputStream.close();\n    assertEquals(\"Page 2\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    assertEquals(\"POST /page1 HTTP/1.1\", server.takeRequest().getRequestLine());\n\n    RecordedRequest page2 = server.takeRequest();\n    assertEquals(\"GET /page2 HTTP/1.1\", page2.getRequestLine());\n    assertNull(page2.getHeader(\"Content-Length\"));\n    assertNull(page2.getHeader(\"Content-Type\"));\n    assertNull(page2.getHeader(\"Transfer-Encoding\"));\n  }\n\n  @Test public void response305UseProxy() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_USE_PROXY)\n        .addHeader(\"Location: \" + server.getUrl(\"/\"))\n        .setBody(\"This page has moved!\"));\n    server.enqueue(new MockResponse().setBody(\"Proxy Response\"));\n\n    connection = client.open(server.getUrl(\"/foo\"));\n    // Fails on the RI, which gets \"Proxy Response\"\n    assertEquals(\"This page has moved!\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    RecordedRequest page1 = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", page1.getRequestLine());\n    assertEquals(1, server.getRequestCount());\n  }\n\n  @Test public void response307WithGet() throws Exception {\n    testRedirect(true, \"GET\");\n  }\n\n  @Test public void response307WithHead() throws Exception {\n    testRedirect(true, \"HEAD\");\n  }\n\n  @Test public void response307WithOptions() throws Exception {\n    testRedirect(true, \"OPTIONS\");\n  }\n\n  @Test public void response307WithPost() throws Exception {\n    testRedirect(true, \"POST\");\n  }\n\n  @Test public void response308WithGet() throws Exception {\n    testRedirect(false, \"GET\");\n  }\n\n  @Test public void response308WithHead() throws Exception {\n    testRedirect(false, \"HEAD\");\n  }\n\n  @Test public void response308WithOptions() throws Exception {\n    testRedirect(false, \"OPTIONS\");\n  }\n\n  @Test public void response308WithPost() throws Exception {\n    testRedirect(false, \"POST\");\n  }\n\n  private void testRedirect(boolean temporary, String method) throws Exception {\n    MockResponse response1 = new MockResponse()\n        .setResponseCode(temporary ? HTTP_TEMP_REDIRECT : HTTP_PERM_REDIRECT)\n        .addHeader(\"Location: /page2\");\n    if (!method.equals(\"HEAD\")) {\n      response1.setBody(\"This page has moved!\");\n    }\n    server.enqueue(response1);\n    server.enqueue(new MockResponse().setBody(\"Page 2\"));\n\n    connection = client.open(server.getUrl(\"/page1\"));\n    connection.setRequestMethod(method);\n    byte[] requestBody = { 'A', 'B', 'C', 'D' };\n    if (method.equals(\"POST\")) {\n      connection.setDoOutput(true);\n      OutputStream outputStream = connection.getOutputStream();\n      outputStream.write(requestBody);\n      outputStream.close();\n    }\n\n    String response = readAscii(connection.getInputStream(), Integer.MAX_VALUE);\n\n    RecordedRequest page1 = server.takeRequest();\n    assertEquals(method + \" /page1 HTTP/1.1\", page1.getRequestLine());\n\n    if (method.equals(\"GET\")) {\n      assertEquals(\"Page 2\", response);\n    } else if (method.equals(\"HEAD\"))  {\n      assertEquals(\"\", response);\n    } else {\n      // Methods other than GET/HEAD shouldn't follow the redirect\n      if (method.equals(\"POST\")) {\n        assertTrue(connection.getDoOutput());\n        assertEquals(\"ABCD\", page1.getBody().readUtf8());\n      }\n      assertEquals(1, server.getRequestCount());\n      assertEquals(\"This page has moved!\", response);\n      return;\n    }\n\n    // GET/HEAD requests should have followed the redirect with the same method\n    assertFalse(connection.getDoOutput());\n    assertEquals(2, server.getRequestCount());\n    RecordedRequest page2 = server.takeRequest();\n    assertEquals(method + \" /page2 HTTP/1.1\", page2.getRequestLine());\n  }\n\n  @Test public void follow20Redirects() throws Exception {\n    for (int i = 0; i < 20; i++) {\n      server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n          .addHeader(\"Location: /\" + (i + 1))\n          .setBody(\"Redirecting to /\" + (i + 1)));\n    }\n    server.enqueue(new MockResponse().setBody(\"Success!\"));\n\n    connection = client.open(server.getUrl(\"/0\"));\n    assertContent(\"Success!\", connection);\n    assertEquals(server.getUrl(\"/20\"), connection.getURL());\n  }\n\n  @Test public void doesNotFollow21Redirects() throws Exception {\n    for (int i = 0; i < 21; i++) {\n      server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n          .addHeader(\"Location: /\" + (i + 1))\n          .setBody(\"Redirecting to /\" + (i + 1)));\n    }\n\n    connection = client.open(server.getUrl(\"/0\"));\n    try {\n      connection.getInputStream();\n      fail();\n    } catch (ProtocolException expected) {\n      assertEquals(HttpURLConnection.HTTP_MOVED_TEMP, connection.getResponseCode());\n      assertEquals(\"Too many follow-up requests: 21\", expected.getMessage());\n      assertContent(\"Redirecting to /21\", connection);\n      assertEquals(server.getUrl(\"/20\"), connection.getURL());\n    }\n  }\n\n  @Test public void httpsWithCustomTrustManager() throws Exception {\n    RecordingHostnameVerifier hostnameVerifier = new RecordingHostnameVerifier();\n    RecordingTrustManager trustManager = new RecordingTrustManager();\n    SSLContext sc = SSLContext.getInstance(\"TLS\");\n    sc.init(null, new TrustManager[] { trustManager }, new java.security.SecureRandom());\n\n    client.client().setHostnameVerifier(hostnameVerifier);\n    client.client().setSslSocketFactory(sc.getSocketFactory());\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().setBody(\"ABC\"));\n    server.enqueue(new MockResponse().setBody(\"DEF\"));\n    server.enqueue(new MockResponse().setBody(\"GHI\"));\n\n    URL url = server.getUrl(\"/\");\n    assertContent(\"ABC\", client.open(url));\n    assertContent(\"DEF\", client.open(url));\n    assertContent(\"GHI\", client.open(url));\n\n    assertEquals(Arrays.asList(\"verify \" + server.getHostName()),\n        hostnameVerifier.calls);\n    assertEquals(Arrays.asList(\"checkServerTrusted [CN=\" + server.getHostName() + \" 1]\"),\n        trustManager.calls);\n  }\n\n  @Test public void readTimeouts() throws IOException {\n    // This relies on the fact that MockWebServer doesn't close the\n    // connection after a response has been sent. This causes the client to\n    // try to read more bytes than are sent, which results in a timeout.\n    MockResponse timeout =\n        new MockResponse().setBody(\"ABC\").clearHeaders().addHeader(\"Content-Length: 4\");\n    server.enqueue(timeout);\n    server.enqueue(new MockResponse().setBody(\"unused\")); // to keep the server alive\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.setReadTimeout(1000);\n    InputStream in = connection.getInputStream();\n    assertEquals('A', in.read());\n    assertEquals('B', in.read());\n    assertEquals('C', in.read());\n    try {\n      in.read(); // if Content-Length was accurate, this would return -1 immediately\n      fail();\n    } catch (SocketTimeoutException expected) {\n    }\n  }\n\n  /** Confirm that an unacknowledged write times out. */\n  @Test public void writeTimeouts() throws IOException {\n    MockWebServer server = new MockWebServer();\n    // Sockets on some platforms can have large buffers that mean writes do not block when\n    // required. These socket factories explicitly set the buffer sizes on sockets created.\n    final int SOCKET_BUFFER_SIZE = 4 * 1024;\n    server.setServerSocketFactory(\n        new DelegatingServerSocketFactory(ServerSocketFactory.getDefault()) {\n          @Override\n          protected ServerSocket configureServerSocket(ServerSocket serverSocket)\n              throws IOException {\n            serverSocket.setReceiveBufferSize(SOCKET_BUFFER_SIZE);\n            return serverSocket;\n          }\n        });\n    client.client().setSocketFactory(new DelegatingSocketFactory(SocketFactory.getDefault()) {\n      @Override\n      protected Socket configureSocket(Socket socket) throws IOException {\n        socket.setReceiveBufferSize(SOCKET_BUFFER_SIZE);\n        socket.setSendBufferSize(SOCKET_BUFFER_SIZE);\n        return socket;\n      }\n    });\n\n    server.start();\n    server.enqueue(new MockResponse()\n        .throttleBody(1, 1, TimeUnit.SECONDS)); // Prevent the server from reading!\n\n    client.client().setWriteTimeout(500, TimeUnit.MILLISECONDS);\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    connection.setChunkedStreamingMode(0);\n    OutputStream out = connection.getOutputStream();\n    try {\n      byte[] data = new byte[2 * 1024 * 1024]; // 2 MiB.\n      out.write(data);\n      fail();\n    } catch (SocketTimeoutException expected) {\n    }\n  }\n\n  @Test public void setChunkedEncodingAsRequestProperty() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse());\n\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setRequestProperty(\"Transfer-encoding\", \"chunked\");\n    connection.setDoOutput(true);\n    connection.getOutputStream().write(\"ABC\".getBytes(\"UTF-8\"));\n    assertEquals(200, connection.getResponseCode());\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"ABC\", request.getBody().readUtf8());\n  }\n\n  @Test public void connectionCloseInRequest() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse()); // server doesn't honor the connection: close header!\n    server.enqueue(new MockResponse());\n\n    HttpURLConnection a = client.open(server.getUrl(\"/\"));\n    a.setRequestProperty(\"Connection\", \"close\");\n    assertEquals(200, a.getResponseCode());\n\n    HttpURLConnection b = client.open(server.getUrl(\"/\"));\n    assertEquals(200, b.getResponseCode());\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(\"When connection: close is used, each request should get its own connection\", 0,\n        server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void connectionCloseInResponse() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse().addHeader(\"Connection: close\"));\n    server.enqueue(new MockResponse());\n\n    HttpURLConnection a = client.open(server.getUrl(\"/\"));\n    assertEquals(200, a.getResponseCode());\n\n    HttpURLConnection b = client.open(server.getUrl(\"/\"));\n    assertEquals(200, b.getResponseCode());\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(\"When connection: close is used, each request should get its own connection\", 0,\n        server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void connectionCloseWithRedirect() throws IOException, InterruptedException {\n    MockResponse response = new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: /foo\")\n        .addHeader(\"Connection: close\");\n    server.enqueue(response);\n    server.enqueue(new MockResponse().setBody(\"This is the new location!\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"This is the new location!\",\n        readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(\"When connection: close is used, each request should get its own connection\", 0,\n        server.takeRequest().getSequenceNumber());\n  }\n\n  /**\n   * Retry redirects if the socket is closed.\n   * https://code.google.com/p/android/issues/detail?id=41576\n   */\n  @Test public void sameConnectionRedirectAndReuse() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .setSocketPolicy(SHUTDOWN_INPUT_AT_END)\n        .addHeader(\"Location: /foo\"));\n    server.enqueue(new MockResponse().setBody(\"This is the new page!\"));\n\n    assertContent(\"This is the new page!\", client.open(server.getUrl(\"/\")));\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void responseCodeDisagreesWithHeaders() throws IOException, InterruptedException {\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NO_CONTENT)\n        .setBody(\"This body is not allowed!\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"This body is not allowed!\",\n        readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n  }\n\n  @Test public void singleByteReadIsSigned() throws IOException {\n    server.enqueue(new MockResponse().setBody(new Buffer().writeByte(-2).writeByte(-1)));\n\n    connection = client.open(server.getUrl(\"/\"));\n    InputStream in = connection.getInputStream();\n    assertEquals(254, in.read());\n    assertEquals(255, in.read());\n    assertEquals(-1, in.read());\n  }\n\n  @Test public void flushAfterStreamTransmittedWithChunkedEncoding() throws IOException {\n    testFlushAfterStreamTransmitted(TransferKind.CHUNKED);\n  }\n\n  @Test public void flushAfterStreamTransmittedWithFixedLength() throws IOException {\n    testFlushAfterStreamTransmitted(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void flushAfterStreamTransmittedWithNoLengthHeaders() throws IOException {\n    testFlushAfterStreamTransmitted(TransferKind.END_OF_STREAM);\n  }\n\n  /**\n   * We explicitly permit apps to close the upload stream even after it has\n   * been transmitted.  We also permit flush so that buffered streams can\n   * do a no-op flush when they are closed. http://b/3038470\n   */\n  private void testFlushAfterStreamTransmitted(TransferKind transferKind) throws IOException {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    byte[] upload = \"def\".getBytes(\"UTF-8\");\n\n    if (transferKind == TransferKind.CHUNKED) {\n      connection.setChunkedStreamingMode(0);\n    } else if (transferKind == TransferKind.FIXED_LENGTH) {\n      connection.setFixedLengthStreamingMode(upload.length);\n    }\n\n    OutputStream out = connection.getOutputStream();\n    out.write(upload);\n    assertEquals(\"abc\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n\n    out.flush(); // Dubious but permitted.\n    try {\n      out.write(\"ghi\".getBytes(\"UTF-8\"));\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void getHeadersThrows() throws IOException {\n    server.enqueue(new MockResponse().setSocketPolicy(DISCONNECT_AT_START));\n\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getInputStream();\n      fail();\n    } catch (IOException expected) {\n    }\n\n    try {\n      connection.getInputStream();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void dnsFailureThrowsIOException() throws IOException {\n    connection = client.open(new URL(\"http://host.unlikelytld\"));\n    try {\n      connection.connect();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void malformedUrlThrowsUnknownHostException() throws IOException {\n    connection = client.open(new URL(\"http://./foo.html\"));\n    try {\n      connection.connect();\n      fail();\n    } catch (UnknownHostException expected) {\n    }\n  }\n\n  @Test public void getKeepAlive() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"ABC\"));\n\n    // The request should work once and then fail\n    HttpURLConnection connection1 = client.open(server.getUrl(\"/\"));\n    connection1.setReadTimeout(100);\n    InputStream input = connection1.getInputStream();\n    assertEquals(\"ABC\", readAscii(input, Integer.MAX_VALUE));\n    server.shutdown();\n    try {\n      HttpURLConnection connection2 = client.open(server.getUrl(\"\"));\n      connection2.setReadTimeout(100);\n      connection2.getInputStream();\n      fail();\n    } catch (ConnectException expected) {\n    }\n  }\n\n  /** http://code.google.com/p/android/issues/detail?id=14562 */\n  @Test public void readAfterLastByte() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"ABC\")\n        .clearHeaders()\n        .addHeader(\"Connection: close\")\n        .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END));\n\n    connection = client.open(server.getUrl(\"/\"));\n    InputStream in = connection.getInputStream();\n    assertEquals(\"ABC\", readAscii(in, 3));\n    assertEquals(-1, in.read());\n    assertEquals(-1, in.read()); // throws IOException in Gingerbread\n  }\n\n  @Test public void getContent() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Content-Type: text/plain\").setBody(\"A\"));\n    connection = client.open(server.getUrl(\"/\"));\n    InputStream in = (InputStream) connection.getContent();\n    assertEquals(\"A\", readAscii(in, Integer.MAX_VALUE));\n  }\n\n  @Test public void getContentOfType() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Content-Type: text/plain\").setBody(\"A\"));\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getContent(null);\n      fail();\n    } catch (NullPointerException expected) {\n    }\n    try {\n      connection.getContent(new Class[] { null });\n      fail();\n    } catch (NullPointerException expected) {\n    }\n    assertNull(connection.getContent(new Class[] { getClass() }));\n  }\n\n  @Test public void getOutputStreamOnGetFails() throws Exception {\n    server.enqueue(new MockResponse());\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getOutputStream();\n      fail();\n    } catch (ProtocolException expected) {\n    }\n  }\n\n  @Test public void getOutputAfterGetInputStreamFails() throws Exception {\n    server.enqueue(new MockResponse());\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    try {\n      connection.getInputStream();\n      connection.getOutputStream();\n      fail();\n    } catch (ProtocolException expected) {\n    }\n  }\n\n  @Test public void setDoOutputOrDoInputAfterConnectFails() throws Exception {\n    server.enqueue(new MockResponse());\n    connection = client.open(server.getUrl(\"/\"));\n    connection.connect();\n    try {\n      connection.setDoOutput(true);\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n    try {\n      connection.setDoInput(true);\n      fail();\n    } catch (IllegalStateException expected) {\n    }\n  }\n\n  @Test public void clientSendsContentLength() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    OutputStream out = connection.getOutputStream();\n    out.write(new byte[] { 'A', 'B', 'C' });\n    out.close();\n    assertEquals(\"A\", readAscii(connection.getInputStream(), Integer.MAX_VALUE));\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"3\", request.getHeader(\"Content-Length\"));\n  }\n\n  @Test public void getContentLengthConnects() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"ABC\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(3, connection.getContentLength());\n  }\n\n  @Test public void getContentTypeConnects() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Content-Type: text/plain\").setBody(\"ABC\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"text/plain\", connection.getContentType());\n  }\n\n  @Test public void getContentEncodingConnects() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Content-Encoding: identity\").setBody(\"ABC\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"identity\", connection.getContentEncoding());\n  }\n\n  // http://b/4361656\n  @Test public void urlContainsQueryButNoPath() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    URL url = new URL(\"http\", server.getHostName(), server.getPort(), \"?query\");\n    assertEquals(\"A\", readAscii(client.open(url).getInputStream(), Integer.MAX_VALUE));\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"GET /?query HTTP/1.1\", request.getRequestLine());\n  }\n\n  @Test public void doOutputForMethodThatDoesntSupportOutput() throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setRequestMethod(\"HEAD\");\n    connection.setDoOutput(true);\n    try {\n      connection.connect();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  // http://code.google.com/p/android/issues/detail?id=20442\n  @Test public void inputStreamAvailableWithChunkedEncoding() throws Exception {\n    testInputStreamAvailable(TransferKind.CHUNKED);\n  }\n\n  @Test public void inputStreamAvailableWithContentLengthHeader() throws Exception {\n    testInputStreamAvailable(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void inputStreamAvailableWithNoLengthHeaders() throws Exception {\n    testInputStreamAvailable(TransferKind.END_OF_STREAM);\n  }\n\n  private void testInputStreamAvailable(TransferKind transferKind) throws IOException {\n    String body = \"ABCDEFGH\";\n    MockResponse response = new MockResponse();\n    transferKind.setBody(response, body, 4);\n    server.enqueue(response);\n    connection = client.open(server.getUrl(\"/\"));\n    InputStream in = connection.getInputStream();\n    for (int i = 0; i < body.length(); i++) {\n      assertTrue(in.available() >= 0);\n      assertEquals(body.charAt(i), in.read());\n    }\n    assertEquals(0, in.available());\n    assertEquals(-1, in.read());\n  }\n\n  @Test public void postFailsWithBufferedRequestForSmallRequest() throws Exception {\n    reusedConnectionFailsWithPost(TransferKind.END_OF_STREAM, 1024);\n  }\n\n  @Test public void postFailsWithBufferedRequestForLargeRequest() throws Exception {\n    reusedConnectionFailsWithPost(TransferKind.END_OF_STREAM, 16384);\n  }\n\n  @Test public void postFailsWithChunkedRequestForSmallRequest() throws Exception {\n    reusedConnectionFailsWithPost(TransferKind.CHUNKED, 1024);\n  }\n\n  @Test public void postFailsWithChunkedRequestForLargeRequest() throws Exception {\n    reusedConnectionFailsWithPost(TransferKind.CHUNKED, 16384);\n  }\n\n  @Test public void postFailsWithFixedLengthRequestForSmallRequest() throws Exception {\n    reusedConnectionFailsWithPost(TransferKind.FIXED_LENGTH, 1024);\n  }\n\n  @Test public void postFailsWithFixedLengthRequestForLargeRequest() throws Exception {\n    reusedConnectionFailsWithPost(TransferKind.FIXED_LENGTH, 16384);\n  }\n\n  private void reusedConnectionFailsWithPost(TransferKind transferKind, int requestSize)\n      throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\").setSocketPolicy(DISCONNECT_AT_END));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n    server.enqueue(new MockResponse().setBody(\"C\"));\n\n    assertContent(\"A\", client.open(server.getUrl(\"/a\")));\n\n    // If the request body is larger than OkHttp's replay buffer, the failure may still occur.\n    byte[] requestBody = new byte[requestSize];\n    new Random(0).nextBytes(requestBody);\n\n    for (int j = 0; j < 2; j++) {\n      try {\n        connection = client.open(server.getUrl(\"/b\"));\n        connection.setRequestMethod(\"POST\");\n        transferKind.setForRequest(connection, requestBody.length);\n        for (int i = 0; i < requestBody.length; i += 1024) {\n          connection.getOutputStream().write(requestBody, i, 1024);\n        }\n        connection.getOutputStream().close();\n        assertContent(\"B\", connection);\n        break;\n      } catch (IOException socketException) {\n        // If there's a socket exception, this must have a streamed request body.\n        assertEquals(0, j);\n        assertTrue(transferKind == TransferKind.CHUNKED\n            || transferKind == TransferKind.FIXED_LENGTH);\n      }\n    }\n\n    RecordedRequest requestA = server.takeRequest();\n    assertEquals(\"/a\", requestA.getPath());\n    RecordedRequest requestB = server.takeRequest();\n    assertEquals(\"/b\", requestB.getPath());\n    assertEquals(Arrays.toString(requestBody), Arrays.toString(requestB.getBody().readByteArray()));\n  }\n\n  @Test public void postBodyRetransmittedOnFailureRecovery() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AFTER_REQUEST));\n    server.enqueue(new MockResponse().setBody(\"def\"));\n\n    // Seed the connection pool so we have something that can fail.\n    assertContent(\"abc\", client.open(server.getUrl(\"/\")));\n\n    HttpURLConnection post = client.open(server.getUrl(\"/\"));\n    post.setDoOutput(true);\n    post.getOutputStream().write(\"body!\".getBytes(Util.UTF_8));\n    assertContent(\"def\", post);\n\n    RecordedRequest get = server.takeRequest();\n    assertEquals(0, get.getSequenceNumber());\n\n    RecordedRequest post1 = server.takeRequest();\n    assertEquals(\"body!\", post1.getBody().readUtf8());\n    assertEquals(1, post1.getSequenceNumber());\n\n    RecordedRequest post2 = server.takeRequest();\n    assertEquals(\"body!\", post2.getBody().readUtf8());\n    assertEquals(0, post2.getSequenceNumber());\n  }\n\n  @Test public void fullyBufferedPostIsTooShort() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    connection = client.open(server.getUrl(\"/b\"));\n    connection.setRequestProperty(\"Content-Length\", \"4\");\n    connection.setRequestMethod(\"POST\");\n    OutputStream out = connection.getOutputStream();\n    out.write('a');\n    out.write('b');\n    out.write('c');\n    try {\n      out.close();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test public void fullyBufferedPostIsTooLong() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    connection = client.open(server.getUrl(\"/b\"));\n    connection.setRequestProperty(\"Content-Length\", \"3\");\n    connection.setRequestMethod(\"POST\");\n    OutputStream out = connection.getOutputStream();\n    out.write('a');\n    out.write('b');\n    out.write('c');\n    try {\n      out.write('d');\n      out.flush();\n      fail();\n    } catch (IOException expected) {\n    }\n  }\n\n  @Test @Ignore public void testPooledConnectionsDetectHttp10() {\n    // TODO: write a test that shows pooled connections detect HTTP/1.0 (vs. HTTP/1.1)\n    fail(\"TODO\");\n  }\n\n  @Test @Ignore public void postBodiesRetransmittedOnAuthProblems() {\n    fail(\"TODO\");\n  }\n\n  @Test @Ignore public void cookiesAndTrailers() {\n    // Do cookie headers get processed too many times?\n    fail(\"TODO\");\n  }\n\n  @Test @Ignore public void headerNamesContainingNullCharacter() {\n    // This is relevant for SPDY\n    fail(\"TODO\");\n  }\n\n  @Test @Ignore public void headerValuesContainingNullCharacter() {\n    // This is relevant for SPDY\n    fail(\"TODO\");\n  }\n\n  @Test public void emptyRequestHeaderValueIsAllowed() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"body\"));\n    connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"B\", \"\");\n    assertContent(\"body\", connection);\n    assertEquals(\"\", connection.getRequestProperty(\"B\"));\n  }\n\n  @Test public void emptyResponseHeaderValueIsAllowed() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"A:\").setBody(\"body\"));\n    connection = client.open(server.getUrl(\"/\"));\n    assertContent(\"body\", connection);\n    assertEquals(\"\", connection.getHeaderField(\"A\"));\n  }\n\n  @Test public void emptyRequestHeaderNameIsStrict() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"body\"));\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.setRequestProperty(\"\", \"A\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void emptyResponseHeaderNameIsLenient() throws Exception {\n    Headers.Builder headers = new Headers.Builder();\n    Internal.instance.addLenient(headers, \":A\");\n    server.enqueue(new MockResponse().setHeaders(headers.build()).setBody(\"body\"));\n    connection = client.open(server.getUrl(\"/\"));\n    connection.getResponseCode();\n    assertEquals(\"A\", connection.getHeaderField(\"\"));\n  }\n\n  @Test public void requestHeaderValidationIsStrict() throws Exception {\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.addRequestProperty(\"a\\tb\", \"Value\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n    try {\n      connection.addRequestProperty(\"Name\", \"c\\u007fd\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n    try {\n      connection.addRequestProperty(\"\", \"Value\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n    try {\n      connection.addRequestProperty(\"\\ud83c\\udf69\", \"Value\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n    try {\n      connection.addRequestProperty(\"Name\", \"\\u2615\\ufe0f\");\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void responseHeaderParsingIsLenient() throws Exception {\n    Headers headers = new Headers.Builder()\n        .add(\"Content-Length\", \"0\")\n        .addLenient(\"a\\tb: c\\u007fd\")\n        .addLenient(\": ef\")\n        .addLenient(\"\\ud83c\\udf69: \\u2615\\ufe0f\")\n        .build();\n    server.enqueue(new MockResponse().setHeaders(headers));\n\n    connection = client.open(server.getUrl(\"/\"));\n    connection.getResponseCode();\n    assertEquals(\"c\\u007fd\", connection.getHeaderField(\"a\\tb\"));\n    assertEquals(\"\\u2615\\ufe0f\", connection.getHeaderField(\"\\ud83c\\udf69\"));\n    assertEquals(\"ef\", connection.getHeaderField(\"\"));\n  }\n\n  @Test @Ignore public void deflateCompression() {\n    fail(\"TODO\");\n  }\n\n  @Test @Ignore public void postBodiesRetransmittedOnIpAddressProblems() {\n    fail(\"TODO\");\n  }\n\n  @Test @Ignore public void pooledConnectionProblemsNotReportedToProxySelector() {\n    fail(\"TODO\");\n  }\n\n  @Test public void customBasicAuthenticator() throws Exception {\n    MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401)\n        .addHeader(\"WWW-Authenticate: Basic realm=\\\"protected area\\\"\")\n        .setBody(\"Please authenticate.\");\n    server.enqueue(pleaseAuthenticate);\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    String credential = Credentials.basic(\"jesse\", \"peanutbutter\");\n    RecordingOkAuthenticator authenticator = new RecordingOkAuthenticator(credential);\n    client.client().setAuthenticator(authenticator);\n    assertContent(\"A\", client.open(server.getUrl(\"/private\")));\n\n    assertNull(server.takeRequest().getHeader(\"Authorization\"));\n    assertEquals(credential, server.takeRequest().getHeader(\"Authorization\"));\n\n    assertEquals(Proxy.NO_PROXY, authenticator.onlyProxy());\n    Response response = authenticator.onlyResponse();\n    assertEquals(\"/private\", response.request().url().getPath());\n    assertEquals(Arrays.asList(new Challenge(\"Basic\", \"protected area\")), response.challenges());\n  }\n\n  @Test public void customTokenAuthenticator() throws Exception {\n    MockResponse pleaseAuthenticate = new MockResponse().setResponseCode(401)\n            .addHeader(\"WWW-Authenticate: Bearer realm=\\\"oauthed\\\"\")\n            .setBody(\"Please authenticate.\");\n    server.enqueue(pleaseAuthenticate);\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    RecordingOkAuthenticator authenticator = new RecordingOkAuthenticator(\"oauthed abc123\");\n    client.client().setAuthenticator(authenticator);\n    assertContent(\"A\", client.open(server.getUrl(\"/private\")));\n\n    assertNull(server.takeRequest().getHeader(\"Authorization\"));\n    assertEquals(\"oauthed abc123\", server.takeRequest().getHeader(\"Authorization\"));\n\n    Response response = authenticator.onlyResponse();\n    assertEquals(\"/private\", response.request().url().getPath());\n    assertEquals(Arrays.asList(new Challenge(\"Bearer\", \"oauthed\")), response.challenges());\n  }\n\n  @Test public void authenticateCallsTrackedAsRedirects() throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(302)\n        .addHeader(\"Location: /b\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(401)\n        .addHeader(\"WWW-Authenticate: Basic realm=\\\"protected area\\\"\"));\n    server.enqueue(new MockResponse().setBody(\"c\"));\n\n    RecordingOkAuthenticator authenticator = new RecordingOkAuthenticator(\n        Credentials.basic(\"jesse\", \"peanutbutter\"));\n    client.client().setAuthenticator(authenticator);\n    assertContent(\"c\", client.open(server.getUrl(\"/a\")));\n\n    Response challengeResponse = authenticator.responses.get(0);\n    assertEquals(\"/b\", challengeResponse.request().url().getPath());\n\n    Response redirectedBy = challengeResponse.priorResponse();\n    assertEquals(\"/a\", redirectedBy.request().url().getPath());\n  }\n\n  @Test public void attemptAuthorization20Times() throws Exception {\n    for (int i = 0; i < 20; i++) {\n      server.enqueue(new MockResponse().setResponseCode(401));\n    }\n    server.enqueue(new MockResponse().setBody(\"Success!\"));\n\n    String credential = Credentials.basic(\"jesse\", \"peanutbutter\");\n    client.client().setAuthenticator(new RecordingOkAuthenticator(credential));\n\n    connection = client.open(server.getUrl(\"/0\"));\n    assertContent(\"Success!\", connection);\n  }\n\n  @Test public void doesNotAttemptAuthorization21Times() throws Exception {\n    for (int i = 0; i < 21; i++) {\n      server.enqueue(new MockResponse().setResponseCode(401));\n    }\n\n    String credential = Credentials.basic(\"jesse\", \"peanutbutter\");\n    client.client().setAuthenticator(new RecordingOkAuthenticator(credential));\n\n    connection = client.open(server.getUrl(\"/\"));\n    try {\n      connection.getInputStream();\n      fail();\n    } catch (ProtocolException expected) {\n      assertEquals(401, connection.getResponseCode());\n      assertEquals(\"Too many follow-up requests: 21\", expected.getMessage());\n    }\n  }\n\n  @Ignore // TODO\n  @Test public void setsNegotiatedProtocolHeader_SPDY_3() throws Exception {\n    setsNegotiatedProtocolHeader(Protocol.SPDY_3);\n  }\n\n  @Ignore // TODO\n  @Test public void setsNegotiatedProtocolHeader_HTTP_2() throws Exception {\n    setsNegotiatedProtocolHeader(Protocol.HTTP_2);\n  }\n\n  private void setsNegotiatedProtocolHeader(Protocol protocol) throws IOException {\n    enableProtocol(protocol);\n    server.enqueue(new MockResponse().setBody(\"A\"));\n    client.client().setProtocols(Arrays.asList(protocol, Protocol.HTTP_1_1));\n    connection = client.open(server.getUrl(\"/\"));\n    List<String> protocolValues = connection.getHeaderFields().get(SELECTED_PROTOCOL);\n    assertEquals(Arrays.asList(protocol.toString()), protocolValues);\n    assertContent(\"A\", connection);\n  }\n\n  @Test public void http10SelectedProtocol() throws Exception {\n    server.enqueue(new MockResponse().setStatus(\"HTTP/1.0 200 OK\"));\n    connection = client.open(server.getUrl(\"/\"));\n    List<String> protocolValues = connection.getHeaderFields().get(SELECTED_PROTOCOL);\n    assertEquals(Arrays.asList(\"http/1.0\"), protocolValues);\n  }\n\n  @Test public void http11SelectedProtocol() throws Exception {\n    server.enqueue(new MockResponse().setStatus(\"HTTP/1.1 200 OK\"));\n    connection = client.open(server.getUrl(\"/\"));\n    List<String> protocolValues = connection.getHeaderFields().get(SELECTED_PROTOCOL);\n    assertEquals(Arrays.asList(\"http/1.1\"), protocolValues);\n  }\n\n  /** For example, empty Protobuf RPC messages end up as a zero-length POST. */\n  @Test public void zeroLengthPost() throws IOException, InterruptedException {\n    zeroLengthPayload(\"POST\");\n  }\n\n  @Test public void zeroLengthPost_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    zeroLengthPost();\n  }\n\n  @Test public void zeroLengthPost_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    zeroLengthPost();\n  }\n\n  /** For example, creating an Amazon S3 bucket ends up as a zero-length POST. */\n  @Test public void zeroLengthPut() throws IOException, InterruptedException {\n    zeroLengthPayload(\"PUT\");\n  }\n\n  @Test public void zeroLengthPut_SPDY_3() throws Exception {\n    enableProtocol(Protocol.SPDY_3);\n    zeroLengthPut();\n  }\n\n  @Test public void zeroLengthPut_HTTP_2() throws Exception {\n    enableProtocol(Protocol.HTTP_2);\n    zeroLengthPut();\n  }\n\n  private void zeroLengthPayload(String method)\n      throws IOException, InterruptedException {\n    server.enqueue(new MockResponse());\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setRequestProperty(\"Content-Length\", \"0\");\n    connection.setRequestMethod(method);\n    connection.setFixedLengthStreamingMode(0);\n    connection.setDoOutput(true);\n    assertContent(\"\", connection);\n    RecordedRequest zeroLengthPayload = server.takeRequest();\n    assertEquals(method, zeroLengthPayload.getMethod());\n    assertEquals(\"0\", zeroLengthPayload.getHeader(\"content-length\"));\n    assertEquals(0L, zeroLengthPayload.getBodySize());\n  }\n\n  @Test public void unspecifiedRequestBodyContentTypeGetsDefault() throws Exception {\n    server.enqueue(new MockResponse());\n\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    connection.getOutputStream().write(\"abc\".getBytes(UTF_8));\n    assertEquals(200, connection.getResponseCode());\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"application/x-www-form-urlencoded\", request.getHeader(\"Content-Type\"));\n    assertEquals(\"3\", request.getHeader(\"Content-Length\"));\n    assertEquals(\"abc\", request.getBody().readUtf8());\n  }\n\n  @Test public void setProtocols() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n    client.client().setProtocols(Arrays.asList(Protocol.HTTP_1_1));\n    assertContent(\"A\", client.open(server.getUrl(\"/\")));\n  }\n\n  @Test public void setProtocolsWithoutHttp11() throws Exception {\n    try {\n      client.client().setProtocols(Arrays.asList(Protocol.SPDY_3));\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void setProtocolsWithNull() throws Exception {\n    try {\n      client.client().setProtocols(Arrays.asList(Protocol.HTTP_1_1, null));\n      fail();\n    } catch (IllegalArgumentException expected) {\n    }\n  }\n\n  @Test public void veryLargeFixedLengthRequest() throws Exception {\n    server.setBodyLimit(0);\n    server.enqueue(new MockResponse());\n\n    connection = client.open(server.getUrl(\"/\"));\n    connection.setDoOutput(true);\n    long contentLength = Integer.MAX_VALUE + 1L;\n    connection.setFixedLengthStreamingMode(contentLength);\n    OutputStream out = connection.getOutputStream();\n    byte[] buffer = new byte[1024 * 1024];\n    for (long bytesWritten = 0; bytesWritten < contentLength; ) {\n      int byteCount = (int) Math.min(buffer.length, contentLength - bytesWritten);\n      out.write(buffer, 0, byteCount);\n      bytesWritten += byteCount;\n    }\n    assertContent(\"\", connection);\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(Long.toString(contentLength), request.getHeader(\"Content-Length\"));\n  }\n\n  /**\n   * We had a bug where we attempted to gunzip responses that didn't have a\n   * body. This only came up with 304s since that response code can include\n   * headers (like \"Content-Encoding\") without any content to go along with it.\n   * https://github.com/square/okhttp/issues/358\n   */\n  @Test public void noTransparentGzipFor304NotModified() throws Exception {\n    server.enqueue(new MockResponse()\n        .clearHeaders()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)\n        .addHeader(\"Content-Encoding: gzip\"));\n    server.enqueue(new MockResponse().setBody(\"b\"));\n\n    HttpURLConnection connection1 = client.open(server.getUrl(\"/\"));\n    assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection1.getResponseCode());\n    assertContent(\"\", connection1);\n\n    HttpURLConnection connection2 = client.open(server.getUrl(\"/\"));\n    assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());\n    assertContent(\"b\", connection2);\n\n    RecordedRequest requestA = server.takeRequest();\n    assertEquals(0, requestA.getSequenceNumber());\n\n    RecordedRequest requestB = server.takeRequest();\n    assertEquals(1, requestB.getSequenceNumber());\n  }\n\n  /**\n   * We had a bug where we weren't closing Gzip streams on redirects.\n   * https://github.com/square/okhttp/issues/441\n   */\n  @Test public void gzipWithRedirectAndConnectionReuse() throws Exception {\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_TEMP)\n        .addHeader(\"Location: /foo\")\n        .addHeader(\"Content-Encoding: gzip\")\n        .setBody(gzip(\"Moved! Moved! Moved!\")));\n    server.enqueue(new MockResponse().setBody(\"This is the new page!\"));\n\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    assertContent(\"This is the new page!\", connection);\n\n    RecordedRequest requestA = server.takeRequest();\n    assertEquals(0, requestA.getSequenceNumber());\n\n    RecordedRequest requestB = server.takeRequest();\n    assertEquals(1, requestB.getSequenceNumber());\n  }\n\n  /**\n   * The RFC is unclear in this regard as it only specifies that this should\n   * invalidate the cache entry (if any).\n   */\n  @Test public void bodyPermittedOnDelete() throws Exception {\n    server.enqueue(new MockResponse());\n\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.setRequestMethod(\"DELETE\");\n    connection.setDoOutput(true);\n    connection.getOutputStream().write(\"BODY\".getBytes(UTF_8));\n    assertEquals(200, connection.getResponseCode());\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"DELETE\", request.getMethod());\n    assertEquals(\"BODY\", request.getBody().readUtf8());\n  }\n\n  @Test public void userAgentPicksUpHttpAgentSystemProperty() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    System.setProperty(\"http.agent\", \"foo\");\n    assertContent(\"abc\", client.open(server.getUrl(\"/\")));\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"foo\", request.getHeader(\"User-Agent\"));\n  }\n\n  /** https://github.com/square/okhttp/issues/891 */\n  @Test public void userAgentSystemPropertyIsNotAscii() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    System.setProperty(\"http.agent\", \"a\\nb\\ud83c\\udf69c\\ud83c\\udf68d\\u007fe\");\n    assertContent(\"abc\", client.open(server.getUrl(\"/\")));\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(\"a?b?c?d?e\", request.getHeader(\"User-Agent\"));\n  }\n\n  @Test public void userAgentDefaultsToOkHttpVersion() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n\n    assertContent(\"abc\", client.open(server.getUrl(\"/\")));\n\n    RecordedRequest request = server.takeRequest();\n    assertEquals(Version.userAgent(), request.getHeader(\"User-Agent\"));\n  }\n\n  @Test public void interceptorsNotInvoked() throws Exception {\n    Interceptor interceptor = new Interceptor() {\n      @Override public Response intercept(Chain chain) throws IOException {\n        throw new AssertionError();\n      }\n    };\n    client.client().interceptors().add(interceptor);\n    client.client().networkInterceptors().add(interceptor);\n\n    server.enqueue(new MockResponse().setBody(\"abc\"));\n    assertContent(\"abc\", client.open(server.getUrl(\"/\")));\n  }\n\n  @Test public void urlWithSpaceInHost() throws Exception {\n    URLConnection urlConnection = client.open(new URL(\"http://and roid.com/\"));\n    try {\n      urlConnection.getInputStream();\n      fail();\n    } catch (UnknownHostException expected) {\n    }\n  }\n\n  @Test public void urlWithSpaceInHostViaHttpProxy() throws Exception {\n    server.enqueue(new MockResponse());\n    URLConnection urlConnection =\n        client.open(new URL(\"http://and roid.com/\"), server.toProxyAddress());\n\n    try {\n      // This test is to check that a NullPointerException is not thrown.\n      urlConnection.getInputStream();\n      fail(); // the RI makes a bogus proxy request for \"GET http://and roid.com/ HTTP/1.1\"\n    } catch (UnknownHostException expected) {\n    }\n  }\n\n  @Test public void urlHostWithNul() throws Exception {\n    URLConnection urlConnection = client.open(new URL(\"http://host\\u0000/\"));\n    try {\n      urlConnection.getInputStream();\n      fail();\n    } catch (UnknownHostException expected) {\n    }\n  }\n\n  @Test public void urlRedirectToHostWithNul() throws Exception {\n    String redirectUrl = \"http://host\\u0000/\";\n    server.enqueue(new MockResponse().setResponseCode(302)\n        .addHeaderLenient(\"Location\", redirectUrl));\n\n    HttpURLConnection urlConnection = client.open(server.getUrl(\"/\"));\n    assertEquals(302, urlConnection.getResponseCode());\n    assertEquals(redirectUrl, urlConnection.getHeaderField(\"Location\"));\n  }\n\n  @Test public void urlWithBadAsciiHost() throws Exception {\n    URLConnection urlConnection = client.open(new URL(\"http://host\\u0001/\"));\n    try {\n      urlConnection.getInputStream();\n      fail();\n    } catch (UnknownHostException expected) {\n    }\n  }\n\n  @Test public void instanceFollowsRedirects() throws Exception {\n    testInstanceFollowsRedirects(\"http://www.google.com/\");\n    testInstanceFollowsRedirects(\"https://www.google.com/\");\n  }\n\n  private void testInstanceFollowsRedirects(String spec) throws Exception {\n    URL url = new URL(spec);\n    HttpURLConnection urlConnection = client.open(url);\n    urlConnection.setInstanceFollowRedirects(true);\n    assertTrue(urlConnection.getInstanceFollowRedirects());\n    urlConnection.setInstanceFollowRedirects(false);\n    assertFalse(urlConnection.getInstanceFollowRedirects());\n  }\n\n  /** Returns a gzipped copy of {@code bytes}. */\n  public Buffer gzip(String data) throws IOException {\n    Buffer result = new Buffer();\n    BufferedSink gzipSink = Okio.buffer(new GzipSink(result));\n    gzipSink.writeUtf8(data);\n    gzipSink.close();\n    return result;\n  }\n\n  /**\n   * Reads at most {@code limit} characters from {@code in} and asserts that\n   * content equals {@code expected}.\n   */\n  private void assertContent(String expected, HttpURLConnection connection, int limit)\n      throws IOException {\n    connection.connect();\n    assertEquals(expected, readAscii(connection.getInputStream(), limit));\n  }\n\n  private void assertContent(String expected, HttpURLConnection connection) throws IOException {\n    assertContent(expected, connection, Integer.MAX_VALUE);\n  }\n\n  private Set<String> newSet(String... elements) {\n    return new LinkedHashSet<>(Arrays.asList(elements));\n  }\n\n  enum TransferKind {\n    CHUNKED() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize)\n          throws IOException {\n        response.setChunkedBody(content, chunkSize);\n      }\n      @Override void setForRequest(HttpURLConnection connection, int contentLength) {\n        connection.setChunkedStreamingMode(5);\n      }\n    },\n    FIXED_LENGTH() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize) {\n        response.setBody(content);\n      }\n      @Override void setForRequest(HttpURLConnection connection, int contentLength) {\n        connection.setFixedLengthStreamingMode(contentLength);\n      }\n    },\n    END_OF_STREAM() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize) {\n        response.setBody(content);\n        response.setSocketPolicy(DISCONNECT_AT_END);\n        response.removeHeader(\"Content-Length\");\n      }\n      @Override void setForRequest(HttpURLConnection connection, int contentLength) {\n      }\n    };\n\n    abstract void setBody(MockResponse response, Buffer content, int chunkSize) throws IOException;\n\n    abstract void setForRequest(HttpURLConnection connection, int contentLength);\n\n    void setBody(MockResponse response, String content, int chunkSize) throws IOException {\n      setBody(response, new Buffer().writeUtf8(content), chunkSize);\n    }\n  }\n\n  enum ProxyConfig {\n    NO_PROXY() {\n      @Override public HttpURLConnection connect(\n          MockWebServer server, OkUrlFactory streamHandlerFactory, URL url)\n          throws IOException {\n        streamHandlerFactory.client().setProxy(Proxy.NO_PROXY);\n        return streamHandlerFactory.open(url);\n      }\n    },\n\n    CREATE_ARG() {\n      @Override public HttpURLConnection connect(\n          MockWebServer server, OkUrlFactory streamHandlerFactory, URL url)\n          throws IOException {\n        streamHandlerFactory.client().setProxy(server.toProxyAddress());\n        return streamHandlerFactory.open(url);\n      }\n    },\n\n    PROXY_SYSTEM_PROPERTY() {\n      @Override public HttpURLConnection connect(\n          MockWebServer server, OkUrlFactory streamHandlerFactory, URL url)\n          throws IOException {\n        System.setProperty(\"proxyHost\", server.getHostName());\n        System.setProperty(\"proxyPort\", Integer.toString(server.getPort()));\n        return streamHandlerFactory.open(url);\n      }\n    },\n\n    HTTP_PROXY_SYSTEM_PROPERTY() {\n      @Override public HttpURLConnection connect(\n          MockWebServer server, OkUrlFactory streamHandlerFactory, URL url)\n          throws IOException {\n        System.setProperty(\"http.proxyHost\", server.getHostName());\n        System.setProperty(\"http.proxyPort\", Integer.toString(server.getPort()));\n        return streamHandlerFactory.open(url);\n      }\n    },\n\n    HTTPS_PROXY_SYSTEM_PROPERTY() {\n      @Override public HttpURLConnection connect(\n          MockWebServer server, OkUrlFactory streamHandlerFactory, URL url)\n          throws IOException {\n        System.setProperty(\"https.proxyHost\", server.getHostName());\n        System.setProperty(\"https.proxyPort\", Integer.toString(server.getPort()));\n        return streamHandlerFactory.open(url);\n      }\n    };\n\n    public abstract HttpURLConnection connect(\n        MockWebServer server, OkUrlFactory streamHandlerFactory, URL url)\n        throws IOException;\n  }\n\n  private static class RecordingTrustManager implements X509TrustManager {\n    private final List<String> calls = new ArrayList<String>();\n\n    public X509Certificate[] getAcceptedIssuers() {\n      return new X509Certificate[] { };\n    }\n\n    public void checkClientTrusted(X509Certificate[] chain, String authType)\n        throws CertificateException {\n      calls.add(\"checkClientTrusted \" + certificatesToString(chain));\n    }\n\n    public void checkServerTrusted(X509Certificate[] chain, String authType)\n        throws CertificateException {\n      calls.add(\"checkServerTrusted \" + certificatesToString(chain));\n    }\n\n    private String certificatesToString(X509Certificate[] certificates) {\n      List<String> result = new ArrayList<String>();\n      for (X509Certificate certificate : certificates) {\n        result.add(certificate.getSubjectDN() + \" \" + certificate.getSerialNumber());\n      }\n      return result.toString();\n    }\n  }\n\n  private static class FakeProxySelector extends ProxySelector {\n    List<Proxy> proxies = new ArrayList<>();\n\n    @Override public List<Proxy> select(URI uri) {\n      // Don't handle 'socket' schemes, which the RI's Socket class may request (for SOCKS).\n      return uri.getScheme().equals(\"http\") || uri.getScheme().equals(\"https\") ? proxies\n          : Collections.singletonList(Proxy.NO_PROXY);\n    }\n\n    @Override public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {\n    }\n  }\n\n  /**\n   * Tests that use this will fail unless boot classpath is set. Ex. {@code\n   * -Xbootclasspath/p:/tmp/alpn-boot-8.0.0.v20140317}\n   */\n  private void enableProtocol(Protocol protocol) {\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(new RecordingHostnameVerifier());\n    client.client().setProtocols(Arrays.asList(protocol, Protocol.HTTP_1_1));\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.setProtocolNegotiationEnabled(true);\n    server.setProtocols(client.client().getProtocols());\n  }\n\n  /**\n   * Used during tests that involve TLS connection fallback attempts. OkHttp includes the\n   * TLS_FALLBACK_SCSV cipher on fallback connections. See\n   * {@link com.squareup.okhttp.FallbackTestClientSocketFactory} for details.\n   */\n  private void suppressTlsFallbackScsv(OkHttpClient client) {\n    FallbackTestClientSocketFactory clientSocketFactory =\n        new FallbackTestClientSocketFactory(sslContext.getSocketFactory());\n    client.setSslSocketFactory(clientSocketFactory);\n  }\n}\n"
  },
  {
    "path": "comsat-okhttp/src/test/java/com/squareup/okhttp/UrlConnectionCacheTest.java",
    "content": "/*\n * Copyright (C) 2011 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.squareup.okhttp;\n\nimport co.paralleluniverse.fibers.okhttp.test.utils.FiberOkHttpClientTestWrapper;\nimport com.squareup.okhttp.internal.Internal;\nimport com.squareup.okhttp.internal.SslContextBuilder;\nimport com.squareup.okhttp.internal.Util;\nimport co.paralleluniverse.fibers.okhttp.test.utils.original.io.InMemoryFileSystem;\nimport com.squareup.okhttp.mockwebserver.MockResponse;\nimport com.squareup.okhttp.mockwebserver.MockWebServer;\nimport com.squareup.okhttp.mockwebserver.RecordedRequest;\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.OutputStream;\nimport java.net.CookieHandler;\nimport java.net.CookieManager;\nimport java.net.HttpCookie;\nimport java.net.HttpURLConnection;\nimport java.net.ResponseCache;\nimport java.net.URL;\nimport java.net.URLConnection;\nimport java.security.Principal;\nimport java.security.cert.Certificate;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.TimeZone;\nimport java.util.concurrent.TimeUnit;\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.HttpsURLConnection;\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLSession;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.GzipSink;\nimport okio.Okio;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\n\nimport static com.squareup.okhttp.mockwebserver.SocketPolicy.DISCONNECT_AT_END;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertNull;\nimport static org.junit.Assert.assertSame;\nimport static org.junit.Assert.assertTrue;\nimport static org.junit.Assert.fail;\n\n/** Test caching with {@link OkUrlFactory}. */\npublic final class UrlConnectionCacheTest {\n  private static final HostnameVerifier NULL_HOSTNAME_VERIFIER = new HostnameVerifier() {\n    @Override public boolean verify(String s, SSLSession sslSession) {\n      return true;\n    }\n  };\n\n  @Rule public MockWebServer server = new MockWebServer();\n  @Rule public MockWebServer server2 = new MockWebServer();\n  @Rule public InMemoryFileSystem fileSystem = new InMemoryFileSystem();\n\n  private final SSLContext sslContext = SslContextBuilder.localhost();\n  private final OkUrlFactory client = new OkUrlFactory(new FiberOkHttpClientTestWrapper());\n  private Cache cache;\n  private final CookieManager cookieManager = new CookieManager();\n\n  @Before public void setUp() throws Exception {\n    server.setProtocolNegotiationEnabled(false);\n    cache = new Cache(new File(\"/cache/\"), Integer.MAX_VALUE, fileSystem);\n    client.client().setCache(cache);\n    CookieHandler.setDefault(cookieManager);\n  }\n\n  @After public void tearDown() throws Exception {\n    ResponseCache.setDefault(null);\n    CookieHandler.setDefault(null);\n    cache.delete();\n  }\n\n  @Test public void responseCacheAccessWithOkHttpMember() throws IOException {\n    assertSame(cache, client.client().getCache());\n  }\n\n  /**\n   * Test that response caching is consistent with the RI and the spec.\n   * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4\n   */\n  @Test public void responseCachingByResponseCode() throws Exception {\n      // Test each documented HTTP/1.1 code, plus the first unused value in each range.\n      // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html\n\n      // We can't test 100 because it's not really a response.\n      // assertCached(false, 100);\n      assertCached(false, 101);\n      assertCached(false, 102);\n      assertCached(true,  200);\n      assertCached(false, 201);\n      assertCached(false, 202);\n      assertCached(true,  203);\n      assertCached(true,  204);\n      assertCached(false, 205);\n      assertCached(false, 206); //Electing to not cache partial responses\n      assertCached(false, 207);\n      assertCached(true,  300);\n      assertCached(true,  301);\n      assertCached(true,  302);\n      assertCached(false, 303);\n      assertCached(false, 304);\n      assertCached(false, 305);\n      assertCached(false, 306);\n      assertCached(true,  307);\n      assertCached(true,  308);\n      assertCached(false, 400);\n      assertCached(false, 401);\n      assertCached(false, 402);\n      assertCached(false, 403);\n      assertCached(true,  404);\n      assertCached(true,  405);\n      assertCached(false, 406);\n      assertCached(false, 408);\n      assertCached(false, 409);\n      // the HTTP spec permits caching 410s, but the RI doesn't.\n      assertCached(true,  410);\n      assertCached(false, 411);\n      assertCached(false, 412);\n      assertCached(false, 413);\n      assertCached(true,  414);\n      assertCached(false, 415);\n      assertCached(false, 416);\n      assertCached(false, 417);\n      assertCached(false, 418);\n\n      assertCached(false, 500);\n      assertCached(true,  501);\n      assertCached(false, 502);\n      assertCached(false, 503);\n      assertCached(false, 504);\n      assertCached(false, 505);\n      assertCached(false, 506);\n  }\n\n  private void assertCached(boolean shouldPut, int responseCode) throws Exception {\n    server = new MockWebServer();\n    MockResponse response = new MockResponse()\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setResponseCode(responseCode)\n        .setBody(\"ABCDE\")\n        .addHeader(\"WWW-Authenticate: challenge\");\n    if (responseCode == HttpURLConnection.HTTP_PROXY_AUTH) {\n      response.addHeader(\"Proxy-Authenticate: Basic realm=\\\"protected area\\\"\");\n    } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {\n      response.addHeader(\"WWW-Authenticate: Basic realm=\\\"protected area\\\"\");\n    }\n    server.enqueue(response);\n    server.start();\n\n    URL url = server.getUrl(\"/\");\n    HttpURLConnection conn = client.open(url);\n    assertEquals(responseCode, conn.getResponseCode());\n\n    // exhaust the content stream\n    readAscii(conn);\n\n    Response cached = cache.get(new Request.Builder().url(url).build());\n    if (shouldPut) {\n      assertNotNull(Integer.toString(responseCode), cached);\n      cached.body().close();\n    } else {\n      assertNull(Integer.toString(responseCode), cached);\n    }\n    server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers\n  }\n\n  @Test public void responseCachingAndInputStreamSkipWithFixedLength() throws IOException {\n    testResponseCaching(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void responseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException {\n    testResponseCaching(TransferKind.CHUNKED);\n  }\n\n  @Test public void responseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException {\n    testResponseCaching(TransferKind.END_OF_STREAM);\n  }\n\n  /**\n   * HttpURLConnection.getInputStream().skip(long) causes ResponseCache corruption\n   * http://code.google.com/p/android/issues/detail?id=8175\n   */\n  private void testResponseCaching(TransferKind transferKind) throws IOException {\n    MockResponse response =\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n            .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n            .setStatus(\"HTTP/1.1 200 Fantastic\");\n    transferKind.setBody(response, \"I love puppies but hate spiders\", 1);\n    server.enqueue(response);\n\n    // Make sure that calling skip() doesn't omit bytes from the cache.\n    HttpURLConnection urlConnection = client.open(server.getUrl(\"/\"));\n    InputStream in = urlConnection.getInputStream();\n    assertEquals(\"I love \", readAscii(urlConnection, \"I love \".length()));\n    reliableSkip(in, \"puppies but hate \".length());\n    assertEquals(\"spiders\", readAscii(urlConnection, \"spiders\".length()));\n    assertEquals(-1, in.read());\n    in.close();\n    assertEquals(1, cache.getWriteSuccessCount());\n    assertEquals(0, cache.getWriteAbortCount());\n\n    urlConnection = client.open(server.getUrl(\"/\")); // cached!\n    in = urlConnection.getInputStream();\n    assertEquals(\"I love puppies but hate spiders\",\n        readAscii(urlConnection, \"I love puppies but hate spiders\".length()));\n    assertEquals(200, urlConnection.getResponseCode());\n    assertEquals(\"Fantastic\", urlConnection.getResponseMessage());\n\n    assertEquals(-1, in.read());\n    in.close();\n    assertEquals(1, cache.getWriteSuccessCount());\n    assertEquals(0, cache.getWriteAbortCount());\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getHitCount());\n  }\n\n  @Test public void secureResponseCaching() throws IOException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setBody(\"ABC\"));\n\n    HttpsURLConnection c1 = (HttpsURLConnection) client.open(server.getUrl(\"/\"));\n    c1.setSSLSocketFactory(sslContext.getSocketFactory());\n    c1.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n    assertEquals(\"ABC\", readAscii(c1));\n\n    // OpenJDK 6 fails on this line, complaining that the connection isn't open yet\n    String suite = c1.getCipherSuite();\n    List<Certificate> localCerts = toListOrNull(c1.getLocalCertificates());\n    List<Certificate> serverCerts = toListOrNull(c1.getServerCertificates());\n    Principal peerPrincipal = c1.getPeerPrincipal();\n    Principal localPrincipal = c1.getLocalPrincipal();\n\n    HttpsURLConnection c2 = (HttpsURLConnection) client.open(server.getUrl(\"/\")); // cached!\n    c2.setSSLSocketFactory(sslContext.getSocketFactory());\n    c2.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n    assertEquals(\"ABC\", readAscii(c2));\n\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(1, cache.getHitCount());\n\n    assertEquals(suite, c2.getCipherSuite());\n    assertEquals(localCerts, toListOrNull(c2.getLocalCertificates()));\n    assertEquals(serverCerts, toListOrNull(c2.getServerCertificates()));\n    assertEquals(peerPrincipal, c2.getPeerPrincipal());\n    assertEquals(localPrincipal, c2.getLocalPrincipal());\n  }\n\n  @Test public void responseCachingAndRedirects() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)\n        .addHeader(\"Location: /foo\"));\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setBody(\"ABC\"));\n    server.enqueue(new MockResponse().setBody(\"DEF\"));\n\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"ABC\", readAscii(connection));\n\n    connection = client.open(server.getUrl(\"/\")); // cached!\n    assertEquals(\"ABC\", readAscii(connection));\n\n    assertEquals(4, cache.getRequestCount()); // 2 requests + 2 redirects\n    assertEquals(2, cache.getNetworkCount());\n    assertEquals(2, cache.getHitCount());\n  }\n\n  @Test public void redirectToCachedResult() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\").setBody(\"ABC\"));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)\n        .addHeader(\"Location: /foo\"));\n    server.enqueue(new MockResponse().setBody(\"DEF\"));\n\n    assertEquals(\"ABC\", readAscii(client.open(server.getUrl(\"/foo\"))));\n    RecordedRequest request1 = server.takeRequest();\n    assertEquals(\"GET /foo HTTP/1.1\", request1.getRequestLine());\n    assertEquals(0, request1.getSequenceNumber());\n\n    assertEquals(\"ABC\", readAscii(client.open(server.getUrl(\"/bar\"))));\n    RecordedRequest request2 = server.takeRequest();\n    assertEquals(\"GET /bar HTTP/1.1\", request2.getRequestLine());\n    assertEquals(1, request2.getSequenceNumber());\n\n    // an unrelated request should reuse the pooled connection\n    assertEquals(\"DEF\", readAscii(client.open(server.getUrl(\"/baz\"))));\n    RecordedRequest request3 = server.takeRequest();\n    assertEquals(\"GET /baz HTTP/1.1\", request3.getRequestLine());\n    assertEquals(2, request3.getSequenceNumber());\n  }\n\n  @Test public void secureResponseCachingAndRedirects() throws IOException {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)\n        .addHeader(\"Location: /foo\"));\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setBody(\"ABC\"));\n    server.enqueue(new MockResponse().setBody(\"DEF\"));\n\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n\n    HttpsURLConnection connection1 = (HttpsURLConnection) client.open(server.getUrl(\"/\"));\n    assertEquals(\"ABC\", readAscii(connection1));\n    assertNotNull(connection1.getCipherSuite());\n\n    // Cached!\n    HttpsURLConnection connection2 = (HttpsURLConnection) client.open(server.getUrl(\"/\"));\n    assertEquals(\"ABC\", readAscii(connection2));\n    assertNotNull(connection2.getCipherSuite());\n\n    assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4\n    assertEquals(2, cache.getHitCount());\n    assertEquals(connection1.getCipherSuite(), connection2.getCipherSuite());\n  }\n\n  /**\n   * We've had bugs where caching and cross-protocol redirects yield class\n   * cast exceptions internal to the cache because we incorrectly assumed that\n   * HttpsURLConnection was always HTTPS and HttpURLConnection was always HTTP;\n   * in practice redirects mean that each can do either.\n   *\n   * https://github.com/square/okhttp/issues/214\n   */\n  @Test public void secureResponseCachingAndProtocolRedirects() throws IOException {\n    server2.useHttps(sslContext.getSocketFactory(), false);\n    server2.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setBody(\"ABC\"));\n    server2.enqueue(new MockResponse().setBody(\"DEF\"));\n\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)\n        .addHeader(\"Location: \" + server2.getUrl(\"/\")));\n\n    client.client().setSslSocketFactory(sslContext.getSocketFactory());\n    client.client().setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n\n    HttpURLConnection connection1 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"ABC\", readAscii(connection1));\n\n    // Cached!\n    HttpURLConnection connection2 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"ABC\", readAscii(connection2));\n\n    assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4\n    assertEquals(2, cache.getHitCount());\n  }\n\n  @Test public void serverDisconnectsPrematurelyWithContentLengthHeader() throws IOException {\n    testServerPrematureDisconnect(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void serverDisconnectsPrematurelyWithChunkedEncoding() throws IOException {\n    testServerPrematureDisconnect(TransferKind.CHUNKED);\n  }\n\n  @Test public void serverDisconnectsPrematurelyWithNoLengthHeaders() throws IOException {\n    // Intentionally empty. This case doesn't make sense because there's no\n    // such thing as a premature disconnect when the disconnect itself\n    // indicates the end of the data stream.\n  }\n\n  private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException {\n    MockResponse response = new MockResponse();\n    transferKind.setBody(response, \"ABCDE\\nFGHIJKLMNOPQRSTUVWXYZ\", 16);\n    server.enqueue(truncateViolently(response, 16));\n    server.enqueue(new MockResponse().setBody(\"Request #2\"));\n\n    BufferedReader reader = new BufferedReader(\n        new InputStreamReader(client.open(server.getUrl(\"/\")).getInputStream()));\n    assertEquals(\"ABCDE\", reader.readLine());\n    try {\n      reader.readLine();\n      fail(\"This implementation silently ignored a truncated HTTP body.\");\n    } catch (IOException expected) {\n    } finally {\n      reader.close();\n    }\n\n    assertEquals(1, cache.getWriteAbortCount());\n    assertEquals(0, cache.getWriteSuccessCount());\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"Request #2\", readAscii(connection));\n    assertEquals(1, cache.getWriteAbortCount());\n    assertEquals(1, cache.getWriteSuccessCount());\n  }\n\n  @Test public void clientPrematureDisconnectWithContentLengthHeader() throws IOException {\n    testClientPrematureDisconnect(TransferKind.FIXED_LENGTH);\n  }\n\n  @Test public void clientPrematureDisconnectWithChunkedEncoding() throws IOException {\n    testClientPrematureDisconnect(TransferKind.CHUNKED);\n  }\n\n  @Test public void clientPrematureDisconnectWithNoLengthHeaders() throws IOException {\n    testClientPrematureDisconnect(TransferKind.END_OF_STREAM);\n  }\n\n  private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException {\n    // Setting a low transfer speed ensures that stream discarding will time out.\n    MockResponse response = new MockResponse().throttleBody(6, 1, TimeUnit.SECONDS);\n    transferKind.setBody(response, \"ABCDE\\nFGHIJKLMNOPQRSTUVWXYZ\", 1024);\n    server.enqueue(response);\n    server.enqueue(new MockResponse().setBody(\"Request #2\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    InputStream in = connection.getInputStream();\n    assertEquals(\"ABCDE\", readAscii(connection, 5));\n    in.close();\n    try {\n      in.read();\n      fail(\"Expected an IOException because the stream is closed.\");\n    } catch (IOException expected) {\n    }\n\n    assertEquals(1, cache.getWriteAbortCount());\n    assertEquals(0, cache.getWriteSuccessCount());\n    connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"Request #2\", readAscii(connection));\n    assertEquals(1, cache.getWriteAbortCount());\n    assertEquals(1, cache.getWriteSuccessCount());\n  }\n\n  @Test public void defaultExpirationDateFullyCachedForLessThan24Hours() throws Exception {\n    //      last modified: 105 seconds ago\n    //             served:   5 seconds ago\n    //   default lifetime: (105 - 5) / 10 = 10 seconds\n    //            expires:  10 seconds from served date = 5 seconds from now\n    server.enqueue(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-105, TimeUnit.SECONDS))\n            .addHeader(\"Date: \" + formatDate(-5, TimeUnit.SECONDS))\n            .setBody(\"A\"));\n\n    URL url = server.getUrl(\"/\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n    URLConnection connection = client.open(url);\n    assertEquals(\"A\", readAscii(connection));\n    assertNull(connection.getHeaderField(\"Warning\"));\n  }\n\n  @Test public void defaultExpirationDateConditionallyCached() throws Exception {\n    //      last modified: 115 seconds ago\n    //             served:  15 seconds ago\n    //   default lifetime: (115 - 15) / 10 = 10 seconds\n    //            expires:  10 seconds from served date = 5 seconds ago\n    String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + lastModifiedDate)\n            .addHeader(\"Date: \" + formatDate(-15, TimeUnit.SECONDS)));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void defaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception {\n    //      last modified: 105 days ago\n    //             served:   5 days ago\n    //   default lifetime: (105 - 5) / 10 = 10 days\n    //            expires:  10 days from served date = 5 days from now\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-105, TimeUnit.DAYS))\n        .addHeader(\"Date: \" + formatDate(-5, TimeUnit.DAYS))\n        .setBody(\"A\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection));\n    assertEquals(\"113 HttpURLConnection \\\"Heuristic expiration\\\"\",\n        connection.getHeaderField(\"Warning\"));\n  }\n\n  @Test public void noDefaultExpirationForUrlsWithQueryString() throws Exception {\n    server.enqueue(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-105, TimeUnit.SECONDS))\n            .addHeader(\"Date: \" + formatDate(-5, TimeUnit.SECONDS))\n            .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/?foo=bar\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n    assertEquals(\"B\", readAscii(client.open(url)));\n  }\n\n  @Test public void expirationDateInThePastWithLastModifiedHeader() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + lastModifiedDate)\n            .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void expirationDateInThePastWithNoLastModifiedHeader() throws Exception {\n    assertNotCached(new MockResponse().addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n  }\n\n  @Test public void expirationDateInTheFuture() throws Exception {\n    assertFullyCached(new MockResponse().addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n  }\n\n  @Test public void maxAgePreferredWithMaxAgeAndExpires() throws Exception {\n    assertFullyCached(new MockResponse().addHeader(\"Date: \" + formatDate(0, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(\n        new MockResponse().addHeader(\"Date: \" + formatDate(-120, TimeUnit.SECONDS))\n            .addHeader(\"Last-Modified: \" + lastModifiedDate)\n            .addHeader(\"Cache-Control: max-age=60\"));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void maxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception {\n    // Chrome interprets max-age relative to the local clock. Both our cache\n    // and Firefox both use the earlier of the local and server's clock.\n    assertNotCached(new MockResponse().addHeader(\"Date: \" + formatDate(-120, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeInTheFutureWithDateHeader() throws Exception {\n    assertFullyCached(new MockResponse().addHeader(\"Date: \" + formatDate(0, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeInTheFutureWithNoDateHeader() throws Exception {\n    assertFullyCached(new MockResponse().addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeWithLastModifiedButNoServedDate() throws Exception {\n    assertFullyCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-120, TimeUnit.SECONDS))\n            .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception {\n    assertFullyCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-120, TimeUnit.SECONDS))\n            .addHeader(\"Date: \" + formatDate(0, TimeUnit.SECONDS))\n            .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void maxAgePreferredOverLowerSharedMaxAge() throws Exception {\n    assertFullyCached(new MockResponse().addHeader(\"Date: \" + formatDate(-2, TimeUnit.MINUTES))\n        .addHeader(\"Cache-Control: s-maxage=60\")\n        .addHeader(\"Cache-Control: max-age=180\"));\n  }\n\n  @Test public void maxAgePreferredOverHigherMaxAge() throws Exception {\n    assertNotCached(new MockResponse().addHeader(\"Date: \" + formatDate(-2, TimeUnit.MINUTES))\n        .addHeader(\"Cache-Control: s-maxage=180\")\n        .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void requestMethodOptionsIsNotCached() throws Exception {\n    testRequestMethod(\"OPTIONS\", false);\n  }\n\n  @Test public void requestMethodGetIsCached() throws Exception {\n    testRequestMethod(\"GET\", true);\n  }\n\n  @Test public void requestMethodHeadIsNotCached() throws Exception {\n    // We could support this but choose not to for implementation simplicity\n    testRequestMethod(\"HEAD\", false);\n  }\n\n  @Test public void requestMethodPostIsNotCached() throws Exception {\n    // We could support this but choose not to for implementation simplicity\n    testRequestMethod(\"POST\", false);\n  }\n\n  @Test public void requestMethodPutIsNotCached() throws Exception {\n    testRequestMethod(\"PUT\", false);\n  }\n\n  @Test public void requestMethodDeleteIsNotCached() throws Exception {\n    testRequestMethod(\"DELETE\", false);\n  }\n\n  @Test public void requestMethodTraceIsNotCached() throws Exception {\n    testRequestMethod(\"TRACE\", false);\n  }\n\n  private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception {\n    // 1. seed the cache (potentially)\n    // 2. expect a cache hit or miss\n    server.enqueue(new MockResponse().addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .addHeader(\"X-Response-ID: 1\"));\n    server.enqueue(new MockResponse().addHeader(\"X-Response-ID: 2\"));\n\n    URL url = server.getUrl(\"/\");\n\n    HttpURLConnection request1 = client.open(url);\n    request1.setRequestMethod(requestMethod);\n    addRequestBodyIfNecessary(requestMethod, request1);\n    request1.getInputStream().close();\n    assertEquals(\"1\", request1.getHeaderField(\"X-Response-ID\"));\n\n    URLConnection request2 = client.open(url);\n    request2.getInputStream().close();\n    if (expectCached) {\n      assertEquals(\"1\", request2.getHeaderField(\"X-Response-ID\"));\n    } else {\n      assertEquals(\"2\", request2.getHeaderField(\"X-Response-ID\"));\n    }\n  }\n\n  @Test public void postInvalidatesCache() throws Exception {\n    testMethodInvalidates(\"POST\");\n  }\n\n  @Test public void putInvalidatesCache() throws Exception {\n    testMethodInvalidates(\"PUT\");\n  }\n\n  @Test public void deleteMethodInvalidatesCache() throws Exception {\n    testMethodInvalidates(\"DELETE\");\n  }\n\n  private void testMethodInvalidates(String requestMethod) throws Exception {\n    // 1. seed the cache\n    // 2. invalidate it\n    // 3. expect a cache miss\n    server.enqueue(\n        new MockResponse().setBody(\"A\").addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n    server.enqueue(new MockResponse().setBody(\"C\"));\n\n    URL url = server.getUrl(\"/\");\n\n    assertEquals(\"A\", readAscii(client.open(url)));\n\n    HttpURLConnection invalidate = client.open(url);\n    invalidate.setRequestMethod(requestMethod);\n    addRequestBodyIfNecessary(requestMethod, invalidate);\n    assertEquals(\"B\", readAscii(invalidate));\n\n    assertEquals(\"C\", readAscii(client.open(url)));\n  }\n\n  @Test public void postInvalidatesCacheWithUncacheableResponse() throws Exception {\n    // 1. seed the cache\n    // 2. invalidate it with uncacheable response\n    // 3. expect a cache miss\n    server.enqueue(\n        new MockResponse().setBody(\"A\").addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse().setBody(\"B\").setResponseCode(500));\n    server.enqueue(new MockResponse().setBody(\"C\"));\n\n    URL url = server.getUrl(\"/\");\n\n    assertEquals(\"A\", readAscii(client.open(url)));\n\n    HttpURLConnection invalidate = client.open(url);\n    invalidate.setRequestMethod(\"POST\");\n    addRequestBodyIfNecessary(\"POST\", invalidate);\n    assertEquals(\"B\", readAscii(invalidate));\n\n    assertEquals(\"C\", readAscii(client.open(url)));\n  }\n\n  @Test public void etag() throws Exception {\n    RecordedRequest conditionalRequest =\n        assertConditionallyCached(new MockResponse().addHeader(\"ETag: v1\"));\n    assertEquals(\"v1\", conditionalRequest.getHeader(\"If-None-Match\"));\n  }\n\n  @Test public void etagAndExpirationDateInThePast() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(\n        new MockResponse().addHeader(\"ETag: v1\")\n            .addHeader(\"Last-Modified: \" + lastModifiedDate)\n            .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n    assertEquals(\"v1\", conditionalRequest.getHeader(\"If-None-Match\"));\n    assertNull(conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void etagAndExpirationDateInTheFuture() throws Exception {\n    assertFullyCached(new MockResponse().addHeader(\"ETag: v1\")\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n  }\n\n  @Test public void cacheControlNoCache() throws Exception {\n    assertNotCached(new MockResponse().addHeader(\"Cache-Control: no-cache\"));\n  }\n\n  @Test public void cacheControlNoCacheAndExpirationDateInTheFuture() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + lastModifiedDate)\n            .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n            .addHeader(\"Cache-Control: no-cache\"));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void pragmaNoCache() throws Exception {\n    assertNotCached(new MockResponse().addHeader(\"Pragma: no-cache\"));\n  }\n\n  @Test public void pragmaNoCacheAndExpirationDateInTheFuture() throws Exception {\n    String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);\n    RecordedRequest conditionalRequest = assertConditionallyCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + lastModifiedDate)\n            .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n            .addHeader(\"Pragma: no-cache\"));\n    assertEquals(lastModifiedDate, conditionalRequest.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void cacheControlNoStore() throws Exception {\n    assertNotCached(new MockResponse().addHeader(\"Cache-Control: no-store\"));\n  }\n\n  @Test public void cacheControlNoStoreAndExpirationDateInTheFuture() throws Exception {\n    assertNotCached(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: no-store\"));\n  }\n\n  @Test public void partialRangeResponsesDoNotCorruptCache() throws Exception {\n    // 1. request a range\n    // 2. request a full document, expecting a cache miss\n    server.enqueue(new MockResponse().setBody(\"AA\")\n        .setResponseCode(HttpURLConnection.HTTP_PARTIAL)\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS))\n        .addHeader(\"Content-Range: bytes 1000-1001/2000\"));\n    server.enqueue(new MockResponse().setBody(\"BB\"));\n\n    URL url = server.getUrl(\"/\");\n\n    URLConnection range = client.open(url);\n    range.addRequestProperty(\"Range\", \"bytes=1000-1001\");\n    assertEquals(\"AA\", readAscii(range));\n\n    assertEquals(\"BB\", readAscii(client.open(url)));\n  }\n\n  @Test public void serverReturnsDocumentOlderThanCache() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse().setBody(\"B\")\n        .addHeader(\"Last-Modified: \" + formatDate(-4, TimeUnit.HOURS)));\n\n    URL url = server.getUrl(\"/\");\n\n    assertEquals(\"A\", readAscii(client.open(url)));\n    assertEquals(\"A\", readAscii(client.open(url)));\n  }\n\n  @Test public void nonIdentityEncodingAndConditionalCache() throws Exception {\n    assertNonIdentityEncodingCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n            .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n  }\n\n  @Test public void nonIdentityEncodingAndFullCache() throws Exception {\n    assertNonIdentityEncodingCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n            .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n  }\n\n  private void assertNonIdentityEncodingCached(MockResponse response) throws Exception {\n    server.enqueue(\n        response.setBody(gzip(\"ABCABCABC\")).addHeader(\"Content-Encoding: gzip\"));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    // At least three request/response pairs are required because after the first request is cached\n    // a different execution path might be taken. Thus modifications to the cache applied during\n    // the second request might not be visible until another request is performed.\n    assertEquals(\"ABCABCABC\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"ABCABCABC\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"ABCABCABC\", readAscii(client.open(server.getUrl(\"/\"))));\n  }\n\n  @Test public void notModifiedSpecifiesEncoding() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(gzip(\"ABCABCABC\"))\n        .addHeader(\"Content-Encoding: gzip\")\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Expires: \" + formatDate(-1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)\n        .addHeader(\"Content-Encoding: gzip\"));\n    server.enqueue(new MockResponse()\n        .setBody(\"DEFDEFDEF\"));\n\n    assertEquals(\"ABCABCABC\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"ABCABCABC\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"DEFDEFDEF\", readAscii(client.open(server.getUrl(\"/\"))));\n  }\n\n  /** https://github.com/square/okhttp/issues/947 */\n  @Test public void gzipAndVaryOnAcceptEncoding() throws Exception {\n    server.enqueue(new MockResponse()\n        .setBody(gzip(\"ABCABCABC\"))\n        .addHeader(\"Content-Encoding: gzip\")\n        .addHeader(\"Vary: Accept-Encoding\")\n        .addHeader(\"Cache-Control: max-age=60\"));\n    server.enqueue(new MockResponse().setBody(\"FAIL\"));\n\n    assertEquals(\"ABCABCABC\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"ABCABCABC\", readAscii(client.open(server.getUrl(\"/\"))));\n  }\n\n  @Test public void conditionalCacheHitIsNotDoublePooled() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"ETag: v1\").setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .clearHeaders()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    ConnectionPool pool = ConnectionPool.getDefault();\n    pool.evictAll();\n    client.client().setConnectionPool(pool);\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(1, client.client().getConnectionPool().getConnectionCount());\n  }\n\n  @Test public void expiresDateBeforeModifiedDate() throws Exception {\n    assertConditionallyCached(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n            .addHeader(\"Expires: \" + formatDate(-2, TimeUnit.HOURS)));\n  }\n\n  @Test public void requestMaxAge() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Last-Modified: \" + formatDate(-2, TimeUnit.HOURS))\n        .addHeader(\"Date: \" + formatDate(-1, TimeUnit.MINUTES))\n        .addHeader(\"Expires: \" + formatDate(1, TimeUnit.HOURS)));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"max-age=30\");\n    assertEquals(\"B\", readAscii(connection));\n  }\n\n  @Test public void requestMinFresh() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"min-fresh=120\");\n    assertEquals(\"B\", readAscii(connection));\n  }\n\n  @Test public void requestMaxStale() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=120\")\n        .addHeader(\"Date: \" + formatDate(-4, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"max-stale=180\");\n    assertEquals(\"A\", readAscii(connection));\n    assertEquals(\"110 HttpURLConnection \\\"Response is stale\\\"\",\n        connection.getHeaderField(\"Warning\"));\n  }\n\n  @Test public void requestMaxStaleNotHonoredWithMustRevalidate() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=120, must-revalidate\")\n        .addHeader(\"Date: \" + formatDate(-4, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"max-stale=180\");\n    assertEquals(\"B\", readAscii(connection));\n  }\n\n  @Test public void requestOnlyIfCachedWithNoResponseCached() throws IOException {\n    // (no responses enqueued)\n\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"only-if-cached\");\n    assertGatewayTimeout(connection);\n    assertEquals(1, cache.getRequestCount());\n    assertEquals(0, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n  }\n\n  @Test public void requestOnlyIfCachedWithFullResponseCached() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"only-if-cached\");\n    assertEquals(\"A\", readAscii(connection));\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(1, cache.getHitCount());\n  }\n\n  @Test public void requestOnlyIfCachedWithConditionalResponseCached() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(-1, TimeUnit.MINUTES)));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"only-if-cached\");\n    assertGatewayTimeout(connection);\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n  }\n\n  @Test public void requestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"only-if-cached\");\n    assertGatewayTimeout(connection);\n    assertEquals(2, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n  }\n\n  @Test public void requestCacheControlNoCache() throws Exception {\n    server.enqueue(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-120, TimeUnit.SECONDS))\n            .addHeader(\"Date: \" + formatDate(0, TimeUnit.SECONDS))\n            .addHeader(\"Cache-Control: max-age=60\")\n            .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n    URLConnection connection = client.open(url);\n    connection.setRequestProperty(\"Cache-Control\", \"no-cache\");\n    assertEquals(\"B\", readAscii(connection));\n  }\n\n  @Test public void requestPragmaNoCache() throws Exception {\n    server.enqueue(\n        new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-120, TimeUnit.SECONDS))\n            .addHeader(\"Date: \" + formatDate(0, TimeUnit.SECONDS))\n            .addHeader(\"Cache-Control: max-age=60\")\n            .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n    URLConnection connection = client.open(url);\n    connection.setRequestProperty(\"Pragma\", \"no-cache\");\n    assertEquals(\"B\", readAscii(connection));\n  }\n\n  @Test public void clientSuppliedIfModifiedSinceWithCachedResult() throws Exception {\n    MockResponse response =\n        new MockResponse().addHeader(\"ETag: v3\").addHeader(\"Cache-Control: max-age=0\");\n    String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS);\n    RecordedRequest request =\n        assertClientSuppliedCondition(response, \"If-Modified-Since\", ifModifiedSinceDate);\n    assertEquals(ifModifiedSinceDate, request.getHeader(\"If-Modified-Since\"));\n    assertNull(request.getHeader(\"If-None-Match\"));\n  }\n\n  @Test public void clientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception {\n    String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES);\n    MockResponse response = new MockResponse().addHeader(\"Last-Modified: \" + lastModifiedDate)\n        .addHeader(\"Date: \" + formatDate(-2, TimeUnit.MINUTES))\n        .addHeader(\"Cache-Control: max-age=0\");\n    RecordedRequest request = assertClientSuppliedCondition(response, \"If-None-Match\", \"v1\");\n    assertEquals(\"v1\", request.getHeader(\"If-None-Match\"));\n    assertNull(request.getHeader(\"If-Modified-Since\"));\n  }\n\n  private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName,\n      String conditionValue) throws Exception {\n    server.enqueue(seed.setBody(\"A\"));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    URL url = server.getUrl(\"/\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n\n    HttpURLConnection connection = client.open(url);\n    connection.addRequestProperty(conditionName, conditionValue);\n    assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode());\n    assertEquals(\"\", readAscii(connection));\n\n    server.takeRequest(); // seed\n    return server.takeRequest();\n  }\n\n  /**\n   * Confirm that {@link URLConnection#setIfModifiedSince} causes an\n   * If-Modified-Since header with a GMT timestamp.\n   *\n   * https://code.google.com/p/android/issues/detail?id=66135\n   */\n  @Test public void setIfModifiedSince() throws Exception {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    URL url = server.getUrl(\"/\");\n    URLConnection connection = client.open(url);\n    connection.setIfModifiedSince(1393666200000L);\n    assertEquals(\"A\", readAscii(connection));\n    RecordedRequest request = server.takeRequest();\n    String ifModifiedSinceHeader = request.getHeader(\"If-Modified-Since\");\n    assertEquals(\"Sat, 01 Mar 2014 09:30:00 GMT\", ifModifiedSinceHeader);\n  }\n\n  /**\n   * For Last-Modified and Date headers, we should echo the date back in the\n   * exact format we were served.\n   */\n  @Test public void retainServedDateFormat() throws Exception {\n    // Serve a response with a non-standard date format that OkHttp supports.\n    Date lastModifiedDate = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(-1));\n    Date servedDate = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(-2));\n    DateFormat dateFormat = new SimpleDateFormat(\"EEE dd-MMM-yyyy HH:mm:ss z\", Locale.US);\n    dateFormat.setTimeZone(TimeZone.getTimeZone(\"EDT\"));\n    String lastModifiedString = dateFormat.format(lastModifiedDate);\n    String servedString = dateFormat.format(servedDate);\n\n    // This response should be conditionally cached.\n    server.enqueue(new MockResponse()\n        .addHeader(\"Last-Modified: \" + lastModifiedString)\n        .addHeader(\"Expires: \" + servedString)\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n\n    // The first request has no conditions.\n    RecordedRequest request1 = server.takeRequest();\n    assertNull(request1.getHeader(\"If-Modified-Since\"));\n\n    // The 2nd request uses the server's date format.\n    RecordedRequest request2 = server.takeRequest();\n    assertEquals(lastModifiedString, request2.getHeader(\"If-Modified-Since\"));\n  }\n\n  @Test public void clientSuppliedConditionWithoutCachedResult() throws Exception {\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    String clientIfModifiedSince = formatDate(-24, TimeUnit.HOURS);\n    connection.addRequestProperty(\"If-Modified-Since\", clientIfModifiedSince);\n    assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode());\n    assertEquals(\"\", readAscii(connection));\n  }\n\n  @Test public void authorizationRequestFullyCached() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\").setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    URLConnection connection = client.open(url);\n    connection.addRequestProperty(\"Authorization\", \"password\");\n    assertEquals(\"A\", readAscii(connection));\n    assertEquals(\"A\", readAscii(client.open(url)));\n  }\n\n  @Test public void contentLocationDoesNotPopulateCache() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Content-Location: /bar\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/foo\"))));\n    assertEquals(\"B\", readAscii(client.open(server.getUrl(\"/bar\"))));\n  }\n\n  @Test public void useCachesFalseDoesNotWriteToCache() throws Exception {\n    server.enqueue(\n        new MockResponse().addHeader(\"Cache-Control: max-age=60\").setBody(\"A\").setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.setUseCaches(false);\n    assertEquals(\"A\", readAscii(connection));\n    assertEquals(\"B\", readAscii(client.open(server.getUrl(\"/\"))));\n  }\n\n  @Test public void useCachesFalseDoesNotReadFromCache() throws Exception {\n    server.enqueue(\n        new MockResponse().addHeader(\"Cache-Control: max-age=60\").setBody(\"A\").setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.setUseCaches(false);\n    assertEquals(\"B\", readAscii(connection));\n  }\n\n  @Test public void defaultUseCachesSetsInitialValueOnly() throws Exception {\n    URL url = new URL(\"http://localhost/\");\n    URLConnection c1 = client.open(url);\n    URLConnection c2 = client.open(url);\n    assertTrue(c1.getDefaultUseCaches());\n    c1.setDefaultUseCaches(false);\n    try {\n      assertTrue(c1.getUseCaches());\n      assertTrue(c2.getUseCaches());\n      URLConnection c3 = client.open(url);\n      assertFalse(c3.getUseCaches());\n    } finally {\n      c1.setDefaultUseCaches(true);\n    }\n  }\n\n  @Test public void connectionIsReturnedToPoolAfterConditionalSuccess() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/a\"))));\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/a\"))));\n    assertEquals(\"B\", readAscii(client.open(server.getUrl(\"/b\"))));\n\n    assertEquals(0, server.takeRequest().getSequenceNumber());\n    assertEquals(1, server.takeRequest().getSequenceNumber());\n    assertEquals(2, server.takeRequest().getSequenceNumber());\n  }\n\n  @Test public void statisticsConditionalCacheMiss() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n    server.enqueue(new MockResponse().setBody(\"C\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(1, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n    assertEquals(\"B\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"C\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(3, cache.getRequestCount());\n    assertEquals(3, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n  }\n\n  @Test public void statisticsConditionalCacheHit() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(1, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(3, cache.getRequestCount());\n    assertEquals(3, cache.getNetworkCount());\n    assertEquals(2, cache.getHitCount());\n  }\n\n  @Test public void statisticsFullCacheHit() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\").setBody(\"A\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(1, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(0, cache.getHitCount());\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(3, cache.getRequestCount());\n    assertEquals(1, cache.getNetworkCount());\n    assertEquals(2, cache.getHitCount());\n  }\n\n  @Test public void varyMatchesChangedRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    HttpURLConnection frConnection = client.open(url);\n    frConnection.addRequestProperty(\"Accept-Language\", \"fr-CA\");\n    assertEquals(\"A\", readAscii(frConnection));\n\n    HttpURLConnection enConnection = client.open(url);\n    enConnection.addRequestProperty(\"Accept-Language\", \"en-US\");\n    assertEquals(\"B\", readAscii(enConnection));\n  }\n\n  @Test public void varyMatchesUnchangedRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    URLConnection connection1 = client.open(url);\n    connection1.addRequestProperty(\"Accept-Language\", \"fr-CA\");\n    assertEquals(\"A\", readAscii(connection1));\n    URLConnection connection2 = client.open(url);\n    connection2.addRequestProperty(\"Accept-Language\", \"fr-CA\");\n    assertEquals(\"A\", readAscii(connection2));\n  }\n\n  @Test public void varyMatchesAbsentRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Foo\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n  }\n\n  @Test public void varyMatchesAddedRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Foo\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    URLConnection fooConnection = client.open(server.getUrl(\"/\"));\n    fooConnection.addRequestProperty(\"Foo\", \"bar\");\n    assertEquals(\"B\", readAscii(fooConnection));\n  }\n\n  @Test public void varyMatchesRemovedRequestHeaderField() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Foo\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URLConnection fooConnection = client.open(server.getUrl(\"/\"));\n    fooConnection.addRequestProperty(\"Foo\", \"bar\");\n    assertEquals(\"A\", readAscii(fooConnection));\n    assertEquals(\"B\", readAscii(client.open(server.getUrl(\"/\"))));\n  }\n\n  @Test public void varyFieldsAreCaseInsensitive() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: ACCEPT-LANGUAGE\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    URLConnection connection1 = client.open(url);\n    connection1.addRequestProperty(\"Accept-Language\", \"fr-CA\");\n    assertEquals(\"A\", readAscii(connection1));\n    URLConnection connection2 = client.open(url);\n    connection2.addRequestProperty(\"accept-language\", \"fr-CA\");\n    assertEquals(\"A\", readAscii(connection2));\n  }\n\n  @Test public void varyMultipleFieldsWithMatch() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language, Accept-Charset\")\n        .addHeader(\"Vary: Accept-Encoding\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    URLConnection connection1 = client.open(url);\n    connection1.addRequestProperty(\"Accept-Language\", \"fr-CA\");\n    connection1.addRequestProperty(\"Accept-Charset\", \"UTF-8\");\n    connection1.addRequestProperty(\"Accept-Encoding\", \"identity\");\n    assertEquals(\"A\", readAscii(connection1));\n    URLConnection connection2 = client.open(url);\n    connection2.addRequestProperty(\"Accept-Language\", \"fr-CA\");\n    connection2.addRequestProperty(\"Accept-Charset\", \"UTF-8\");\n    connection2.addRequestProperty(\"Accept-Encoding\", \"identity\");\n    assertEquals(\"A\", readAscii(connection2));\n  }\n\n  @Test public void varyMultipleFieldsWithNoMatch() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language, Accept-Charset\")\n        .addHeader(\"Vary: Accept-Encoding\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    URLConnection frConnection = client.open(url);\n    frConnection.addRequestProperty(\"Accept-Language\", \"fr-CA\");\n    frConnection.addRequestProperty(\"Accept-Charset\", \"UTF-8\");\n    frConnection.addRequestProperty(\"Accept-Encoding\", \"identity\");\n    assertEquals(\"A\", readAscii(frConnection));\n    URLConnection enConnection = client.open(url);\n    enConnection.addRequestProperty(\"Accept-Language\", \"en-CA\");\n    enConnection.addRequestProperty(\"Accept-Charset\", \"UTF-8\");\n    enConnection.addRequestProperty(\"Accept-Encoding\", \"identity\");\n    assertEquals(\"B\", readAscii(enConnection));\n  }\n\n  @Test public void varyMultipleFieldValuesWithMatch() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    URLConnection connection1 = client.open(url);\n    connection1.addRequestProperty(\"Accept-Language\", \"fr-CA, fr-FR\");\n    connection1.addRequestProperty(\"Accept-Language\", \"en-US\");\n    assertEquals(\"A\", readAscii(connection1));\n\n    URLConnection connection2 = client.open(url);\n    connection2.addRequestProperty(\"Accept-Language\", \"fr-CA, fr-FR\");\n    connection2.addRequestProperty(\"Accept-Language\", \"en-US\");\n    assertEquals(\"A\", readAscii(connection2));\n  }\n\n  @Test public void varyMultipleFieldValuesWithNoMatch() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    URLConnection connection1 = client.open(url);\n    connection1.addRequestProperty(\"Accept-Language\", \"fr-CA, fr-FR\");\n    connection1.addRequestProperty(\"Accept-Language\", \"en-US\");\n    assertEquals(\"A\", readAscii(connection1));\n\n    URLConnection connection2 = client.open(url);\n    connection2.addRequestProperty(\"Accept-Language\", \"fr-CA\");\n    connection2.addRequestProperty(\"Accept-Language\", \"en-US\");\n    assertEquals(\"B\", readAscii(connection2));\n  }\n\n  @Test public void varyAsterisk() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: *\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    assertEquals(\"B\", readAscii(client.open(server.getUrl(\"/\"))));\n  }\n\n  @Test public void varyAndHttps() throws Exception {\n    server.useHttps(sslContext.getSocketFactory(), false);\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=60\")\n        .addHeader(\"Vary: Accept-Language\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    HttpsURLConnection connection1 = (HttpsURLConnection) client.open(url);\n    connection1.setSSLSocketFactory(sslContext.getSocketFactory());\n    connection1.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n    connection1.addRequestProperty(\"Accept-Language\", \"en-US\");\n    assertEquals(\"A\", readAscii(connection1));\n\n    HttpsURLConnection connection2 = (HttpsURLConnection) client.open(url);\n    connection2.setSSLSocketFactory(sslContext.getSocketFactory());\n    connection2.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);\n    connection2.addRequestProperty(\"Accept-Language\", \"en-US\");\n    assertEquals(\"A\", readAscii(connection2));\n  }\n\n  @Test public void cachePlusCookies() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\n        \"Set-Cookie: a=FIRST; domain=\" + server.getCookieDomain() + \";\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().addHeader(\n        \"Set-Cookie: a=SECOND; domain=\" + server.getCookieDomain() + \";\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    URL url = server.getUrl(\"/\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n    assertCookies(url, \"a=FIRST\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n    assertCookies(url, \"a=SECOND\");\n  }\n\n  @Test public void getHeadersReturnsNetworkEndToEndHeaders() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Allow: GET, HEAD\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().addHeader(\"Allow: GET, HEAD, PUT\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    URLConnection connection1 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection1));\n    assertEquals(\"GET, HEAD\", connection1.getHeaderField(\"Allow\"));\n\n    URLConnection connection2 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection2));\n    assertEquals(\"GET, HEAD, PUT\", connection2.getHeaderField(\"Allow\"));\n  }\n\n  @Test public void getHeadersReturnsCachedHopByHopHeaders() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Transfer-Encoding: identity\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().addHeader(\"Transfer-Encoding: none\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    URLConnection connection1 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection1));\n    assertEquals(\"identity\", connection1.getHeaderField(\"Transfer-Encoding\"));\n\n    URLConnection connection2 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection2));\n    assertEquals(\"identity\", connection2.getHeaderField(\"Transfer-Encoding\"));\n  }\n\n  @Test public void getHeadersDeletesCached100LevelWarnings() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Warning: 199 test danger\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    URLConnection connection1 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection1));\n    assertEquals(\"199 test danger\", connection1.getHeaderField(\"Warning\"));\n\n    URLConnection connection2 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection2));\n    assertEquals(null, connection2.getHeaderField(\"Warning\"));\n  }\n\n  @Test public void getHeadersRetainsCached200LevelWarnings() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Warning: 299 test danger\")\n        .addHeader(\"Last-Modified: \" + formatDate(-1, TimeUnit.HOURS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    URLConnection connection1 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection1));\n    assertEquals(\"299 test danger\", connection1.getHeaderField(\"Warning\"));\n\n    URLConnection connection2 = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection2));\n    assertEquals(\"299 test danger\", connection2.getHeaderField(\"Warning\"));\n  }\n\n  public void assertCookies(URL url, String... expectedCookies) throws Exception {\n    List<String> actualCookies = new ArrayList<>();\n    for (HttpCookie cookie : cookieManager.getCookieStore().get(url.toURI())) {\n      actualCookies.add(cookie.toString());\n    }\n    assertEquals(Arrays.asList(expectedCookies), actualCookies);\n  }\n\n  @Test public void cachePlusRange() throws Exception {\n    assertNotCached(new MockResponse().setResponseCode(HttpURLConnection.HTTP_PARTIAL)\n            .addHeader(\"Date: \" + formatDate(0, TimeUnit.HOURS))\n            .addHeader(\"Content-Range: bytes 100-100/200\")\n            .addHeader(\"Cache-Control: max-age=60\"));\n  }\n\n  @Test public void conditionalHitUpdatesCache() throws Exception {\n    server.enqueue(new MockResponse().addHeader(\"Last-Modified: \" + formatDate(0, TimeUnit.SECONDS))\n        .addHeader(\"Cache-Control: max-age=0\")\n        .setBody(\"A\"));\n    server.enqueue(new MockResponse().addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Allow: GET, HEAD\")\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    // cache miss; seed the cache\n    HttpURLConnection connection1 = client.open(server.getUrl(\"/a\"));\n    assertEquals(\"A\", readAscii(connection1));\n    assertEquals(null, connection1.getHeaderField(\"Allow\"));\n\n    // conditional cache hit; update the cache\n    HttpURLConnection connection2 = client.open(server.getUrl(\"/a\"));\n    assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());\n    assertEquals(\"A\", readAscii(connection2));\n    assertEquals(\"GET, HEAD\", connection2.getHeaderField(\"Allow\"));\n\n    // full cache hit\n    HttpURLConnection connection3 = client.open(server.getUrl(\"/a\"));\n    assertEquals(\"A\", readAscii(connection3));\n    assertEquals(\"GET, HEAD\", connection3.getHeaderField(\"Allow\"));\n\n    assertEquals(2, server.getRequestCount());\n  }\n\n  @Test public void responseSourceHeaderCached() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    connection.addRequestProperty(\"Cache-Control\", \"only-if-cached\");\n    assertEquals(\"A\", readAscii(connection));\n  }\n\n  @Test public void responseSourceHeaderConditionalCacheFetched() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(-31, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse().setBody(\"B\")\n        .addHeader(\"Cache-Control: max-age=30\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"B\", readAscii(connection));\n  }\n\n  @Test public void responseSourceHeaderConditionalCacheNotFetched() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\")\n        .addHeader(\"Cache-Control: max-age=0\")\n        .addHeader(\"Date: \" + formatDate(0, TimeUnit.MINUTES)));\n    server.enqueue(new MockResponse().setResponseCode(304));\n\n    assertEquals(\"A\", readAscii(client.open(server.getUrl(\"/\"))));\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection));\n  }\n\n  @Test public void responseSourceHeaderFetched() throws IOException {\n    server.enqueue(new MockResponse().setBody(\"A\"));\n\n    URLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", readAscii(connection));\n  }\n\n  @Test public void emptyResponseHeaderNameFromCacheIsLenient() throws Exception {\n    Headers.Builder headers = new Headers.Builder()\n        .add(\"Cache-Control: max-age=120\");\n    Internal.instance.addLenient(headers, \": A\");\n    server.enqueue(new MockResponse().setHeaders(headers.build()).setBody(\"body\"));\n\n    HttpURLConnection connection = client.open(server.getUrl(\"/\"));\n    assertEquals(\"A\", connection.getHeaderField(\"\"));\n    assertEquals(\"body\", readAscii(connection));\n  }\n\n  /**\n   * Old implementations of OkHttp's response cache wrote header fields like\n   * \":status: 200 OK\". This broke our cached response parser because it split\n   * on the first colon. This regression test exists to help us read these old\n   * bad cache entries.\n   *\n   * https://github.com/square/okhttp/issues/227\n   */\n  @Test public void testGoldenCacheResponse() throws Exception {\n    cache.close();\n    server.enqueue(new MockResponse()\n        .clearHeaders()\n        .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    URL url = server.getUrl(\"/\");\n    String urlKey = Util.md5Hex(url.toString());\n    String entryMetadata = \"\"\n        + \"\" + url + \"\\n\"\n        + \"GET\\n\"\n        + \"0\\n\"\n        + \"HTTP/1.1 200 OK\\n\"\n        + \"7\\n\"\n        + \":status: 200 OK\\n\"\n        + \":version: HTTP/1.1\\n\"\n        + \"etag: foo\\n\"\n        + \"content-length: 3\\n\"\n        + \"OkHttp-Received-Millis: \" + System.currentTimeMillis() + \"\\n\"\n        + \"X-Android-Response-Source: NETWORK 200\\n\"\n        + \"OkHttp-Sent-Millis: \" + System.currentTimeMillis() + \"\\n\"\n        + \"\\n\"\n        + \"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\\n\"\n        + \"1\\n\"\n        + \"MIIBpDCCAQ2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDEw1qd2lsc29uLmxvY2FsMB4XDTEzMDgy\"\n        + \"OTA1MDE1OVoXDTEzMDgzMDA1MDE1OVowGDEWMBQGA1UEAxMNandpbHNvbi5sb2NhbDCBnzANBgkqhkiG9w0BAQEF\"\n        + \"AAOBjQAwgYkCgYEAlFW+rGo/YikCcRghOyKkJanmVmJSce/p2/jH1QvNIFKizZdh8AKNwojt3ywRWaDULA/RlCUc\"\n        + \"ltF3HGNsCyjQI/+Lf40x7JpxXF8oim1E6EtDoYtGWAseelawus3IQ13nmo6nWzfyCA55KhAWf4VipelEy8DjcuFK\"\n        + \"v6L0xwXnI0ECAwEAATANBgkqhkiG9w0BAQsFAAOBgQAuluNyPo1HksU3+Mr/PyRQIQS4BI7pRXN8mcejXmqyscdP\"\n        + \"7S6J21FBFeRR8/XNjVOp4HT9uSc2hrRtTEHEZCmpyoxixbnM706ikTmC7SN/GgM+SmcoJ1ipJcNcl8N0X6zym4dm\"\n        + \"yFfXKHu2PkTo7QFdpOJFvP3lIigcSZXozfmEDg==\\n\"\n        + \"-1\\n\";\n    String entryBody = \"abc\";\n    String journalBody = \"\"\n        + \"libcore.io.DiskLruCache\\n\"\n        + \"1\\n\"\n        + \"201105\\n\"\n        + \"2\\n\"\n        + \"\\n\"\n        + \"CLEAN \" + urlKey + \" \" + entryMetadata.length() + \" \" + entryBody.length() + \"\\n\";\n    writeFile(cache.getDirectory(), urlKey + \".0\", entryMetadata);\n    writeFile(cache.getDirectory(), urlKey + \".1\", entryBody);\n    writeFile(cache.getDirectory(), \"journal\", journalBody);\n    cache = new Cache(cache.getDirectory(), Integer.MAX_VALUE, fileSystem);\n    client.client().setCache(cache);\n\n    HttpURLConnection connection = client.open(url);\n    assertEquals(entryBody, readAscii(connection));\n    assertEquals(\"3\", connection.getHeaderField(\"Content-Length\"));\n    assertEquals(\"foo\", connection.getHeaderField(\"etag\"));\n  }\n\n  private void writeFile(File directory, String file, String content) throws IOException {\n    BufferedSink sink = Okio.buffer(fileSystem.sink(new File(directory, file)));\n    sink.writeUtf8(content);\n    sink.close();\n  }\n\n  /**\n   * @param delta the offset from the current date to use. Negative\n   * values yield dates in the past; positive values yield dates in the\n   * future.\n   */\n  private String formatDate(long delta, TimeUnit timeUnit) {\n    return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta)));\n  }\n\n  private String formatDate(Date date) {\n    DateFormat rfc1123 = new SimpleDateFormat(\"EEE, dd MMM yyyy HH:mm:ss zzz\", Locale.US);\n    rfc1123.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\n    return rfc1123.format(date);\n  }\n\n  private void addRequestBodyIfNecessary(String requestMethod, HttpURLConnection invalidate)\n      throws IOException {\n    if (requestMethod.equals(\"POST\") || requestMethod.equals(\"PUT\")) {\n      invalidate.setDoOutput(true);\n      OutputStream requestBody = invalidate.getOutputStream();\n      requestBody.write('x');\n      requestBody.close();\n    }\n  }\n\n  private void assertNotCached(MockResponse response) throws Exception {\n    server.enqueue(response.setBody(\"A\"));\n    server.enqueue(new MockResponse().setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n    assertEquals(\"B\", readAscii(client.open(url)));\n  }\n\n  /** @return the request with the conditional get headers. */\n  private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception {\n    // scenario 1: condition succeeds\n    server.enqueue(response.setBody(\"A\").setStatus(\"HTTP/1.1 200 A-OK\"));\n    server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));\n\n    // scenario 2: condition fails\n    server.enqueue(response.setBody(\"B\").setStatus(\"HTTP/1.1 200 B-OK\"));\n    server.enqueue(new MockResponse().setStatus(\"HTTP/1.1 200 C-OK\").setBody(\"C\"));\n\n    URL valid = server.getUrl(\"/valid\");\n    HttpURLConnection connection1 = client.open(valid);\n    assertEquals(\"A\", readAscii(connection1));\n    assertEquals(HttpURLConnection.HTTP_OK, connection1.getResponseCode());\n    assertEquals(\"A-OK\", connection1.getResponseMessage());\n    HttpURLConnection connection2 = client.open(valid);\n    assertEquals(\"A\", readAscii(connection2));\n    assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());\n    assertEquals(\"A-OK\", connection2.getResponseMessage());\n\n    URL invalid = server.getUrl(\"/invalid\");\n    HttpURLConnection connection3 = client.open(invalid);\n    assertEquals(\"B\", readAscii(connection3));\n    assertEquals(HttpURLConnection.HTTP_OK, connection3.getResponseCode());\n    assertEquals(\"B-OK\", connection3.getResponseMessage());\n    HttpURLConnection connection4 = client.open(invalid);\n    assertEquals(\"C\", readAscii(connection4));\n    assertEquals(HttpURLConnection.HTTP_OK, connection4.getResponseCode());\n    assertEquals(\"C-OK\", connection4.getResponseMessage());\n\n    server.takeRequest(); // regular get\n    return server.takeRequest(); // conditional get\n  }\n\n  private void assertFullyCached(MockResponse response) throws Exception {\n    server.enqueue(response.setBody(\"A\"));\n    server.enqueue(response.setBody(\"B\"));\n\n    URL url = server.getUrl(\"/\");\n    assertEquals(\"A\", readAscii(client.open(url)));\n    assertEquals(\"A\", readAscii(client.open(url)));\n  }\n\n  /**\n   * Shortens the body of {@code response} but not the corresponding headers.\n   * Only useful to test how clients respond to the premature conclusion of\n   * the HTTP body.\n   */\n  private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) {\n    response.setSocketPolicy(DISCONNECT_AT_END);\n    Headers headers = response.getHeaders();\n    Buffer truncatedBody = new Buffer();\n    truncatedBody.write(response.getBody(), numBytesToKeep);\n    response.setBody(truncatedBody);\n    response.setHeaders(headers);\n    return response;\n  }\n\n  /**\n   * Reads {@code count} characters from the stream. If the stream is\n   * exhausted before {@code count} characters can be read, the remaining\n   * characters are returned and the stream is closed.\n   */\n  private String readAscii(URLConnection connection, int count) throws IOException {\n    HttpURLConnection httpConnection = (HttpURLConnection) connection;\n    InputStream in = httpConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST\n        ? connection.getInputStream()\n        : httpConnection.getErrorStream();\n    StringBuilder result = new StringBuilder();\n    for (int i = 0; i < count; i++) {\n      int value = in.read();\n      if (value == -1) {\n        in.close();\n        break;\n      }\n      result.append((char) value);\n    }\n    return result.toString();\n  }\n\n  private String readAscii(URLConnection connection) throws IOException {\n    return readAscii(connection, Integer.MAX_VALUE);\n  }\n\n  private void reliableSkip(InputStream in, int length) throws IOException {\n    while (length > 0) {\n      length -= in.skip(length);\n    }\n  }\n\n  private void assertGatewayTimeout(HttpURLConnection connection) throws IOException {\n    try {\n      connection.getInputStream();\n      fail();\n    } catch (FileNotFoundException expected) {\n    }\n    assertEquals(504, connection.getResponseCode());\n    assertEquals(-1, connection.getErrorStream().read());\n  }\n\n  enum TransferKind {\n    CHUNKED() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize)\n          throws IOException {\n        response.setChunkedBody(content, chunkSize);\n      }\n    },\n    FIXED_LENGTH() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize) {\n        response.setBody(content);\n      }\n    },\n    END_OF_STREAM() {\n      @Override void setBody(MockResponse response, Buffer content, int chunkSize) {\n        response.setBody(content);\n        response.setSocketPolicy(DISCONNECT_AT_END);\n        response.removeHeader(\"Content-Length\");\n      }\n    };\n\n    abstract void setBody(MockResponse response, Buffer content, int chunkSize) throws IOException;\n\n    void setBody(MockResponse response, String content, int chunkSize) throws IOException {\n      setBody(response, new Buffer().writeUtf8(content), chunkSize);\n    }\n  }\n\n  private <T> List<T> toListOrNull(T[] arrayOrNull) {\n    return arrayOrNull != null ? Arrays.asList(arrayOrNull) : null;\n  }\n\n  /** Returns a gzipped copy of {@code bytes}. */\n  public Buffer gzip(String data) throws IOException {\n    Buffer result = new Buffer();\n    BufferedSink sink = Okio.buffer(new GzipSink(result));\n    sink.writeUtf8(data);\n    sink.close();\n    return result;\n  }\n}\n"
  },
  {
    "path": "comsat-retrofit/src/main/java/co/paralleluniverse/fibers/retrofit/FiberRestAdapterBuilder.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.retrofit;\n\nimport co.paralleluniverse.fibers.httpclient.FiberHttpClient;\nimport co.paralleluniverse.fibers.httpclient.FiberHttpClientBuilder;\nimport co.paralleluniverse.fibers.okhttp.FiberOkHttpClient;\nimport com.squareup.okhttp.OkHttpClient;\nimport org.apache.http.client.HttpClient;\nimport retrofit.RestAdapter;\nimport retrofit.client.ApacheClient;\nimport retrofit.client.Client;\nimport retrofit.client.OkClient;\n\npublic final class FiberRestAdapterBuilder extends RestAdapter.Builder {\n    private HttpClient httpClient;\n    private OkHttpClient okHttpClient;\n\n    @Override\n    public final RestAdapter.Builder setClient(Client.Provider clientProvider) {\n        throw new UnsupportedOperationException(\"Only Fiber Apache Http or OkHttp clients are allowed here. Use setClient(FiberHttpClient) or setClient(FiberOkHttpClient) instead.\");\n    }\n\n    @Override\n    public final RestAdapter.Builder setClient(Client client) {\n        throw new UnsupportedOperationException(\"Only Fiber Apache Http or OkHttp clients are allowed here. Use setClient(FiberHttpClient) or setClient(FiberOkHttpClient) instead.\");\n\n    }\n\n    public final RestAdapter.Builder setClient(FiberHttpClient client) {\n        this.httpClient = client;\n        return this;\n    }\n\n    public final RestAdapter.Builder setClient(FiberOkHttpClient client) {\n        this.okHttpClient = client;\n        return this;\n    }\n\n    @Override\n    public RestAdapter build() {\n        if (okHttpClient != null) {\n            super.setClient(providerFor(new OkClient(okHttpClient)));\n        } else {\n            if (httpClient == null)\n                // setUserAgent(\"\") is not default it ApacheHttpClient, and is needed for the github API  \n                this.httpClient = FiberHttpClientBuilder.create().setUserAgent(\"\").build();\n            super.setClient(providerFor(new ApacheClient(httpClient)));\n        }\n        return super.build();\n    }\n\n    private static Client.Provider providerFor(final Client client) {\n        return new Client.Provider() {\n            @Override\n            public Client get() {\n                return client;\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "comsat-retrofit/src/main/resources/META-INF/suspendables",
    "content": "retrofit.client.ApacheClient.execute\nretrofit.RestAdapter$RestHandler.invokeRequest\nretrofit.RestAdapter$RestHandler.invoke"
  },
  {
    "path": "comsat-retrofit/src/test/java/co/paralleluniverse/fibers/retrofit/FiberRestAdapterBuilderTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.retrofit;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.fibers.okhttp.FiberOkHttpClient;\nimport co.paralleluniverse.fibers.retrofit.HelloWorldApplication.Contributor;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.util.List;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.conn.HttpHostConnectException;\nimport org.apache.http.impl.client.HttpClients;\nimport static org.junit.Assert.*;\nimport org.junit.BeforeClass;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.Timeout;\nimport retrofit.http.GET;\nimport retrofit.http.Path;\n\npublic class FiberRestAdapterBuilderTest {\n    @BeforeClass\n    public static void setUpClass() throws InterruptedException, IOException {\n        Thread t = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    new HelloWorldApplication().run(new String[]{\"server\"});\n                } catch (Exception ex) {\n                }\n            }\n        });\n        t.setDaemon(true);\n        t.start();\n        waitUrlAvailable(\"http://localhost:8080\");\n    }\n\n    @Test\n    public void testGet() throws IOException, InterruptedException, Exception {\n        // snippet registration\n        final MyGitHub github = new FiberRestAdapterBuilder().setEndpoint(\"http://localhost:8080\").build().create(MyGitHub.class);\n        // end of snippet\n        new Fiber<Void>(new MyGitHubRunner(github)).start().join();\n    }\n\n    @Test\n    public void testGetWithOkHttp() throws IOException, InterruptedException, Exception {\n        // snippet registration\n        final FiberOkHttpClient client = new FiberOkHttpClient();\n        final MyGitHub github = new FiberRestAdapterBuilder().setClient(client).setEndpoint(\"http://localhost:8080\").build().create(MyGitHub.class);\n        // end of snippet\n        new Fiber<Void>(new MyGitHubRunner(github)).start().join();\n    }\n    \n    // snippet interface\n    @Suspendable\n    public static interface MyGitHub {\n        @GET(value = \"/repos/{owner}/{repo}/contributors\")\n        List<Contributor> contributors(@Path(value = \"owner\") String owner, @Path(value = \"repo\") String repo);\n    }\n    // end of snippet\n\n    public static void waitUrlAvailable(final String url) throws InterruptedException, IOException {\n        for (;;) {\n            Thread.sleep(10);\n            try {\n                if (HttpClients.createDefault().execute(new HttpGet(url)).getStatusLine().getStatusCode() > -100)\n                    break;\n            } catch (HttpHostConnectException ex) {\n            }\n        }\n    }\n\n    @Rule\n    public Timeout globalTimeout = new Timeout(10000); // 10 seconds max per method tested\n\n    static class MyGitHubRunner implements SuspendableRunnable {\n        private final MyGitHub github;\n\n        MyGitHubRunner(MyGitHub github) {\n            this.github = github;\n        }\n\n        @Override\n        public void run() throws SuspendExecution, InterruptedException {\n            // snippet usage\n            List<Contributor> contributors = github.contributors(\"puniverse\", \"comsat\");\n            String result = contributors.get(1).login;\n            // end of snippet\n            assertEquals(\"puniverse\", result);\n            assertEquals(4, contributors.size());\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-retrofit/src/test/java/co/paralleluniverse/fibers/retrofit/HelloWorldApplication.java",
    "content": "/*\r\n * COMSAT\r\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\r\n *\r\n * This program and the accompanying materials are dual-licensed under\r\n * either the terms of the Eclipse Public License v1.0 as published by\r\n * the Eclipse Foundation\r\n *\r\n *   or (per the licensee's choosing)\r\n *\r\n * under the terms of the GNU Lesser General Public License version 3.0\r\n * as published by the Free Software Foundation.\r\n */\r\npackage co.paralleluniverse.fibers.retrofit;\r\n\r\nimport co.paralleluniverse.fibers.SuspendExecution;\r\nimport com.fasterxml.jackson.annotation.JsonProperty;\r\nimport com.google.common.collect.Lists;\r\nimport javax.inject.Singleton;\r\nimport io.dropwizard.Application;\r\nimport io.dropwizard.Configuration;\r\nimport io.dropwizard.setup.Bootstrap;\r\nimport io.dropwizard.setup.Environment;\r\nimport java.util.List;\r\nimport javax.ws.rs.GET;\r\nimport javax.ws.rs.Path;\r\nimport javax.ws.rs.PathParam;\r\nimport javax.ws.rs.Produces;\r\nimport javax.ws.rs.core.MediaType;\r\n\r\n@Singleton\r\n@Path(\"/repos/{owner}/{repo}/contributors\")\r\n@Produces(MediaType.APPLICATION_JSON)\r\npublic class HelloWorldApplication extends Application<Configuration> {\r\n    @Override\r\n    public void run(Configuration configuration,\r\n            final Environment environment) throws ClassNotFoundException {\r\n        environment.jersey().register(this);\r\n    }\r\n\r\n    @GET\r\n    public List<Contributor> get(@PathParam(\"owner\") String owner, @PathParam(\"repo\") String repo) throws SuspendExecution {\r\n        return Lists.newArrayList(new Contributor(\"foo\", 10), new Contributor(owner, 20),\r\n                new Contributor(repo, 30), new Contributor(\"bar\", 40));\r\n    }\r\n\r\n    public static class Contributor {\r\n        String login;\r\n        int contributions;\r\n\r\n        public Contributor(String login, int contributions) {\r\n            this.login = login;\r\n            this.contributions = contributions;\r\n        }\r\n\r\n        @JsonProperty\r\n        public String getLogin() {\r\n            return login;\r\n        }\r\n\r\n        @JsonProperty\r\n        public int getContributions() {\r\n            return contributions;\r\n        }\r\n    }\r\n\r\n    @Override\r\n    public void initialize(Bootstrap<Configuration> bootstrap) {\r\n    }\r\n}\r\n"
  },
  {
    "path": "comsat-ring-jetty9/project.clj",
    "content": "(def quasar-pulsar-version \"0.7.6\")\n\n(defproject co.paralleluniverse/comsat-ring-jetty9 \"0.7.1-SNAPSHOT\"\n  :description \"Comsat integration for the Ring Clojure web framework: Jetty 9 fiber-blocking adapter.\"\n  :url \"https://github.com/puniverse/comsat\"\n  :scm {:name \"git\" :url \"https://github.com/puniverse/comsat\"}\n\n  :licenses [{:name \"Eclipse Public License\" :url \"http://www.eclipse.org/legal/epl-v10.html\"}\n             {:name \"GNU Lesser General Public License - v 3\" :url \"http://www.gnu.org/licenses/lgpl.html\"}]\n\n  :distribution :repo\n\n  :dependencies\n    [[org.clojure/clojure \"1.7.0\"]\n\n     [ring/ring-core \"1.4.0\"]\n     [ring/ring-devel \"1.4.0\"]\n     [ring/ring-servlet \"1.4.0\"]\n\n     [org.eclipse.jetty/jetty-server \"9.3.8.v20160314\"]\n\n     [org.slf4j/slf4j-simple \"1.7.21\"]\n\n     [co.paralleluniverse/pulsar ~quasar-pulsar-version]]\n\n  :repositories [[\"snapshots\" \"http://oss.sonatype.org/content/repositories/snapshots\"]]\n\n  :java-agents [[co.paralleluniverse/quasar-core ~quasar-pulsar-version]]\n\n  :profiles\n    {:dev {:dependencies [[clj-http \"2.1.0\"]]}})\n"
  },
  {
    "path": "comsat-ring-jetty9/src/co/paralleluniverse/fiber/ring/jetty9.clj",
    "content": ";\n; COMSAT\n; Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n;\n; This program and the accompanying materials are dual-licensed under\n; either the terms of the Eclipse Public License v1.0 as published by\n; the Eclipse Foundation\n;\n;   or (per the licensee's choosing)\n;\n; under the terms of the GNU Lesser General Public License version 3.0\n; as published by the Free Software Foundation.\n;\n\n;\n; Based on ring.adapter.jetty in Ring (https://github.com/ring-clojure/ring)\n; Copyright the original Authors (https://github.com/ring-clojure/ring/blob/master/CONTRIBUTORS.md)\n; Released under the MIT license.\n;\n\n(ns ^{:author \"circlespainter\"} co.paralleluniverse.fiber.ring.jetty9\n  \"A Ring adapter that uses the Jetty 9 embedded web server in async mode and dispatches to Quasar fibers.\n   Adapters are used to convert Ring handlers into running web servers.\"\n  (:import (java.security KeyStore)\n           (javax.servlet AsyncContext DispatcherType)\n           (org.eclipse.jetty.server Server Request HttpConnectionFactory HttpConfiguration)\n           (org.eclipse.jetty.server.handler AbstractHandler)\n           (org.eclipse.jetty.server ServerConnector)\n           (org.eclipse.jetty.util.thread QueuedThreadPool)\n           (org.eclipse.jetty.util BlockingArrayQueue)\n           (org.eclipse.jetty.util.ssl SslContextFactory))\n  (:require [ring.util.servlet :as servlet]\n            [co.paralleluniverse.pulsar.core :as pc]))\n\n(def ^:private ^String async-exception-attribute-name \"co.paralleluniverse.fiber.ring.jetty9.asyncException\")\n(def ^:private ^String writer-mode-stream-exception-message \"WRITER\")\n\n(defn- fiber-async-proxy-handler\n  \"Returns a async fiber-dispatching Jetty Handler implementation for the given Ring handler.\"\n  [handler]\n  ; The handler will always be instrumented, assuming it will fiber-block,\n  ; just like Pulsar does with fns passed to its API\n  (pc/suspendable! handler)\n  (proxy [AbstractHandler] []\n    (handle [_ ^Request base-request request response]\n      (if-let [^Throwable exc\n                (and\n                  (= DispatcherType/ASYNC (.getDispatcherType request))\n                  (.getAttribute request async-exception-attribute-name))]\n        ; CASE: dispatch because of exception in fiber's async processing\n        (do\n          ; 1 - Clean the request from the temporary attribute used to carry the exception across the dispatch\n          (.removeAttribute request async-exception-attribute-name)\n          ; 2 - Throw the exception in the servlet thread\n          (throw exc))\n        ; CASE: normal execution\n        (let [^AsyncContext async-context (.startAsync request)]\n          (pc/spawn-fiber #(try\n                            (let [request-map  (servlet/build-request-map request)\n                                  response-map (handler request-map)]\n                              (when response-map\n                                (servlet/update-servlet-response response response-map)\n                                ; When writing to the stream directly, the output has to be flushed or the fiber could\n                                ; end before it's been completely written (because of buffering).\n                                ; Ignoring IllegalStateException as \"flush\" is not allowed when the stream has been put\n                                ; in \"writer\" mode, which happens with strings\n                                (try (.. response getOutputStream flush)\n                                     (catch\n                                       IllegalStateException ise\n                                       (if (not= writer-mode-stream-exception-message (.getMessage ise)) (throw ise)))))\n                              (.complete async-context)\n                              (.setHandled base-request true))\n                            ; Exception handling must be managed through \"dispatch\" and request attributes\n                            (catch\n                              Throwable t\n                              (do\n                                ; Not sure why I'm getting \"wrong rumber of arguments\" when calling setAttributes\n                                ; on \"request\" rather than \"base-request\"\n                                (.setAttribute base-request async-exception-attribute-name t)\n                                (.dispatch async-context))\n                              ))))))))\n\n(defn- ssl-context-factory\n  \"Creates a new SslContextFactory instance from a map of options.\"\n  [options]\n  (let [context (SslContextFactory.)]\n    (if (string? (options :keystore))\n      (.setKeyStorePath context (options :keystore))\n      (.setKeyStore context ^KeyStore (options :keystore)))\n    (.setKeyStorePassword context (options :key-password))\n    (cond\n      (string? (options :truststore))\n      (.setTrustStore context ^String (options :truststore))\n      (instance? KeyStore (options :truststore))\n      (.setTrustStore context ^KeyStore (options :truststore)))\n    (when (options :trust-password)\n      (.setTrustStorePassword context (options :trust-password)))\n    (case (options :client-auth)\n      :need (.setNeedClientAuth context true)\n      :want (.setWantClientAuth context true)\n      nil)\n    context))\n\n(defn- ssl-connector\n  \"Creates a SslSelectChannelConnector instance.\"\n  [^Server server options]\n  (doto (ServerConnector. server (ssl-context-factory options))\n    (.setPort (options :ssl-port 443))\n    (.setHost (options :host))\n    (.setIdleTimeout (options :max-idle-time 200000))))\n\n(defn- create-blocking-array-queue [^Integer capacity ^Integer grow-by & [^Integer max-capacity]]\n  (if max-capacity\n    (BlockingArrayQueue. capacity grow-by max-capacity)\n    (BlockingArrayQueue. capacity grow-by)))\n\n(defn- create-server\n  \"Construct a Jetty Server instance.\"\n  [options]\n  (let [^Integer min-threads\n          (options :min-threads 5)\n        ^Integer max-threads\n          (options :max-threads (+ 5 (.availableProcessors (Runtime/getRuntime))))\n        ^BlockingArrayQueue q\n         (create-blocking-array-queue min-threads min-threads)\n        ^QueuedThreadPool p\n          (QueuedThreadPool. max-threads min-threads 60000 q)\n        ^Server\n          server (Server. p)\n        ^ServerConnector connector\n          (doto (ServerConnector. server)\n            (.setPort (options :port 80))\n            (.setHost (options :host))\n            (.setIdleTimeout (options :max-idle-time 200000)))]\n    (.addConnector server connector)\n    (when-let [queued (options :max-queued)]\n      (.setAcceptQueueSize connector queued))\n    (when (:daemon? options false)\n      (.setDaemon p true))\n    (when (or (options :ssl?) (options :ssl-port))\n      (let [connector-ssl (ssl-connector server options)]\n        (when-let [queued (options :max-queued)]\n          (.setAcceptQueueSize connector-ssl queued))\n        (.addConnector server connector-ssl)))\n    (doseq [conn-factory (.getConnectionFactories connector)]\n      (if (instance? HttpConnectionFactory conn-factory)\n        (let [^HttpConfiguration http-conf (.getHttpConfiguration conn-factory)]\n          (.setSendDateHeader http-conf true))))\n    server))\n\n(defn ^Server run-jetty\n  \"Start a Jetty webserver to serve the given handler according to the\n  supplied options:\n  :configurator   - a function called with the Jetty Server instance\n  :port           - the port to listen on (defaults to 80)\n  :host           - the hostname to listen on\n  :join?          - blocks the thread until server ends (defaults to true)\n  :daemon?        - use daemon threads (defaults to false)\n  :ssl?           - allow connections over HTTPS\n  :ssl-port       - the SSL port to listen on (defaults to 443, implies :ssl?)\n  :keystore       - the keystore to use for SSL connections\n  :key-password   - the password to the keystore\n  :truststore     - a truststore to use for SSL connections\n  :trust-password - the password to the truststore\n  :max-threads    - the maximum number of threads to use (default 10)\n  :min-threads    - the minimum number of threads to use (default 5)\n  :max-queued     - the maximum number of requests to queue (default unbounded)\n  :max-idle-time  - the maximum idle time in milliseconds for a connection (default 200000)\n  :client-auth    - SSL client certificate authenticate, may be set to :need,\n                    :want or :none (defaults to :none)\"\n  [handler options]\n  (let [^Server s (create-server (dissoc options :configurator))]\n    (.setHandler s (fiber-async-proxy-handler handler))\n    (when-let [configurator (:configurator options)]\n      (configurator s))\n    (try\n      (.start s)\n      (when (:join? options true)\n        (.join s))\n      s\n      (catch Exception ex\n        (.stop s)\n        (throw ex)))))\n"
  },
  {
    "path": "comsat-ring-jetty9/test/co/paralleluniverse/fiber/ring/test/jetty9_test.clj",
    "content": "\n; COMSAT\n; Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n;\n; This program and the accompanying materials are dual-licensed under\n; either the terms of the Eclipse Public License v1.0 as published by\n; the Eclipse Foundation\n;\n;   or (per the licensee's choosing)\n;\n; under the terms of the GNU Lesser General Public License version 3.0\n; as published by the Free Software Foundation.\n;\n\n;\n; Based on ring.adapter.test.jetty in Ring (https://github.com/ring-clojure/ring)\n; Copyright the original Authors (https://github.com/ring-clojure/ring/blob/master/CONTRIBUTORS.md)\n; Released under the MIT license.\n;\n\n(ns ^{:author \"circlespainter\"} co.paralleluniverse.fiber.ring.test.jetty9-test\n  (:use clojure.test\n        co.paralleluniverse.fiber.ring.jetty9)\n  (:require [clj-http.client :as http])\n  (:import (org.eclipse.jetty.util.thread QueuedThreadPool)\n           (org.eclipse.jetty.server Server Request)\n           (org.eclipse.jetty.server.handler AbstractHandler)\n           (co.paralleluniverse.fibers Fiber)))\n\n(defn- hello-world [request]\n  (Fiber/sleep 100)\n  {:status  200\n   :headers {\"Content-Type\" \"text/plain\"}\n   :body    \"Hello World\"})\n\n(defn- content-type-handler [content-type]\n  (constantly\n    {:status  200\n     :headers {\"Content-Type\" content-type}\n     :body    \"\"}))\n\n(defn- echo-handler [request]\n  (Fiber/sleep 100)\n  {:status 200\n   :headers {\"request-map\" (str (dissoc request :body))}\n   :body (:body request)})\n\n(defn- exception-throwing-handler [_]\n  (throw (RuntimeException. \"testExc\")))\n\n(defn- all-threads []\n  (.keySet (Thread/getAllStackTraces)))\n\n(defmacro with-server [app options & body]\n  `(let [server# (run-jetty ~app ~(assoc options :join? false))]\n     (try\n       ~@body\n       (finally (.stop server#)))))\n\n(deftest test-run-jetty\n  (testing \"HTTP server\"\n    (with-server hello-world {:port 4347}\n                 (let [response (http/get \"http://localhost:4347\")]\n                   (is (= (:status response) 200))\n                   (is (.startsWith (get-in response [:headers \"content-type\"])\n                                    \"text/plain\"))\n                   (is (= (:body response) \"Hello World\")))))\n\n  (testing \"HTTP server exception\"\n    (with-server exception-throwing-handler {:port 4347}\n                 (let [response (http/get \"http://localhost:4347\" {:throw-exceptions false})]\n                   (is (= (:status response) 500))\n                   (is (.contains\n                         (:body response)\n                         \"java.lang.RuntimeException\")))))\n\n  (testing \"HTTPS server\"\n    (with-server hello-world {:port 4347\n                              :ssl-port 4348\n                              :keystore \"test/keystore.jks\"\n                              :key-password \"password\"}\n                 (let [response (http/get \"https://localhost:4348\" {:insecure? true})]\n                   (is (= (:status response) 200))\n                   (is (= (:body response) \"Hello World\")))))\n\n  (testing \"HTTPS server exception\"\n    (with-server exception-throwing-handler {:port 4347\n                                             :ssl-port 4348\n                                             :keystore \"test/keystore.jks\"\n                                             :key-password \"password\"}\n                 (let [response (http/get \"https://localhost:4348\" {:insecure? true :throw-exceptions false})]\n                   (is (= (:status response) 500))\n                   (is (.contains\n                         (:body response)\n                         \"java.lang.RuntimeException\")))))\n\n  (testing \"configurator set to run last\"\n    (let [new-handler  (proxy [AbstractHandler] []\n                         (handle [_ ^Request base-request request response]))\n          configurator (fn [server]\n                         (.setHandler server new-handler))\n          server (run-jetty hello-world\n                            {:join? false :port 4347 :configurator configurator})]\n      (is (identical? new-handler (.getHandler server)))\n      (is (= 1 (count (.getHandlers server))))\n      (.stop server)))\n\n  (testing \"setting daemon threads\"\n    (testing \"default (daemon off)\"\n      (let [^Server server (run-jetty hello-world {:port 4347 :join? false})]\n        (is (not (.. server getThreadPool isDaemon)))\n        (.stop server)))\n    (testing \"daemon on\"\n      (let [^Server server (run-jetty hello-world {:port 4347 :join? false :daemon? true})]\n        (is (.. server getThreadPool isDaemon))\n        (.stop server)))\n    (testing \"daemon off\"\n      (let [^Server server (run-jetty hello-world {:port 4347 :join? false :daemon? false})]\n        (is (not (.. server getThreadPool isDaemon)))\n        (.stop server))))\n\n  (testing \"setting max idle timeout\"\n    (let [server (run-jetty hello-world {:port 4347\n                                         :ssl-port 4348\n                                         :keystore \"test/keystore.jks\"\n                                         :key-password \"password\"\n                                         :join? false\n                                         :max-idle-time 5000})\n          connectors (.getConnectors server)]\n      (is (= 5000 (.getIdleTimeout (first connectors))))\n      (is (= 5000 (.getIdleTimeout (second connectors))))\n      (.stop server)))\n\n  (testing \"using the default max idle time\"\n    (let [server (run-jetty hello-world {:port 4347\n                                         :ssl-port 4348\n                                         :keystore \"test/keystore.jks\"\n                                         :key-password \"password\"\n                                         :join? false})\n          connectors (.getConnectors server)]\n      (is (= 200000 (.getIdleTimeout (first connectors))))\n      (is (= 200000 (.getIdleTimeout (second connectors))))\n      (.stop server)))\n\n  (testing \"setting min-threads\"\n    (let [server (run-jetty hello-world {:port 4347\n                                         :min-threads 3\n                                         :join? false})\n          thread-pool (.getThreadPool server)]\n      (is (= 3 (.getMinThreads thread-pool)))\n      (.stop server)))\n\n  (testing \"default min-threads\"\n    (let [^Server server (run-jetty hello-world {:port 4347\n                                                 :join? false})\n          thread-pool (.getThreadPool server)]\n      (is (= 5 (.getMinThreads thread-pool)))\n      (.stop server)))\n\n  (testing \"setting max-queued\"\n    (let [server (run-jetty hello-world {:port 4347\n                                         :max-queued 7\n                                         :join? false})]\n      (doseq [connector (.getConnectors server)]\n        (is (= 7 (.getAcceptQueueSize connector))))\n      (.stop server)))\n\n  (testing \"default character encoding\"\n    (with-server (content-type-handler \"text/plain\") {:port 4347}\n                 (let [response (http/get \"http://localhost:4347\")]\n                   (is (.contains\n                         (get-in response [:headers \"content-type\"])\n                         \"text/plain\")))))\n\n  (testing \"custom content-type\"\n    (with-server (content-type-handler \"text/plain;charset=UTF-16;version=1\") {:port 4347}\n                 (let [response (http/get \"http://localhost:4347\")]\n                   (let [response (http/get \"http://localhost:4347\")]\n                     (is (= (get-in response [:headers \"content-type\"])\n                            \"text/plain;charset=UTF-16;version=1\")))))\n\n    (testing \"request translation\"\n      (with-server echo-handler {:port 4347}\n                   (let [response (http/post \"http://localhost:4347/foo/bar/baz?surname=jones&age=123\" {:body \"hello\"})]\n                     (is (= (:status response) 200))\n                     (is (= (:body response) \"hello\"))\n                     (let [request-map (read-string (get-in response [:headers \"request-map\"]))]\n                       (is (= (:query-string request-map) \"surname=jones&age=123\"))\n                       (is (= (:uri request-map) \"/foo/bar/baz\"))\n                       (is (= (:content-length request-map) 5))\n                       (is (= (:character-encoding request-map) \"UTF-8\"))\n                       (is (= (:request-method request-map) :post))\n                       (is (= (:content-type request-map) \"text/plain; charset=UTF-8\"))\n                       (is (= (:remote-addr request-map) \"127.0.0.1\"))\n                       (is (= (:scheme request-map) :http))\n                       (is (= (:server-name request-map) \"localhost\"))\n                       (is (= (:server-port request-map) 4347))\n                       (is (= (:ssl-client-cert request-map) nil))))))\n\n    (testing \"resource cleanup on exception\"\n      (with-server hello-world {:port 4347}\n                   (let [thread-count (count (all-threads))]\n                     (is (thrown? Exception (run-jetty hello-world {:port 4347})))\n                     (is (= thread-count (count (all-threads)))))))))\n"
  },
  {
    "path": "comsat-servlet/src/main/java/co/paralleluniverse/fibers/servlet/FiberHttpServlet.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.servlet;\n\nimport co.paralleluniverse.common.util.SystemProperties;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.io.IOException;\nimport java.io.OutputStreamWriter;\nimport java.io.PrintWriter;\nimport java.io.UnsupportedEncodingException;\nimport java.lang.reflect.Method;\nimport java.text.MessageFormat;\nimport java.util.Enumeration;\nimport java.util.ResourceBundle;\nimport java.util.concurrent.ForkJoinPool;\nimport javax.servlet.*;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpServletResponseWrapper;\n\n/**\n * Fiber-blocking HttpServlet base class.\n * \n * @author eithan\n * @author circlespainter\n */\npublic class FiberHttpServlet extends HttpServlet {\n    private static final String METHOD_DELETE = \"DELETE\";\n    private static final String METHOD_HEAD = \"HEAD\";\n    private static final String METHOD_GET = \"GET\";\n    private static final String METHOD_OPTIONS = \"OPTIONS\";\n    private static final String METHOD_POST = \"POST\";\n    private static final String METHOD_PUT = \"PUT\";\n    private static final String METHOD_TRACE = \"TRACE\";\n\n    private static final String HEADER_IFMODSINCE = \"If-Modified-Since\";\n    private static final String HEADER_LASTMOD = \"Last-Modified\";\n\n    private static final String LSTRING_FILE =\n        \"javax.servlet.http.LocalStrings\";\n    private static ResourceBundle lStrings =\n        ResourceBundle.getBundle(LSTRING_FILE);\n\n    private static final String PROP_ASYNC_TIMEOUT = FiberHttpServlet.class.getName() + \".asyncTimeout\";\n    static final Long asyncTimeout;\n\n    public static final String PROP_DEBUG_BYPASS_TO_REGULAR_FJP = FiberHttpServlet.class.getName() + \".debug.bypassToRegularFJP\";\n    static final boolean debugBypassToRegularJFPGlobal = SystemProperties.isEmptyOrTrue(PROP_DEBUG_BYPASS_TO_REGULAR_FJP);\n\n    public static final String PROP_DISABLE_SYNC_EXCEPTIONS = FiberHttpServlet.class.getName() + \".disableSyncExceptions\";\n    static final boolean disableSyncExceptionsGlobal = SystemProperties.isEmptyOrTrue(PROP_DISABLE_SYNC_EXCEPTIONS);\n    public static final String PROP_DISABLE_SYNC_FORWARD = FiberHttpServlet.class.getName() + \".disableSyncForward\";\n    static final boolean disableSyncForwardGlobal = SystemProperties.isEmptyOrTrue(PROP_DISABLE_SYNC_FORWARD);\n\n    public static final String PROP_DISABLE_JETTY_ASYNC_FIXES = FiberHttpServlet.class.getName() + \".disableJettyAsyncFixes\";\n    static final Boolean disableJettyAsyncFixesGlobal;\n    public static final String PROP_DISABLE_TOMCAT_ASYNC_FIXES = FiberHttpServlet.class.getName() + \".disableTomcatAsyncFixes\";\n    static final Boolean disableTomcatAsyncFixesGlobal;\n\n    static {\n        asyncTimeout = getLong(PROP_ASYNC_TIMEOUT);\n        disableJettyAsyncFixesGlobal = getBoolean(PROP_DISABLE_JETTY_ASYNC_FIXES);\n        disableTomcatAsyncFixesGlobal = getBoolean(PROP_DISABLE_TOMCAT_ASYNC_FIXES);\n    }\n\n    private static final long serialVersionUID = 1L;\n\n    private static final String FIBER_ASYNC_REQUEST_EXCEPTION = \"co.paralleluniverse.fibers.servlet.exception\";\n\n    private final ThreadLocal<AsyncContext> currentAsyncContext = new ThreadLocal<>();\n\n    private int stackSize = -1;\n\n    private transient FiberServletContext contextAD;\n\n    private ForkJoinPool fjp = new ForkJoinPool();\n\n    boolean debugBypassToRegularJFP, disableSyncExceptions, disableSyncForward, disableJettyAsyncFixes, disableTomcatAsyncFixes;\n\n    /**\n     * @return Wrapped version of the ServletContext initiated by {@link #init(javax.servlet.ServletConfig) }\n     * @inheritDoc\n     */\n    @Override\n    public ServletContext getServletContext() {\n        return disableSyncForward ? super.getServletContext() : contextAD;\n    }\n\n    @Override\n    public void init(ServletConfig config) throws ServletException {\n        super.init(config);\n\n        this.contextAD = new FiberServletContext(config.getServletContext(), currentAsyncContext);\n\n        final String ss = config.getInitParameter(\"stack-size\");\n        if (ss != null)\n            stackSize = Integer.parseInt(ss);\n\n        final String debugByPassToJFP = config.getInitParameter(PROP_DEBUG_BYPASS_TO_REGULAR_FJP);\n        if (debugByPassToJFP != null)\n            debugBypassToRegularJFP = debugBypassToRegularJFPGlobal;\n\n        final String disableSE = config.getInitParameter(PROP_DISABLE_SYNC_EXCEPTIONS);\n        if (disableSE != null)\n            disableSyncExceptions = disableSyncExceptionsGlobal;\n\n        final String disableSF = config.getInitParameter(PROP_DISABLE_SYNC_FORWARD);\n        if (disableSF != null)\n            disableSyncForward = disableSyncForwardGlobal;\n\n        final String disableJF = config.getInitParameter(PROP_DISABLE_JETTY_ASYNC_FIXES);\n        if (disableJF != null)\n            disableJettyAsyncFixes = disableJettyAsyncFixesGlobal != null ? disableJettyAsyncFixesGlobal : !isJetty(config);\n\n        final String disableTF = config.getInitParameter(PROP_DISABLE_TOMCAT_ASYNC_FIXES);\n        if (disableTF != null)\n            disableTomcatAsyncFixes = disableTomcatAsyncFixesGlobal != null ? disableTomcatAsyncFixesGlobal : !isTomcat(config);\n    }\n\n    protected final void setStackSize(int stackSize) {\n        this.stackSize = stackSize;\n    }\n\n    protected final int getStackSize() {\n        return stackSize;\n    }\n\n    @Override\n    @Suspendable\n    final public void service(final ServletRequest req, ServletResponse res) throws ServletException, IOException {\n        if (!disableSyncExceptions && DispatcherType.ASYNC.equals(req.getDispatcherType())) {\n            final Throwable ex = (Throwable) req.getAttribute(FIBER_ASYNC_REQUEST_EXCEPTION);\n            if (ex != null)\n                throw new ServletException(ex);\n        }\n\n        final HttpServletRequest request;\n        final HttpServletResponse response;\n        try {\n            request = (HttpServletRequest) req;\n            response = (HttpServletResponse) res;\n        } catch (final ClassCastException cce) {\n            throw new ServletException(\"Unsupported non-HTTP request or response detected\");\n        }\n\n        if (!disableTomcatAsyncFixes)\n            req.setAttribute(\"org.apache.catalina.ASYNC_SUPPORTED\", true);\n\n        final AsyncContext ac = req.startAsync();\n\n        if (asyncTimeout != null)\n            ac.setTimeout(asyncTimeout);\n\n        final HttpServletRequest r =\n            !disableJettyAsyncFixes ?\n                new FiberHttpServletRequest(this, request) :\n                request;\n        if (debugBypassToRegularJFP)\n            fjp.execute(new ServletRunnable(this, ac, r, response));\n        else\n            new Fiber(null, stackSize, new ServletSuspendableRunnable(this, ac, r, response)).start();\n    }\n\n    private final static class ServletSuspendableRunnable implements SuspendableRunnable {\n        private final AsyncContext ac;\n        private final HttpServletRequest request;\n        private final HttpServletResponse response;\n        private final FiberHttpServlet servlet;\n\n        ServletSuspendableRunnable(FiberHttpServlet servlet, AsyncContext ac, HttpServletRequest request, HttpServletResponse response) {\n            this.servlet = servlet;\n            this.ac = ac;\n            this.request = request;\n            this.response = response;\n        }\n\n        @Override\n        public final void run() throws SuspendExecution, InterruptedException {\n            servlet.exec(servlet, ac, request, response);\n        }\n    }\n\n    private static class ServletRunnable implements Runnable {\n        private final FiberHttpServlet servlet;\n        private final AsyncContext ac;\n        private final HttpServletRequest request;\n        private final HttpServletResponse response;\n\n        ServletRunnable(FiberHttpServlet servlet, AsyncContext ac, HttpServletRequest request, HttpServletResponse response) {\n            this.servlet = servlet;\n            this.ac = ac;\n            this.request = request;\n            this.response = response;\n        }\n\n        @Override\n        public final void run() {\n            servlet.exec(servlet, ac, request, response);\n        }\n    }\n\n    @Suspendable\n    final void exec(FiberHttpServlet servlet, AsyncContext ac, HttpServletRequest request, HttpServletResponse response) {\n        if (!disableSyncExceptions) {\n            try {\n                exec0(servlet, ac, request, response);\n            } catch (final ServletException | IOException ex) {\n                // Multi-catch above seems to break ASM during instrumentation in some circumstances\n                // seemingly tied to structured class-loading, as in standalone servlet containers\n                servlet.log(\"Exception in servlet's fiber, dispatching to container\", ex);\n                request.setAttribute(FIBER_ASYNC_REQUEST_EXCEPTION, ex);\n                if (!disableSyncForward)\n                    servlet.currentAsyncContext.set(null);\n                ac.dispatch();\n            }\n        } else {\n            try {\n                exec0(servlet, ac, request, response);\n            } catch (final Throwable t) {\n                servlet.log(\"Error during pool-based execution\", t);\n                ((HttpServletResponse) ac.getResponse()).setStatus(500);\n                try {\n                    ac.complete();\n                } catch (final IllegalStateException ignored) {}\n            }\n        }\n    }\n\n    @Suspendable\n    private void exec0(FiberHttpServlet servlet, AsyncContext ac, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {\n        // TODO: check if ac has expired\n        if (!disableSyncForward)\n            servlet.currentAsyncContext.set(ac);\n        servlet.service(request, response);\n        try {\n            ac.complete();\n        } catch (final IllegalStateException ignored) {}\n    }\n\n    private static boolean isJetty(ServletConfig config) {\n        return config.getClass().getName().startsWith(\"org.eclipse.jetty.\");\n    }\n\n    private static boolean isTomcat(ServletConfig config) {\n        return config.getClass().getName().startsWith(\"org.apache.tomcat.\");\n    }\n\n    private static Long getLong(String propName) {\n        final String asyncTimeoutS = System.getProperty(propName);\n        if (asyncTimeoutS != null) {\n            Long l = null;\n            try {\n                l = Long.parseLong(asyncTimeoutS);\n            } catch (final NumberFormatException ignored) {\n            }\n            return l;\n        } else {\n            return null;\n        }\n    }\n\n    private static Boolean getBoolean(String propName) {\n        final String disableJettyAsyncFixesGlobalS = System.getProperty(propName);\n        if (disableJettyAsyncFixesGlobalS != null) {\n            Boolean b = null;\n            if (Boolean.TRUE.toString().equals(disableJettyAsyncFixesGlobalS))\n                b = true;\n            else if (Boolean.FALSE.toString().equals(disableJettyAsyncFixesGlobalS))\n                b = false;\n            return b;\n        } else {\n            return null;\n        }\n    }\n\n    ////////////////////////////////////////////////////////////////////////////////////////////////////\n    // The rest is copied from HttpServlet as we don't instrument by default \"java\" and \"javax\" packages\n    ////////////////////////////////////////////////////////////////////////////////////////////////////\n\n    @Override\n    @Suspendable\n    protected void service(HttpServletRequest req, HttpServletResponse resp)\n        throws ServletException, IOException\n    {\n        final String method = req.getMethod();\n\n        //noinspection IfCanBeSwitch\n        if (method.equals(METHOD_GET)) {\n            long lastModified = getLastModified(req);\n            if (lastModified == -1) {\n                // servlet doesn't support if-modified-since, no reason\n                // to go through further expensive logic\n                doGet(req, resp);\n            } else {\n                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);\n                if (ifModifiedSince < lastModified) {\n                    // If the servlet mod time is later, call doGet()\n                    // Round down to the nearest second for a proper compare\n                    // A ifModifiedSince of -1 will always be less\n                    maybeSetLastModified(resp, lastModified);\n                    doGet(req, resp);\n                } else {\n                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);\n                }\n            }\n\n        } else if (method.equals(METHOD_HEAD)) {\n            final long lastModified = getLastModified(req);\n            maybeSetLastModified(resp, lastModified);\n            doHead(req, resp);\n\n        } else if (method.equals(METHOD_POST)) {\n            doPost(req, resp);\n\n        } else if (method.equals(METHOD_PUT)) {\n            doPut(req, resp);\n\n        } else if (method.equals(METHOD_DELETE)) {\n            doDelete(req, resp);\n\n        } else if (method.equals(METHOD_OPTIONS)) {\n            doOptions(req,resp);\n\n        } else if (method.equals(METHOD_TRACE)) {\n            doTrace(req,resp);\n\n        } else {\n            //\n            // Note that this means NO servlet supports whatever\n            // method was requested, anywhere on this server.\n            //\n\n            String errMsg = lStrings.getString(\"http.method_not_implemented\");\n            final Object[] errArgs = new Object[1];\n            errArgs[0] = method;\n            errMsg = MessageFormat.format(errMsg, errArgs);\n\n            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);\n        }\n    }\n\n    @Override\n    @Suspendable\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp)\n        throws ServletException, IOException\n    {\n        final String protocol = req.getProtocol();\n        final String msg = lStrings.getString(\"http.method_get_not_supported\");\n        if (protocol.endsWith(\"1.1\")) {\n            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);\n        } else {\n            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);\n        }\n    }\n\n    @Override\n    @Suspendable\n    protected void doPost(HttpServletRequest req, HttpServletResponse resp)\n        throws ServletException, IOException\n    {\n        final String protocol = req.getProtocol();\n        final String msg = lStrings.getString(\"http.method_post_not_supported\");\n        if (protocol.endsWith(\"1.1\")) {\n            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);\n        } else {\n            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);\n        }\n    }\n\n    @Override\n    @Suspendable\n    protected void doPut(HttpServletRequest req, HttpServletResponse resp)\n        throws ServletException, IOException\n    {\n        final String protocol = req.getProtocol();\n        final String msg = lStrings.getString(\"http.method_put_not_supported\");\n        if (protocol.endsWith(\"1.1\")) {\n            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);\n        } else {\n            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);\n        }\n    }\n\n    @Override\n    @Suspendable\n    protected void doDelete(HttpServletRequest req,\n                            HttpServletResponse resp)\n        throws ServletException, IOException\n    {\n        final String protocol = req.getProtocol();\n        final String msg = lStrings.getString(\"http.method_delete_not_supported\");\n        if (protocol.endsWith(\"1.1\")) {\n            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);\n        } else {\n            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);\n        }\n    }\n\n    @Override\n    @Suspendable\n    protected void doOptions(HttpServletRequest req, HttpServletResponse resp)\n        throws ServletException, IOException\n    {\n        final Method[] methods = getAllDeclaredMethods(this.getClass());\n\n        boolean ALLOW_GET = false;\n        boolean ALLOW_HEAD = false;\n        boolean ALLOW_POST = false;\n        boolean ALLOW_PUT = false;\n        boolean ALLOW_DELETE = false;\n        final boolean ALLOW_TRACE = true;\n        final boolean ALLOW_OPTIONS = true;\n\n        for (final Method m : methods) {\n            if (m.getName().equals(\"doGet\")) {\n                ALLOW_GET = true;\n                ALLOW_HEAD = true;\n            }\n            if (m.getName().equals(\"doPost\"))\n                ALLOW_POST = true;\n            if (m.getName().equals(\"doPut\"))\n                ALLOW_PUT = true;\n            if (m.getName().equals(\"doDelete\"))\n                ALLOW_DELETE = true;\n\n        }\n\n        String allow = null;\n        if (ALLOW_GET)\n            allow=METHOD_GET;\n        if (ALLOW_HEAD)\n            if (allow==null) allow=METHOD_HEAD;\n            else allow += \", \" + METHOD_HEAD;\n        if (ALLOW_POST)\n            if (allow==null) allow=METHOD_POST;\n            else allow += \", \" + METHOD_POST;\n        if (ALLOW_PUT)\n            if (allow==null) allow=METHOD_PUT;\n            else allow += \", \" + METHOD_PUT;\n        if (ALLOW_DELETE)\n            if (allow==null) allow=METHOD_DELETE;\n            else allow += \", \" + METHOD_DELETE;\n        if (ALLOW_TRACE)\n            if (allow==null) allow=METHOD_TRACE;\n            else allow += \", \" + METHOD_TRACE;\n        if (ALLOW_OPTIONS)\n            if (allow==null) allow=METHOD_OPTIONS;\n            else allow += \", \" + METHOD_OPTIONS;\n\n        resp.setHeader(\"Allow\", allow);\n    }\n\n    private Method[] getAllDeclaredMethods(Class<?> c) {\n\n        if (c.equals(javax.servlet.http.HttpServlet.class)) {\n            return null;\n        }\n\n        final Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());\n        Method[] thisMethods = c.getDeclaredMethods();\n\n        if ((parentMethods != null) && (parentMethods.length > 0)) {\n            final Method[] allMethods =\n                new Method[parentMethods.length + thisMethods.length];\n            System.arraycopy(parentMethods, 0, allMethods, 0,\n                parentMethods.length);\n            System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,\n                thisMethods.length);\n\n            thisMethods = allMethods;\n        }\n\n        return thisMethods;\n    }\n\n    @Override\n    @Suspendable\n    protected void doTrace(HttpServletRequest req, HttpServletResponse resp)\n        throws ServletException, IOException\n    {\n\n        int responseLength;\n\n        final String CRLF = \"\\r\\n\";\n        final StringBuilder buffer = new StringBuilder(\"TRACE \").append(req.getRequestURI())\n            .append(\" \").append(req.getProtocol());\n\n        final Enumeration<String> reqHeaderEnum = req.getHeaderNames();\n\n        while (reqHeaderEnum.hasMoreElements()) {\n            final String headerName = reqHeaderEnum.nextElement();\n            buffer.append(CRLF).append(headerName).append(\": \")\n                .append(req.getHeader(headerName));\n        }\n\n        buffer.append(CRLF);\n\n        responseLength = buffer.length();\n\n        resp.setContentType(\"message/http\");\n        resp.setContentLength(responseLength);\n        final ServletOutputStream out = resp.getOutputStream();\n        out.print(buffer.toString());\n    }\n\n    @Override\n    @Suspendable\n    protected void doHead(HttpServletRequest req, HttpServletResponse resp)\n        throws ServletException, IOException\n    {\n        final NoBodyResponse response = new NoBodyResponse(resp);\n\n        doGet(req, response);\n        response.setContentLength();\n    }\n\n    private void maybeSetLastModified(HttpServletResponse resp,\n                                      long lastModified) {\n        if (resp.containsHeader(HEADER_LASTMOD))\n            return;\n        if (lastModified >= 0)\n            resp.setDateHeader(HEADER_LASTMOD, lastModified);\n    }\n}\n\nfinal class NoBodyResponse extends HttpServletResponseWrapper {\n    private static final ResourceBundle lStrings\n        = ResourceBundle.getBundle(\"javax.servlet.http.LocalStrings\");\n\n    private NoBodyOutputStream noBody;\n    private PrintWriter writer;\n    private boolean didSetContentLength;\n    private boolean usingOutputStream;\n\n    NoBodyResponse(HttpServletResponse r) {\n        super(r);\n        noBody = new NoBodyOutputStream();\n    }\n\n    final void setContentLength() {\n        if (!didSetContentLength) {\n            if (writer != null) {\n                writer.flush();\n            }\n            setContentLength(noBody.getContentLength());\n        }\n    }\n\n    @Override\n    public final void setContentLength(int len) {\n        super.setContentLength(len);\n        didSetContentLength = true;\n    }\n\n    @Override\n    public final ServletOutputStream getOutputStream() throws IOException {\n\n        if (writer != null) {\n            throw new IllegalStateException(\n                lStrings.getString(\"err.ise.getOutputStream\"));\n        }\n        usingOutputStream = true;\n\n        return noBody;\n    }\n\n    @Override\n    public final PrintWriter getWriter() throws UnsupportedEncodingException {\n\n        if (usingOutputStream) {\n            throw new IllegalStateException(\n                lStrings.getString(\"err.ise.getWriter\"));\n        }\n\n        if (writer == null) {\n            final OutputStreamWriter w = new OutputStreamWriter(\n                noBody, getCharacterEncoding());\n            writer = new PrintWriter(w);\n        }\n\n        return writer;\n    }\n}\n\nfinal class NoBodyOutputStream extends ServletOutputStream {\n\n    private static final String LSTRING_FILE =\n        \"javax.servlet.http.LocalStrings\";\n    private static ResourceBundle lStrings =\n        ResourceBundle.getBundle(LSTRING_FILE);\n\n    private int contentLength = 0;\n\n    NoBodyOutputStream() {}\n\n    final int getContentLength() {\n        return contentLength;\n    }\n\n    @Override\n    public final void write(int b) {\n        contentLength++;\n    }\n\n    @Override\n    public final void write(byte buf[], int offset, int len)\n        throws IOException\n    {\n        if (len >= 0) {\n            contentLength += len;\n        } else {\n            // This should have thrown an IllegalArgumentException, but\n            // changing this would break backwards compatibility\n            throw new IOException(lStrings.getString(\"err.io.negativelength\"));\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-servlet/src/main/java/co/paralleluniverse/fibers/servlet/FiberHttpServletRequest.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.servlet;\n\nimport java.io.IOException;\nimport java.security.Principal;\nimport java.util.Collection;\nimport java.util.Enumeration;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpSession;\nimport javax.servlet.http.Part;\n\n/**\n *\n * @author eitan\n */\npublic class FiberHttpServletRequest extends FiberServletRequest implements HttpServletRequest {\n    private final String contextPath;\n    private final String servletPath;\n    private final String pathInfo;\n\n    public FiberHttpServletRequest(FiberHttpServlet servlet, javax.servlet.http.HttpServletRequest req) {\n        super(servlet, req);\n        // Jetty (what about other containers?) nullifies the following values in the request\n        // when the service method returns. If we want to access them in an async context (in\n        // the fiber), we need to capture them.\n        pathInfo = req.getPathInfo();\n        servletPath = req.getServletPath();\n        contextPath = req.getContextPath();\n    }\n\n    @Override\n    javax.servlet.http.HttpServletRequest getReq() {\n        return (javax.servlet.http.HttpServletRequest) super.getReq();\n    }\n\n    // Delegations \n    @Override\n    public String getAuthType() {\n        return getReq().getAuthType();\n    }\n\n    @Override\n    public Cookie[] getCookies() {\n        return getReq().getCookies();\n    }\n\n    @Override\n    public long getDateHeader(String name) {\n        return getReq().getDateHeader(name);\n    }\n\n    @Override\n    public String getHeader(String name) {\n        return getReq().getHeader(name);\n    }\n\n    @Override\n    public Enumeration<String> getHeaders(String name) {\n        return getReq().getHeaders(name);\n    }\n\n    @Override\n    public Enumeration<String> getHeaderNames() {\n        return getReq().getHeaderNames();\n    }\n\n    @Override\n    public int getIntHeader(String name) {\n        return getReq().getIntHeader(name);\n    }\n\n    @Override\n    public String getMethod() {\n        return getReq().getMethod();\n    }\n\n    @Override\n    public String getPathInfo() {\n        return pathInfo;\n    }\n\n    @Override\n    public String getPathTranslated() {\n        return getReq().getPathTranslated();\n    }\n\n    @Override\n    public String getContextPath() {\n        return contextPath;\n    }\n\n    @Override\n    public String getQueryString() {\n        return getReq().getQueryString();\n    }\n\n    @Override\n    public String getRemoteUser() {\n        return getReq().getRemoteUser();\n    }\n\n    @Override\n    public boolean isUserInRole(String role) {\n        return getReq().isUserInRole(role);\n    }\n\n    @Override\n    public Principal getUserPrincipal() {\n        return getReq().getUserPrincipal();\n    }\n\n    @Override\n    public String getRequestedSessionId() {\n        return getReq().getRequestedSessionId();\n    }\n\n    @Override\n    public String getRequestURI() {\n        return getReq().getRequestURI();\n    }\n\n    @Override\n    public StringBuffer getRequestURL() {\n        return getReq().getRequestURL();\n    }\n\n    @Override\n    public String getServletPath() {\n        return servletPath;\n    }\n\n    @Override\n    public HttpSession getSession(boolean create) {\n        return getReq().getSession(create);\n    }\n\n    @Override\n    public HttpSession getSession() {\n        return getReq().getSession();\n    }\n\n    @Override\n    public boolean isRequestedSessionIdValid() {\n        return getReq().isRequestedSessionIdValid();\n    }\n\n    @Override\n    public boolean isRequestedSessionIdFromCookie() {\n        return getReq().isRequestedSessionIdFromCookie();\n    }\n\n    @Override\n    public boolean isRequestedSessionIdFromURL() {\n        return getReq().isRequestedSessionIdFromURL();\n    }\n\n    @Override\n    @Deprecated\n    @SuppressWarnings(\"deprecation\")\n    public boolean isRequestedSessionIdFromUrl() {\n        return getReq().isRequestedSessionIdFromUrl();\n    }\n\n    @Override\n    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {\n        return getReq().authenticate(response);\n    }\n\n    @Override\n    public void login(String username, String password) throws ServletException {\n        getReq().login(username, password);\n    }\n\n    @Override\n    public void logout() throws ServletException {\n        getReq().logout();\n    }\n\n    @Override\n    public Collection<Part> getParts() throws IOException, ServletException {\n        return getReq().getParts();\n    }\n\n    @Override\n    public Part getPart(String name) throws IOException, ServletException {\n        return getReq().getPart(name);\n    }\n}\n"
  },
  {
    "path": "comsat-servlet/src/main/java/co/paralleluniverse/fibers/servlet/FiberRequestDispatcher.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.servlet;\n\nimport java.io.IOException;\nimport javax.servlet.AsyncContext;\nimport javax.servlet.RequestDispatcher;\nimport javax.servlet.ServletException;\nimport javax.servlet.ServletRequest;\nimport javax.servlet.ServletResponse;\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n *\n * @author eitan\n */\nclass FiberRequestDispatcher implements RequestDispatcher {\n    public static final String SLASH = \"/\";\n    private final String path;\n    private final AsyncContext ac;\n\n    public FiberRequestDispatcher(String path, AsyncContext ac) {\n        this.path = path;\n        this.ac = ac;\n    }\n\n    @Override\n    public void forward(ServletRequest request, final ServletResponse response) throws ServletException, IOException {\n        if (ac == null)\n            throw new UnsupportedOperationException(\"Sync forward emulation is disabled\");\n        final ServletRequest baseReq = ((FiberServletRequest) request).getReq();\n        if (baseReq != ac.getRequest() || response != ac.getResponse())\n            throw new UnsupportedOperationException(\"Changing the request or the response in forward is not yet supported from fiber servlet\");\n        response.reset();\n        if (ac.getRequest() instanceof HttpServletRequest)\n            ac.dispatch(relToAbs((HttpServletRequest) ac.getRequest(), path));\n        else\n            ac.dispatch(path); // TODO: think about relative forward in GenericServlet\n    }\n\n    @Override\n    public void include(ServletRequest request, final ServletResponse response) throws ServletException {\n        throw new UnsupportedOperationException(\"Include calls are not yet supported by fiber servlet\");\n    }\n\n    public static String relToAbs(HttpServletRequest req, String rel) {\n        if (!rel.startsWith(\"/\")) {\n            String relTo = addPaths(req.getServletPath(), req.getPathInfo());\n            int slash = relTo.lastIndexOf(\"/\");\n            if (slash > 1)\n                relTo = relTo.substring(0, slash + 1);\n            else\n                relTo = \"/\";\n            rel = addPaths(relTo, rel);\n        }\n        return rel;\n    }\n\n    public static String addPaths(String p1, String p2) {\n        if (p1 == null || p1.length() == 0) {\n            if (p1 != null && p2 == null)\n                return p1;\n            return p2;\n        }\n        if (p2 == null || p2.length() == 0)\n            return p1;\n\n        int split = p1.indexOf(';');\n        if (split < 0)\n            split = p1.indexOf('?');\n        if (split == 0)\n            return p2 + p1;\n        if (split < 0)\n            split = p1.length();\n\n        StringBuilder buf = new StringBuilder(p1.length() + p2.length() + 2);\n        buf.append(p1);\n\n        if (buf.charAt(split - 1) == '/') {\n            if (p2.startsWith(SLASH)) {\n                buf.deleteCharAt(split - 1);\n                buf.insert(split - 1, p2);\n            } else\n                buf.insert(split, p2);\n        } else {\n            if (p2.startsWith(SLASH))\n                buf.insert(split, p2);\n            else {\n                buf.insert(split, SLASH);\n                buf.insert(split + 1, p2);\n            }\n        }\n\n        return buf.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-servlet/src/main/java/co/paralleluniverse/fibers/servlet/FiberServletContext.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.servlet;\n\nimport java.io.InputStream;\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.util.Enumeration;\nimport java.util.EventListener;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.servlet.AsyncContext;\nimport javax.servlet.Filter;\nimport javax.servlet.FilterRegistration;\nimport javax.servlet.RequestDispatcher;\nimport javax.servlet.Servlet;\nimport javax.servlet.ServletContext;\nimport javax.servlet.ServletException;\nimport javax.servlet.ServletRegistration;\nimport javax.servlet.ServletRegistration.Dynamic;\nimport javax.servlet.SessionCookieConfig;\nimport javax.servlet.SessionTrackingMode;\nimport javax.servlet.descriptor.JspConfigDescriptor;\n\n/**\n *\n * @author eitan\n */\nclass FiberServletContext implements ServletContext {\n    private final ServletContext sc;\n    private final ThreadLocal<AsyncContext> ac;\n\n    public FiberServletContext(ServletContext sc, ThreadLocal<AsyncContext> ac) {\n        this.sc = sc;\n        this.ac = ac;\n    }\n\n    @Override\n    public RequestDispatcher getRequestDispatcher(String path) {\n        return new FiberRequestDispatcher(path, ac.get());\n    }\n\n    @Override\n    public ServletContext getContext(String uripath) {\n        return new FiberServletContext(sc.getContext(uripath), ac);\n    }\n\n    @Override\n    public RequestDispatcher getNamedDispatcher(String name) {\n        throw new UnsupportedOperationException(\"Not yet implemented\");\n//        return new RequestDispatcher(sc.getNamedDispatcher(name).;\n    }\n\n    @Override\n    public String getContextPath() {\n        return sc.getContextPath();\n    }\n\n    @Override\n    public int getMajorVersion() {\n        return sc.getMajorVersion();\n    }\n\n    @Override\n    public int getMinorVersion() {\n        return sc.getMinorVersion();\n    }\n\n    @Override\n    public int getEffectiveMajorVersion() {\n        return sc.getEffectiveMajorVersion();\n    }\n\n    @Override\n    public int getEffectiveMinorVersion() {\n        return sc.getEffectiveMinorVersion();\n    }\n\n    @Override\n    public String getMimeType(String file) {\n        return sc.getMimeType(file);\n    }\n\n    @Override\n    public Set<String> getResourcePaths(String path) {\n        return sc.getResourcePaths(path);\n    }\n\n    @Override\n    public URL getResource(String path) throws MalformedURLException {\n        return sc.getResource(path);\n    }\n\n    @Override\n    public InputStream getResourceAsStream(String path) {\n        return sc.getResourceAsStream(path);\n    }\n\n    @Override\n    @Deprecated\n    @SuppressWarnings(\"deprecation\")\n    public Servlet getServlet(String name) throws ServletException {\n        return sc.getServlet(name);\n    }\n\n    @Override\n    @Deprecated\n    @SuppressWarnings(\"deprecation\")\n    public Enumeration<Servlet> getServlets() {\n        return sc.getServlets();\n    }\n\n    @Override\n    @Deprecated\n    @SuppressWarnings(\"deprecation\")\n    public Enumeration<String> getServletNames() {\n        return sc.getServletNames();\n    }\n\n    @Override\n    public void log(String msg) {\n        sc.log(msg);\n    }\n\n    @Override\n    @Deprecated\n    @SuppressWarnings(\"deprecation\")\n    public void log(Exception exception, String msg) {\n        sc.log(exception, msg);\n    }\n\n    @Override\n    public void log(String message, Throwable throwable) {\n        sc.log(message, throwable);\n    }\n\n    @Override\n    public String getRealPath(String path) {\n        return sc.getRealPath(path);\n    }\n\n    @Override\n    public String getServerInfo() {\n        return sc.getServerInfo();\n    }\n\n    @Override\n    public String getInitParameter(String name) {\n        return sc.getInitParameter(name);\n    }\n\n    @Override\n    public Enumeration<String> getInitParameterNames() {\n        return sc.getInitParameterNames();\n    }\n\n    @Override\n    public boolean setInitParameter(String name, String value) {\n        return sc.setInitParameter(name, value);\n    }\n\n    @Override\n    public Object getAttribute(String name) {\n        return sc.getAttribute(name);\n    }\n\n    @Override\n    public Enumeration<String> getAttributeNames() {\n        return sc.getAttributeNames();\n    }\n\n    @Override\n    public void setAttribute(String name, Object object) {\n        sc.setAttribute(name, object);\n    }\n\n    @Override\n    public void removeAttribute(String name) {\n        sc.removeAttribute(name);\n    }\n\n    @Override\n    public String getServletContextName() {\n        return sc.getServletContextName();\n    }\n\n    @Override\n    public Dynamic addServlet(String servletName, String className) {\n        return sc.addServlet(servletName, className);\n    }\n\n    @Override\n    public Dynamic addServlet(String servletName, Servlet servlet) {\n        return sc.addServlet(servletName, servlet);\n    }\n\n    @Override\n    public Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {\n        return sc.addServlet(servletName, servletClass);\n    }\n\n    @Override\n    public <T extends Servlet> T createServlet(Class<T> clazz) throws ServletException {\n        return sc.createServlet(clazz);\n    }\n\n    @Override\n    public ServletRegistration getServletRegistration(String servletName) {\n        return sc.getServletRegistration(servletName);\n    }\n\n    @Override\n    public Map<String, ? extends ServletRegistration> getServletRegistrations() {\n        return sc.getServletRegistrations();\n    }\n\n    @Override\n    public FilterRegistration.Dynamic addFilter(String filterName, String className) {\n        return sc.addFilter(filterName, className);\n    }\n\n    @Override\n    public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {\n        return sc.addFilter(filterName, filter);\n    }\n\n    @Override\n    public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {\n        return sc.addFilter(filterName, filterClass);\n    }\n\n    @Override\n    public <T extends Filter> T createFilter(Class<T> clazz) throws ServletException {\n        return sc.createFilter(clazz);\n    }\n\n    @Override\n    public FilterRegistration getFilterRegistration(String filterName) {\n        return sc.getFilterRegistration(filterName);\n    }\n\n    @Override\n    public Map<String, ? extends FilterRegistration> getFilterRegistrations() {\n        return sc.getFilterRegistrations();\n    }\n\n    @Override\n    public SessionCookieConfig getSessionCookieConfig() {\n        return sc.getSessionCookieConfig();\n    }\n\n    @Override\n    public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) {\n        sc.setSessionTrackingModes(sessionTrackingModes);\n    }\n\n    @Override\n    public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {\n        return sc.getDefaultSessionTrackingModes();\n    }\n\n    @Override\n    public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {\n        return sc.getEffectiveSessionTrackingModes();\n    }\n\n    @Override\n    public void addListener(String className) {\n        sc.addListener(className);\n    }\n\n    @Override\n    public <T extends EventListener> void addListener(T t) {\n        sc.addListener(t);\n    }\n\n    @Override\n    public void addListener(Class<? extends EventListener> listenerClass) {\n        sc.addListener(listenerClass);\n    }\n\n    @Override\n    public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException {\n        return sc.createListener(clazz);\n    }\n\n    @Override\n    public JspConfigDescriptor getJspConfigDescriptor() {\n        return sc.getJspConfigDescriptor();\n    }\n\n    @Override\n    public ClassLoader getClassLoader() {\n        return sc.getClassLoader();\n    }\n\n    @Override\n    public void declareRoles(String... roleNames) {\n        sc.declareRoles(roleNames);\n    }\n\n    @Override\n    public int hashCode() {\n        return sc.hashCode();\n    }\n\n    @Override\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    public boolean equals(Object obj) {\n        return sc.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return sc.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-servlet/src/main/java/co/paralleluniverse/fibers/servlet/FiberServletRequest.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.servlet;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.UnsupportedEncodingException;\nimport java.util.Enumeration;\nimport java.util.Locale;\nimport java.util.Map;\nimport javax.servlet.*;\n\n/**\n *\n * @author eitan\n */\npublic class FiberServletRequest implements ServletRequest {\n    private final ServletRequest req;\n    private final ServletContext servletContext;\n    private final FiberHttpServlet servlet;\n\n    public FiberServletRequest(FiberHttpServlet servlet, ServletRequest req) {\n        this.servlet = servlet;\n        this.req = req;\n        // Jetty (what about other containers?) nullifies the following values in the request\n        // when the service method returns. If we want to access them in an async context (in\n        // the fiber), we need to capture them.\n        servletContext = req.getServletContext();\n    }\n\n    @Override\n    public RequestDispatcher getRequestDispatcher(String path) {\n        if (!servlet.disableSyncForward)\n            return new FiberRequestDispatcher(path, req.getAsyncContext());\n        else\n            return req.getRequestDispatcher(path);\n    }\n\n    javax.servlet.ServletRequest getReq() {\n        return req;\n    }\n\n    // Delegations\n    @Override\n    public Object getAttribute(String name) {\n        return req.getAttribute(name);\n    }\n\n    @Override\n    public Enumeration<String> getAttributeNames() {\n        return req.getAttributeNames();\n    }\n\n    @Override\n    public String getCharacterEncoding() {\n        return req.getCharacterEncoding();\n    }\n\n    @Override\n    public void setCharacterEncoding(String env) throws UnsupportedEncodingException {\n        req.setCharacterEncoding(env);\n    }\n\n    @Override\n    public int getContentLength() {\n        return req.getContentLength();\n    }\n\n    @Override\n    public String getContentType() {\n        return req.getContentType();\n    }\n\n    @Override\n    public ServletInputStream getInputStream() throws IOException {\n        return req.getInputStream();\n    }\n\n    @Override\n    public String getParameter(String name) {\n        return req.getParameter(name);\n    }\n\n    @Override\n    public Enumeration<String> getParameterNames() {\n        return req.getParameterNames();\n    }\n\n    @Override\n    public String[] getParameterValues(String name) {\n        return req.getParameterValues(name);\n    }\n\n    @Override\n    public Map<String, String[]> getParameterMap() {\n        return req.getParameterMap();\n    }\n\n    @Override\n    public String getProtocol() {\n        return req.getProtocol();\n    }\n\n    @Override\n    public String getScheme() {\n        return req.getScheme();\n    }\n\n    @Override\n    public String getServerName() {\n        return req.getServerName();\n    }\n\n    @Override\n    public int getServerPort() {\n        return req.getServerPort();\n    }\n\n    @Override\n    public BufferedReader getReader() throws IOException {\n        return req.getReader();\n    }\n\n    @Override\n    public String getRemoteAddr() {\n        return req.getRemoteAddr();\n    }\n\n    @Override\n    public String getRemoteHost() {\n        return req.getRemoteHost();\n    }\n\n    @Override\n    public void setAttribute(String name, Object o) {\n        req.setAttribute(name, o);\n    }\n\n    @Override\n    public void removeAttribute(String name) {\n        req.removeAttribute(name);\n    }\n\n    @Override\n    public Locale getLocale() {\n        return req.getLocale();\n    }\n\n    @Override\n    public Enumeration<Locale> getLocales() {\n        return req.getLocales();\n    }\n\n    @Override\n    public boolean isSecure() {\n        return req.isSecure();\n    }\n\n    @Override\n    @Deprecated\n    @SuppressWarnings(\"deprecation\")\n    public String getRealPath(String path) {\n        return req.getRealPath(path);\n    }\n\n    @Override\n    public int getRemotePort() {\n        return req.getRemotePort();\n    }\n\n    @Override\n    public String getLocalName() {\n        return req.getLocalName();\n    }\n\n    @Override\n    public String getLocalAddr() {\n        return req.getLocalAddr();\n    }\n\n    @Override\n    public int getLocalPort() {\n        return req.getLocalPort();\n    }\n\n    @Override\n    public ServletContext getServletContext() {\n        return servletContext;\n    }\n\n    @Override\n    public AsyncContext startAsync() throws IllegalStateException {\n        throw new UnsupportedOperationException(\"you can't use startAsync mechanism from fiber.servlet\");\n    }\n\n    @Override\n    public AsyncContext startAsync(javax.servlet.ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException {\n        throw new UnsupportedOperationException(\"you can't use startAsync mechanism from fiber.servlet\");\n    }\n\n    @Override\n    public boolean isAsyncStarted() {\n        return req.isAsyncStarted();\n    }\n\n    @Override\n    public boolean isAsyncSupported() {\n        return false;\n    }\n\n    @Override\n    public AsyncContext getAsyncContext() {\n        return null;\n    }\n\n    @Override\n    public DispatcherType getDispatcherType() {\n        return req.getDispatcherType();\n    }\n\n    @Override\n    public int hashCode() {\n        return req.hashCode();\n    }\n\n    @Override\n    @SuppressWarnings(\"EqualsWhichDoesntCheckParameterClass\")\n    public boolean equals(Object obj) {\n        return req.equals(obj);\n    }\n\n    @Override\n    public String toString() {\n        return req.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-servlet/src/main/java/co/paralleluniverse/fibers/servlet/package-info.java",
    "content": "/*\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n * \n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *  \n *   or (per the licensee's choosing)\n *  \n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/**\n * {@link javax.servlet Servlet} Integration for Quasar Fibers\n */\npackage co.paralleluniverse.fibers.servlet;\n"
  },
  {
    "path": "comsat-servlet/src/test/java/co/paralleluniverse/fibers/servlet/FiberHttpServletTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.servlet;\n\nimport co.paralleluniverse.embedded.containers.EmbeddedServer;\nimport co.paralleluniverse.embedded.containers.JettyServer;\nimport co.paralleluniverse.embedded.containers.TomcatServer;\nimport co.paralleluniverse.embedded.containers.UndertowServer;\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.*;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.junit.After;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\nimport static org.junit.Assume.*;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class FiberHttpServletTest {\n\n    @Parameterized.Parameters(name = \"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {JettyServer.class},\n            {TomcatServer.class},\n            {UndertowServer.class},});\n    }\n    private final Class<? extends EmbeddedServer> cls;\n    private EmbeddedServer server;\n    private CloseableHttpClient client;\n\n    public FiberHttpServletTest(Class<? extends EmbeddedServer> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        this.server = cls.newInstance();\n        // snippet servlet registration\n        server.addServlet(\"test\", FiberTestServlet.class, \"/\");\n        // end of snippet\n        server.addServlet(\"forward\", FiberForwardServlet.class, \"/forward\");\n        server.addServlet(\"inline\", FiberForwardServlet.class, \"/inline\");\n        server.addServlet(\"redirect\", FiberRedirectServlet.class, \"/redirect\");\n        server.start();\n        this.client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()\n                .setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000)\n                .build()).build();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        server.stop();\n        client.close();\n    }\n\n    @Test\n    public void testGet() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testGet\", client.execute(new HttpGet(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER));\n    }\n\n    @Test\n    public void testRedirect() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++) {\n            final HttpGet httpGet = new HttpGet(\"http://localhost:8080/redirect\");\n            final CloseableHttpResponse res = HttpClients.custom().disableRedirectHandling().build().execute(httpGet);\n            assertEquals(302, res.getStatusLine().getStatusCode());\n            assertTrue(res.getFirstHeader(\"Location\").getValue().endsWith(\"/foo\"));\n        }\n    }\n\n    @Test\n    // Passes on undertow\n    public void testForward() throws IOException, InterruptedException, Exception {\n        assumeTrue(UndertowServer.class.equals(server.getClass()));\n\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"Faild on iteration \" + i, \"testGet\", client.execute(new HttpGet(\"http://localhost:8080/forward\"), BASIC_RESPONSE_HANDLER));\n    }\n\n//    @Test\n    // Inline is not supported yet by fiberServlet\n    public void testInline() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testInlinetestGet\", client.execute(new HttpGet(\"http://localhost:8080/inline\"), BASIC_RESPONSE_HANDLER));\n    }\n\n    @Test\n    public void testPost() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testPost\", client.execute(new HttpPost(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER));\n    }\n\n    @Test\n    public void testPut() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testPut\", client.execute(new HttpPut(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER));\n    }\n\n/*\n    @Test\n    public void testPatch() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testPatch\", client.execute(new HttpPatch(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER));\n    }\n*/\n\n    @Test\n    public void testDelete() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testDelete\", client.execute(new HttpDelete(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER));\n    }\n\n    @Test\n    public void testTrace() throws IOException, InterruptedException, Exception {\n        assumeFalse(TomcatServer.class.equals(server.getClass()));\n\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testTrace\", client.execute(new HttpTrace(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER));\n    }\n\n    @Test\n    public void testHead() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testHead\", client.execute(new HttpHead(\"http://localhost:8080\")).getFirstHeader(\"X-Head\").getValue());\n    }\n\n    @Test\n    public void testOptions() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testOptions\", client.execute(new HttpOptions(\"http://localhost:8080\")).getFirstHeader(\"X-Head\").getValue());\n    }\n\n    // snippet FiberHttpServlet example\n    public static class FiberTestServlet extends FiberHttpServlet {\n        // snippet_exclude_begin\n        @Override\n        @Suspendable\n        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Fiber.sleep(100); // <== Some blocking code\n                out.print(\"testPost\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n        @Override\n        @Suspendable\n        protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try {\n                Fiber.sleep(100); // <== Some blocking code\n                resp.setHeader(\"x-Head\", \"testHead\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n        @Override\n        @Suspendable\n        protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try {\n                Fiber.sleep(100); // <== Some blocking code\n                resp.setHeader(\"x-Head\", \"testOptions\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n        @Override\n        @Suspendable\n        protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Fiber.sleep(100); // <== Some blocking code\n                out.print(\"testPut\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n/*\n        @Override\n        @Suspendable\n        protected void doPatch(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Fiber.sleep(100); // <== Some blocking code\n                out.print(\"testPatch\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n*/\n        @Override\n        @Suspendable\n        protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Fiber.sleep(100); // <== Some blocking code\n                out.print(\"testDelete\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n        @Override\n        @Suspendable\n        protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Fiber.sleep(100); // <== Some blocking code\n                out.print(\"testTrace\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n        // snippet_exclude_end\n        @Override\n        @Suspendable\n        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Fiber.sleep(100); // <== Some blocking code\n                out.print(\"testGet\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n    }\n    // end of snippet\n\n    public static class FiberForwardServlet extends FiberHttpServlet {\n        @Override\n        @Suspendable\n        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try {\n                Fiber.sleep(100);\n                getServletContext().getRequestDispatcher(\"/\").forward(req, resp);\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n    }\n\n    public static class FiberRedirectServlet extends FiberHttpServlet {\n        @Override\n        @Suspendable\n        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try {\n                Fiber.sleep(100);\n                resp.sendRedirect(\"/foo\");\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n    }\n\n    public static class FiberInlineServlet extends FiberHttpServlet {\n        @Override\n        @Suspendable\n        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                Fiber.sleep(1);\n                out.print(\"testInline\");\n                getServletContext().getRequestDispatcher(\"/\").include(req, resp);\n            } catch (InterruptedException | SuspendExecution e) {\n            }\n        }\n    }\n\n    private static final BasicResponseHandler BASIC_RESPONSE_HANDLER = new BasicResponseHandler();\n\n}\n"
  },
  {
    "path": "comsat-shiro/src/main/resources/META-INF/suspendable-supers",
    "content": "org.apache.shiro.authc.AbstractAuthenticator.doAuthenticate\norg.apache.shiro.authc.Authenticator.authenticate\norg.apache.shiro.realm.Realm.getAuthenticationInfo\norg.apache.shiro.realm.AuthenticatingRealm.doGetAuthenticationInfo\norg.apache.shiro.realm.AuthorizingRealm.doGetAuthorizationInfo\norg.apache.shiro.mgt.SecurityManager.login\norg.apache.shiro.subject.Subject.isPermitted\norg.apache.shiro.subject.Subject.isPermittedAll\norg.apache.shiro.subject.Subject.checkPermission\norg.apache.shiro.subject.Subject.checkPermissions\norg.apache.shiro.subject.Subject.hasRole\norg.apache.shiro.subject.Subject.hasRoles\norg.apache.shiro.subject.Subject.hasAllRoles\norg.apache.shiro.subject.Subject.checkRole\norg.apache.shiro.subject.Subject.checkRoles\norg.apache.shiro.subject.Subject.login\norg.apache.shiro.authz.Authorizer.isPermitted\norg.apache.shiro.authz.Authorizer.isPermittedAll\norg.apache.shiro.authz.Authorizer.checkPermission\norg.apache.shiro.authz.Authorizer.checkPermissions\norg.apache.shiro.authz.Authorizer.hasRole\norg.apache.shiro.authz.Authorizer.hasRoles\norg.apache.shiro.authz.Authorizer.hasAllRoles\norg.apache.shiro.authz.Authorizer.checkRole\norg.apache.shiro.authz.Authorizer.checkRoles\norg.apache.shiro.authz.Authorizer.checkRoles"
  },
  {
    "path": "comsat-shiro/src/main/resources/META-INF/suspendables",
    "content": "org.apache.shiro.authc.pam.ModularRealmAuthenticator.doMultiRealmAuthentication\norg.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication\norg.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate\norg.apache.shiro.authc.AbstractAuthenticator.authenticate\norg.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate\norg.apache.shiro.mgt.DefaultSecurityManager.login\norg.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo\norg.apache.shiro.subject.support.DelegatingSubject.isPermitted\norg.apache.shiro.subject.support.DelegatingSubject.isPermittedAll\norg.apache.shiro.subject.support.DelegatingSubject.checkPermission\norg.apache.shiro.subject.support.DelegatingSubject.checkPermissions\norg.apache.shiro.subject.support.DelegatingSubject.hasRole\norg.apache.shiro.subject.support.DelegatingSubject.hasRoles\norg.apache.shiro.subject.support.DelegatingSubject.hasAllRoles\norg.apache.shiro.subject.support.DelegatingSubject.checkRole\norg.apache.shiro.subject.support.DelegatingSubject.checkRoles\norg.apache.shiro.subject.support.DelegatingSubject.login\norg.apache.shiro.mgt.AuthorizingSecurityManager.isPermitted\norg.apache.shiro.mgt.AuthorizingSecurityManager.isPermittedAll\norg.apache.shiro.mgt.AuthorizingSecurityManager.checkPermission\norg.apache.shiro.mgt.AuthorizingSecurityManager.checkPermissions\norg.apache.shiro.mgt.AuthorizingSecurityManager.hasRole\norg.apache.shiro.mgt.AuthorizingSecurityManager.hasRoles\norg.apache.shiro.mgt.AuthorizingSecurityManager.hasAllRoles\norg.apache.shiro.mgt.AuthorizingSecurityManager.checkRole\norg.apache.shiro.mgt.AuthorizingSecurityManager.checkRoles\norg.apache.shiro.authz.ModularRealmAuthorizer.isPermitted\norg.apache.shiro.authz.ModularRealmAuthorizer.isPermittedAll\norg.apache.shiro.authz.ModularRealmAuthorizer.checkPermission\norg.apache.shiro.authz.ModularRealmAuthorizer.checkPermissions\norg.apache.shiro.authz.ModularRealmAuthorizer.hasRole\norg.apache.shiro.authz.ModularRealmAuthorizer.hasRoles\norg.apache.shiro.authz.ModularRealmAuthorizer.hasAllRoles\norg.apache.shiro.authz.ModularRealmAuthorizer.checkRole\norg.apache.shiro.authz.ModularRealmAuthorizer.checkRoles\norg.apache.shiro.authz.ModularRealmAuthorizer.checkRoles\norg.apache.shiro.realm.AuthorizingRealm.isPermitted\norg.apache.shiro.realm.AuthorizingRealm.isPermittedAll\norg.apache.shiro.realm.AuthorizingRealm.checkPermission\norg.apache.shiro.realm.AuthorizingRealm.checkPermissions\norg.apache.shiro.realm.AuthorizingRealm.hasRole\norg.apache.shiro.realm.AuthorizingRealm.hasRoles\norg.apache.shiro.realm.AuthorizingRealm.hasAllRoles\norg.apache.shiro.realm.AuthorizingRealm.checkRole\norg.apache.shiro.realm.AuthorizingRealm.checkRoles\norg.apache.shiro.realm.AuthorizingRealm.getAuthorizationInfo"
  },
  {
    "path": "comsat-shiro/src/test/java/co/paralleluniverse/fibers/shiro/FiberShiroRealmTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.fibers.shiro;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.FiberUtil;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.SuspendableCallable;\n\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.authc.UsernamePasswordToken;\nimport org.apache.shiro.config.IniSecurityManagerFactory;\nimport org.apache.shiro.mgt.SecurityManager;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertTrue;\n\nimport java.util.concurrent.ExecutionException;\n\n/**\n * @author rodedb\n */\npublic class FiberShiroRealmTest {\n\n    @Test\n    public void testSingleRealm() throws ExecutionException, InterruptedException {\n        final IniSecurityManagerFactory factory = new IniSecurityManagerFactory(\"classpath:shiro-single-realm.ini\");\n        final SecurityManager securityManager = factory.getInstance();\n        SecurityUtils.setSecurityManager(securityManager);\n\n        final Boolean authed = FiberUtil.runInFiber(new SuspendableCallable<Boolean>() {\n            @Override\n            public Boolean run() throws SuspendExecution, InterruptedException {\n                SecurityUtils.getSubject().login(new UsernamePasswordToken(\"test\", \"test\"));\n                return SecurityUtils.getSubject().isAuthenticated()\n                    && SecurityUtils.getSubject().hasRole(\"roleA\")\n                    && SecurityUtils.getSubject().isPermitted(\"resource:actionA\");\n            }\n        });\n        assertTrue(authed);\n    }\n\n    @Test\n    public void testMultiRealm() throws ExecutionException, InterruptedException {\n        final IniSecurityManagerFactory factory = new IniSecurityManagerFactory(\"classpath:shiro-multi-realm.ini\");\n        final SecurityManager securityManager = factory.getInstance();\n        SecurityUtils.setSecurityManager(securityManager);\n\n        final Boolean authed = FiberUtil.runInFiber(new SuspendableCallable<Boolean>() {\n            @Override\n            public Boolean run() throws SuspendExecution, InterruptedException {\n                SecurityUtils.getSubject().login(new UsernamePasswordToken(\"test\", \"test\"));\n                return SecurityUtils.getSubject().isAuthenticated()\n                    && SecurityUtils.getSubject().hasRole(\"roleA\")\n                    && SecurityUtils.getSubject().isPermitted(\"resource:actionA\");\n            }\n        });\n        assertTrue(authed);\n    }\n}\n"
  },
  {
    "path": "comsat-shiro/src/test/java/co/paralleluniverse/fibers/shiro/FiberedRealm.java",
    "content": "package co.paralleluniverse.fibers.shiro;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\n\nimport org.apache.shiro.authc.AuthenticationException;\nimport org.apache.shiro.authc.AuthenticationInfo;\nimport org.apache.shiro.authc.AuthenticationToken;\nimport org.apache.shiro.authc.SimpleAuthenticationInfo;\nimport org.apache.shiro.authz.AuthorizationInfo;\nimport org.apache.shiro.authz.SimpleAuthorizationInfo;\nimport org.apache.shiro.realm.AuthorizingRealm;\nimport org.apache.shiro.subject.PrincipalCollection;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * @author rodedb\n */\npublic class FiberedRealm extends AuthorizingRealm {\n\n    @Suspendable\n    @Override\n    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {\n        final Set<String> roles = new HashSet<>();\n        roles.add(\"roleA\");\n        roles.add(\"roleB\");\n        final SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(roles);\n        authorizationInfo.addStringPermission(\"resource:actionA\");\n        authorizationInfo.addStringPermission(\"resource:actionB\");\n        try {\n            Fiber.sleep(10);\n        } catch (InterruptedException e) {\n            return null;\n        } catch (SuspendExecution suspendExecution) {\n            throw new AssertionError(\"Should not happen\");\n        }\n\n        return authorizationInfo;\n    }\n\n    @Suspendable\n    @Override\n    protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) throws AuthenticationException {\n        final SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), \"FiberedRealm\");\n        try {\n            Fiber.sleep(10);\n        } catch (InterruptedException e) {\n            return null;\n        } catch (SuspendExecution suspendExecution) {\n            throw new AssertionError(\"Should not happen\");\n        }\n        return authenticationInfo;\n    }\n}\n"
  },
  {
    "path": "comsat-shiro/src/test/resources/shiro-multi-realm.ini",
    "content": "[main]\nfiberedRealmA = co.paralleluniverse.fibers.shiro.FiberedRealm\nfiberedRealmB = co.paralleluniverse.fibers.shiro.FiberedRealm\nsecurityManager.realms = $fiberedRealmA, $fiberedRealmB"
  },
  {
    "path": "comsat-shiro/src/test/resources/shiro-single-realm.ini",
    "content": "[main]\nfiberedRealm = co.paralleluniverse.fibers.shiro.FiberedRealm\nsecurityManager.realms = $fiberedRealm"
  },
  {
    "path": "comsat-spring/build.gradle",
    "content": "subprojects {\n    dependencies {\n        testCompile 'org.assertj:assertj-core:2.4.0'\n\n        testCompile (project(':comsat-test-utils')) {\n            exclude group: 'org.eclipse.jetty', module: '*'\n            exclude group: 'org.eclipse.jetty.websocket', module: '*'\n            exclude group: 'org.glassfish.jersey.core', module: '*'\n            exclude group: 'org.glassfish.jersey.media', module: '*'\n            exclude group: 'io.undertow', module: '*'\n            exclude group: 'com.h2database', module: '*'\n            exclude group: 'org.apache.tomcat', module: '*'\n            exclude group: 'org.apache.tomcat.embed', module: '*'\n            exclude group: 'org.apache.httpcomponents', module: '*'\n        }\n    }\n\n    if ('true' == \"$System.env.CI\") {\n        test {\n            useJUnit {\n                includeCategories 'co.paralleluniverse.test.categories.CI'\n            }\n        }\n    }\n}\n\nclasses.enabled = false\ninstall.enabled = false\nuploadArchives.enabled = false\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/build.gradle",
    "content": "subprojects {\n    install.enabled = false\n    uploadArchives.enabled = false\n}\n\ndependencies {\n    compile (\"org.springframework.boot:spring-boot-starter-web:$springBootVer\") {\n        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'\n    }\n    compile \"org.springframework.boot:spring-boot-starter:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-webmvc\")\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-jdbc:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-security:$springBootVer\"\n    compile \"com.h2database:h2:$h2Ver\"\n    compile project(\":comsat-spring:comsat-spring-boot-security\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/main/java/comsat/sample/actuator/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n\n    @Autowired\n    private ServiceProperties configuration;\n\n    public String getHelloMessage() {\n        return \"Hello \" + this.configuration.getName();\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/main/java/comsat/sample/actuator/SampleActuatorApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport co.paralleluniverse.springframework.boot.security.autoconfigure.web.FiberSecureSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.scheduling.annotation.EnableAsync;\n\n// snippet import\n// The following will enable fiber-blocking and will let fibers inherit security context\n@FiberSecureSpringBootApplication\n// end of snippet\n@EnableConfigurationProperties\n@EnableAsync\npublic class SampleActuatorApplication {\n    public static void main(String[] args) throws Exception, InterruptedException {\n        SpringApplication.run(SampleActuatorApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/main/java/comsat/sample/actuator/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport org.hibernate.validator.constraints.NotBlank;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Description;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.validation.annotation.Validated;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\n@Controller\n@Description(\"A controller for handling requests for hello messages\")\npublic class SampleController {\n\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(value = \"/helloThreadBlocking\", method = RequestMethod.GET)\n    @ResponseBody\n    public Map<String, String> helloThreadBlocking() {\n        return Collections.singletonMap(\"message\",\n                this.helloWorldService.getHelloMessage());\n    }\n\n    // snippet suspendable\n    @RequestMapping(value = \"/\", method = RequestMethod.GET)\n    @ResponseBody\n    public Map<String, String> hello() throws SuspendExecution, InterruptedException {\n        Fiber.sleep(10);\n        return Collections.singletonMap(\"message\",\n                this.helloWorldService.getHelloMessage());\n    }\n    // end of snippet\n\n    @RequestMapping(value = \"/\", method = RequestMethod.POST)\n    @ResponseBody\n    public Map<String, Object> olleh(@Validated Message message) throws SuspendExecution, InterruptedException {\n        Fiber.sleep(10);\n        Map<String, Object> model = new LinkedHashMap<>();\n        model.put(\"message\", message.getValue());\n        model.put(\"title\", \"Hello Home\");\n        model.put(\"date\", new Date());\n        return model;\n    }\n\n    @RequestMapping(\"/foo\")\n    @ResponseBody\n    public String foo() throws SuspendExecution, InterruptedException {\n        Fiber.sleep(10);\n        throw new IllegalArgumentException(\"Server error\");\n    }\n\n    protected static class Message {\n\n        @NotBlank(message = \"Message value cannot be empty\")\n        private String value;\n\n        public String getValue() {\n            return this.value;\n        }\n\n        public void setValue(String value) {\n            this.value = value;\n        }\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/main/java/comsat/sample/actuator/ServiceProperties.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.stereotype.Component;\n\n@ConfigurationProperties(prefix = \"service\", ignoreUnknownFields = false)\n@Component\npublic class ServiceProperties {\n\n    private String name = \"World\";\n\n    public String getName() {\n        return this.name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/main/resources/application.properties",
    "content": "logging.file: /tmp/logs/app.log\nlogging.level.org.springframework.security: INFO\nmanagement.address: 127.0.0.1\n#management.port: 8181\nendpoints.shutdown.enabled: true\nserver.tomcat.basedir: target/tomcat\nserver.tomcat.access_log_enabled: true\nserver.tomcat.access_log_pattern: %h %t \"%r\" %s %b\nsecurity.require_ssl: false\nservice.name: Phil\n#http.mappers.json_pretty_print: true\nshell.ssh.enabled: true\nshell.ssh.port: 2222\n#shell.telnet.enabled: false\n#shell.telnet.port: 1111\nshell.auth: spring\n#shell.auth: key\n#shell.auth.key.path: ${user.home}/test/id_rsa.pub.pem\n#shell.auth: simple\nspring.jmx.enabled: true\n\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/test/java/comsat/sample/actuator/SampleActuatorApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport co.paralleluniverse.test.categories.CI;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.Test;\nimport org.junit.experimental.categories.Category;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\n/**\n * Basic integration tests for service demo application.\n *\n * @author Dave Syer\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleActuatorApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleActuatorApplicationTests {\n    @Autowired\n    private SecurityProperties security;\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHomeIsSecure() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port, Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"Wrong body: \" + body, \"Unauthorized\", body.get(\"error\"));\n        assertFalse(\"Wrong headers: \" + entity.getHeaders(), entity.getHeaders().containsKey(\"Set-Cookie\"));\n    }\n\n    @Test\n    public void testMetricsIsSecure() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/metrics\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n        entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/metrics/\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n        entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/metrics/foo\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n        entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/metrics.json\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n    }\n\n    @Test\n    public void testHome() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate(\"user\", getPassword()).getForEntity(\"http://localhost:\" + this.port, Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"Hello Phil\", body.get(\"message\"));\n    }\n\n    @Test\n    public void testHomeThreadBlocking() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate(\"user\", getPassword()).getForEntity(\"http://localhost:\" + this.port + \"/helloThreadBlocking\", Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"Hello Phil\", body.get(\"message\"));\n    }\n\n    @Test\n    public void testMetrics() throws Exception {\n        testHome(); // makes sure some requests have been made\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate(\"user\", getPassword()).getForEntity(\"http://localhost:\" + this.port + \"/metrics\", Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertTrue(\"Wrong body: \" + body, body.containsKey(\"counter.status.200.root\"));\n    }\n\n    @Test\n    public void testEnv() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate(\"user\", getPassword()).getForEntity(\"http://localhost:\" + this.port + \"/env\", Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertTrue(\"Wrong body: \" + body, body.containsKey(\"systemProperties\"));\n    }\n\n    @Test\n    public void testHealth() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/health\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body: \" + entity.getBody(), entity.getBody().contains(\"\\\"status\\\":\\\"UP\\\"\"));\n    }\n\n    @Test\n    public void testErrorPage() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate(\"user\", getPassword()).getForEntity(\"http://localhost:\" + this.port + \"/foo\", String.class);\n        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode());\n        String body = entity.getBody();\n        assertNotNull(body);\n        assertTrue(\"Wrong body: \" + body, body.contains(\"\\\"error\\\":\"));\n    }\n\n    @Test\n    public void testHtmlErrorPage() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        HttpEntity<?> request = new HttpEntity<>(headers);\n        ResponseEntity<String> entity = new TestRestTemplate(\"user\", getPassword()).exchange(\"http://localhost:\" + this.port + \"/foo\", HttpMethod.GET, request, String.class);\n        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode());\n        String body = entity.getBody();\n        assertNotNull(\"Body was null\", body);\n        assertTrue(\"Wrong body: \" + body, body.contains(\"This application has no explicit mapping for /error\"));\n    }\n\n    @Test\n    public void testTrace() throws Exception {\n        new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/health\", String.class);\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<List> entity = new TestRestTemplate(\"user\", getPassword()).getForEntity(\"http://localhost:\" + this.port + \"/trace\", List.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        List<Map<String, Object>> list = entity.getBody();\n        Map<String, Object> trace = list.get(list.size() - 1);\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> map = (Map<String, Object>) ((Map<String, Object>) ((Map<String, Object>) trace.get(\"info\")).get(\"headers\")).get(\"response\");\n        assertEquals(\"200\", map.get(\"status\"));\n    }\n\n    @Test\n    public void testErrorPageDirectAccess() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/error\", Map.class);\n        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"None\", body.get(\"error\"));\n        assertEquals(999, body.get(\"status\"));\n    }\n\n    @Test\n    public void testBeans() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<List> entity = new TestRestTemplate(\"user\", getPassword()).getForEntity(\"http://localhost:\" + this.port + \"/beans\", List.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(1, entity.getBody().size());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = (Map<String, Object>) entity.getBody().get(0);\n        assertTrue(\"Wrong body: \" + body, ((String) body.get(\"context\")).startsWith(\"application\"));\n    }\n\n    private String getPassword() {\n        return this.security.getUser().getPassword();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/test/resources/application-endpoints.properties",
    "content": "error.path: /oops\nmanagement.contextPath: /admin"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-async/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-jdbc:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-security:$springBootVer\"\n    compile \"com.h2database:h2:$h2Ver\"\n    compile project(\":comsat-spring:comsat-spring-boot-security\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-async/src/main/java/comsat/sample/actuator/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n\n    @Autowired\n    private ServiceProperties configuration;\n\n    public String getHelloMessage() {\n        return \"Hello \" + this.configuration.getName();\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-async/src/main/java/comsat/sample/actuator/SampleActuatorApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport co.paralleluniverse.springframework.boot.security.autoconfigure.web.FiberSecureSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.scheduling.annotation.EnableAsync;\n\n// The following will enable fiber-blocking and will let fibers inherit security context\n@FiberSecureSpringBootApplication\n@EnableConfigurationProperties\n@EnableAsync\npublic class SampleActuatorApplication {\n    public static void main(String[] args) throws Exception, InterruptedException {\n        SpringApplication.run(SampleActuatorApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-async/src/main/java/comsat/sample/actuator/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.strands.SuspendableCallable;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.concurrent.Callable;\nimport org.hibernate.validator.constraints.NotBlank;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Description;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.validation.annotation.Validated;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.context.request.async.DeferredResult;\n\n@Controller\n@Description(\"A controller for handling requests for hello messages\")\npublic class SampleController {\n\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    private Callable<Map<String, String>> helloCallable(final DeferredResult<Map<String, String>> optDeferred) throws SuspendExecution {\n        return new Callable<Map<String, String>>() {\n            @Override\n            @Suspendable\n            public Map<String, String> call() throws Exception {\n                try {\n                    Fiber.sleep(10);\n                    Map<String, String> ret = Collections.singletonMap(\"message\", helloWorldService.getHelloMessage());\n                    if (optDeferred != null) optDeferred.setResult(ret);\n                    return ret;\n                } catch (Throwable t) {\n                    if (optDeferred != null) optDeferred.setErrorResult(t);\n                    throw t;\n                }\n            }\n        };\n    }\n    \n    @RequestMapping(value = \"/callable\", method = RequestMethod.GET)\n    @ResponseBody\n    public Callable<Map<String, String>> helloCallable() throws SuspendExecution {\n        return helloCallable(null);\n    }\n    \n    @RequestMapping(value = \"/deferred\", method = RequestMethod.GET)\n    @ResponseBody\n    public DeferredResult<Map<String, String>> helloDeferred() {\n        final DeferredResult<Map<String, String>> ret = new DeferredResult<>();\n        new Fiber(new SuspendableCallable<Map<String, String>>() {\n            @Override\n            public Map<String, String> run() throws SuspendExecution, InterruptedException {\n                try {\n                    return helloCallable(ret).call();\n                } catch (Exception ex) {\n                    ret.setErrorResult(ret);\n                    throw new RuntimeException(ex);\n                }\n            }\n        }).start();\n        return ret;\n    }\n    \n    private Callable<Map<String, Object>> ollehCallable(final Message message, final DeferredResult<Map<String, Object>> optDeferred) throws SuspendExecution {\n        return new Callable<Map<String, Object>>() {\n            @Override\n            @Suspendable\n            public Map<String, Object> call() throws Exception {\n                try {\n                    Fiber.sleep(10);\n                    Map<String, Object> model = new LinkedHashMap<>();\n                    model.put(\"message\", message.getValue());\n                    model.put(\"title\", \"Hello Home\");\n                    model.put(\"date\", new Date());\n                    if (optDeferred != null) optDeferred.setResult(model);\n                    return model;\n                } catch (Throwable t) {\n                    if (optDeferred != null) optDeferred.setErrorResult(t);\n                    throw t;\n                }\n            }\n        };\n    }\n    \n    @RequestMapping(value = \"/callable\", method = RequestMethod.POST)\n    @ResponseBody\n    public Callable<Map<String, Object>> ollehCallable(final Message message) throws SuspendExecution {\n        return ollehCallable(message, null);\n    }\n    \n    @RequestMapping(value = \"/deferred\", method = RequestMethod.POST)\n    @ResponseBody\n    public DeferredResult<Map<String, Object>> ollehDeferred(@Validated final Message message) {\n        final DeferredResult<Map<String, Object>> ret = new DeferredResult<>();\n        new Fiber(new SuspendableCallable<Map<String, Object>>() {\n            @Override\n            public Map<String, Object> run() throws SuspendExecution, InterruptedException {\n                try {\n                    return ollehCallable(message, ret).call();\n                } catch (Exception ex) {\n                    ret.setErrorResult(ret);\n                    throw new RuntimeException(ex);\n                }\n            }\n        }).start();\n        return ret;\n    }\n\n    private Callable<String> fooCallable(final DeferredResult<String> optDeferred) throws SuspendExecution {\n        return new Callable<String>() {\n            @Override\n            @Suspendable\n            public String call() throws Exception {\n                try {\n                    Fiber.sleep(10);\n                    throw new IllegalArgumentException(\"Server error\");\n                } catch (Throwable t) {\n                    if (optDeferred != null) optDeferred.setErrorResult(t);\n                    throw t;\n                }\n            }\n        };\n    }\n    \n    @RequestMapping(\"/callable/foo\")\n    @ResponseBody\n    public Callable<String> fooCallable() throws SuspendExecution {\n        return fooCallable(null);\n    }\n    \n    @RequestMapping(\"/deferred/foo\")\n    @ResponseBody\n    public DeferredResult<String> fooDeferred() {\n        final DeferredResult<String> ret = new DeferredResult<>();\n        new Fiber(new SuspendableCallable<String>() {\n            @Override\n            public String run() throws SuspendExecution, InterruptedException {\n                try {\n                    return fooCallable(ret).call();\n                } catch (Exception ex) {\n                    ret.setErrorResult(ret);\n                    throw new RuntimeException(ex);\n                }\n            }\n        }).start();\n        return ret;\n    }\n\n    protected static class Message {\n\n        @NotBlank(message = \"Message value cannot be empty\")\n        private String value;\n\n        public String getValue() {\n            return this.value;\n        }\n\n        public void setValue(String value) {\n            this.value = value;\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-async/src/main/java/comsat/sample/actuator/ServiceProperties.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.stereotype.Component;\n\n@ConfigurationProperties(prefix = \"service\", ignoreUnknownFields = false)\n@Component\npublic class ServiceProperties {\n\n    private String name = \"World\";\n\n    public String getName() {\n        return this.name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-async/src/main/resources/application.properties",
    "content": "logging.file: /tmp/logs/app.log\nlogging.level.org.springframework.security: INFO\nmanagement.address: 127.0.0.1\n#management.port: 8181\nendpoints.shutdown.enabled: true\nserver.tomcat.basedir: target/tomcat\nserver.tomcat.access_log_enabled: true\nserver.tomcat.access_log_pattern: %h %t \"%r\" %s %b\nsecurity.require_ssl: false\nservice.name: Phil\n#http.mappers.json_pretty_print: true\nshell.ssh.enabled: true\nshell.ssh.port: 2222\n#shell.telnet.enabled: false\n#shell.telnet.port: 1111\nshell.auth: spring\n#shell.auth: key\n#shell.auth.key.path: ${user.home}/test/id_rsa.pub.pem\n#shell.auth: simple\nspring.jmx.enabled: true\n\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-async/src/test/java/comsat/sample/actuator/SampleActuatorApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator;\n\nimport co.paralleluniverse.test.categories.CI;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.Test;\nimport org.junit.experimental.categories.Category;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\n/**\n * Basic integration tests for service demo application.\n *\n * @author Dave Syer\n * @author circlespainter\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleActuatorApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleActuatorApplicationTests {\n\n    @Autowired\n    private SecurityProperties security;\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    private String emptyIfNull(String s) {\n        return (s != null ? s : \"\");\n    }\n    \n    private void testHomeIsSecure(final String path) throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/\" + emptyIfNull(path), Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"Wrong body: \" + body, \"Unauthorized\", body.get(\"error\"));\n        assertFalse(\"Wrong headers: \" + entity.getHeaders(), entity.getHeaders()\n                .containsKey(\"Set-Cookie\"));\n    }\n    \n    @Test\n    public void testHomeIsSecureDeferred() throws Exception {\n        testHomeIsSecure(\"deferred\");\n    }\n\n    @Test\n    public void testHomeIsSecureCallable() throws Exception {\n        testHomeIsSecure(\"callable\");\n    }\n\n    @Test\n    public void testMetricsIsSecure() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/metrics\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n        entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port\n                + \"/metrics/\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n        entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port\n                + \"/metrics/foo\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n        entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port\n                + \"/metrics.json\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n    }\n\n    private void testHome(final String path) throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate(\"user\", getPassword())\n                .getForEntity(\"http://localhost:\" + this.port + \"/\" + emptyIfNull(path), Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"Hello Phil\", body.get(\"message\"));\n    }\n    \n    @Test\n    public void testHomeDeferred() throws Exception {\n        testHome(\"deferred\");\n    }\n\n    @Test\n    public void testHomeCallable() throws Exception {\n        testHome(\"callable\");\n    }\n\n    @Test\n    public void testMetrics() throws Exception {\n        testHomeCallable(); // makes sure some requests have been made\n        testHomeDeferred(); // makes sure some requests have been made\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate(\"user\", getPassword())\n                .getForEntity(\"http://localhost:\" + this.port + \"/metrics\", Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertTrue(\"Wrong body: \" + body, body.containsKey(\"counter.status.200.callable\"));\n        assertTrue(\"Wrong body: \" + body, body.containsKey(\"counter.status.200.deferred\"));\n    }\n\n    @Test\n    public void testEnv() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate(\"user\", getPassword())\n                .getForEntity(\"http://localhost:\" + this.port + \"/env\", Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertTrue(\"Wrong body: \" + body, body.containsKey(\"systemProperties\"));\n    }\n\n    @Test\n    public void testHealth() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/health\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body: \" + entity.getBody(),\n                entity.getBody().contains(\"\\\"status\\\":\\\"UP\\\"\"));\n    }\n\n    private void testErrorPage(final String path) throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate(\"user\", getPassword())\n                .getForEntity(\"http://localhost:\" + this.port + \"/\" + emptyIfNull(path) + \"/foo\", String.class);\n        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode());\n        String body = entity.getBody();\n        assertNotNull(body);\n        assertTrue(\"Wrong body: \" + body, body.contains(\"\\\"error\\\":\"));\n    }\n\n    @Test\n    public void testErrorPageDeferred() throws Exception {\n        testErrorPage(\"deferred\");\n    }\n\n    @Test\n    public void testErrorPageCallable() throws Exception {\n        testErrorPage(\"callable\");\n    }\n\n    private void testHtmlErrorPage(final String path) throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        HttpEntity<?> request = new HttpEntity<Void>(headers);\n        ResponseEntity<String> entity = new TestRestTemplate(\"user\", getPassword())\n                .exchange(\"http://localhost:\" + this.port + \"/\" + emptyIfNull(path) + \"/foo\", HttpMethod.GET,\n                        request, String.class);\n        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode());\n        String body = entity.getBody();\n        assertNotNull(\"Body was null\", body);\n        assertTrue(\"Wrong body: \" + body,\n                body.contains(\"This application has no explicit mapping for /error\"));\n    }\n\n    @Test\n    public void testHtmlErrorPageDeferred() throws Exception {\n        testHtmlErrorPage(\"deferred\");\n    }\n\n    @Test\n    public void testHtmlErrorPageCallable() throws Exception {\n        testHtmlErrorPage(\"callable\");\n    }\n\n    @Test\n    public void testTrace() throws Exception {\n        new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/health\",\n                String.class);\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<List> entity = new TestRestTemplate(\"user\", getPassword())\n                .getForEntity(\"http://localhost:\" + this.port + \"/trace\", List.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        List<Map<String, Object>> list = entity.getBody();\n        Map<String, Object> trace = list.get(list.size() - 1);\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> map = (Map<String, Object>) ((Map<String, Object>) ((Map<String, Object>) trace\n                .get(\"info\")).get(\"headers\")).get(\"response\");\n        assertEquals(\"200\", map.get(\"status\"));\n    }\n\n    @Test\n    public void testErrorPageDirectAccess() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/error\", Map.class);\n        assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"None\", body.get(\"error\"));\n        assertEquals(999, body.get(\"status\"));\n    }\n\n    @Test\n    public void testBeans() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<List> entity = new TestRestTemplate(\"user\", getPassword())\n                .getForEntity(\"http://localhost:\" + this.port + \"/beans\", List.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(1, entity.getBody().size());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = (Map<String, Object>) entity.getBody().get(0);\n        assertTrue(\"Wrong body: \" + body,\n                ((String) body.get(\"context\")).startsWith(\"application\"));\n    }\n\n    private String getPassword() {\n        return this.security.getUser().getPassword();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-async/src/test/resources/application-endpoints.properties",
    "content": "error.path: /oops\nmanagement.contextPath: /admin"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j/build.gradle",
    "content": "dependencies {\n    compile(\"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\") {\n        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'\n    }\n    compile(\"org.springframework.boot:spring-boot-starter-log4j:$springBootVer\") {\n        exclude group: 'org.slf4j', module: 'slf4j-log4j12'\n    }\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile(\"org.springframework.boot:spring-boot-starter-test:$springBootVer\") {\n        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging' \n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j/src/main/java/comsat/sample/actuator/log4j/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n\n    @Autowired\n    private ServiceProperties configuration;\n\n    public String getHelloMessage() {\n        return \"Hello \" + this.configuration.getName();\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j/src/main/java/comsat/sample/actuator/log4j/SampleActuatorApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.scheduling.annotation.EnableAsync;\n\n@FiberSpringBootApplication\n@EnableConfigurationProperties\n@EnableAsync\npublic class SampleActuatorApplication {\n    public static void main(String[] args) throws Exception, InterruptedException {\n        SpringApplication.run(SampleActuatorApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j/src/main/java/comsat/sample/actuator/log4j/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Collections;\nimport java.util.Map;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\n@Controller\npublic class SampleController {\n\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public Map<String, String> helloWorld() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return Collections.singletonMap(\"message\",\n                this.helloWorldService.getHelloMessage());\n    }\n\n    @RequestMapping(\"/foo\")\n    @ResponseBody\n    public String foo() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new IllegalArgumentException(\"Server error\");\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j/src/main/java/comsat/sample/actuator/log4j/ServiceProperties.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.stereotype.Component;\n\n@ConfigurationProperties(prefix = \"service\", ignoreUnknownFields = false)\n@Component\npublic class ServiceProperties {\n\n    private String name = \"World\";\n\n    public String getName() {\n        return this.name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j/src/main/resources/application.properties",
    "content": "logging.file: /tmp/logs/app.log\n#server.port: 8080\n#management.port: 8080\nmanagement.address: 127.0.0.1\nendpoints.shutdown.enabled: true\nserver.tomcat.basedir: target/tomcat\nserver.tomcat.access_log_pattern: %h %t \"%r\" %s %b\nsecurity.require_ssl: false\nservice.name: Phil\nshell.ssh.enabled: true\nshell.ssh.port: 2222\n#shell.telnet.enabled: false\n#shell.telnet.port: 1111\nshell.auth: spring\n#shell.auth: key\n#shell.auth.key.path: ${user.home}/test/id_rsa.pub.pem\n#shell.auth: simple\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j/src/main/resources/log4j.properties",
    "content": "log4j.rootCategory=INFO, CONSOLE\n\nPID=????\nLOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] log4j%X{context} - ${PID} %5p [%t] --- %c{1}: %m%n\n\n# CONSOLE is set to be a ConsoleAppender using a PatternLayout.\nlog4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender\nlog4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout\nlog4j.appender.CONSOLE.layout.ConversionPattern=${LOG_PATTERN}\n\nlog4j.category.org.hibernate.validator.internal.util.Version=WARN\nlog4j.category.org.apache.coyote.http11.Http11NioProtocol=WARN\nlog4j.category.org.apache.tomcat.util.net.NioSelectorPool=WARN\nlog4j.category.org.apache.catalina.startup.DigesterFactory=ERROR\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j/src/test/java/comsat/sample/actuator/log4j/SampleActuatorApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j;\n\nimport java.util.Map;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\n/**\n * Basic integration tests for service demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleActuatorApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleActuatorApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + port, Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"Hello Phil\", body.get(\"message\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j2/build.gradle",
    "content": "dependencies {\n    compile(\"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\") {\n        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'\n    }\n    compile(\"org.springframework.boot:spring-boot-starter-log4j:$springBootVer\") {\n        exclude group: 'org.slf4j', module: 'slf4j-log4j12'\n    }\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile(\"org.springframework.boot:spring-boot-starter-test:$springBootVer\") {\n        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging' \n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j2/src/main/java/comsat/sample/actuator/log4j2/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j2;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n    @Autowired\n    private ServiceProperties configuration;\n\n    public String getHelloMessage() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"Hello \" + this.configuration.getName();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j2/src/main/java/comsat/sample/actuator/log4j2/SampleActuatorLog4J2Application.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j2;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.scheduling.annotation.EnableAsync;\n\n@FiberSpringBootApplication\n@EnableConfigurationProperties\n@EnableAsync\npublic class SampleActuatorLog4J2Application {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleActuatorLog4J2Application.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j2/src/main/java/comsat/sample/actuator/log4j2/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j2;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Collections;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\n@Controller\npublic class SampleController {\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public Map<String, String> helloWorld() throws InterruptedException, SuspendExecution {\n        return Collections.singletonMap(\"message\", this.helloWorldService.getHelloMessage());\n    }\n\n    @RequestMapping(\"/foo\")\n    @ResponseBody\n    public String foo() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new IllegalArgumentException(\"Server error\");\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j2/src/main/java/comsat/sample/actuator/log4j2/ServiceProperties.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j2;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.stereotype.Component;\n\n@ConfigurationProperties(prefix = \"service\", ignoreUnknownFields = false)\n@Component\npublic class ServiceProperties {\n    private String name = \"World\";\n\n    public String getName() {\n            return this.name;\n    }\n\n    public void setName(String name) {\n            this.name = name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j2/src/main/resources/application.properties",
    "content": "#logging.file: /tmp/logs/app.log\n#server.port: 8080\n#management.port: 8080\nmanagement.address: 127.0.0.1\nendpoints.shutdown.enabled: true\nserver.tomcat.basedir: target/tomcat\nserver.tomcat.access_log_pattern: %h %t \"%r\" %s %b\nsecurity.require_ssl: false\nservice.name: Daniel\nshell.ssh.enabled: true\nshell.ssh.port: 2222\n#shell.telnet.enabled: false\n#shell.telnet.port: 1111\nshell.auth: spring\n#shell.auth: key\n#shell.auth.key.path: ${user.home}/test/id_rsa.pub.pem\n#shell.auth: simple\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j2/src/main/resources/log4j2.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Configuration status=\"WARN\">\n    <Properties>\n        <Property name=\"PID\">????</Property>\n        <Property name=\"LOG_PATTERN\">[%d{yyyy-MM-dd HH:mm:ss.SSS}] log4j2%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n</Property>\n    </Properties>\n    <Appenders>\n        <Console name=\"Console\" target=\"SYSTEM_OUT\" follow=\"true\">\n            <PatternLayout pattern=\"${LOG_PATTERN}\"/>\n        </Console>\n    </Appenders>\n    <Loggers>\n        <Logger name=\"org.hibernate.validator.internal.util.Version\" level=\"warn\" />\n        <Logger name=\"org.apache.coyote.http11.Http11NioProtocol\" level=\"warn\" />\n        <Logger name=\"org.apache.tomcat.util.net.NioSelectorPool\" level=\"warn\" />\n        <Logger name=\"org.apache.catalina.startup.DigesterFactory\" level=\"error\" />\n\n        <Root level=\"info\">\n            <AppenderRef ref=\"Console\"/>\n        </Root>\n    </Loggers>\n</Configuration>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-log4j2/src/test/java/comsat/sample/actuator/log4j2/SampleActuatorApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.log4j2;\n\nimport java.util.Map;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * Basic integration tests for service demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleActuatorLog4J2Application.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleActuatorApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + port, Map.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        @SuppressWarnings(\"unchecked\")\n        Map<String, Object> body = entity.getBody();\n        assertEquals(\"Hello Daniel\", body.get(\"message\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-ui/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-freemarker:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-security:$springBootVer\"\n    compile \"org.jolokia:jolokia-core:$jolokiaVer\"\n    compile project(\":comsat-spring:comsat-spring-boot-security\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-ui/src/main/java/comsat/sample/actuator/ui/SampleActuatorUiApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.ui;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.springframework.boot.security.autoconfigure.web.FiberSecureSpringBootApplication;\nimport java.util.Date;\nimport java.util.Map;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@Controller\n@FiberSecureSpringBootApplication\npublic class SampleActuatorUiApplication {\n    @RequestMapping(\"/\")\n    public String home(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"message\", \"Hello World\");\n        model.put(\"title\", \"Hello Home\");\n        model.put(\"date\", new Date());\n        return \"home\";\n    }\n\n    @RequestMapping(\"/foo\")\n    public String foo() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new RuntimeException(\"Expected exception in controller\");\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleActuatorUiApplication.class, args);\n    }\n\n    @Bean\n    public SecurityProperties securityProperties() {\n        SecurityProperties security = new SecurityProperties();\n        security.getBasic().setPath(\"\"); // empty so home page is unsecured\n        return security;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-ui/src/main/resources/templates/error.ftl",
    "content": "<#import \"/spring.ftl\" as spring />\n<!DOCTYPE html>\n<html>\n<head>\n<title>Error</title>\n<#assign home><@spring.url relativeUrl=\"/\"/></#assign>\n<#assign bootstrap><@spring.url relativeUrl=\"/css/bootstrap.min.css\"/></#assign>\n<link rel=\"stylesheet\" href=\"${bootstrap}\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Freemarker -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a href=\"${home}\"> Home </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1>Error Page</h1>\n\t\t<div id=\"created\">${timestamp?datetime}</div>\n\t\t<div>\n\t\t\tThere was an unexpected error (type=${error}, status=${status}).\n\t\t</div>\n\t\t<div>${message}</div>\n\t\t<div>\n\t\t\tPlease contact the operator with the above information.\n\t\t</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-ui/src/main/resources/templates/home.ftl",
    "content": "<#import \"/spring.ftl\" as spring />\n<!DOCTYPE html>\n<html>\n<head>\n<title>${title}</title>\n<#assign home><@spring.url relativeUrl=\"/\"/></#assign>\n<#assign bootstrap><@spring.url relativeUrl=\"/css/bootstrap.min.css\"/></#assign>\n<link rel=\"stylesheet\" href=\"${bootstrap}\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Freemarker -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a href=\"${home}\"> Home </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1>${title}</h1>\n\t\t<div>${message}</div>\n\t\t<div id=\"created\">${date?datetime}</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-ui/src/test/java/comsat/sample/actuator/ui/SampleActuatorUiApplicationPortTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.ui;\n\nimport java.util.Map;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\n/**\n * Integration tests for separate management and main service ports.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleActuatorUiApplication.class)\n@WebAppConfiguration\n@IntegrationTest({\"server.port=0\", \"management.port:0\"})\n@DirtiesContext\npublic class SampleActuatorUiApplicationPortTests {\n\n    @Autowired\n    private SecurityProperties security;\n\n    @Value(\"${local.server.port}\")\n    private int port = 9010;\n\n    @Value(\"${local.management.port}\")\n    private int managementPort = 9011;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n    }\n\n    @Test\n    public void testMetrics() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.managementPort + \"/metrics\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n    }\n\n    @Test\n    public void testHealth() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.managementPort + \"/health\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"{\\\"status\\\":\\\"UP\\\"}\", entity.getBody());\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator-ui/src/test/java/comsat/sample/actuator/ui/SampleActuatorUiApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.actuator.ui;\n\nimport java.util.Arrays;\nimport java.util.Map;\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleActuatorUiApplication.class)\n@IntegrationTest(\"server.port=0\")\n@WebAppConfiguration\n@DirtiesContext\npublic class SampleActuatorUiApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port, HttpMethod.GET, new HttpEntity<Void>(\n                        headers), String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body (title doesn't match):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"<title>Hello\"));\n    }\n\n    @Test\n    public void testCss() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/css/bootstrap.min.css\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"body\"));\n    }\n\n    @Test\n    public void testMetrics() throws Exception {\n        @SuppressWarnings(\"rawtypes\")\n        ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/metrics\", Map.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n    }\n\n    @Test\n    public void testError() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n            \"http://localhost:\" + this.port + \"/error\", HttpMethod.GET,\n            new HttpEntity<Void>(headers), String.class);\n        assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);\n        assertThat(entity.getBody()).contains(\"<html>\").contains(\"<body>\")\n            .contains(\"Please contact the operator with the above information\");\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-data-jpa:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n    runtime \"org.hsqldb:hsqldb:$hsqlVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/SampleDataJpaApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleDataJpaApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleDataJpaApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/domain/City.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.domain;\n\nimport java.io.Serializable;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\n\n@Entity\npublic class City implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @Column(nullable = false)\n    private String name;\n\n    @Column(nullable = false)\n    private String state;\n\n    @Column(nullable = false)\n    private String country;\n\n    @Column(nullable = false)\n    private String map;\n\n    protected City() {\n    }\n\n    public City(String name, String country) {\n        super();\n        this.name = name;\n        this.country = country;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getState() {\n        return this.state;\n    }\n\n    public String getCountry() {\n        return this.country;\n    }\n\n    public String getMap() {\n        return this.map;\n    }\n\n    @Override\n    public String toString() {\n        return getName() + \",\" + getState() + \",\" + getCountry();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/domain/Hotel.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.domain;\n\nimport java.io.Serializable;\nimport java.util.Set;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.FetchType;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport javax.persistence.ManyToOne;\nimport javax.persistence.OneToMany;\n\nimport org.hibernate.annotations.NaturalId;\n\n@Entity\npublic class Hotel implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @ManyToOne(optional = false)\n    @NaturalId\n    private City city;\n\n    @Column(nullable = false)\n    @NaturalId\n    private String name;\n\n    @Column(nullable = false)\n    private String address;\n\n    @Column(nullable = false)\n    private String zip;\n\n    @OneToMany(fetch = FetchType.LAZY, mappedBy = \"hotel\")\n    private Set<Review> reviews;\n\n    protected Hotel() {\n    }\n\n    public Hotel(City city, String name) {\n        this.city = city;\n        this.name = name;\n    }\n\n    public City getCity() {\n        return this.city;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getAddress() {\n        return this.address;\n    }\n\n    public String getZip() {\n        return this.zip;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/domain/HotelSummary.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.domain;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.math.MathContext;\nimport java.math.RoundingMode;\n\npublic class HotelSummary implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private static final MathContext MATH_CONTEXT = new MathContext(2,\n            RoundingMode.HALF_UP);\n\n    private final City city;\n\n    private final String name;\n\n    private final Double averageRating;\n\n    private final Integer averageRatingRounded;\n\n    public HotelSummary(City city, String name, Double averageRating) {\n        this.city = city;\n        this.name = name;\n        this.averageRating = averageRating == null ? null : new BigDecimal(averageRating,\n                MATH_CONTEXT).doubleValue();\n        this.averageRatingRounded = averageRating == null ? null : (int) Math\n                .round(averageRating);\n    }\n\n    public City getCity() {\n        return this.city;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public Double getAverageRating() {\n        return this.averageRating;\n    }\n\n    public Integer getAverageRatingRounded() {\n        return this.averageRatingRounded;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/domain/Rating.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.domain;\n\npublic enum Rating {\n    TERRIBLE, POOR, AVERAGE, GOOD, EXCELLENT,\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/domain/RatingCount.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.domain;\n\nimport java.io.Serializable;\n\npublic class RatingCount implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private final Rating rating;\n\n    private final long count;\n\n    public RatingCount(Rating rating, long count) {\n        this.rating = rating;\n        this.count = count;\n    }\n\n    public Rating getRating() {\n        return this.rating;\n    }\n\n    public long getCount() {\n        return this.count;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/domain/Review.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.domain;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\nimport javax.persistence.Column;\nimport javax.persistence.Entity;\nimport javax.persistence.EnumType;\nimport javax.persistence.Enumerated;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.Id;\nimport javax.persistence.ManyToOne;\nimport javax.persistence.Temporal;\nimport javax.persistence.TemporalType;\n\nimport org.springframework.util.Assert;\n\n@Entity\npublic class Review implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    @Id\n    @GeneratedValue\n    private Long id;\n\n    @ManyToOne(optional = false)\n    private Hotel hotel;\n\n    @Column(nullable = false, name = \"idx\")\n    private int index;\n\n    @Column(nullable = false)\n    @Enumerated(EnumType.ORDINAL)\n    private Rating rating;\n\n    @Column(nullable = false)\n    @Temporal(TemporalType.DATE)\n    private Date checkInDate;\n\n    @Column(nullable = false)\n    @Enumerated(EnumType.ORDINAL)\n    private TripType tripType;\n\n    @Column(nullable = false)\n    private String title;\n\n    @Column(nullable = false, length = 5000)\n    private String details;\n\n    protected Review() {\n    }\n\n    public Review(Hotel hotel, int index, ReviewDetails details) {\n        Assert.notNull(hotel, \"Hotel must not be null\");\n        Assert.notNull(details, \"Details must not be null\");\n        this.hotel = hotel;\n        this.index = index;\n        this.rating = details.getRating();\n        this.checkInDate = details.getCheckInDate();\n        this.tripType = details.getTripType();\n        this.title = details.getTitle();\n        this.details = details.getDetails();\n    }\n\n    public Hotel getHotel() {\n        return this.hotel;\n    }\n\n    public int getIndex() {\n        return this.index;\n    }\n\n    public Rating getRating() {\n        return this.rating;\n    }\n\n    public void setRating(Rating rating) {\n        this.rating = rating;\n    }\n\n    public Date getCheckInDate() {\n        return this.checkInDate;\n    }\n\n    public void setCheckInDate(Date checkInDate) {\n        this.checkInDate = checkInDate;\n    }\n\n    public TripType getTripType() {\n        return this.tripType;\n    }\n\n    public void setTripType(TripType tripType) {\n        this.tripType = tripType;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public String getDetails() {\n        return this.details;\n    }\n\n    public void setDetails(String details) {\n        this.details = details;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/domain/ReviewDetails.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.domain;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\npublic class ReviewDetails implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private Rating rating;\n\n    private Date checkInDate;\n\n    private TripType tripType;\n\n    private String title;\n\n    private String details;\n\n    public ReviewDetails() {\n    }\n\n    public Rating getRating() {\n        return this.rating;\n    }\n\n    public void setRating(Rating rating) {\n        this.rating = rating;\n    }\n\n    public Date getCheckInDate() {\n        return this.checkInDate;\n    }\n\n    public void setCheckInDate(Date checkInDate) {\n        this.checkInDate = checkInDate;\n    }\n\n    public TripType getTripType() {\n        return this.tripType;\n    }\n\n    public void setTripType(TripType tripType) {\n        this.tripType = tripType;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public String getDetails() {\n        return this.details;\n    }\n\n    public void setDetails(String details) {\n        this.details = details;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/domain/TripType.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.domain;\n\npublic enum TripType {\n    BUSINESS, COUPLES, FAMILY, FRIENDS, SOLO\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/CityRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.repository.Repository;\n\nimport comsat.sample.data.jpa.domain.City;\n\ninterface CityRepository extends Repository<City, Long> {\n\n    Page<City> findAll(Pageable pageable);\n\n    Page<City> findByNameContainingAndCountryContainingAllIgnoringCase(String name,\n            String country, Pageable pageable);\n\n    City findByNameAndCountryAllIgnoringCase(String name, String country);\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/CitySearchCriteria.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport java.io.Serializable;\n\nimport org.springframework.util.Assert;\n\npublic class CitySearchCriteria implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private String name;\n\n    public CitySearchCriteria() {\n    }\n\n    public CitySearchCriteria(String name) {\n        Assert.notNull(name, \"Name must not be null\");\n        this.name = name;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/CityService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\n\nimport comsat.sample.data.jpa.domain.City;\nimport comsat.sample.data.jpa.domain.HotelSummary;\n\npublic interface CityService {\n\n    Page<City> findCities(CitySearchCriteria criteria, Pageable pageable);\n\n    City getCity(String name, String country);\n\n    Page<HotelSummary> getHotels(City city, Pageable pageable);\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/CityServiceImpl.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.Assert;\nimport org.springframework.util.StringUtils;\n\nimport comsat.sample.data.jpa.domain.City;\nimport comsat.sample.data.jpa.domain.HotelSummary;\n\n@Component(\"cityService\")\n@Transactional\nclass CityServiceImpl implements CityService {\n\n    private final CityRepository cityRepository;\n\n    private final HotelRepository hotelRepository;\n\n    @Autowired\n    public CityServiceImpl(CityRepository cityRepository, HotelRepository hotelRepository) {\n        this.cityRepository = cityRepository;\n        this.hotelRepository = hotelRepository;\n    }\n\n    @Override\n    public Page<City> findCities(CitySearchCriteria criteria, Pageable pageable) {\n\n        Assert.notNull(criteria, \"Criteria must not be null\");\n        String name = criteria.getName();\n\n        if (!StringUtils.hasLength(name)) {\n            return this.cityRepository.findAll(null);\n        }\n\n        String country = \"\";\n        int splitPos = name.lastIndexOf(\",\");\n\n        if (splitPos >= 0) {\n            country = name.substring(splitPos + 1);\n            name = name.substring(0, splitPos);\n        }\n\n        return this.cityRepository\n                .findByNameContainingAndCountryContainingAllIgnoringCase(name.trim(),\n                        country.trim(), pageable);\n    }\n\n    @Override\n    public City getCity(String name, String country) {\n        Assert.notNull(name, \"Name must not be null\");\n        Assert.notNull(country, \"Country must not be null\");\n        return this.cityRepository.findByNameAndCountryAllIgnoringCase(name, country);\n    }\n\n    @Override\n    public Page<HotelSummary> getHotels(City city, Pageable pageable) {\n        Assert.notNull(city, \"City must not be null\");\n        return this.hotelRepository.findByCity(city, pageable);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/HotelRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport java.util.List;\n\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.jpa.repository.Query;\nimport org.springframework.data.repository.Repository;\n\nimport comsat.sample.data.jpa.domain.City;\nimport comsat.sample.data.jpa.domain.Hotel;\nimport comsat.sample.data.jpa.domain.HotelSummary;\nimport comsat.sample.data.jpa.domain.RatingCount;\n\ninterface HotelRepository extends Repository<Hotel, Long> {\n\n    Hotel findByCityAndName(City city, String name);\n\n    @Query(\"select new comsat.sample.data.jpa.domain.HotelSummary(h.city, h.name, avg(r.rating)) \"\n            + \"from Hotel h left outer join h.reviews r where h.city = ?1 group by h\")\n    Page<HotelSummary> findByCity(City city, Pageable pageable);\n\n    @Query(\"select new comsat.sample.data.jpa.domain.RatingCount(r.rating, count(r)) \"\n            + \"from Review r where r.hotel = ?1 group by r.rating order by r.rating DESC\")\n    List<RatingCount> findRatingCounts(Hotel hotel);\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/HotelService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\n\nimport comsat.sample.data.jpa.domain.City;\nimport comsat.sample.data.jpa.domain.Hotel;\nimport comsat.sample.data.jpa.domain.Review;\nimport comsat.sample.data.jpa.domain.ReviewDetails;\n\npublic interface HotelService {\n\n    Hotel getHotel(City city, String name);\n\n    Page<Review> getReviews(Hotel hotel, Pageable pageable);\n\n    Review getReview(Hotel hotel, int index);\n\n    Review addReview(Hotel hotel, ReviewDetails details);\n\n    ReviewsSummary getReviewSummary(Hotel hotel);\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/HotelServiceImpl.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.stereotype.Component;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.Assert;\n\nimport comsat.sample.data.jpa.domain.City;\nimport comsat.sample.data.jpa.domain.Hotel;\nimport comsat.sample.data.jpa.domain.Rating;\nimport comsat.sample.data.jpa.domain.RatingCount;\nimport comsat.sample.data.jpa.domain.Review;\nimport comsat.sample.data.jpa.domain.ReviewDetails;\n\n@Component(\"hotelService\")\n@Transactional\nclass HotelServiceImpl implements HotelService {\n\n    private final HotelRepository hotelRepository;\n\n    private final ReviewRepository reviewRepository;\n\n    @Autowired\n    public HotelServiceImpl(HotelRepository hotelRepository,\n            ReviewRepository reviewRepository) {\n        this.hotelRepository = hotelRepository;\n        this.reviewRepository = reviewRepository;\n    }\n\n    @Override\n    public Hotel getHotel(City city, String name) {\n        Assert.notNull(city, \"City must not be null\");\n        Assert.hasLength(name, \"Name must not be empty\");\n        return this.hotelRepository.findByCityAndName(city, name);\n    }\n\n    @Override\n    public Page<Review> getReviews(Hotel hotel, Pageable pageable) {\n        Assert.notNull(hotel, \"Hotel must not be null\");\n        return this.reviewRepository.findByHotel(hotel, pageable);\n    }\n\n    @Override\n    public Review getReview(Hotel hotel, int reviewNumber) {\n        Assert.notNull(hotel, \"Hotel must not be null\");\n        return this.reviewRepository.findByHotelAndIndex(hotel, reviewNumber);\n    }\n\n    @Override\n    public Review addReview(Hotel hotel, ReviewDetails details) {\n        Review review = new Review(hotel, 1, details);\n        return reviewRepository.save(review);\n    }\n\n    @Override\n    public ReviewsSummary getReviewSummary(Hotel hotel) {\n        List<RatingCount> ratingCounts = this.hotelRepository.findRatingCounts(hotel);\n        return new ReviewsSummaryImpl(ratingCounts);\n    }\n\n    private static class ReviewsSummaryImpl implements ReviewsSummary {\n\n        private final Map<Rating, Long> ratingCount;\n\n        public ReviewsSummaryImpl(List<RatingCount> ratingCounts) {\n            this.ratingCount = new HashMap<Rating, Long>();\n            for (RatingCount ratingCount : ratingCounts) {\n                this.ratingCount.put(ratingCount.getRating(), ratingCount.getCount());\n            }\n        }\n\n        @Override\n        public long getNumberOfReviewsWithRating(Rating rating) {\n            Long count = this.ratingCount.get(rating);\n            return count == null ? 0 : count;\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/ReviewRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.repository.Repository;\n\nimport comsat.sample.data.jpa.domain.Hotel;\nimport comsat.sample.data.jpa.domain.Review;\n\ninterface ReviewRepository extends Repository<Review, Long> {\n\n    Page<Review> findByHotel(Hotel hotel, Pageable pageable);\n\n    Review findByHotelAndIndex(Hotel hotel, int index);\n\n    Review save(Review review);\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/service/ReviewsSummary.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.service;\n\nimport comsat.sample.data.jpa.domain.Rating;\n\npublic interface ReviewsSummary {\n\n    long getNumberOfReviewsWithRating(Rating rating);\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/java/comsat/sample/data/jpa/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa.web;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport comsat.sample.data.jpa.service.CityService;\n\n@Controller\npublic class SampleController {\n\n    @Autowired\n    private CityService cityService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    @Transactional(readOnly = true)\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return this.cityService.getCity(\"Bath\", \"UK\").getName();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/main/resources/import.sql",
    "content": "--\n-- Sample dataset containing a number of Hotels in various Cities across the world.  The reviews are entirely fictional :)\n--\n\n-- =================================================================================================\n-- AUSTRALIA\n\n-- Brisbane\ninsert into city(country, name, state, map) values ('Australia', 'Brisbane', 'Queensland', '-27.470933, 153.023502')\ninsert into hotel(city_id, name, address, zip) values (1, 'Conrad Treasury Place', 'William & George Streets', '4001')\n\n-- Melbourne\ninsert into city(country, name, state, map) values ('Australia', 'Melbourne', 'Victoria', '-37.813187, 144.96298')\ninsert into hotel(city_id, name, address, zip) values (2, 'The Langham', '1 Southgate Ave, Southbank', '3006')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (2, 0, '2005-05-10', 2, 4, 'Pretty average', 'I stayed in 2005, the hotel was nice enough but nothing special.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (2, 1, '2006-01-12', 4, 2, 'Bright hotel with big rooms', 'This hotel has a fantastic lovely big windows.  The room we stayed in had lots of space.  Recommended.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (2, 2, '2006-05-25', 3, 1, 'Pretty good', 'I liked this hotel and would stay again.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (2, 3, '2009-01-20', 3, 2, 'Nice clean rooms', 'The rooms are maintained to a high standard and very clean, the bathroom was spotless!!')\n\n-- Sydney\ninsert into city(country, name, state, map) values ('Australia', 'Sydney', 'New South Wales', '-33.868901, 151.207091')\ninsert into hotel(city_id, name, address, zip) values (3, 'Swissotel', '68 Market Street', '2000')\n\n\n-- =================================================================================================\n-- CANADA\n\n-- Montreal\ninsert into city(country, name, state, map) values ('Canada', 'Montreal', 'Quebec', '45.508889, -73.554167')\ninsert into hotel(city_id, name, address, zip) values (4, 'Ritz Carlton', '1228 Sherbrooke St', 'H3G1H6')\n\n\n-- =================================================================================================\n-- ISRAEL\n\n-- Tel Aviv\ninsert into city(country, name, state, map) values ('Israel', 'Tel Aviv', '', '32.066157, 34.777821')\ninsert into hotel(city_id, name, address, zip) values (5, 'Hilton Tel Aviv', 'Independence Park', '63405')\n\n\n-- =================================================================================================\n-- JAPAN\n\n-- Tokyo\ninsert into city(country, name, state, map) values ('Japan', 'Tokyo', '', '35.689488, 139.691706')\ninsert into hotel(city_id, name, address, zip) values (6, 'InterContinental Tokyo Bay', 'Takeshiba Pier', '105')\n\n\n-- =================================================================================================\n-- SPAIN\n\n-- Barcelona\ninsert into city(country, name, state, map) values ('Spain', 'Barcelona', 'Catalunya', '41.387917, 2.169919')\ninsert into hotel(city_id, name, address, zip) values (7, 'Hilton Diagonal Mar', 'Passeig del Taulat 262-264', '08019')\n\n-- =================================================================================================\n-- SWITZERLAND\n\n-- Neuchatel\ninsert into city(country, name, state, map) values ('Switzerland', 'Neuchatel', '', '46.992979, 6.931933')\ninsert into hotel(city_id, name, address, zip) values (8, 'Hotel Beaulac', ' Esplanade Leopold-Robert 2', '2000')\n\n\n-- =================================================================================================\n-- UNITED KINGDOM\n\n-- Bath\ninsert into city(country, name, state, map) values ('UK', 'Bath', 'Somerset', '51.381428, -2.357454')\ninsert into hotel(city_id, name, address, zip) values (9, 'The Bath Priory Hotel', 'Weston Road', 'BA1 2XT')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 0, '2000-01-23', 4, 1, 'A lovely hotel', 'We stayed here after a wedding and it was fantastic.  Recommend to all.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 1, '2000-08-04', 3, 1, 'Very special', 'A very special hotel with lovely staff.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 2, '2001-01-01', 2, 4, 'Nice but too hot', 'Stayed during the summer heat wave (exceptional for England!) and the room was very hot.  Still recommended.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 3, '2002-01-20', 3, 1, 'Big rooms and a great view', 'Considering how central this hotel is the rooms are a very good size.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 4, '2002-11-03', 2, 1, 'Good but pricey', 'A nice hotel but be prepared to pay over the odds for your stay.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 5, '2003-09-18', 4, 1, 'Fantastic place', 'Just lovely.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 6, '2004-03-21', 4, 3, 'A very special place', 'I stayed here in 2004 and found it to be very relaxing, a nice pool and good gym is cherry on the cake.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 7, '2004-04-10', 0, 0, 'Terrible', 'I complained after I was told I could not check out after 11pm.  Ridiculous!!!')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 8, '2004-12-20', 4, 4, 'A perfect location', 'Central location makes this a perfect hotel.  Be warned though, it''s not cheap.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 9, '2005-04-19', 3, 2, 'Expensive but worth it', 'Dig deep into your pockets and enjoy this lovely City and fantastic hotel.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 10, '2005-05-21', 4, 1, 'The best hotel in the area', 'Top hotel in the area, would not stay anywhere else.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 11, '2005-11-17', 4, 2, 'Lovely hotel, fantastic grounds', 'The garden upkeep run into thousands (perhaps explaining why the rooms are so much) but so lovely and relaxing.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 12, '2006-01-04', 3, 4, 'Gorgeous Top Quality Hotel', 'Top draw stuff.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 13, '2006-01-21', 4, 1, 'Fabulous Hotel and Restaurant', 'The food at this hotel is second to none, try the peppered steak!')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 14, '2006-01-29', 4, 4, 'Feels like home', 'A lovely home away from home.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 15, '2006-03-21', 1, 1, 'Far too expensive', 'Overpriced, Overpriced, Overpriced!!')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 16, '2006-05-10', 4, 1, 'Excellent Hotel, Wonderful Staff', 'The staff went out of their way to help us after we missed our last train home, organising a Taxi back to Newport even after we had checked out.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 17, '2007-09-11', 3, 2, 'The perfect retreat', 'If you want a relaxing stay, this is the place.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 18, '2008-06-01', 3, 3, 'Lovely stay, fantastic staff', 'As other reviews have noted, the staff in this hotel really are the best in Bath.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 19, '2009-05-14', 4, 2, 'Can''t Wait to go back', 'We will stay again for sure.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 20, '2010-04-26', 4, 1, 'Amazing Hotel', 'We won a trip here after entering a competition.  Not sure we would pay the full price but such a wonderful place.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (9, 21, '2010-10-26', 2, 2, 'Dissapointed', 'The pool was closed, the chief was ill, the staff were rude my wallet is bruised!')\ninsert into hotel(city_id, name, address, zip) values (9, 'Bath Travelodge', 'Rossiter Road, Widcombe Basin', 'BA2 4JP')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 0, '2002-08-21', 0, 2, 'Terrible hotel', 'One of the worst hotels that I have ever stayed in.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 1, '2003-01-28', 0, 0, 'Rude and unpleasant staff', 'The staff refused to help me with any aspect of my stay, I will not stay here again.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 2, '2004-06-17', 1, 0, 'Below par', 'Don''t stay here!!')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 3, '2005-07-12', 0, 1, 'Small and Unpleasant', 'The room was far too small and felt unclean.  Not recommended.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 4, '2006-01-07', 1, 4, 'Cheap if you are not fussy', 'This hotel has some rough edges but I challenge you to find somewhere cheaper.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 5, '2006-01-13', 0, 2, 'Terrible', 'Just terrible!')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 6, '2006-03-25', 0, 0, 'Smelly and dirty room', 'My room smelt of damp and I found the socks of the previous occupant under my bed.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 7, '2006-04-09', 0, 4, 'Grim', 'Grim.  I would try elsewhere before staying here.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 8, '2006-08-01', 1, 3, 'Very Noisy', 'Building work during the day and a disco at night.  Good grief!')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 9, '2009-01-03', 1, 4, 'Tired and falling down', 'This hotel is in serious need of refurbishment, the windows are rotting, the paintwork is tired and the carpets are from the 1970s.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 10, '2009-07-20', 0, 0, 'Not suitable for human habitation', 'I would not put my dog up in this hotel.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 11, '2010-05-20', 1, 0, 'Conveient for the railway', 'Average place but useful if you need to commute')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 12, '2010-01-22', 2, 2, 'Not as bad as the reviews', 'Some of the reviews seem a bit harsh, it''s not too bad for the price.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (10, 13, '2011-01-10', 3, 1, 'Reburished and nice', 'Looks like this hotel has had a major facelift.  If you have stayed before 2011 perhaps it''s time to give this hotel another try.  Very good value for money and pretty nice.')\n\n-- London\ninsert into city(country, name, state, map) values ('UK', 'London', '', '51.500152, -0.126236')\ninsert into hotel(city_id, name, address, zip) values (10, 'Melia White House', 'Albany Street', 'NW1 3UP')\n\n-- Southampton\ninsert into city(country, name, state, map) values ('UK', 'Southampton', 'Hampshire', '50.902571, -1.397238')\ninsert into hotel(city_id, name, address, zip) values (11, 'Chilworth Manor', 'The Cottage, Southampton Business Park', 'SO16 7JF')\n\n\n-- =================================================================================================\n-- USA\n\n-- Atlanta\ninsert into city(country, name, state, map) values ('USA', 'Atlanta', 'GA', '33.748995, -84.387982')\ninsert into hotel(city_id, name, address, zip) values (12, 'Marriott Courtyard', 'Tower Place, Buckhead', '30305')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (13, 0, '2009-01-20', 3, 0, 'Better than most', 'Most other hotels is this area are a bit ropey, this one is actually pretty good.')\ninsert into hotel(city_id, name, address, zip) values (12, 'Ritz Carlton', 'Peachtree Rd, Buckhead', '30326')\ninsert into hotel(city_id, name, address, zip) values (12, 'Doubletree', 'Tower Place, Buckhead', '30305')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (15, 0, '2006-01-12', 2, 3, 'No fuss hotel', 'Cheap, no fuss hotel.  Good if you are travelling on business and just need a place to stay.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (15, 1, '2009-01-20', 2, 2, 'Nice area but small rooms', 'The area felt nice and safe but the rooms are a little on the small side')\n\n-- Chicago\ninsert into city(country, name, state, map) values ('USA', 'Chicago', 'IL', '41.878114, -87.629798')\ninsert into hotel(city_id, name, address, zip) values (13, 'Hotel Allegro', '171 West Randolph Street', '60601')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (16, 0, '2009-12-15', 3, 2, 'Cheap and Recommended', 'Good value for money, can''t really fault it.')\n\n-- Eau Claire\ninsert into city(country, name, state, map) values ('USA', 'Eau Claire', 'WI', '44.811349, -91.498494')\ninsert into hotel(city_id, name, address, zip) values (14, 'Sea Horse Inn', '2106 N Clairemont Ave', '54703')\ninsert into hotel(city_id, name, address, zip) values (14, 'Super 8 Eau Claire Campus Area', '1151 W Macarthur Ave', '54701')\n\n-- Hollywood\ninsert into city(country, name, state, map) values ('USA', 'Hollywood', 'FL', '26.011201, -80.14949')\ninsert into hotel(city_id, name, address, zip) values (15, 'Westin Diplomat', '3555 S. Ocean Drive', '33019')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (19, 0, '2006-01-11', 0, 0, 'Avoid', 'The hotel has a very bad reputation.  I would avoid it if I were you.')\n\n-- Miami\ninsert into city(country, name, state, map) values ('USA', 'Miami', 'FL', '25.788969, -80.226439')\ninsert into hotel(city_id, name, address, zip) values (16, 'Conrad Miami', '1395 Brickell Ave', '33131')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (20, 0, '2010-01-09', 3, 2, 'Close to the local attractions', 'Fantastic access to all the local attractions mean you won''t mind the small rooms.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (20, 1, '2010-09-10', 2, 2, 'Good value and friendly', 'Not expensive and very welcoming staff. I would stay again.')\n\n-- Melbourne\ninsert into city(country, name, state, map) values ('USA', 'Melbourne', 'FL', '28.083627, -80.608109')\ninsert into hotel(city_id, name, address, zip) values (17, 'Radisson Suite Hotel Oceanfront', '3101 North Hwy', '32903')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (21, 0, '2005-06-15', 3, 3, 'A very nice hotel', 'I can''t fault this hotel and I have stayed here many times.  Always friendly staff and lovely atmosphere.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (21, 1, '2006-01-20', 2, 4, 'Comfortable and good value', 'To complaints at all.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (21, 2, '2007-08-21', 3, 1, 'Above average', 'Better than a lot of hotels in the area and not too pricey.')\n\n-- New York\ninsert into city(country, name, state, map) values ('USA', 'New York', 'NY', '40.714353, -74.005973')\ninsert into hotel(city_id, name, address, zip) values (18, 'W Union Hotel', 'Union Square, Manhattan', '10011')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (22, 0, '2002-01-19', 0, 1, 'Too noisy, too small', 'The city never sleeps and neither will you if you say here.  The rooms are small and the sound insulation is poor!')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (22, 1, '2004-03-10', 1, 4, 'Overpriced', 'Far too much money for such a tiny room!')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (22, 2, '2007-04-11', 2, 0, 'So so, nothing special', 'Not brilliant but not too bad either.')\ninsert into hotel(city_id, name, address, zip) values (18, 'W Lexington Hotel', 'Lexington Ave, Manhattan', '10011')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (23, 0, '2004-07-21', 3, 2, 'Excellent location', 'So close to the heart of the city.  Recommended.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (23, 1, '2006-05-20', 3, 1, 'Very nice', 'I can''t fault this hotel, clean, good location and nice staff.')\ninsert into hotel(city_id, name, address, zip) values (18, '70 Park Avenue Hotel', '70 Park Avenue', '10011')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (24, 0, '2003-11-10', 4, 1, 'Great!!', 'I own this hotel and I think it is pretty darn good.')\n\n-- Palm Bay\ninsert into city(country, name, state, map) values ('USA', 'Palm Bay', 'FL', '28.034462, -80.588665')\ninsert into hotel(city_id, name, address, zip) values (19, 'Jameson Inn', '890 Palm Bay Rd NE', '32905')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (25, 0, '2005-10-20', 3, 2, 'Fantastical', 'This is the BEST hotel in Palm Bay, not complaints at all.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (25, 1, '2006-01-12', 4, 1, 'Top marks', 'I rate this hotel 5 stars, the best in the area by miles.')\n\n-- San Francisco\ninsert into city(country, name, state, map) values ('USA', 'San Francisco', 'CA', '37.77493, -122.419415')\ninsert into hotel(city_id, name, address, zip) values (20, 'Marriot Downtown', '55 Fourth Street', '94103')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (26, 0, '2006-07-02', 2, 3, 'Could be better', 'I stayed in late 2006 with work, the room was very small and the restaurant does not stay open very late.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (26, 1, '2008-07-01', 1, 4, 'Brrrr cold!', 'My room was freezing cold, I would not recommend this place.')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (26, 2, '2009-01-05', 3, 2, 'Nice for money', 'You can''t really go wrong here for the money.  There may be better places to stay but not for this price.')\n\n-- Washington\ninsert into city(country, name, state, map) values ('USA', 'Washington', 'DC', '38.895112, -77.036366')\ninsert into hotel(city_id, name, address, zip) values (21, 'Hotel Rouge', '1315 16th Street NW', '20036')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (27, 0, '2000-01-29', 0, 2, 'Never again', 'I will never ever stay here again!!  They wanted extra cash to get fresh batteries for the TV remote')\ninsert into review(hotel_id, idx, check_in_date, rating, trip_type, title, details) values (27, 1, '2006-02-20', 0, 0, 'Avoid', 'This place is the pits, they charged us twice for a single night stay.  I only got refunded after contacting my credit card company.')\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/test/java/comsat/sample/data/jpa/SampleDataJpaApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Oliver Gierke.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.data.jpa;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.Test;\nimport org.junit.experimental.categories.Category;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.ActiveProfiles;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport co.paralleluniverse.test.categories.CI;\n\n/**\n * Integration test to run the application.\n *\n * @author Oliver Gierke\n * @author circlespainter\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\n@ActiveProfiles(\"scratch\")\n// Separate profile for web tests to avoid clashing databases\npublic class SampleDataJpaApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body (doesn't contain 'Bath'):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"Bath\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-data-jpa/src/test/resources/application-scratch.properties",
    "content": "spring.datasource.url: jdbc:hsqldb:mem:scratchdb\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty/build.gradle",
    "content": "configurations.testRuntime {\n    resolutionStrategy {\n        force \"javax.servlet:javax.servlet-api:3.1.0\"\n    }\n}\n\ndependencies {\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-jetty:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty/src/main/java/comsat/sample/jetty/SampleJettyApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleJettyApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleJettyApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty/src/main/java/comsat/sample/jetty/service/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty.service;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n\n    @Value(\"${name:World}\")\n    private String name;\n\n    public String getHelloMessage() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"Hello \" + this.name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty/src/main/java/comsat/sample/jetty/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty.web;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport comsat.sample.jetty.service.HelloWorldService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\n@Controller\npublic class SampleController {\n\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        return this.helloWorldService.getHelloMessage();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty/src/test/java/comsat/sample/jetty/SampleJettyApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty;\n\nimport co.paralleluniverse.test.categories.CI;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Test;\nimport org.junit.experimental.categories.Category;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleJettyApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleJettyApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello World\", entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty-ssl/build.gradle",
    "content": "configurations.testRuntime {\n    resolutionStrategy {\n        force \"javax.servlet:javax.servlet-api:3.1.0\"\n    }\n}\n\ndependencies {\n    compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-jetty:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty-ssl/src/main/java/comsat/sample/jetty/SampleJettySslApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\n@EnableConfigurationProperties\npublic class SampleJettySslApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleJettySslApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty-ssl/src/main/java/comsat/sample/jetty/service/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty.service;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n    @Value(\"${name:World}\")\n    private String name;\n\n    public String getHelloMessage() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"Hello \" + this.name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty-ssl/src/main/java/comsat/sample/jetty/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty.web;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport comsat.sample.jetty.service.HelloWorldService;\n\n@Controller\npublic class SampleController {\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        return this.helloWorldService.getHelloMessage();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty-ssl/src/main/resources/application.properties",
    "content": "server.port = 8443\nserver.ssl.key-store = classpath:sample.jks\nserver.ssl.key-store-password = secret\nserver.ssl.key-password = password"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty-ssl/src/test/java/comsat/sample/jetty/SampleJettySslApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty;\n\nimport co.paralleluniverse.test.categories.CI;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.conn.ssl.SSLConnectionSocketFactory;\nimport org.apache.http.conn.ssl.SSLContextBuilder;\nimport org.apache.http.conn.ssl.TrustSelfSignedStrategy;\nimport org.apache.http.impl.client.HttpClients;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.client.HttpComponentsClientHttpRequestFactory;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport org.junit.experimental.categories.Category;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleJettySslApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleJettySslApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(\n                        new SSLContextBuilder().loadTrustMaterial(null,\n                                        new TrustSelfSignedStrategy()).build());\n\n        HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)\n                        .build();\n\n        TestRestTemplate testRestTemplate = new TestRestTemplate();\n        ((HttpComponentsClientHttpRequestFactory) testRestTemplate.getRequestFactory())\n                        .setHttpClient(httpClient);\n        ResponseEntity<String> entity = testRestTemplate.getForEntity(\n                        \"https://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello World\", entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8/build.gradle",
    "content": "configurations.testRuntime {\n    resolutionStrategy {\n        eachDependency {\n            if (it.requested.group == 'org.eclipse.jetty') {\n                it.useVersion '8.1.15.v20140411'\n            }\n        }\n    }\n}\n\ndependencies {\n    compile(\"org.springframework.boot:spring-boot-starter-jetty:$springBootVer\") {\n        exclude group: 'org.eclipse.jetty.websocket', module: '*'\n    }\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8/src/main/java/comsat/sample/jetty/SampleJetty8Application.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleJetty8Application {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleJetty8Application.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8/src/main/java/comsat/sample/jetty/service/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty.service;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n    @Value(\"${name:World}\")\n    private String name;\n\n    public String getHelloMessage() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"Hello \" + this.name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8/src/main/java/comsat/sample/jetty/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty.web;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport comsat.sample.jetty.service.HelloWorldService;\n\n@Controller\npublic class SampleController {\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        return this.helloWorldService.getHelloMessage();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8/src/test/java/comsat/sample/jetty/SampleJetty8ApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty;\n\nimport co.paralleluniverse.test.categories.CI;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport org.junit.experimental.categories.Category;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleJetty8Application.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleJetty8ApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello World\", entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8-ssl/build.gradle",
    "content": "configurations.testRuntime {\n    resolutionStrategy {\n        eachDependency {\n            if (it.requested.group == 'org.eclipse.jetty') {\n                it.useVersion '8.1.15.v20140411'\n            }\n        }\n    }\n}\n\ndependencies {\n    compile(\"org.springframework.boot:spring-boot-starter-jetty:$springBootVer\") {\n        exclude group: 'org.eclipse.jetty.websocket', module: '*'\n    }\n    compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8-ssl/src/main/java/comsat/sample/jetty/SampleJetty8SslApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleJetty8SslApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleJetty8SslApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8-ssl/src/main/java/comsat/sample/jetty/service/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty.service;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n    @Value(\"${name:World}\")\n    private String name;\n\n    public String getHelloMessage() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"Hello \" + this.name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8-ssl/src/main/java/comsat/sample/jetty/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty.web;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport comsat.sample.jetty.service.HelloWorldService;\n\n@Controller\npublic class SampleController {\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        return this.helloWorldService.getHelloMessage();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8-ssl/src/main/resources/application.properties",
    "content": "server.port = 8443\nserver.ssl.key-store = classpath:sample.jks\nserver.ssl.key-store-password = secret\nserver.ssl.key-password = password"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jetty8-ssl/src/test/java/comsat/sample/jetty/SampleJetty8SslApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jetty;\n\nimport co.paralleluniverse.test.categories.CI;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.conn.ssl.SSLConnectionSocketFactory;\nimport org.apache.http.conn.ssl.SSLContextBuilder;\nimport org.apache.http.conn.ssl.TrustSelfSignedStrategy;\nimport org.apache.http.impl.client.HttpClients;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.client.HttpComponentsClientHttpRequestFactory;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport org.junit.experimental.categories.Category;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleJetty8SslApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleJetty8SslApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build());\n\n        HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).build();\n\n        TestRestTemplate testRestTemplate = new TestRestTemplate();\n        ((HttpComponentsClientHttpRequestFactory) testRestTemplate.getRequestFactory()).setHttpClient(httpClient);\n        ResponseEntity<String> entity = testRestTemplate.getForEntity(\"https://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello World\", entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/build.gradle",
    "content": "configurations.testRuntime {\n    resolutionStrategy { // Forcing earlier Tomcat version as later ones fail with \"`getWriter` already called on response\"\n        force 'org.apache.tomcat.embed:tomcat-embed-core:8.0.28'\n        force 'org.apache.tomcat.embed:tomcat-embed-el:8.0.28'\n    }\n}\n\ndependencies {\n    compile \"org.springframework:spring-orm:$springVer\"\n    compile \"org.springframework.boot:spring-boot-starter-freemarker:$springBootVer\"\n    compile \"org.hibernate:hibernate-entitymanager:$hibernateVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n    runtime \"org.hsqldb:hsqldb:$hsqlVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/java/comsat/sample/jpa/SampleJpaApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication\npublic class SampleJpaApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleJpaApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/java/comsat/sample/jpa/domain/Note.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.domain;\n\nimport java.util.List;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\nimport javax.persistence.ManyToMany;\n\n@Entity\npublic class Note {\n    @Id\n    @GeneratedValue(strategy = GenerationType.AUTO)\n    private long id;\n\n    private String title;\n\n    private String body;\n\n    @ManyToMany\n    private List<Tag> tags;\n\n    public long getId() {\n        return this.id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getTitle() {\n        return this.title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public String getBody() {\n        return this.body;\n    }\n\n    public void setBody(String body) {\n        this.body = body;\n    }\n\n    public List<Tag> getTags() {\n        return this.tags;\n    }\n\n    public void setTags(List<Tag> tags) {\n        this.tags = tags;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/java/comsat/sample/jpa/domain/Tag.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.domain;\n\nimport java.util.List;\n\nimport javax.persistence.Entity;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\nimport javax.persistence.ManyToMany;\n\n@Entity\npublic class Tag {\n    @Id\n    @GeneratedValue(strategy = GenerationType.AUTO)\n    private long id;\n\n    private String name;\n\n    @ManyToMany(mappedBy = \"tags\")\n    private List<Note> notes;\n\n    public long getId() {\n        return this.id;\n    }\n\n    public void setId(long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public List<Note> getNotes() {\n        return this.notes;\n    }\n\n    public void setNotes(List<Note> notes) {\n        this.notes = notes;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/java/comsat/sample/jpa/repository/JpaNoteRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.repository;\n\nimport java.util.List;\n\nimport javax.persistence.EntityManager;\nimport javax.persistence.PersistenceContext;\n\nimport org.springframework.stereotype.Repository;\n\nimport comsat.sample.jpa.domain.Note;\n\n@Repository\nclass JpaNoteRepository implements NoteRepository {\n    @PersistenceContext\n    private EntityManager entityManager;\n\n    @Override\n    public List<Note> findAll() {\n        return this.entityManager.createQuery(\"SELECT n FROM Note n\", Note.class).getResultList();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/java/comsat/sample/jpa/repository/JpaTagRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.repository;\n\nimport java.util.List;\n\nimport javax.persistence.EntityManager;\nimport javax.persistence.PersistenceContext;\n\nimport org.springframework.stereotype.Repository;\n\nimport comsat.sample.jpa.domain.Tag;\n\n@Repository\nclass JpaTagRepository implements TagRepository {\n    @PersistenceContext\n    private EntityManager entityManager;\n\n    @Override\n    public List<Tag> findAll() {\n        return this.entityManager.createQuery(\"SELECT t FROM Tag t\", Tag.class).getResultList();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/java/comsat/sample/jpa/repository/NoteRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.repository;\n\nimport java.util.List;\n\nimport comsat.sample.jpa.domain.Note;\n\npublic interface NoteRepository {\n    List<Note> findAll();\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/java/comsat/sample/jpa/repository/TagRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.repository;\n\nimport java.util.List;\n\nimport comsat.sample.jpa.domain.Tag;\n\npublic interface TagRepository {\n    List<Tag> findAll();\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/java/comsat/sample/jpa/web/IndexController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.web;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.List;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport comsat.sample.jpa.domain.Note;\nimport comsat.sample.jpa.repository.NoteRepository;\n\n@Controller\npublic class IndexController {\n    @Autowired\n    private NoteRepository noteRepository;\n\n    @RequestMapping(\"/\")\n    @Transactional(readOnly = true)\n    public ModelAndView index() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        List<Note> notes = this.noteRepository.findAll();\n        ModelAndView modelAndView = new ModelAndView(\"index\");\n        modelAndView.addObject(\"notes\", notes);\n        return modelAndView;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/resources/import.sql",
    "content": "insert into tag(name) values ('Spring projects')\ninsert into tag(name) values ('Apache projects')\ninsert into tag(name) values ('Open source')\n\ninsert into note(title, body) values ('Spring Boot', 'Takes an opinionated view of building production-ready Spring applications.')\ninsert into note(title, body) values ('Spring Framework', 'Core support for dependency injection, transaction management, web applications, data access, messaging, testing and more.')\ninsert into note(title, body) values ('Spring Integration', 'Extends the Spring programming model to support the well-known Enterprise Integration Patterns.')\ninsert into note(title, body) values ('Tomcat', 'Apache Tomcat is an open source software implementation of the Java Servlet and JavaServer Pages technologies.')\n\ninsert into note_tags(notes_id, tags_id) values (1, 1)\ninsert into note_tags(notes_id, tags_id) values (2, 1)\ninsert into note_tags(notes_id, tags_id) values (3, 1)\ninsert into note_tags(notes_id, tags_id) values (1, 3)\ninsert into note_tags(notes_id, tags_id) values (2, 3)\ninsert into note_tags(notes_id, tags_id) values (3, 3)\ninsert into note_tags(notes_id, tags_id) values (4, 2)\ninsert into note_tags(notes_id, tags_id) values (4, 3)"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/main/resources/templates/index.ftl",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<body>\n\t<table>\n\t\t<thead>\n\t\t\t<tr>\n\t\t\t\t<td>Title</td>\n\t\t\t\t<td>Body</td>\n\t\t\t\t<td>Tags</td>\n\t\t\t</tr>\n\t\t</thead>\n\t\t<tbody>\n<#list notes as note>\n\t\t\t<tr>\n\t\t\t\t<td>${note.title}</td>\n\t\t\t\t<td>${note.body}</td>\n\t\t\t\t<td>\n<#list note.tags as tag>\n\t\t\t\t\t<span>${tag.name}</span>\n</#list>\n\t\t\t\t</td>\n\t\t\t</tr>\n</#list>\n\t\t</tbody>\n\t</table>\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/test/java/comsat/sample/jpa/SampleJpaApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa;\n\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath;\n\n/**\n * Integration test to run the application.\n *\n * @author Oliver Gierke\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleJpaApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\npublic class SampleJpaApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        // TODO Check that //tbody/tr count is 4\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/test/java/comsat/sample/jpa/repository/JpaNoteRepositoryIntegrationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.repository;\n\nimport java.util.List;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\nimport comsat.sample.jpa.SampleJpaApplication;\nimport comsat.sample.jpa.domain.Note;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * Integration tests for {@link JpaNoteRepository}.\n *\n * @author Andy Wilkinson\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleJpaApplication.class)\npublic class JpaNoteRepositoryIntegrationTests {\n    @Autowired\n    JpaNoteRepository repository;\n\n    @Test\n    public void findsAllNotes() {\n        List<Note> notes = this.repository.findAll();\n        assertEquals(4, notes.size());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-jpa/src/test/java/comsat/sample/jpa/repository/JpaTagRepositoryIntegrationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jpa.repository;\n\nimport java.util.List;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\nimport comsat.sample.jpa.SampleJpaApplication;\nimport comsat.sample.jpa.domain.Tag;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * Integration tests for {@link JpaTagRepository}.\n *\n * @author Andy Wilkinson\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleJpaApplication.class)\npublic class JpaTagRepositoryIntegrationTests {\n    @Autowired\n    JpaTagRepository repository;\n\n    @Test\n    public void findsAllTags() {\n        List<Tag> tags = this.repository.findAll();\n        assertEquals(3, tags.size());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-servlet/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-security:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-boot-security\")\n    compile project(\":comsat-servlet\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-servlet/src/main/java/comsat/sample/servlet/SampleServletApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.servlet;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.io.IOException;\n\nimport co.paralleluniverse.fibers.servlet.FiberHttpServlet;\nimport javax.servlet.Servlet;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.boot.context.web.SpringBootServletInitializer;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n@Configuration\n@EnableAutoConfiguration\npublic class SampleServletApplication extends SpringBootServletInitializer {\n    @SuppressWarnings(\"serial\")\n    @Bean\n    public Servlet dispatcherServlet() {\n        return new FiberHttpServlet() {\n            @Override\n            @Suspendable\n            public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {\n                try {\n                    Fiber.sleep(10);\n                    res.setContentType(\"text/plain\");\n                    res.getWriter().append(\"Hello World\");\n                } catch (InterruptedException | SuspendExecution ex) {\n                    throw new AssertionError(ex);\n                }\n            }\n        };\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleServletApplication.class, args);\n    }\n\n    @Override\n    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {\n        return application.sources(SampleServletApplication.class);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-servlet/src/test/java/comsat/sample/servlet/SampleServletApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.servlet;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleServletApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleServletApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Autowired\n    private SecurityProperties security;\n\n    @Test\n    public void testHomeIsSecure() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n    }\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity =\n            new TestRestTemplate(\"user\", getPassword()).getForEntity(\"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello World\", entity.getBody());\n    }\n\n    private String getPassword() {\n            return this.security.getUser().getPassword();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat/build.gradle",
    "content": "dependencies {\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat/src/main/java/comsat/sample/tomcat/SampleTomcatApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport javax.servlet.ServletContextEvent;\nimport javax.servlet.ServletContextListener;\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\n@EnableConfigurationProperties\npublic class SampleTomcatApplication {\n    private static final Log logger = LogFactory.getLog(SampleTomcatApplication.class);\n\n    @Bean\n    protected ServletContextListener listener() {\n        return new ServletContextListener() {\n            @Override\n            public void contextInitialized(ServletContextEvent sce) {\n                logger.info(\"ServletContext initialized\");\n            }\n\n            @Override\n            public void contextDestroyed(ServletContextEvent sce) {\n                logger.info(\"ServletContext destroyed\");\n            }\n        };\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleTomcatApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat/src/main/java/comsat/sample/tomcat/service/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat.service;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n\n    @Value(\"${name:World}\")\n    private String name;\n\n    public String getHelloMessage() {\n        return \"Hello \" + this.name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat/src/main/java/comsat/sample/tomcat/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat.web;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport comsat.sample.tomcat.service.HelloWorldService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\n@Controller\npublic class SampleController {\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return this.helloWorldService.getHelloMessage();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat/src/main/resources/public/test.css",
    "content": "p.{}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat/src/test/java/comsat/sample/tomcat/NonAutoConfigurationSampleTomcatApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberWebMvcAutoConfiguration;\nimport comsat.sample.tomcat.NonAutoConfigurationSampleTomcatApplicationTests.NonAutoConfigurationSampleTomcatApplication;\nimport comsat.sample.tomcat.service.HelloWorldService;\nimport comsat.sample.tomcat.web.SampleController;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;\nimport org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;\nimport org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;\nimport org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration;\nimport org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Import;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = NonAutoConfigurationSampleTomcatApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class NonAutoConfigurationSampleTomcatApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Configuration\n    @Import({EmbeddedServletContainerAutoConfiguration.class,\n        DispatcherServletAutoConfiguration.class,\n        ServerPropertiesAutoConfiguration.class, FiberWebMvcAutoConfiguration.class,\n        HttpMessageConvertersAutoConfiguration.class,\n        PropertyPlaceholderAutoConfiguration.class})\n    @ComponentScan(basePackageClasses = {SampleController.class, HelloWorldService.class})\n    public static class NonAutoConfigurationSampleTomcatApplication {\n\n        public static void main(String[] args) throws Exception {\n            SpringApplication.run(SampleTomcatApplication.class, args);\n        }\n    }\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello World\", entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat/src/test/java/comsat/sample/tomcat/SampleTomcatApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat;\n\nimport co.paralleluniverse.test.categories.CI;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Test;\nimport org.junit.experimental.categories.Category;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleTomcatApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleTomcatApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello World\", entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-jsp/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n    compile \"org.apache.tomcat.embed:tomcat-embed-jasper:$tomcatVer\"\n    compile \"org.apache.tomcat.embed:tomcat-embed-jasper:$tomcatVer\"\n\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    provided \"javax.servlet:jstl:$jstlVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-jsp/src/main/java/comsat/sample/jsp/SampleTomcatJspApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.boot.context.web.SpringBootServletInitializer;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\n@EnableConfigurationProperties\npublic class SampleTomcatJspApplication extends SpringBootServletInitializer {\n    @Override\n    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {\n        return application.sources(SampleTomcatJspApplication.class);\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleTomcatJspApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-jsp/src/main/java/comsat/sample/jsp/WelcomeController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@Controller\npublic class WelcomeController {\n\n    @Value(\"${application.message:Hello World}\")\n    private String message = \"Hello World\";\n\n    @RequestMapping(\"/\")\n    public String welcome(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"time\", new Date());\n        model.put(\"message\", this.message);\n        return \"welcome\";\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-jsp/src/main/resources/application.properties",
    "content": "spring.mvc.view.prefix: /WEB-INF/jsp/\nspring.mvc.view.suffix: .jsp\napplication.message: Hello Phil"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-jsp/src/main/webapp/WEB-INF/jsp/welcome.jsp",
    "content": "<!DOCTYPE html>\n\n<%@ taglib prefix=\"spring\" uri=\"http://www.springframework.org/tags\"%>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\n\n<html lang=\"en\">\n\n<body>\n\t<c:url value=\"/resources/text.txt\" var=\"url\"/>\n\t<spring:url value=\"/resources/text.txt\" htmlEscape=\"true\" var=\"springUrl\" />\n\tSpring URL: ${springUrl} at ${time}\n\t<br>\n\tJSTL URL: ${url}\n\t<br>\n\tMessage: ${message}\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-jsp/src/test/java/comsat/sample/jsp/SampleWebJspApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Phillip Webb.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for JSP application.\n *\n * @author Phillip Webb\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleTomcatJspApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleWebJspApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testJspWithEl() throws Exception {\n        System.out.println(\"Sleeping...\");\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"/resources/text.txt\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-multi-connectors/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-multi-connectors/src/main/java/comsat/sample/tomcat/SampleTomcatTwoConnectorsApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Brock Mills.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.apache.catalina.connector.Connector;\nimport org.apache.coyote.http11.Http11NioProtocol;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;\nimport org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.util.FileCopyUtils;\nimport org.springframework.util.SocketUtils;\n\n/**\n * Sample Application to show Tomcat running 2 connectors\n *\n * @author Brock Mills\n */\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleTomcatTwoConnectorsApplication {\n    @Bean\n    public int port() {\n        return SocketUtils.findAvailableTcpPort();\n    }\n\n    @Bean\n    public EmbeddedServletContainerFactory servletContainer() {\n        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();\n        tomcat.addAdditionalTomcatConnectors(createSslConnector());\n        return tomcat;\n    }\n\n    private Connector createSslConnector() {\n        Connector connector = new Connector(\"org.apache.coyote.http11.Http11NioProtocol\");\n        Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();\n        try {\n            File keystore = getKeyStoreFile();\n            File truststore = keystore;\n            connector.setScheme(\"https\");\n            connector.setSecure(true);\n            connector.setPort(port());\n            protocol.setSSLEnabled(true);\n            protocol.setKeystoreFile(keystore.getAbsolutePath());\n            protocol.setKeystorePass(\"changeit\");\n            protocol.setTruststoreFile(truststore.getAbsolutePath());\n            protocol.setTruststorePass(\"changeit\");\n            protocol.setKeyAlias(\"apitester\");\n            return connector;\n        } catch (IOException ex) {\n            throw new IllegalStateException(\"cant access keystore: [\" + \"keystore\"\n                    + \"] or truststore: [\" + \"keystore\" + \"]\", ex);\n        }\n    }\n\n    private File getKeyStoreFile() throws IOException {\n        ClassPathResource resource = new ClassPathResource(\"keystore\");\n        try {\n            return resource.getFile();\n        } catch (Exception ex) {\n            File temp = File.createTempFile(\"keystore\", \".tmp\");\n            FileCopyUtils.copy(resource.getInputStream(), new FileOutputStream(temp));\n            return temp;\n        }\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleTomcatTwoConnectorsApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-multi-connectors/src/main/java/comsat/sample/tomcat/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat.web;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\npublic class SampleController {\n\n    @RequestMapping(\"/hello\")\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"hello\";\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-multi-connectors/src/test/java/comsat/sample/tomcat/SampleTomcatTwoConnectorsApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on sample.jetty.SampleJettyApplication\n * in Spring Boot Samples.\n * Copyright the original author Brock Mills.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat;\n\nimport comsat.sample.tomcat.SampleTomcatTwoConnectorsApplication;\nimport java.io.IOException;\nimport java.net.HttpURLConnection;\n\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.HttpsURLConnection;\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLSession;\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.X509TrustManager;\n\nimport org.junit.BeforeClass;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.client.SimpleClientHttpRequestFactory;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.web.client.RestTemplate;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * Basic integration tests for 2 connector demo application.\n *\n * @author Brock Mills\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleTomcatTwoConnectorsApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleTomcatTwoConnectorsApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private String port;\n\n    @Autowired\n    private ApplicationContext context;\n\n    @BeforeClass\n    public static void setUp() {\n        try {\n            // setup ssl context to ignore certificate errors\n            SSLContext ctx = SSLContext.getInstance(\"TLS\");\n            X509TrustManager tm = new X509TrustManager() {\n\n                @Override\n                public void checkClientTrusted(\n                        java.security.cert.X509Certificate[] chain, String authType)\n                        throws java.security.cert.CertificateException {\n                }\n\n                @Override\n                public void checkServerTrusted(\n                        java.security.cert.X509Certificate[] chain, String authType)\n                        throws java.security.cert.CertificateException {\n                }\n\n                @Override\n                public java.security.cert.X509Certificate[] getAcceptedIssuers() {\n                    return null;\n                }\n            };\n            ctx.init(null, new TrustManager[]{tm}, null);\n            SSLContext.setDefault(ctx);\n        } catch (Exception ex) {\n            ex.printStackTrace();\n        }\n    }\n\n    @Test\n    public void testHello() throws Exception {\n        RestTemplate template = new RestTemplate();\n        final MySimpleClientHttpRequestFactory factory = new MySimpleClientHttpRequestFactory(\n                new HostnameVerifier() {\n\n                    @Override\n                    public boolean verify(final String hostname, final SSLSession session) {\n                        return true; // these guys are alright by me...\n                    }\n                });\n        template.setRequestFactory(factory);\n\n        ResponseEntity<String> entity = template.getForEntity(\"http://localhost:\"\n                + this.port + \"/hello\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"hello\", entity.getBody());\n\n        ResponseEntity<String> httpsEntity = template.getForEntity(\"https://localhost:\"\n                + this.context.getBean(\"port\") + \"/hello\", String.class);\n        assertEquals(HttpStatus.OK, httpsEntity.getStatusCode());\n        assertEquals(\"hello\", httpsEntity.getBody());\n    }\n\n    /**\n     * Http Request Factory for ignoring SSL hostname errors. Not for production\n     * use!\n     */\n    class MySimpleClientHttpRequestFactory extends SimpleClientHttpRequestFactory {\n\n        private final HostnameVerifier verifier;\n\n        public MySimpleClientHttpRequestFactory(final HostnameVerifier verifier) {\n            this.verifier = verifier;\n        }\n\n        @Override\n        protected void prepareConnection(final HttpURLConnection connection,\n                final String httpMethod) throws IOException {\n            if (connection instanceof HttpsURLConnection) {\n                ((HttpsURLConnection) connection).setHostnameVerifier(this.verifier);\n            }\n            super.prepareConnection(connection, httpMethod);\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-ssl/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter:$springBootVer\"\n    compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n    compile \"org.yaml:snakeyaml:$snakeYamlVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-ssl/src/main/java/comsat/sample/tomcat/SampleTomcatSslApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\n@EnableConfigurationProperties\npublic class SampleTomcatSslApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleTomcatSslApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-ssl/src/main/java/comsat/sample/tomcat/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat.web;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\n@Controller\npublic class SampleController {\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"Hello, world\";\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-ssl/src/main/resources/application.properties",
    "content": "server.port = 8443\nserver.ssl.key-store = sample.jks\nserver.ssl.key-store-password = secret\nserver.ssl.key-password = password"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat-ssl/src/test/java/comsat/sample/tomcat/SampleTomcatSslApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.tomcat;\n\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.conn.ssl.SSLConnectionSocketFactory;\nimport org.apache.http.conn.ssl.SSLContextBuilder;\nimport org.apache.http.conn.ssl.TrustSelfSignedStrategy;\nimport org.apache.http.impl.client.HttpClients;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.client.HttpComponentsClientHttpRequestFactory;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleTomcatSslApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleTomcatSslApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(\n                new SSLContextBuilder().loadTrustMaterial(null,\n                        new TrustSelfSignedStrategy()).build());\n\n        HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)\n                .build();\n\n        TestRestTemplate testRestTemplate = new TestRestTemplate();\n        ((HttpComponentsClientHttpRequestFactory) testRestTemplate.getRequestFactory())\n                .setHttpClient(httpClient);\n        ResponseEntity<String> entity = testRestTemplate.getForEntity(\n                \"https://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello, world\", entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat7-jsp/.gitignore",
    "content": "/target/\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat7-jsp/build.gradle",
    "content": "configurations.testRuntime {\n    resolutionStrategy {\n        eachDependency {\n            if (it.requested.group == 'org.apache.tomcat.embed') {\n                it.useVersion '7.0.59'\n            }\n        }\n    }\n}\n\ndependencies {\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    compile \"org.apache.tomcat.embed:tomcat-embed-jasper:$tomcatVer\"\n\n    provided \"javax.servlet:jstl:$jstlVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n\n    testRuntime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat7-jsp/src/main/java/comsat/sample/jsp/SampleTomcat7JspApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.boot.context.web.SpringBootServletInitializer;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\n@EnableConfigurationProperties\npublic class SampleTomcat7JspApplication extends SpringBootServletInitializer {\n    @Override\n    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {\n        return application.sources(SampleTomcat7JspApplication.class);\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleTomcat7JspApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat7-jsp/src/main/java/comsat/sample/jsp/WelcomeController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@Controller\npublic class WelcomeController {\n    @Value(\"${application.message:Hello World}\")\n    private String message = \"Hello World\";\n\n    @RequestMapping(\"/\")\n    public String welcome(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"time\", new Date());\n        model.put(\"message\", this.message);\n        return \"welcome\";\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat7-jsp/src/main/resources/application.properties",
    "content": "spring.mvc.view.prefix: /WEB-INF/jsp/\nspring.mvc.view.suffix: .jsp\napplication.message: Hello Phil"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat7-jsp/src/main/webapp/WEB-INF/jsp/welcome.jsp",
    "content": "<!DOCTYPE html>\n\n<%@ taglib prefix=\"spring\" uri=\"http://www.springframework.org/tags\"%>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\n\n<html lang=\"en\">\n\n<body>\n\t<c:url value=\"/resources/text.txt\" var=\"url\"/>\n\t<spring:url value=\"/resources/text.txt\" htmlEscape=\"true\" var=\"springUrl\" />\n\tSpring URL: ${springUrl} at ${time}\n\t<br>\n\tJSTL URL: ${url}\n\t<br>\n\tMessage: ${message}\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-tomcat7-jsp/src/test/java/comsat/sample/jsp/SampleWebJspApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Phillip Webb.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport co.paralleluniverse.test.categories.CI;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.experimental.categories.Category;\n\n/**\n * Basic integration tests for JSP application.\n *\n * @author Phillip Webb\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleTomcat7JspApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleWebJspApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testJspWithEl() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"/resources/text.txt\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/build.gradle",
    "content": "dependencies {\n    compile \"org.apache.tomcat.embed:tomcat-embed-jasper:$tomcatVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/main/java/comsat/sample/traditional/SampleTraditionalApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.traditional;\n\nimport co.paralleluniverse.springframework.web.servlet.config.annotation.FiberWebMvcConfigurationSupport;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.EnableAutoConfiguration;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Import;\n\n//snippet import\n@Configuration\n@Import(FiberWebMvcConfigurationSupport.class)\n@EnableAutoConfiguration\n@ComponentScan\npublic class SampleTraditionalApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleTraditionalApplication.class, args);\n    }\n}\n// end of snippet\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/main/java/comsat/sample/traditional/config/WebConfig.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.traditional.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.servlet.DispatcherServlet;\nimport org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;\nimport org.springframework.web.servlet.config.annotation.EnableWebMvc;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\nimport org.springframework.web.servlet.view.InternalResourceViewResolver;\n\n@EnableWebMvc\n@ComponentScan\n@Configuration\npublic class WebConfig extends WebMvcConfigurerAdapter {\n    @Override\n    public void addViewControllers(ViewControllerRegistry registry) {\n        registry.addViewController(\"/\").setViewName(\"home\");\n    }\n\n    @Bean\n    public InternalResourceViewResolver viewResolver() {\n        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();\n        viewResolver.setPrefix(\"/WEB-INF/views/\");\n        viewResolver.setSuffix(\".jsp\");\n        return viewResolver;\n    }\n\n    @Bean\n    // Only used when running in embedded servlet\n    public DispatcherServlet dispatcherServlet() {\n        return new DispatcherServlet();\n    }\n\n    @Override\n    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {\n        configurer.enable();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/main/resources/log4j.properties",
    "content": "log4j.rootCategory=INFO, stdout\n\nlog4j.appender.stdout=org.apache.log4j.ConsoleAppender\nlog4j.appender.stdout.layout=org.apache.log4j.PatternLayout\nlog4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n\n\nlog4j.category.org.springframework.web=DEBUG\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/main/webapp/WEB-INF/views/home.jsp",
    "content": "<%@ page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Home</title>\n</head>\n<body>\n  <h1>Home</h1>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/main/webapp/WEB-INF/web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<web-app version=\"2.5\" xmlns=\"http://java.sun.com/xml/ns/javaee\"\n\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n\txsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\">\n\n\t<servlet>\n\t\t<servlet-name>appServlet</servlet-name>\n\t\t<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>\n\t\t<init-param>\n\t\t\t<param-name>contextClass</param-name>\n\t\t\t<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>\n\t\t</init-param>\n\t\t<init-param>\n\t\t\t<param-name>contextConfigLocation</param-name>\n\t\t\t<param-value>sample.traditional.config</param-value>\n\t\t</init-param>\n\t\t<load-on-startup>1</load-on-startup>\n\t</servlet>\n\n\t<servlet-mapping>\n\t\t<servlet-name>appServlet</servlet-name>\n\t\t<url-pattern>/</url-pattern>\n\t</servlet-mapping>\n\n\t<!-- Disables Servlet Container welcome file handling. Needed for compatibility \n\t\twith Servlet 3.0 and Tomcat 7.0 -->\n\t<welcome-file-list>\n\t\t<welcome-file></welcome-file>\n\t</welcome-file-list>\n\n</web-app>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/main/webapp/index.html",
    "content": "<html>\n<body>\n<h1>Hello</h1>\nHello World!\n</body>\n</html>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/test/java/comsat/sample/traditional/SampleTraditionalApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.traditional;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleTraditionalApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleTraditionalApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHomeJsp() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        String body = entity.getBody();\n        assertTrue(\"Wrong body:\\n\" + body, body.contains(\"<html>\"));\n        assertTrue(\"Wrong body:\\n\" + body, body.contains(\"<h1>Home</h1>\"));\n    }\n\n    @Test\n    public void testStaticPage() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + \"/index.html\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        String body = entity.getBody();\n        assertTrue(\"Wrong body:\\n\" + body, body.contains(\"<html>\"));\n        assertTrue(\"Wrong body:\\n\" + body, body.contains(\"<h1>Hello</h1>\"));\n    }\n\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/test/resources/log4j.properties",
    "content": "log4j.rootCategory=INFO, stdout\n\nlog4j.appender.stdout=org.apache.log4j.ConsoleAppender\nlog4j.appender.stdout.layout=org.apache.log4j.PatternLayout\nlog4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n\n\nlog4j.category.org.springframework.web=DEBUG\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow/build.gradle",
    "content": "dependencies {\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-undertow:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow/src/main/java/comsat/sample/undertow/SampleUndertowApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.undertow;\n\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.scheduling.annotation.EnableAsync;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\n@EnableConfigurationProperties\n@EnableAsync\npublic class SampleUndertowApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleUndertowApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow/src/main/java/comsat/sample/undertow/service/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.undertow.service;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n    @Value(\"${name:World}\")\n    private String name;\n\n    public String getHelloMessage() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"Hello \" + this.name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow/src/main/java/comsat/sample/undertow/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.undertow.web;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.util.concurrent.Callable;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport comsat.sample.undertow.service.HelloWorldService;\n\n@RestController\npublic class SampleController {\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        return this.helloWorldService.getHelloMessage();\n    }\n\n    @RequestMapping(\"/async\")\n    public Callable<String> helloWorldAsync() throws SuspendExecution {\n        return new Callable<String>() {\n            @Override\n            @Suspendable\n            public String call() throws Exception {\n                return \"async: \" + SampleController.this.helloWorldService.getHelloMessage();\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow/src/test/java/comsat/sample/undertow/SampleUndertowApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.undertow;\n\nimport co.paralleluniverse.test.categories.CI;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport org.junit.experimental.categories.Category;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Ivan Sopov\n * @author Andy Wilkinson\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleUndertowApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleUndertowApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        assertOkResponse(\"/\", \"Hello World\");\n    }\n\n    @Test\n    public void testAsync() throws Exception {\n        assertOkResponse(\"/async\", \"async: Hello World\");\n    }\n\n    private void assertOkResponse(String path, String body) {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port + path, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(body, entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow-ssl/build.gradle",
    "content": "dependencies {\n    compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-undertow:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow-ssl/src/main/java/comsat/sample/undertow/SampleUndertowSslApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.undertow;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleUndertowSslApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleUndertowSslApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow-ssl/src/main/java/comsat/sample/undertow/service/HelloWorldService.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.undertow.service;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class HelloWorldService {\n    @Value(\"${name:World}\")\n    private String name;\n\n    public String getHelloMessage() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"Hello \" + this.name;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow-ssl/src/main/java/comsat/sample/undertow/web/SampleController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.undertow.web;\n\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.ResponseBody;\n\nimport comsat.sample.undertow.service.HelloWorldService;\n\n@Controller\npublic class SampleController {\n    @Autowired\n    private HelloWorldService helloWorldService;\n\n    @RequestMapping(\"/\")\n    @ResponseBody\n    public String helloWorld() throws InterruptedException, SuspendExecution {\n        return this.helloWorldService.getHelloMessage();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow-ssl/src/main/resources/application.properties",
    "content": "server.port = 8443\nserver.ssl.key-store = classpath:sample.jks\nserver.ssl.key-store-password = secret\nserver.ssl.key-password = password"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-undertow-ssl/src/test/java/comsat/sample/undertow/SampleUndertowSslApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.undertow;\n\nimport co.paralleluniverse.test.categories.CI;\nimport org.apache.http.client.HttpClient;\nimport org.apache.http.conn.ssl.SSLConnectionSocketFactory;\nimport org.apache.http.conn.ssl.SSLContextBuilder;\nimport org.apache.http.conn.ssl.TrustSelfSignedStrategy;\nimport org.apache.http.impl.client.HttpClients;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.client.HttpComponentsClientHttpRequestFactory;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport org.junit.experimental.categories.Category;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Ivan Sopov\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleUndertowSslApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleUndertowSslApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        SSLConnectionSocketFactory socketFactory =\n            new SSLConnectionSocketFactory(new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build());\n\n        HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).build();\n\n        TestRestTemplate testRestTemplate = new TestRestTemplate();\n        ((HttpComponentsClientHttpRequestFactory) testRestTemplate.getRequestFactory()).setHttpClient(httpClient);\n        ResponseEntity<String> entity = testRestTemplate.getForEntity(\"https://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertEquals(\"Hello World\", entity.getBody());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-freemarker/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-freemarker:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-freemarker/src/main/java/comsat/sample/freemarker/SampleWebFreeMarkerApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.freemarker;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleWebFreeMarkerApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleWebFreeMarkerApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-freemarker/src/main/java/comsat/sample/freemarker/WelcomeController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.freemarker;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@Controller\npublic class WelcomeController {\n\n    @Value(\"${application.message:Hello World}\")\n    private String message = \"Hello World\";\n\n    @RequestMapping(\"/\")\n    public String welcome(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"time\", new Date());\n        model.put(\"message\", this.message);\n        return \"welcome\";\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-freemarker/src/main/resources/application.properties",
    "content": "application.message: Hello, Andy"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-freemarker/src/main/resources/templates/error.ftl",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<body>\n\tSomething went wrong: ${status} ${error}\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-freemarker/src/main/resources/templates/welcome.ftl",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<body>\n\tDate: ${time?date}\n\t<br>\n\tTime: ${time?time}\n\t<br>\n\tMessage: ${message}\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-freemarker/src/test/java/comsat/sample/freemarker/SampleWebFreeMarkerApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original authors Phillip Webb and Andy Wilkinson.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.freemarker;\n\nimport java.util.Arrays;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for FreeMarker application.\n *\n * @author Phillip Webb\n * @author Andy Wilkinson\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebFreeMarkerApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleWebFreeMarkerApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testFreeMarkerTemplate() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(),\n                entity.getBody().contains(\"Hello, Andy\"));\n    }\n\n    @Test\n    public void testFreeMarkerErrorTemplate() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        HttpEntity<String> requestEntity = new HttpEntity<String>(headers);\n\n        ResponseEntity<String> responseEntity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + port + \"/does-not-exist\", HttpMethod.GET,\n                requestEntity, String.class);\n\n        assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + responseEntity.getBody(), responseEntity.getBody()\n                .contains(\"Something went wrong: 404 Not Found\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-groovy-templates:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/java/comsat/sample/ui/InMemoryMessageRespository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.AtomicLong;\n\npublic class InMemoryMessageRespository implements MessageRepository {\n\n    private static AtomicLong counter = new AtomicLong();\n\n    private final ConcurrentMap<Long, Message> messages = new ConcurrentHashMap<Long, Message>();\n\n    @Override\n    public Iterable<Message> findAll() {\n        return this.messages.values();\n    }\n\n    @Override\n    public Message save(Message message) {\n        Long id = message.getId();\n        if (id == null) {\n            id = counter.incrementAndGet();\n            message.setId(id);\n        }\n        this.messages.put(id, message);\n        return message;\n    }\n\n    @Override\n    public Message findMessage(Long id) {\n        return this.messages.get(id);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/java/comsat/sample/ui/Message.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport java.util.Date;\n\nimport org.hibernate.validator.constraints.NotEmpty;\n\npublic class Message {\n\n    private Long id;\n\n    @NotEmpty(message = \"Message is required.\")\n    private String text;\n\n    @NotEmpty(message = \"Summary is required.\")\n    private String summary;\n\n    private Date created = new Date();\n\n    public Long getId() {\n        return this.id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public Date getCreated() {\n        return this.created;\n    }\n\n    public void setCreated(Date created) {\n        this.created = created;\n    }\n\n    public String getText() {\n        return this.text;\n    }\n\n    public void setText(String text) {\n        this.text = text;\n    }\n\n    public String getSummary() {\n        return this.summary;\n    }\n\n    public void setSummary(String summary) {\n        this.summary = summary;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/java/comsat/sample/ui/MessageRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\npublic interface MessageRepository {\n\n    Iterable<Message> findAll();\n\n    Message save(Message message);\n\n    Message findMessage(Long id);\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/java/comsat/sample/ui/SampleGroovyTemplateApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.core.convert.converter.Converter;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n// snippet import\n@FiberSpringBootApplication // This will enable fiber-blocking\n// end of snippet\npublic class SampleGroovyTemplateApplication {\n    @Bean\n    public MessageRepository messageRepository() {\n        return new InMemoryMessageRespository();\n    }\n\n    @Bean\n    public Converter<String, Message> messageConverter() {\n        return new Converter<String, Message>() {\n            @Override\n            public Message convert(String id) {\n                return messageRepository().findMessage(Long.valueOf(id));\n            }\n        };\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleGroovyTemplateApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/java/comsat/sample/ui/mvc/MessageController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.mvc;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.validation.Valid;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.validation.BindingResult;\nimport org.springframework.validation.FieldError;\nimport org.springframework.validation.ObjectError;\nimport org.springframework.web.bind.annotation.ModelAttribute;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.servlet.mvc.support.RedirectAttributes;\n\nimport comsat.sample.ui.Message;\nimport comsat.sample.ui.MessageRepository;\n\n@Controller\n@RequestMapping(\"/\")\npublic class MessageController {\n\n    private final MessageRepository messageRepository;\n\n    @Autowired\n    public MessageController(MessageRepository messageRepository) {\n        this.messageRepository = messageRepository;\n    }\n\n    @RequestMapping\n    public ModelAndView list() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        Iterable<Message> messages = this.messageRepository.findAll();\n        return new ModelAndView(\"messages/list\", \"messages\", messages);\n    }\n\n    @RequestMapping(\"{id}\")\n    public ModelAndView view(@PathVariable(\"id\") Message message) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return new ModelAndView(\"messages/view\", \"message\", message);\n    }\n\n    @RequestMapping(params = \"form\", method = RequestMethod.GET)\n    public String createForm(@ModelAttribute Message message) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"messages/form\";\n    }\n\n    @RequestMapping(method = RequestMethod.POST)\n    public ModelAndView create(@Valid Message message, BindingResult result,\n            RedirectAttributes redirect) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        if (result.hasErrors()) {\n            ModelAndView mav = new ModelAndView(\"messages/form\");\n            mav.addObject(\"formErrors\", result.getAllErrors());\n            mav.addObject(\"fieldErrors\", getFieldErrors(result));\n            return mav;\n        }\n        message = this.messageRepository.save(message);\n        redirect.addFlashAttribute(\"globalMessage\", \"Successfully created a new message\");\n        return new ModelAndView(\"redirect:/{message.id}\", \"message.id\", message.getId());\n    }\n\n    private Map<String, ObjectError> getFieldErrors(BindingResult result) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        Map<String, ObjectError> map = new HashMap<String, ObjectError>();\n        for (FieldError error : result.getFieldErrors()) {\n            map.put(error.getField(), error);\n        }\n        return map;\n    }\n\n    @RequestMapping(\"foo\")\n    public String foo() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new RuntimeException(\"Expected exception in controller\");\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/resources/application.properties",
    "content": "# Allow templates to be reloaded at dev time\nspring.groovy.template.cache: false\nlogging.level.org.springframework.web: INFO"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/resources/static/js/jquery-1.7.2.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n  navigator = window.navigator,\n  location = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n    // The jQuery object is actually just the init constructor 'enhanced'\n    return new jQuery.fn.init( selector, context, rootjQuery );\n  },\n\n  // Map over jQuery in case of overwrite\n  _jQuery = window.jQuery,\n\n  // Map over the $ in case of overwrite\n  _$ = window.$,\n\n  // A central reference to the root jQuery(document)\n  rootjQuery,\n\n  // A simple way to check for HTML strings or ID strings\n  // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n  quickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n  // Check if a string has a non-whitespace character in it\n  rnotwhite = /\\S/,\n\n  // Used for trimming whitespace\n  trimLeft = /^\\s+/,\n  trimRight = /\\s+$/,\n\n  // Match a standalone tag\n  rsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n  // JSON RegExp\n  rvalidchars = /^[\\],:{}\\s]*$/,\n  rvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n  rvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n  rvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n  // Useragent RegExp\n  rwebkit = /(webkit)[ \\/]([\\w.]+)/,\n  ropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n  rmsie = /(msie) ([\\w.]+)/,\n  rmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n  // Matches dashed string for camelizing\n  rdashAlpha = /-([a-z]|[0-9])/ig,\n  rmsPrefix = /^-ms-/,\n\n  // Used by jQuery.camelCase as callback to replace()\n  fcamelCase = function( all, letter ) {\n    return ( letter + \"\" ).toUpperCase();\n  },\n\n  // Keep a UserAgent string for use with jQuery.browser\n  userAgent = navigator.userAgent,\n\n  // For matching the engine and version of the browser\n  browserMatch,\n\n  // The deferred used on DOM ready\n  readyList,\n\n  // The ready event handler\n  DOMContentLoaded,\n\n  // Save a reference to some core methods\n  toString = Object.prototype.toString,\n  hasOwn = Object.prototype.hasOwnProperty,\n  push = Array.prototype.push,\n  slice = Array.prototype.slice,\n  trim = String.prototype.trim,\n  indexOf = Array.prototype.indexOf,\n\n  // [[Class]] -> type pairs\n  class2type = {};\n\njQuery.fn = jQuery.prototype = {\n  constructor: jQuery,\n  init: function( selector, context, rootjQuery ) {\n    var match, elem, ret, doc;\n\n    // Handle $(\"\"), $(null), or $(undefined)\n    if ( !selector ) {\n      return this;\n    }\n\n    // Handle $(DOMElement)\n    if ( selector.nodeType ) {\n      this.context = this[0] = selector;\n      this.length = 1;\n      return this;\n    }\n\n    // The body element only exists once, optimize finding it\n    if ( selector === \"body\" && !context && document.body ) {\n      this.context = document;\n      this[0] = document.body;\n      this.selector = selector;\n      this.length = 1;\n      return this;\n    }\n\n    // Handle HTML strings\n    if ( typeof selector === \"string\" ) {\n      // Are we dealing with HTML string or an ID?\n      if ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n        // Assume that strings that start and end with <> are HTML and skip the regex check\n        match = [ null, selector, null ];\n\n      } else {\n        match = quickExpr.exec( selector );\n      }\n\n      // Verify a match, and that no context was specified for #id\n      if ( match && (match[1] || !context) ) {\n\n        // HANDLE: $(html) -> $(array)\n        if ( match[1] ) {\n          context = context instanceof jQuery ? context[0] : context;\n          doc = ( context ? context.ownerDocument || context : document );\n\n          // If a single string is passed in and it's a single tag\n          // just do a createElement and skip the rest\n          ret = rsingleTag.exec( selector );\n\n          if ( ret ) {\n            if ( jQuery.isPlainObject( context ) ) {\n              selector = [ document.createElement( ret[1] ) ];\n              jQuery.fn.attr.call( selector, context, true );\n\n            } else {\n              selector = [ doc.createElement( ret[1] ) ];\n            }\n\n          } else {\n            ret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n            selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n          }\n\n          return jQuery.merge( this, selector );\n\n        // HANDLE: $(\"#id\")\n        } else {\n          elem = document.getElementById( match[2] );\n\n          // Check parentNode to catch when Blackberry 4.6 returns\n          // nodes that are no longer in the document #6963\n          if ( elem && elem.parentNode ) {\n            // Handle the case where IE and Opera return items\n            // by name instead of ID\n            if ( elem.id !== match[2] ) {\n              return rootjQuery.find( selector );\n            }\n\n            // Otherwise, we inject the element directly into the jQuery object\n            this.length = 1;\n            this[0] = elem;\n          }\n\n          this.context = document;\n          this.selector = selector;\n          return this;\n        }\n\n      // HANDLE: $(expr, $(...))\n      } else if ( !context || context.jquery ) {\n        return ( context || rootjQuery ).find( selector );\n\n      // HANDLE: $(expr, context)\n      // (which is just equivalent to: $(context).find(expr)\n      } else {\n        return this.constructor( context ).find( selector );\n      }\n\n    // HANDLE: $(function)\n    // Shortcut for document ready\n    } else if ( jQuery.isFunction( selector ) ) {\n      return rootjQuery.ready( selector );\n    }\n\n    if ( selector.selector !== undefined ) {\n      this.selector = selector.selector;\n      this.context = selector.context;\n    }\n\n    return jQuery.makeArray( selector, this );\n  },\n\n  // Start with an empty selector\n  selector: \"\",\n\n  // The current version of jQuery being used\n  jquery: \"1.7.2\",\n\n  // The default length of a jQuery object is 0\n  length: 0,\n\n  // The number of elements contained in the matched element set\n  size: function() {\n    return this.length;\n  },\n\n  toArray: function() {\n    return slice.call( this, 0 );\n  },\n\n  // Get the Nth element in the matched element set OR\n  // Get the whole matched element set as a clean array\n  get: function( num ) {\n    return num == null ?\n\n      // Return a 'clean' array\n      this.toArray() :\n\n      // Return just the object\n      ( num < 0 ? this[ this.length + num ] : this[ num ] );\n  },\n\n  // Take an array of elements and push it onto the stack\n  // (returning the new matched element set)\n  pushStack: function( elems, name, selector ) {\n    // Build a new jQuery matched element set\n    var ret = this.constructor();\n\n    if ( jQuery.isArray( elems ) ) {\n      push.apply( ret, elems );\n\n    } else {\n      jQuery.merge( ret, elems );\n    }\n\n    // Add the old object onto the stack (as a reference)\n    ret.prevObject = this;\n\n    ret.context = this.context;\n\n    if ( name === \"find\" ) {\n      ret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n    } else if ( name ) {\n      ret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n    }\n\n    // Return the newly-formed element set\n    return ret;\n  },\n\n  // Execute a callback for every element in the matched set.\n  // (You can seed the arguments with an array of args, but this is\n  // only used internally.)\n  each: function( callback, args ) {\n    return jQuery.each( this, callback, args );\n  },\n\n  ready: function( fn ) {\n    // Attach the listeners\n    jQuery.bindReady();\n\n    // Add the callback\n    readyList.add( fn );\n\n    return this;\n  },\n\n  eq: function( i ) {\n    i = +i;\n    return i === -1 ?\n      this.slice( i ) :\n      this.slice( i, i + 1 );\n  },\n\n  first: function() {\n    return this.eq( 0 );\n  },\n\n  last: function() {\n    return this.eq( -1 );\n  },\n\n  slice: function() {\n    return this.pushStack( slice.apply( this, arguments ),\n      \"slice\", slice.call(arguments).join(\",\") );\n  },\n\n  map: function( callback ) {\n    return this.pushStack( jQuery.map(this, function( elem, i ) {\n      return callback.call( elem, i, elem );\n    }));\n  },\n\n  end: function() {\n    return this.prevObject || this.constructor(null);\n  },\n\n  // For internal use only.\n  // Behaves like an Array's method, not like a jQuery method.\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n  var options, name, src, copy, copyIsArray, clone,\n    target = arguments[0] || {},\n    i = 1,\n    length = arguments.length,\n    deep = false;\n\n  // Handle a deep copy situation\n  if ( typeof target === \"boolean\" ) {\n    deep = target;\n    target = arguments[1] || {};\n    // skip the boolean and the target\n    i = 2;\n  }\n\n  // Handle case when target is a string or something (possible in deep copy)\n  if ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n    target = {};\n  }\n\n  // extend jQuery itself if only one argument is passed\n  if ( length === i ) {\n    target = this;\n    --i;\n  }\n\n  for ( ; i < length; i++ ) {\n    // Only deal with non-null/undefined values\n    if ( (options = arguments[ i ]) != null ) {\n      // Extend the base object\n      for ( name in options ) {\n        src = target[ name ];\n        copy = options[ name ];\n\n        // Prevent never-ending loop\n        if ( target === copy ) {\n          continue;\n        }\n\n        // Recurse if we're merging plain objects or arrays\n        if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n          if ( copyIsArray ) {\n            copyIsArray = false;\n            clone = src && jQuery.isArray(src) ? src : [];\n\n          } else {\n            clone = src && jQuery.isPlainObject(src) ? src : {};\n          }\n\n          // Never move original objects, clone them\n          target[ name ] = jQuery.extend( deep, clone, copy );\n\n        // Don't bring in undefined values\n        } else if ( copy !== undefined ) {\n          target[ name ] = copy;\n        }\n      }\n    }\n  }\n\n  // Return the modified object\n  return target;\n};\n\njQuery.extend({\n  noConflict: function( deep ) {\n    if ( window.$ === jQuery ) {\n      window.$ = _$;\n    }\n\n    if ( deep && window.jQuery === jQuery ) {\n      window.jQuery = _jQuery;\n    }\n\n    return jQuery;\n  },\n\n  // Is the DOM ready to be used? Set to true once it occurs.\n  isReady: false,\n\n  // A counter to track how many items to wait for before\n  // the ready event fires. See #6781\n  readyWait: 1,\n\n  // Hold (or release) the ready event\n  holdReady: function( hold ) {\n    if ( hold ) {\n      jQuery.readyWait++;\n    } else {\n      jQuery.ready( true );\n    }\n  },\n\n  // Handle when the DOM is ready\n  ready: function( wait ) {\n    // Either a released hold or an DOMready/load event and not yet ready\n    if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n      // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n      if ( !document.body ) {\n        return setTimeout( jQuery.ready, 1 );\n      }\n\n      // Remember that the DOM is ready\n      jQuery.isReady = true;\n\n      // If a normal DOM Ready event fired, decrement, and wait if need be\n      if ( wait !== true && --jQuery.readyWait > 0 ) {\n        return;\n      }\n\n      // If there are functions bound, to execute\n      readyList.fireWith( document, [ jQuery ] );\n\n      // Trigger any bound ready events\n      if ( jQuery.fn.trigger ) {\n        jQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n      }\n    }\n  },\n\n  bindReady: function() {\n    if ( readyList ) {\n      return;\n    }\n\n    readyList = jQuery.Callbacks( \"once memory\" );\n\n    // Catch cases where $(document).ready() is called after the\n    // browser event has already occurred.\n    if ( document.readyState === \"complete\" ) {\n      // Handle it asynchronously to allow scripts the opportunity to delay ready\n      return setTimeout( jQuery.ready, 1 );\n    }\n\n    // Mozilla, Opera and webkit nightlies currently support this event\n    if ( document.addEventListener ) {\n      // Use the handy event callback\n      document.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n      // A fallback to window.onload, that will always work\n      window.addEventListener( \"load\", jQuery.ready, false );\n\n    // If IE event model is used\n    } else if ( document.attachEvent ) {\n      // ensure firing before onload,\n      // maybe late but safe also for iframes\n      document.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n      // A fallback to window.onload, that will always work\n      window.attachEvent( \"onload\", jQuery.ready );\n\n      // If IE and not a frame\n      // continually check to see if the document is ready\n      var toplevel = false;\n\n      try {\n        toplevel = window.frameElement == null;\n      } catch(e) {}\n\n      if ( document.documentElement.doScroll && toplevel ) {\n        doScrollCheck();\n      }\n    }\n  },\n\n  // See test/unit/core.js for details concerning isFunction.\n  // Since version 1.3, DOM methods and functions like alert\n  // aren't supported. They return false on IE (#2968).\n  isFunction: function( obj ) {\n    return jQuery.type(obj) === \"function\";\n  },\n\n  isArray: Array.isArray || function( obj ) {\n    return jQuery.type(obj) === \"array\";\n  },\n\n  isWindow: function( obj ) {\n    return obj != null && obj == obj.window;\n  },\n\n  isNumeric: function( obj ) {\n    return !isNaN( parseFloat(obj) ) && isFinite( obj );\n  },\n\n  type: function( obj ) {\n    return obj == null ?\n      String( obj ) :\n      class2type[ toString.call(obj) ] || \"object\";\n  },\n\n  isPlainObject: function( obj ) {\n    // Must be an Object.\n    // Because of IE, we also have to check the presence of the constructor property.\n    // Make sure that DOM nodes and window objects don't pass through, as well\n    if ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n      return false;\n    }\n\n    try {\n      // Not own constructor property must be Object\n      if ( obj.constructor &&\n        !hasOwn.call(obj, \"constructor\") &&\n        !hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n        return false;\n      }\n    } catch ( e ) {\n      // IE8,9 Will throw exceptions on certain host objects #9897\n      return false;\n    }\n\n    // Own properties are enumerated firstly, so to speed up,\n    // if last one is own, then all properties are own.\n\n    var key;\n    for ( key in obj ) {}\n\n    return key === undefined || hasOwn.call( obj, key );\n  },\n\n  isEmptyObject: function( obj ) {\n    for ( var name in obj ) {\n      return false;\n    }\n    return true;\n  },\n\n  error: function( msg ) {\n    throw new Error( msg );\n  },\n\n  parseJSON: function( data ) {\n    if ( typeof data !== \"string\" || !data ) {\n      return null;\n    }\n\n    // Make sure leading/trailing whitespace is removed (IE can't handle it)\n    data = jQuery.trim( data );\n\n    // Attempt to parse using the native JSON parser first\n    if ( window.JSON && window.JSON.parse ) {\n      return window.JSON.parse( data );\n    }\n\n    // Make sure the incoming data is actual JSON\n    // Logic borrowed from http://json.org/json2.js\n    if ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n      .replace( rvalidtokens, \"]\" )\n      .replace( rvalidbraces, \"\")) ) {\n\n      return ( new Function( \"return \" + data ) )();\n\n    }\n    jQuery.error( \"Invalid JSON: \" + data );\n  },\n\n  // Cross-browser xml parsing\n  parseXML: function( data ) {\n    if ( typeof data !== \"string\" || !data ) {\n      return null;\n    }\n    var xml, tmp;\n    try {\n      if ( window.DOMParser ) { // Standard\n        tmp = new DOMParser();\n        xml = tmp.parseFromString( data , \"text/xml\" );\n      } else { // IE\n        xml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n        xml.async = \"false\";\n        xml.loadXML( data );\n      }\n    } catch( e ) {\n      xml = undefined;\n    }\n    if ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n      jQuery.error( \"Invalid XML: \" + data );\n    }\n    return xml;\n  },\n\n  noop: function() {},\n\n  // Evaluates a script in a global context\n  // Workarounds based on findings by Jim Driscoll\n  // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n  globalEval: function( data ) {\n    if ( data && rnotwhite.test( data ) ) {\n      // We use execScript on Internet Explorer\n      // We use an anonymous function so that context is window\n      // rather than jQuery in Firefox\n      ( window.execScript || function( data ) {\n        window[ \"eval\" ].call( window, data );\n      } )( data );\n    }\n  },\n\n  // Convert dashed to camelCase; used by the css and data modules\n  // Microsoft forgot to hump their vendor prefix (#9572)\n  camelCase: function( string ) {\n    return string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n  },\n\n  nodeName: function( elem, name ) {\n    return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n  },\n\n  // args is for internal usage only\n  each: function( object, callback, args ) {\n    var name, i = 0,\n      length = object.length,\n      isObj = length === undefined || jQuery.isFunction( object );\n\n    if ( args ) {\n      if ( isObj ) {\n        for ( name in object ) {\n          if ( callback.apply( object[ name ], args ) === false ) {\n            break;\n          }\n        }\n      } else {\n        for ( ; i < length; ) {\n          if ( callback.apply( object[ i++ ], args ) === false ) {\n            break;\n          }\n        }\n      }\n\n    // A special, fast, case for the most common use of each\n    } else {\n      if ( isObj ) {\n        for ( name in object ) {\n          if ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n            break;\n          }\n        }\n      } else {\n        for ( ; i < length; ) {\n          if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n            break;\n          }\n        }\n      }\n    }\n\n    return object;\n  },\n\n  // Use native String.trim function wherever possible\n  trim: trim ?\n    function( text ) {\n      return text == null ?\n        \"\" :\n        trim.call( text );\n    } :\n\n    // Otherwise use our own trimming functionality\n    function( text ) {\n      return text == null ?\n        \"\" :\n        text.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n    },\n\n  // results is for internal usage only\n  makeArray: function( array, results ) {\n    var ret = results || [];\n\n    if ( array != null ) {\n      // The window, strings (and functions) also have 'length'\n      // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n      var type = jQuery.type( array );\n\n      if ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n        push.call( ret, array );\n      } else {\n        jQuery.merge( ret, array );\n      }\n    }\n\n    return ret;\n  },\n\n  inArray: function( elem, array, i ) {\n    var len;\n\n    if ( array ) {\n      if ( indexOf ) {\n        return indexOf.call( array, elem, i );\n      }\n\n      len = array.length;\n      i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n      for ( ; i < len; i++ ) {\n        // Skip accessing in sparse arrays\n        if ( i in array && array[ i ] === elem ) {\n          return i;\n        }\n      }\n    }\n\n    return -1;\n  },\n\n  merge: function( first, second ) {\n    var i = first.length,\n      j = 0;\n\n    if ( typeof second.length === \"number\" ) {\n      for ( var l = second.length; j < l; j++ ) {\n        first[ i++ ] = second[ j ];\n      }\n\n    } else {\n      while ( second[j] !== undefined ) {\n        first[ i++ ] = second[ j++ ];\n      }\n    }\n\n    first.length = i;\n\n    return first;\n  },\n\n  grep: function( elems, callback, inv ) {\n    var ret = [], retVal;\n    inv = !!inv;\n\n    // Go through the array, only saving the items\n    // that pass the validator function\n    for ( var i = 0, length = elems.length; i < length; i++ ) {\n      retVal = !!callback( elems[ i ], i );\n      if ( inv !== retVal ) {\n        ret.push( elems[ i ] );\n      }\n    }\n\n    return ret;\n  },\n\n  // arg is for internal usage only\n  map: function( elems, callback, arg ) {\n    var value, key, ret = [],\n      i = 0,\n      length = elems.length,\n      // jquery objects are treated as arrays\n      isArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n    // Go through the array, translating each of the items to their\n    if ( isArray ) {\n      for ( ; i < length; i++ ) {\n        value = callback( elems[ i ], i, arg );\n\n        if ( value != null ) {\n          ret[ ret.length ] = value;\n        }\n      }\n\n    // Go through every key on the object,\n    } else {\n      for ( key in elems ) {\n        value = callback( elems[ key ], key, arg );\n\n        if ( value != null ) {\n          ret[ ret.length ] = value;\n        }\n      }\n    }\n\n    // Flatten any nested arrays\n    return ret.concat.apply( [], ret );\n  },\n\n  // A global GUID counter for objects\n  guid: 1,\n\n  // Bind a function to a context, optionally partially applying any\n  // arguments.\n  proxy: function( fn, context ) {\n    if ( typeof context === \"string\" ) {\n      var tmp = fn[ context ];\n      context = fn;\n      fn = tmp;\n    }\n\n    // Quick check to determine if target is callable, in the spec\n    // this throws a TypeError, but we will just return undefined.\n    if ( !jQuery.isFunction( fn ) ) {\n      return undefined;\n    }\n\n    // Simulated bind\n    var args = slice.call( arguments, 2 ),\n      proxy = function() {\n        return fn.apply( context, args.concat( slice.call( arguments ) ) );\n      };\n\n    // Set the guid of unique handler to the same of original handler, so it can be removed\n    proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n    return proxy;\n  },\n\n  // Mutifunctional method to get and set values to a collection\n  // The value/s can optionally be executed if it's a function\n  access: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n    var exec,\n      bulk = key == null,\n      i = 0,\n      length = elems.length;\n\n    // Sets many values\n    if ( key && typeof key === \"object\" ) {\n      for ( i in key ) {\n        jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n      }\n      chainable = 1;\n\n    // Sets one value\n    } else if ( value !== undefined ) {\n      // Optionally, function values get executed if exec is true\n      exec = pass === undefined && jQuery.isFunction( value );\n\n      if ( bulk ) {\n        // Bulk operations only iterate when executing function values\n        if ( exec ) {\n          exec = fn;\n          fn = function( elem, key, value ) {\n            return exec.call( jQuery( elem ), value );\n          };\n\n        // Otherwise they run against the entire set\n        } else {\n          fn.call( elems, value );\n          fn = null;\n        }\n      }\n\n      if ( fn ) {\n        for (; i < length; i++ ) {\n          fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n        }\n      }\n\n      chainable = 1;\n    }\n\n    return chainable ?\n      elems :\n\n      // Gets\n      bulk ?\n        fn.call( elems ) :\n        length ? fn( elems[0], key ) : emptyGet;\n  },\n\n  now: function() {\n    return ( new Date() ).getTime();\n  },\n\n  // Use of jQuery.browser is frowned upon.\n  // More details: http://docs.jquery.com/Utilities/jQuery.browser\n  uaMatch: function( ua ) {\n    ua = ua.toLowerCase();\n\n    var match = rwebkit.exec( ua ) ||\n      ropera.exec( ua ) ||\n      rmsie.exec( ua ) ||\n      ua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n      [];\n\n    return { browser: match[1] || \"\", version: match[2] || \"0\" };\n  },\n\n  sub: function() {\n    function jQuerySub( selector, context ) {\n      return new jQuerySub.fn.init( selector, context );\n    }\n    jQuery.extend( true, jQuerySub, this );\n    jQuerySub.superclass = this;\n    jQuerySub.fn = jQuerySub.prototype = this();\n    jQuerySub.fn.constructor = jQuerySub;\n    jQuerySub.sub = this.sub;\n    jQuerySub.fn.init = function init( selector, context ) {\n      if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n        context = jQuerySub( context );\n      }\n\n      return jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n    };\n    jQuerySub.fn.init.prototype = jQuerySub.fn;\n    var rootjQuerySub = jQuerySub(document);\n    return jQuerySub;\n  },\n\n  browser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n  class2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n  jQuery.browser[ browserMatch.browser ] = true;\n  jQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n  jQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n  trimLeft = /^[\\s\\xA0]+/;\n  trimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n  DOMContentLoaded = function() {\n    document.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n    jQuery.ready();\n  };\n\n} else if ( document.attachEvent ) {\n  DOMContentLoaded = function() {\n    // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n    if ( document.readyState === \"complete\" ) {\n      document.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n      jQuery.ready();\n    }\n  };\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n  if ( jQuery.isReady ) {\n    return;\n  }\n\n  try {\n    // If IE is used, use the trick by Diego Perini\n    // http://javascript.nwbox.com/IEContentLoaded/\n    document.documentElement.doScroll(\"left\");\n  } catch(e) {\n    setTimeout( doScrollCheck, 1 );\n    return;\n  }\n\n  // and execute any waiting functions\n  jQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n  var object = flagsCache[ flags ] = {},\n    i, length;\n  flags = flags.split( /\\s+/ );\n  for ( i = 0, length = flags.length; i < length; i++ ) {\n    object[ flags[i] ] = true;\n  }\n  return object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n  // Convert flags from String-formatted to Object-formatted\n  // (we check in cache first)\n  flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n  var // Actual callback list\n    list = [],\n    // Stack of fire calls for repeatable lists\n    stack = [],\n    // Last fire value (for non-forgettable lists)\n    memory,\n    // Flag to know if list was already fired\n    fired,\n    // Flag to know if list is currently firing\n    firing,\n    // First callback to fire (used internally by add and fireWith)\n    firingStart,\n    // End of the loop when firing\n    firingLength,\n    // Index of currently firing callback (modified by remove if needed)\n    firingIndex,\n    // Add one or several callbacks to the list\n    add = function( args ) {\n      var i,\n        length,\n        elem,\n        type,\n        actual;\n      for ( i = 0, length = args.length; i < length; i++ ) {\n        elem = args[ i ];\n        type = jQuery.type( elem );\n        if ( type === \"array\" ) {\n          // Inspect recursively\n          add( elem );\n        } else if ( type === \"function\" ) {\n          // Add if not in unique mode and callback is not in\n          if ( !flags.unique || !self.has( elem ) ) {\n            list.push( elem );\n          }\n        }\n      }\n    },\n    // Fire callbacks\n    fire = function( context, args ) {\n      args = args || [];\n      memory = !flags.memory || [ context, args ];\n      fired = true;\n      firing = true;\n      firingIndex = firingStart || 0;\n      firingStart = 0;\n      firingLength = list.length;\n      for ( ; list && firingIndex < firingLength; firingIndex++ ) {\n        if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n          memory = true; // Mark as halted\n          break;\n        }\n      }\n      firing = false;\n      if ( list ) {\n        if ( !flags.once ) {\n          if ( stack && stack.length ) {\n            memory = stack.shift();\n            self.fireWith( memory[ 0 ], memory[ 1 ] );\n          }\n        } else if ( memory === true ) {\n          self.disable();\n        } else {\n          list = [];\n        }\n      }\n    },\n    // Actual Callbacks object\n    self = {\n      // Add a callback or a collection of callbacks to the list\n      add: function() {\n        if ( list ) {\n          var length = list.length;\n          add( arguments );\n          // Do we need to add the callbacks to the\n          // current firing batch?\n          if ( firing ) {\n            firingLength = list.length;\n          // With memory, if we're not firing then\n          // we should call right away, unless previous\n          // firing was halted (stopOnFalse)\n          } else if ( memory && memory !== true ) {\n            firingStart = length;\n            fire( memory[ 0 ], memory[ 1 ] );\n          }\n        }\n        return this;\n      },\n      // Remove a callback from the list\n      remove: function() {\n        if ( list ) {\n          var args = arguments,\n            argIndex = 0,\n            argLength = args.length;\n          for ( ; argIndex < argLength ; argIndex++ ) {\n            for ( var i = 0; i < list.length; i++ ) {\n              if ( args[ argIndex ] === list[ i ] ) {\n                // Handle firingIndex and firingLength\n                if ( firing ) {\n                  if ( i <= firingLength ) {\n                    firingLength--;\n                    if ( i <= firingIndex ) {\n                      firingIndex--;\n                    }\n                  }\n                }\n                // Remove the element\n                list.splice( i--, 1 );\n                // If we have some unicity property then\n                // we only need to do this once\n                if ( flags.unique ) {\n                  break;\n                }\n              }\n            }\n          }\n        }\n        return this;\n      },\n      // Control if a given callback is in the list\n      has: function( fn ) {\n        if ( list ) {\n          var i = 0,\n            length = list.length;\n          for ( ; i < length; i++ ) {\n            if ( fn === list[ i ] ) {\n              return true;\n            }\n          }\n        }\n        return false;\n      },\n      // Remove all callbacks from the list\n      empty: function() {\n        list = [];\n        return this;\n      },\n      // Have the list do nothing anymore\n      disable: function() {\n        list = stack = memory = undefined;\n        return this;\n      },\n      // Is it disabled?\n      disabled: function() {\n        return !list;\n      },\n      // Lock the list in its current state\n      lock: function() {\n        stack = undefined;\n        if ( !memory || memory === true ) {\n          self.disable();\n        }\n        return this;\n      },\n      // Is it locked?\n      locked: function() {\n        return !stack;\n      },\n      // Call all callbacks with the given context and arguments\n      fireWith: function( context, args ) {\n        if ( stack ) {\n          if ( firing ) {\n            if ( !flags.once ) {\n              stack.push( [ context, args ] );\n            }\n          } else if ( !( flags.once && memory ) ) {\n            fire( context, args );\n          }\n        }\n        return this;\n      },\n      // Call all the callbacks with the given arguments\n      fire: function() {\n        self.fireWith( this, arguments );\n        return this;\n      },\n      // To know if the callbacks have already been called at least once\n      fired: function() {\n        return !!fired;\n      }\n    };\n\n  return self;\n};\n\n\n\n\nvar // Static reference to slice\n  sliceDeferred = [].slice;\n\njQuery.extend({\n\n  Deferred: function( func ) {\n    var doneList = jQuery.Callbacks( \"once memory\" ),\n      failList = jQuery.Callbacks( \"once memory\" ),\n      progressList = jQuery.Callbacks( \"memory\" ),\n      state = \"pending\",\n      lists = {\n        resolve: doneList,\n        reject: failList,\n        notify: progressList\n      },\n      promise = {\n        done: doneList.add,\n        fail: failList.add,\n        progress: progressList.add,\n\n        state: function() {\n          return state;\n        },\n\n        // Deprecated\n        isResolved: doneList.fired,\n        isRejected: failList.fired,\n\n        then: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n          deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n          return this;\n        },\n        always: function() {\n          deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n          return this;\n        },\n        pipe: function( fnDone, fnFail, fnProgress ) {\n          return jQuery.Deferred(function( newDefer ) {\n            jQuery.each( {\n              done: [ fnDone, \"resolve\" ],\n              fail: [ fnFail, \"reject\" ],\n              progress: [ fnProgress, \"notify\" ]\n            }, function( handler, data ) {\n              var fn = data[ 0 ],\n                action = data[ 1 ],\n                returned;\n              if ( jQuery.isFunction( fn ) ) {\n                deferred[ handler ](function() {\n                  returned = fn.apply( this, arguments );\n                  if ( returned && jQuery.isFunction( returned.promise ) ) {\n                    returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n                  } else {\n                    newDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n                  }\n                });\n              } else {\n                deferred[ handler ]( newDefer[ action ] );\n              }\n            });\n          }).promise();\n        },\n        // Get a promise for this deferred\n        // If obj is provided, the promise aspect is added to the object\n        promise: function( obj ) {\n          if ( obj == null ) {\n            obj = promise;\n          } else {\n            for ( var key in promise ) {\n              obj[ key ] = promise[ key ];\n            }\n          }\n          return obj;\n        }\n      },\n      deferred = promise.promise({}),\n      key;\n\n    for ( key in lists ) {\n      deferred[ key ] = lists[ key ].fire;\n      deferred[ key + \"With\" ] = lists[ key ].fireWith;\n    }\n\n    // Handle state\n    deferred.done( function() {\n      state = \"resolved\";\n    }, failList.disable, progressList.lock ).fail( function() {\n      state = \"rejected\";\n    }, doneList.disable, progressList.lock );\n\n    // Call given func if any\n    if ( func ) {\n      func.call( deferred, deferred );\n    }\n\n    // All done!\n    return deferred;\n  },\n\n  // Deferred helper\n  when: function( firstParam ) {\n    var args = sliceDeferred.call( arguments, 0 ),\n      i = 0,\n      length = args.length,\n      pValues = new Array( length ),\n      count = length,\n      pCount = length,\n      deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n        firstParam :\n        jQuery.Deferred(),\n      promise = deferred.promise();\n    function resolveFunc( i ) {\n      return function( value ) {\n        args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n        if ( !( --count ) ) {\n          deferred.resolveWith( deferred, args );\n        }\n      };\n    }\n    function progressFunc( i ) {\n      return function( value ) {\n        pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n        deferred.notifyWith( promise, pValues );\n      };\n    }\n    if ( length > 1 ) {\n      for ( ; i < length; i++ ) {\n        if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n          args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n        } else {\n          --count;\n        }\n      }\n      if ( !count ) {\n        deferred.resolveWith( deferred, args );\n      }\n    } else if ( deferred !== firstParam ) {\n      deferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n    }\n    return promise;\n  }\n});\n\n\n\n\njQuery.support = (function() {\n\n  var support,\n    all,\n    a,\n    select,\n    opt,\n    input,\n    fragment,\n    tds,\n    events,\n    eventName,\n    i,\n    isSupported,\n    div = document.createElement( \"div\" ),\n    documentElement = document.documentElement;\n\n  // Preliminary tests\n  div.setAttribute(\"className\", \"t\");\n  div.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n  all = div.getElementsByTagName( \"*\" );\n  a = div.getElementsByTagName( \"a\" )[ 0 ];\n\n  // Can't get basic test support\n  if ( !all || !all.length || !a ) {\n    return {};\n  }\n\n  // First batch of supports tests\n  select = document.createElement( \"select\" );\n  opt = select.appendChild( document.createElement(\"option\") );\n  input = div.getElementsByTagName( \"input\" )[ 0 ];\n\n  support = {\n    // IE strips leading whitespace when .innerHTML is used\n    leadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n    // Make sure that tbody elements aren't automatically inserted\n    // IE will insert them into empty tables\n    tbody: !div.getElementsByTagName(\"tbody\").length,\n\n    // Make sure that link elements get serialized correctly by innerHTML\n    // This requires a wrapper element in IE\n    htmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n    // Get the style information from getAttribute\n    // (IE uses .cssText instead)\n    style: /top/.test( a.getAttribute(\"style\") ),\n\n    // Make sure that URLs aren't manipulated\n    // (IE normalizes it by default)\n    hrefNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n    // Make sure that element opacity exists\n    // (IE uses filter instead)\n    // Use a regex to work around a WebKit issue. See #5145\n    opacity: /^0.55/.test( a.style.opacity ),\n\n    // Verify style float existence\n    // (IE uses styleFloat instead of cssFloat)\n    cssFloat: !!a.style.cssFloat,\n\n    // Make sure that if no value is specified for a checkbox\n    // that it defaults to \"on\".\n    // (WebKit defaults to \"\" instead)\n    checkOn: ( input.value === \"on\" ),\n\n    // Make sure that a selected-by-default option has a working selected property.\n    // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n    optSelected: opt.selected,\n\n    // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n    getSetAttribute: div.className !== \"t\",\n\n    // Tests for enctype support on a form(#6743)\n    enctype: !!document.createElement(\"form\").enctype,\n\n    // Makes sure cloning an html5 element does not cause problems\n    // Where outerHTML is undefined, this still works\n    html5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n    // Will be defined later\n    submitBubbles: true,\n    changeBubbles: true,\n    focusinBubbles: false,\n    deleteExpando: true,\n    noCloneEvent: true,\n    inlineBlockNeedsLayout: false,\n    shrinkWrapBlocks: false,\n    reliableMarginRight: true,\n    pixelMargin: true\n  };\n\n  // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n  jQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n  // Make sure checked status is properly cloned\n  input.checked = true;\n  support.noCloneChecked = input.cloneNode( true ).checked;\n\n  // Make sure that the options inside disabled selects aren't marked as disabled\n  // (WebKit marks them as disabled)\n  select.disabled = true;\n  support.optDisabled = !opt.disabled;\n\n  // Test to see if it's possible to delete an expando from an element\n  // Fails in Internet Explorer\n  try {\n    delete div.test;\n  } catch( e ) {\n    support.deleteExpando = false;\n  }\n\n  if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n    div.attachEvent( \"onclick\", function() {\n      // Cloning a node shouldn't copy over any\n      // bound event handlers (IE does this)\n      support.noCloneEvent = false;\n    });\n    div.cloneNode( true ).fireEvent( \"onclick\" );\n  }\n\n  // Check if a radio maintains its value\n  // after being appended to the DOM\n  input = document.createElement(\"input\");\n  input.value = \"t\";\n  input.setAttribute(\"type\", \"radio\");\n  support.radioValue = input.value === \"t\";\n\n  input.setAttribute(\"checked\", \"checked\");\n\n  // #11217 - WebKit loses check when the name is after the checked attribute\n  input.setAttribute( \"name\", \"t\" );\n\n  div.appendChild( input );\n  fragment = document.createDocumentFragment();\n  fragment.appendChild( div.lastChild );\n\n  // WebKit doesn't clone checked state correctly in fragments\n  support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n  // Check if a disconnected checkbox will retain its checked\n  // value of true after appended to the DOM (IE6/7)\n  support.appendChecked = input.checked;\n\n  fragment.removeChild( input );\n  fragment.appendChild( div );\n\n  // Technique from Juriy Zaytsev\n  // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n  // We only care about the case where non-standard event systems\n  // are used, namely in IE. Short-circuiting here helps us to\n  // avoid an eval call (in setAttribute) which can cause CSP\n  // to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n  if ( div.attachEvent ) {\n    for ( i in {\n      submit: 1,\n      change: 1,\n      focusin: 1\n    }) {\n      eventName = \"on\" + i;\n      isSupported = ( eventName in div );\n      if ( !isSupported ) {\n        div.setAttribute( eventName, \"return;\" );\n        isSupported = ( typeof div[ eventName ] === \"function\" );\n      }\n      support[ i + \"Bubbles\" ] = isSupported;\n    }\n  }\n\n  fragment.removeChild( div );\n\n  // Null elements to avoid leaks in IE\n  fragment = select = opt = div = input = null;\n\n  // Run tests that need a body at doc ready\n  jQuery(function() {\n    var container, outer, inner, table, td, offsetSupport,\n      marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n      paddingMarginBorderVisibility, paddingMarginBorder,\n      body = document.getElementsByTagName(\"body\")[0];\n\n    if ( !body ) {\n      // Return for frameset docs that don't have a body\n      return;\n    }\n\n    conMarginTop = 1;\n    paddingMarginBorder = \"padding:0;margin:0;border:\";\n    positionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n    paddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n    style = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n    html = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n      \"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n      \"<tr><td></td></tr></table>\";\n\n    container = document.createElement(\"div\");\n    container.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n    body.insertBefore( container, body.firstChild );\n\n    // Construct the test element\n    div = document.createElement(\"div\");\n    container.appendChild( div );\n\n    // Check if table cells still have offsetWidth/Height when they are set\n    // to display:none and there are still other visible table cells in a\n    // table row; if so, offsetWidth/Height are not reliable for use when\n    // determining if an element has been hidden directly using\n    // display:none (it is still safe to use offsets if a parent element is\n    // hidden; don safety goggles and see bug #4512 for more information).\n    // (only IE 8 fails this test)\n    div.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n    tds = div.getElementsByTagName( \"td\" );\n    isSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n    tds[ 0 ].style.display = \"\";\n    tds[ 1 ].style.display = \"none\";\n\n    // Check if empty table cells still have offsetWidth/Height\n    // (IE <= 8 fail this test)\n    support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n    // Check if div with explicit width and no margin-right incorrectly\n    // gets computed margin-right based on width of container. For more\n    // info see bug #3333\n    // Fails in WebKit before Feb 2011 nightlies\n    // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n    if ( window.getComputedStyle ) {\n      div.innerHTML = \"\";\n      marginDiv = document.createElement( \"div\" );\n      marginDiv.style.width = \"0\";\n      marginDiv.style.marginRight = \"0\";\n      div.style.width = \"2px\";\n      div.appendChild( marginDiv );\n      support.reliableMarginRight =\n        ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n    }\n\n    if ( typeof div.style.zoom !== \"undefined\" ) {\n      // Check if natively block-level elements act like inline-block\n      // elements when setting their display to 'inline' and giving\n      // them layout\n      // (IE < 8 does this)\n      div.innerHTML = \"\";\n      div.style.width = div.style.padding = \"1px\";\n      div.style.border = 0;\n      div.style.overflow = \"hidden\";\n      div.style.display = \"inline\";\n      div.style.zoom = 1;\n      support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n      // Check if elements with layout shrink-wrap their children\n      // (IE 6 does this)\n      div.style.display = \"block\";\n      div.style.overflow = \"visible\";\n      div.innerHTML = \"<div style='width:5px;'></div>\";\n      support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n    }\n\n    div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n    div.innerHTML = html;\n\n    outer = div.firstChild;\n    inner = outer.firstChild;\n    td = outer.nextSibling.firstChild.firstChild;\n\n    offsetSupport = {\n      doesNotAddBorder: ( inner.offsetTop !== 5 ),\n      doesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n    };\n\n    inner.style.position = \"fixed\";\n    inner.style.top = \"20px\";\n\n    // safari subtracts parent border width here which is 5px\n    offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n    inner.style.position = inner.style.top = \"\";\n\n    outer.style.overflow = \"hidden\";\n    outer.style.position = \"relative\";\n\n    offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n    offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n    if ( window.getComputedStyle ) {\n      div.style.marginTop = \"1%\";\n      support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n    }\n\n    if ( typeof container.style.zoom !== \"undefined\" ) {\n      container.style.zoom = 1;\n    }\n\n    body.removeChild( container );\n    marginDiv = div = container = null;\n\n    jQuery.extend( support, offsetSupport );\n  });\n\n  return support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n  rmultiDash = /([A-Z])/g;\n\njQuery.extend({\n  cache: {},\n\n  // Please use with caution\n  uuid: 0,\n\n  // Unique for each copy of jQuery on the page\n  // Non-digits removed to match rinlinejQuery\n  expando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n  // The following elements throw uncatchable exceptions if you\n  // attempt to add expando properties to them.\n  noData: {\n    \"embed\": true,\n    // Ban all objects except for Flash (which handle expandos)\n    \"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n    \"applet\": true\n  },\n\n  hasData: function( elem ) {\n    elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n    return !!elem && !isEmptyDataObject( elem );\n  },\n\n  data: function( elem, name, data, pvt /* Internal Use Only */ ) {\n    if ( !jQuery.acceptData( elem ) ) {\n      return;\n    }\n\n    var privateCache, thisCache, ret,\n      internalKey = jQuery.expando,\n      getByName = typeof name === \"string\",\n\n      // We have to handle DOM nodes and JS objects differently because IE6-7\n      // can't GC object references properly across the DOM-JS boundary\n      isNode = elem.nodeType,\n\n      // Only DOM nodes need the global jQuery cache; JS object data is\n      // attached directly to the object so GC can occur automatically\n      cache = isNode ? jQuery.cache : elem,\n\n      // Only defining an ID for JS objects if its cache already exists allows\n      // the code to shortcut on the same path as a DOM node with no cache\n      id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n      isEvents = name === \"events\";\n\n    // Avoid doing any more work than we need to when trying to get data on an\n    // object that has no data at all\n    if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n      return;\n    }\n\n    if ( !id ) {\n      // Only DOM nodes need a new unique ID for each element since their data\n      // ends up in the global cache\n      if ( isNode ) {\n        elem[ internalKey ] = id = ++jQuery.uuid;\n      } else {\n        id = internalKey;\n      }\n    }\n\n    if ( !cache[ id ] ) {\n      cache[ id ] = {};\n\n      // Avoids exposing jQuery metadata on plain JS objects when the object\n      // is serialized using JSON.stringify\n      if ( !isNode ) {\n        cache[ id ].toJSON = jQuery.noop;\n      }\n    }\n\n    // An object can be passed to jQuery.data instead of a key/value pair; this gets\n    // shallow copied over onto the existing cache\n    if ( typeof name === \"object\" || typeof name === \"function\" ) {\n      if ( pvt ) {\n        cache[ id ] = jQuery.extend( cache[ id ], name );\n      } else {\n        cache[ id ].data = jQuery.extend( cache[ id ].data, name );\n      }\n    }\n\n    privateCache = thisCache = cache[ id ];\n\n    // jQuery data() is stored in a separate object inside the object's internal data\n    // cache in order to avoid key collisions between internal data and user-defined\n    // data.\n    if ( !pvt ) {\n      if ( !thisCache.data ) {\n        thisCache.data = {};\n      }\n\n      thisCache = thisCache.data;\n    }\n\n    if ( data !== undefined ) {\n      thisCache[ jQuery.camelCase( name ) ] = data;\n    }\n\n    // Users should not attempt to inspect the internal events object using jQuery.data,\n    // it is undocumented and subject to change. But does anyone listen? No.\n    if ( isEvents && !thisCache[ name ] ) {\n      return privateCache.events;\n    }\n\n    // Check for both converted-to-camel and non-converted data property names\n    // If a data property was specified\n    if ( getByName ) {\n\n      // First Try to find as-is property data\n      ret = thisCache[ name ];\n\n      // Test for null|undefined property data\n      if ( ret == null ) {\n\n        // Try to find the camelCased property\n        ret = thisCache[ jQuery.camelCase( name ) ];\n      }\n    } else {\n      ret = thisCache;\n    }\n\n    return ret;\n  },\n\n  removeData: function( elem, name, pvt /* Internal Use Only */ ) {\n    if ( !jQuery.acceptData( elem ) ) {\n      return;\n    }\n\n    var thisCache, i, l,\n\n      // Reference to internal data cache key\n      internalKey = jQuery.expando,\n\n      isNode = elem.nodeType,\n\n      // See jQuery.data for more information\n      cache = isNode ? jQuery.cache : elem,\n\n      // See jQuery.data for more information\n      id = isNode ? elem[ internalKey ] : internalKey;\n\n    // If there is already no cache entry for this object, there is no\n    // purpose in continuing\n    if ( !cache[ id ] ) {\n      return;\n    }\n\n    if ( name ) {\n\n      thisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n      if ( thisCache ) {\n\n        // Support array or space separated string names for data keys\n        if ( !jQuery.isArray( name ) ) {\n\n          // try the string as a key before any manipulation\n          if ( name in thisCache ) {\n            name = [ name ];\n          } else {\n\n            // split the camel cased version by spaces unless a key with the spaces exists\n            name = jQuery.camelCase( name );\n            if ( name in thisCache ) {\n              name = [ name ];\n            } else {\n              name = name.split( \" \" );\n            }\n          }\n        }\n\n        for ( i = 0, l = name.length; i < l; i++ ) {\n          delete thisCache[ name[i] ];\n        }\n\n        // If there is no data left in the cache, we want to continue\n        // and let the cache object itself get destroyed\n        if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n          return;\n        }\n      }\n    }\n\n    // See jQuery.data for more information\n    if ( !pvt ) {\n      delete cache[ id ].data;\n\n      // Don't destroy the parent cache unless the internal data object\n      // had been the only thing left in it\n      if ( !isEmptyDataObject(cache[ id ]) ) {\n        return;\n      }\n    }\n\n    // Browsers that fail expando deletion also refuse to delete expandos on\n    // the window, but it will allow it on all other JS objects; other browsers\n    // don't care\n    // Ensure that `cache` is not a window object #10080\n    if ( jQuery.support.deleteExpando || !cache.setInterval ) {\n      delete cache[ id ];\n    } else {\n      cache[ id ] = null;\n    }\n\n    // We destroyed the cache and need to eliminate the expando on the node to avoid\n    // false lookups in the cache for entries that no longer exist\n    if ( isNode ) {\n      // IE does not allow us to delete expando properties from nodes,\n      // nor does it have a removeAttribute function on Document nodes;\n      // we must handle all of these cases\n      if ( jQuery.support.deleteExpando ) {\n        delete elem[ internalKey ];\n      } else if ( elem.removeAttribute ) {\n        elem.removeAttribute( internalKey );\n      } else {\n        elem[ internalKey ] = null;\n      }\n    }\n  },\n\n  // For internal use only.\n  _data: function( elem, name, data ) {\n    return jQuery.data( elem, name, data, true );\n  },\n\n  // A method for determining if a DOM node can handle the data expando\n  acceptData: function( elem ) {\n    if ( elem.nodeName ) {\n      var match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n      if ( match ) {\n        return !(match === true || elem.getAttribute(\"classid\") !== match);\n      }\n    }\n\n    return true;\n  }\n});\n\njQuery.fn.extend({\n  data: function( key, value ) {\n    var parts, part, attr, name, l,\n      elem = this[0],\n      i = 0,\n      data = null;\n\n    // Gets all values\n    if ( key === undefined ) {\n      if ( this.length ) {\n        data = jQuery.data( elem );\n\n        if ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n          attr = elem.attributes;\n          for ( l = attr.length; i < l; i++ ) {\n            name = attr[i].name;\n\n            if ( name.indexOf( \"data-\" ) === 0 ) {\n              name = jQuery.camelCase( name.substring(5) );\n\n              dataAttr( elem, name, data[ name ] );\n            }\n          }\n          jQuery._data( elem, \"parsedAttrs\", true );\n        }\n      }\n\n      return data;\n    }\n\n    // Sets multiple values\n    if ( typeof key === \"object\" ) {\n      return this.each(function() {\n        jQuery.data( this, key );\n      });\n    }\n\n    parts = key.split( \".\", 2 );\n    parts[1] = parts[1] ? \".\" + parts[1] : \"\";\n    part = parts[1] + \"!\";\n\n    return jQuery.access( this, function( value ) {\n\n      if ( value === undefined ) {\n        data = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n        // Try to fetch any internally stored data first\n        if ( data === undefined && elem ) {\n          data = jQuery.data( elem, key );\n          data = dataAttr( elem, key, data );\n        }\n\n        return data === undefined && parts[1] ?\n          this.data( parts[0] ) :\n          data;\n      }\n\n      parts[1] = value;\n      this.each(function() {\n        var self = jQuery( this );\n\n        self.triggerHandler( \"setData\" + part, parts );\n        jQuery.data( this, key, value );\n        self.triggerHandler( \"changeData\" + part, parts );\n      });\n    }, null, value, arguments.length > 1, null, false );\n  },\n\n  removeData: function( key ) {\n    return this.each(function() {\n      jQuery.removeData( this, key );\n    });\n  }\n});\n\nfunction dataAttr( elem, key, data ) {\n  // If nothing was found internally, try to fetch any\n  // data from the HTML5 data-* attribute\n  if ( data === undefined && elem.nodeType === 1 ) {\n\n    var name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n    data = elem.getAttribute( name );\n\n    if ( typeof data === \"string\" ) {\n      try {\n        data = data === \"true\" ? true :\n        data === \"false\" ? false :\n        data === \"null\" ? null :\n        jQuery.isNumeric( data ) ? +data :\n          rbrace.test( data ) ? jQuery.parseJSON( data ) :\n          data;\n      } catch( e ) {}\n\n      // Make sure we set the data so it isn't changed later\n      jQuery.data( elem, key, data );\n\n    } else {\n      data = undefined;\n    }\n  }\n\n  return data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n  for ( var name in obj ) {\n\n    // if the public data object is empty, the private is still empty\n    if ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n      continue;\n    }\n    if ( name !== \"toJSON\" ) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n  var deferDataKey = type + \"defer\",\n    queueDataKey = type + \"queue\",\n    markDataKey = type + \"mark\",\n    defer = jQuery._data( elem, deferDataKey );\n  if ( defer &&\n    ( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n    ( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n    // Give room for hard-coded callbacks to fire first\n    // and eventually mark/queue something else on the element\n    setTimeout( function() {\n      if ( !jQuery._data( elem, queueDataKey ) &&\n        !jQuery._data( elem, markDataKey ) ) {\n        jQuery.removeData( elem, deferDataKey, true );\n        defer.fire();\n      }\n    }, 0 );\n  }\n}\n\njQuery.extend({\n\n  _mark: function( elem, type ) {\n    if ( elem ) {\n      type = ( type || \"fx\" ) + \"mark\";\n      jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n    }\n  },\n\n  _unmark: function( force, elem, type ) {\n    if ( force !== true ) {\n      type = elem;\n      elem = force;\n      force = false;\n    }\n    if ( elem ) {\n      type = type || \"fx\";\n      var key = type + \"mark\",\n        count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n      if ( count ) {\n        jQuery._data( elem, key, count );\n      } else {\n        jQuery.removeData( elem, key, true );\n        handleQueueMarkDefer( elem, type, \"mark\" );\n      }\n    }\n  },\n\n  queue: function( elem, type, data ) {\n    var q;\n    if ( elem ) {\n      type = ( type || \"fx\" ) + \"queue\";\n      q = jQuery._data( elem, type );\n\n      // Speed up dequeue by getting out quickly if this is just a lookup\n      if ( data ) {\n        if ( !q || jQuery.isArray(data) ) {\n          q = jQuery._data( elem, type, jQuery.makeArray(data) );\n        } else {\n          q.push( data );\n        }\n      }\n      return q || [];\n    }\n  },\n\n  dequeue: function( elem, type ) {\n    type = type || \"fx\";\n\n    var queue = jQuery.queue( elem, type ),\n      fn = queue.shift(),\n      hooks = {};\n\n    // If the fx queue is dequeued, always remove the progress sentinel\n    if ( fn === \"inprogress\" ) {\n      fn = queue.shift();\n    }\n\n    if ( fn ) {\n      // Add a progress sentinel to prevent the fx queue from being\n      // automatically dequeued\n      if ( type === \"fx\" ) {\n        queue.unshift( \"inprogress\" );\n      }\n\n      jQuery._data( elem, type + \".run\", hooks );\n      fn.call( elem, function() {\n        jQuery.dequeue( elem, type );\n      }, hooks );\n    }\n\n    if ( !queue.length ) {\n      jQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n      handleQueueMarkDefer( elem, type, \"queue\" );\n    }\n  }\n});\n\njQuery.fn.extend({\n  queue: function( type, data ) {\n    var setter = 2;\n\n    if ( typeof type !== \"string\" ) {\n      data = type;\n      type = \"fx\";\n      setter--;\n    }\n\n    if ( arguments.length < setter ) {\n      return jQuery.queue( this[0], type );\n    }\n\n    return data === undefined ?\n      this :\n      this.each(function() {\n        var queue = jQuery.queue( this, type, data );\n\n        if ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n          jQuery.dequeue( this, type );\n        }\n      });\n  },\n  dequeue: function( type ) {\n    return this.each(function() {\n      jQuery.dequeue( this, type );\n    });\n  },\n  // Based off of the plugin by Clint Helfers, with permission.\n  // http://blindsignals.com/index.php/2009/07/jquery-delay/\n  delay: function( time, type ) {\n    time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n    type = type || \"fx\";\n\n    return this.queue( type, function( next, hooks ) {\n      var timeout = setTimeout( next, time );\n      hooks.stop = function() {\n        clearTimeout( timeout );\n      };\n    });\n  },\n  clearQueue: function( type ) {\n    return this.queue( type || \"fx\", [] );\n  },\n  // Get a promise resolved when queues of a certain type\n  // are emptied (fx is the type by default)\n  promise: function( type, object ) {\n    if ( typeof type !== \"string\" ) {\n      object = type;\n      type = undefined;\n    }\n    type = type || \"fx\";\n    var defer = jQuery.Deferred(),\n      elements = this,\n      i = elements.length,\n      count = 1,\n      deferDataKey = type + \"defer\",\n      queueDataKey = type + \"queue\",\n      markDataKey = type + \"mark\",\n      tmp;\n    function resolve() {\n      if ( !( --count ) ) {\n        defer.resolveWith( elements, [ elements ] );\n      }\n    }\n    while( i-- ) {\n      if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n          ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n            jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n          jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n        count++;\n        tmp.add( resolve );\n      }\n    }\n    resolve();\n    return defer.promise( object );\n  }\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n  rspace = /\\s+/,\n  rreturn = /\\r/g,\n  rtype = /^(?:button|input)$/i,\n  rfocusable = /^(?:button|input|object|select|textarea)$/i,\n  rclickable = /^a(?:rea)?$/i,\n  rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n  getSetAttribute = jQuery.support.getSetAttribute,\n  nodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n  attr: function( name, value ) {\n    return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n  },\n\n  removeAttr: function( name ) {\n    return this.each(function() {\n      jQuery.removeAttr( this, name );\n    });\n  },\n\n  prop: function( name, value ) {\n    return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n  },\n\n  removeProp: function( name ) {\n    name = jQuery.propFix[ name ] || name;\n    return this.each(function() {\n      // try/catch handles cases where IE balks (such as removing a property on window)\n      try {\n        this[ name ] = undefined;\n        delete this[ name ];\n      } catch( e ) {}\n    });\n  },\n\n  addClass: function( value ) {\n    var classNames, i, l, elem,\n      setClass, c, cl;\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( j ) {\n        jQuery( this ).addClass( value.call(this, j, this.className) );\n      });\n    }\n\n    if ( value && typeof value === \"string\" ) {\n      classNames = value.split( rspace );\n\n      for ( i = 0, l = this.length; i < l; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.nodeType === 1 ) {\n          if ( !elem.className && classNames.length === 1 ) {\n            elem.className = value;\n\n          } else {\n            setClass = \" \" + elem.className + \" \";\n\n            for ( c = 0, cl = classNames.length; c < cl; c++ ) {\n              if ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n                setClass += classNames[ c ] + \" \";\n              }\n            }\n            elem.className = jQuery.trim( setClass );\n          }\n        }\n      }\n    }\n\n    return this;\n  },\n\n  removeClass: function( value ) {\n    var classNames, i, l, elem, className, c, cl;\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( j ) {\n        jQuery( this ).removeClass( value.call(this, j, this.className) );\n      });\n    }\n\n    if ( (value && typeof value === \"string\") || value === undefined ) {\n      classNames = ( value || \"\" ).split( rspace );\n\n      for ( i = 0, l = this.length; i < l; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.nodeType === 1 && elem.className ) {\n          if ( value ) {\n            className = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n            for ( c = 0, cl = classNames.length; c < cl; c++ ) {\n              className = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n            }\n            elem.className = jQuery.trim( className );\n\n          } else {\n            elem.className = \"\";\n          }\n        }\n      }\n    }\n\n    return this;\n  },\n\n  toggleClass: function( value, stateVal ) {\n    var type = typeof value,\n      isBool = typeof stateVal === \"boolean\";\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( i ) {\n        jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n      });\n    }\n\n    return this.each(function() {\n      if ( type === \"string\" ) {\n        // toggle individual class names\n        var className,\n          i = 0,\n          self = jQuery( this ),\n          state = stateVal,\n          classNames = value.split( rspace );\n\n        while ( (className = classNames[ i++ ]) ) {\n          // check each className given, space seperated list\n          state = isBool ? state : !self.hasClass( className );\n          self[ state ? \"addClass\" : \"removeClass\" ]( className );\n        }\n\n      } else if ( type === \"undefined\" || type === \"boolean\" ) {\n        if ( this.className ) {\n          // store className if set\n          jQuery._data( this, \"__className__\", this.className );\n        }\n\n        // toggle whole className\n        this.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n      }\n    });\n  },\n\n  hasClass: function( selector ) {\n    var className = \" \" + selector + \" \",\n      i = 0,\n      l = this.length;\n    for ( ; i < l; i++ ) {\n      if ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n        return true;\n      }\n    }\n\n    return false;\n  },\n\n  val: function( value ) {\n    var hooks, ret, isFunction,\n      elem = this[0];\n\n    if ( !arguments.length ) {\n      if ( elem ) {\n        hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n        if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n          return ret;\n        }\n\n        ret = elem.value;\n\n        return typeof ret === \"string\" ?\n          // handle most common string cases\n          ret.replace(rreturn, \"\") :\n          // handle cases where value is null/undef or number\n          ret == null ? \"\" : ret;\n      }\n\n      return;\n    }\n\n    isFunction = jQuery.isFunction( value );\n\n    return this.each(function( i ) {\n      var self = jQuery(this), val;\n\n      if ( this.nodeType !== 1 ) {\n        return;\n      }\n\n      if ( isFunction ) {\n        val = value.call( this, i, self.val() );\n      } else {\n        val = value;\n      }\n\n      // Treat null/undefined as \"\"; convert numbers to string\n      if ( val == null ) {\n        val = \"\";\n      } else if ( typeof val === \"number\" ) {\n        val += \"\";\n      } else if ( jQuery.isArray( val ) ) {\n        val = jQuery.map(val, function ( value ) {\n          return value == null ? \"\" : value + \"\";\n        });\n      }\n\n      hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n      // If set returns undefined, fall back to normal setting\n      if ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n        this.value = val;\n      }\n    });\n  }\n});\n\njQuery.extend({\n  valHooks: {\n    option: {\n      get: function( elem ) {\n        // attributes.value is undefined in Blackberry 4.7 but\n        // uses .value. See #6932\n        var val = elem.attributes.value;\n        return !val || val.specified ? elem.value : elem.text;\n      }\n    },\n    select: {\n      get: function( elem ) {\n        var value, i, max, option,\n          index = elem.selectedIndex,\n          values = [],\n          options = elem.options,\n          one = elem.type === \"select-one\";\n\n        // Nothing was selected\n        if ( index < 0 ) {\n          return null;\n        }\n\n        // Loop through all the selected options\n        i = one ? index : 0;\n        max = one ? index + 1 : options.length;\n        for ( ; i < max; i++ ) {\n          option = options[ i ];\n\n          // Don't return options that are disabled or in a disabled optgroup\n          if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n              (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n            // Get the specific value for the option\n            value = jQuery( option ).val();\n\n            // We don't need an array for one selects\n            if ( one ) {\n              return value;\n            }\n\n            // Multi-Selects return an array\n            values.push( value );\n          }\n        }\n\n        // Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n        if ( one && !values.length && options.length ) {\n          return jQuery( options[ index ] ).val();\n        }\n\n        return values;\n      },\n\n      set: function( elem, value ) {\n        var values = jQuery.makeArray( value );\n\n        jQuery(elem).find(\"option\").each(function() {\n          this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n        });\n\n        if ( !values.length ) {\n          elem.selectedIndex = -1;\n        }\n        return values;\n      }\n    }\n  },\n\n  attrFn: {\n    val: true,\n    css: true,\n    html: true,\n    text: true,\n    data: true,\n    width: true,\n    height: true,\n    offset: true\n  },\n\n  attr: function( elem, name, value, pass ) {\n    var ret, hooks, notxml,\n      nType = elem.nodeType;\n\n    // don't get/set attributes on text, comment and attribute nodes\n    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n      return;\n    }\n\n    if ( pass && name in jQuery.attrFn ) {\n      return jQuery( elem )[ name ]( value );\n    }\n\n    // Fallback to prop when attributes are not supported\n    if ( typeof elem.getAttribute === \"undefined\" ) {\n      return jQuery.prop( elem, name, value );\n    }\n\n    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n    // All attributes are lowercase\n    // Grab necessary hook if one is defined\n    if ( notxml ) {\n      name = name.toLowerCase();\n      hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n    }\n\n    if ( value !== undefined ) {\n\n      if ( value === null ) {\n        jQuery.removeAttr( elem, name );\n        return;\n\n      } else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n        return ret;\n\n      } else {\n        elem.setAttribute( name, \"\" + value );\n        return value;\n      }\n\n    } else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n      return ret;\n\n    } else {\n\n      ret = elem.getAttribute( name );\n\n      // Non-existent attributes return null, we normalize to undefined\n      return ret === null ?\n        undefined :\n        ret;\n    }\n  },\n\n  removeAttr: function( elem, value ) {\n    var propName, attrNames, name, l, isBool,\n      i = 0;\n\n    if ( value && elem.nodeType === 1 ) {\n      attrNames = value.toLowerCase().split( rspace );\n      l = attrNames.length;\n\n      for ( ; i < l; i++ ) {\n        name = attrNames[ i ];\n\n        if ( name ) {\n          propName = jQuery.propFix[ name ] || name;\n          isBool = rboolean.test( name );\n\n          // See #9699 for explanation of this approach (setting first, then removal)\n          // Do not do this for boolean attributes (see #10870)\n          if ( !isBool ) {\n            jQuery.attr( elem, name, \"\" );\n          }\n          elem.removeAttribute( getSetAttribute ? name : propName );\n\n          // Set corresponding property to false for boolean attributes\n          if ( isBool && propName in elem ) {\n            elem[ propName ] = false;\n          }\n        }\n      }\n    }\n  },\n\n  attrHooks: {\n    type: {\n      set: function( elem, value ) {\n        // We can't allow the type property to be changed (since it causes problems in IE)\n        if ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n          jQuery.error( \"type property can't be changed\" );\n        } else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n          // Setting the type on a radio button after the value resets the value in IE6-9\n          // Reset value to it's default in case type is set after value\n          // This is for element creation\n          var val = elem.value;\n          elem.setAttribute( \"type\", value );\n          if ( val ) {\n            elem.value = val;\n          }\n          return value;\n        }\n      }\n    },\n    // Use the value property for back compat\n    // Use the nodeHook for button elements in IE6/7 (#1954)\n    value: {\n      get: function( elem, name ) {\n        if ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n          return nodeHook.get( elem, name );\n        }\n        return name in elem ?\n          elem.value :\n          null;\n      },\n      set: function( elem, value, name ) {\n        if ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n          return nodeHook.set( elem, value, name );\n        }\n        // Does not return so that setAttribute is also used\n        elem.value = value;\n      }\n    }\n  },\n\n  propFix: {\n    tabindex: \"tabIndex\",\n    readonly: \"readOnly\",\n    \"for\": \"htmlFor\",\n    \"class\": \"className\",\n    maxlength: \"maxLength\",\n    cellspacing: \"cellSpacing\",\n    cellpadding: \"cellPadding\",\n    rowspan: \"rowSpan\",\n    colspan: \"colSpan\",\n    usemap: \"useMap\",\n    frameborder: \"frameBorder\",\n    contenteditable: \"contentEditable\"\n  },\n\n  prop: function( elem, name, value ) {\n    var ret, hooks, notxml,\n      nType = elem.nodeType;\n\n    // don't get/set properties on text, comment and attribute nodes\n    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n      return;\n    }\n\n    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n    if ( notxml ) {\n      // Fix name and attach hooks\n      name = jQuery.propFix[ name ] || name;\n      hooks = jQuery.propHooks[ name ];\n    }\n\n    if ( value !== undefined ) {\n      if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n        return ret;\n\n      } else {\n        return ( elem[ name ] = value );\n      }\n\n    } else {\n      if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n        return ret;\n\n      } else {\n        return elem[ name ];\n      }\n    }\n  },\n\n  propHooks: {\n    tabIndex: {\n      get: function( elem ) {\n        // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n        // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n        var attributeNode = elem.getAttributeNode(\"tabindex\");\n\n        return attributeNode && attributeNode.specified ?\n          parseInt( attributeNode.value, 10 ) :\n          rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n            0 :\n            undefined;\n      }\n    }\n  }\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n  get: function( elem, name ) {\n    // Align boolean attributes with corresponding properties\n    // Fall back to attribute presence where some booleans are not supported\n    var attrNode,\n      property = jQuery.prop( elem, name );\n    return property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n      name.toLowerCase() :\n      undefined;\n  },\n  set: function( elem, value, name ) {\n    var propName;\n    if ( value === false ) {\n      // Remove boolean attributes when set to false\n      jQuery.removeAttr( elem, name );\n    } else {\n      // value is true since we know at this point it's type boolean and not false\n      // Set boolean attributes to the same name and set the DOM property\n      propName = jQuery.propFix[ name ] || name;\n      if ( propName in elem ) {\n        // Only set the IDL specifically if it already exists on the element\n        elem[ propName ] = true;\n      }\n\n      elem.setAttribute( name, name.toLowerCase() );\n    }\n    return name;\n  }\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n  fixSpecified = {\n    name: true,\n    id: true,\n    coords: true\n  };\n\n  // Use this for any attribute in IE6/7\n  // This fixes almost every IE6/7 issue\n  nodeHook = jQuery.valHooks.button = {\n    get: function( elem, name ) {\n      var ret;\n      ret = elem.getAttributeNode( name );\n      return ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n        ret.nodeValue :\n        undefined;\n    },\n    set: function( elem, value, name ) {\n      // Set the existing or create a new attribute node\n      var ret = elem.getAttributeNode( name );\n      if ( !ret ) {\n        ret = document.createAttribute( name );\n        elem.setAttributeNode( ret );\n      }\n      return ( ret.nodeValue = value + \"\" );\n    }\n  };\n\n  // Apply the nodeHook to tabindex\n  jQuery.attrHooks.tabindex.set = nodeHook.set;\n\n  // Set width and height to auto instead of 0 on empty string( Bug #8150 )\n  // This is for removals\n  jQuery.each([ \"width\", \"height\" ], function( i, name ) {\n    jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n      set: function( elem, value ) {\n        if ( value === \"\" ) {\n          elem.setAttribute( name, \"auto\" );\n          return value;\n        }\n      }\n    });\n  });\n\n  // Set contenteditable to false on removals(#10429)\n  // Setting to empty string throws an error as an invalid value\n  jQuery.attrHooks.contenteditable = {\n    get: nodeHook.get,\n    set: function( elem, value, name ) {\n      if ( value === \"\" ) {\n        value = \"false\";\n      }\n      nodeHook.set( elem, value, name );\n    }\n  };\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n  jQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n    jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n      get: function( elem ) {\n        var ret = elem.getAttribute( name, 2 );\n        return ret === null ? undefined : ret;\n      }\n    });\n  });\n}\n\nif ( !jQuery.support.style ) {\n  jQuery.attrHooks.style = {\n    get: function( elem ) {\n      // Return undefined in the case of empty string\n      // Normalize to lowercase since IE uppercases css property names\n      return elem.style.cssText.toLowerCase() || undefined;\n    },\n    set: function( elem, value ) {\n      return ( elem.style.cssText = \"\" + value );\n    }\n  };\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n  jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n    get: function( elem ) {\n      var parent = elem.parentNode;\n\n      if ( parent ) {\n        parent.selectedIndex;\n\n        // Make sure that it also works with optgroups, see #5701\n        if ( parent.parentNode ) {\n          parent.parentNode.selectedIndex;\n        }\n      }\n      return null;\n    }\n  });\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n  jQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n  jQuery.each([ \"radio\", \"checkbox\" ], function() {\n    jQuery.valHooks[ this ] = {\n      get: function( elem ) {\n        // Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n        return elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n      }\n    };\n  });\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n  jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n    set: function( elem, value ) {\n      if ( jQuery.isArray( value ) ) {\n        return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n      }\n    }\n  });\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n  rtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n  rhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n  rkeyEvent = /^key/,\n  rmouseEvent = /^(?:mouse|contextmenu)|click/,\n  rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n  rquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n  quickParse = function( selector ) {\n    var quick = rquickIs.exec( selector );\n    if ( quick ) {\n      //   0  1    2   3\n      // [ _, tag, id, class ]\n      quick[1] = ( quick[1] || \"\" ).toLowerCase();\n      quick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n    }\n    return quick;\n  },\n  quickIs = function( elem, m ) {\n    var attrs = elem.attributes || {};\n    return (\n      (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n      (!m[2] || (attrs.id || {}).value === m[2]) &&\n      (!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n    );\n  },\n  hoverHack = function( events ) {\n    return jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n  };\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n  add: function( elem, types, handler, data, selector ) {\n\n    var elemData, eventHandle, events,\n      t, tns, type, namespaces, handleObj,\n      handleObjIn, quick, handlers, special;\n\n    // Don't attach events to noData or text/comment nodes (allow plain objects tho)\n    if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n      return;\n    }\n\n    // Caller can pass in an object of custom data in lieu of the handler\n    if ( handler.handler ) {\n      handleObjIn = handler;\n      handler = handleObjIn.handler;\n      selector = handleObjIn.selector;\n    }\n\n    // Make sure that the handler has a unique ID, used to find/remove it later\n    if ( !handler.guid ) {\n      handler.guid = jQuery.guid++;\n    }\n\n    // Init the element's event structure and main handler, if this is the first\n    events = elemData.events;\n    if ( !events ) {\n      elemData.events = events = {};\n    }\n    eventHandle = elemData.handle;\n    if ( !eventHandle ) {\n      elemData.handle = eventHandle = function( e ) {\n        // Discard the second event of a jQuery.event.trigger() and\n        // when an event is called after a page has unloaded\n        return typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n          jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n          undefined;\n      };\n      // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n      eventHandle.elem = elem;\n    }\n\n    // Handle multiple events separated by a space\n    // jQuery(...).bind(\"mouseover mouseout\", fn);\n    types = jQuery.trim( hoverHack(types) ).split( \" \" );\n    for ( t = 0; t < types.length; t++ ) {\n\n      tns = rtypenamespace.exec( types[t] ) || [];\n      type = tns[1];\n      namespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n      // If event changes its type, use the special event handlers for the changed type\n      special = jQuery.event.special[ type ] || {};\n\n      // If selector defined, determine special event api type, otherwise given type\n      type = ( selector ? special.delegateType : special.bindType ) || type;\n\n      // Update special based on newly reset type\n      special = jQuery.event.special[ type ] || {};\n\n      // handleObj is passed to all event handlers\n      handleObj = jQuery.extend({\n        type: type,\n        origType: tns[1],\n        data: data,\n        handler: handler,\n        guid: handler.guid,\n        selector: selector,\n        quick: selector && quickParse( selector ),\n        namespace: namespaces.join(\".\")\n      }, handleObjIn );\n\n      // Init the event handler queue if we're the first\n      handlers = events[ type ];\n      if ( !handlers ) {\n        handlers = events[ type ] = [];\n        handlers.delegateCount = 0;\n\n        // Only use addEventListener/attachEvent if the special events handler returns false\n        if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n          // Bind the global event handler to the element\n          if ( elem.addEventListener ) {\n            elem.addEventListener( type, eventHandle, false );\n\n          } else if ( elem.attachEvent ) {\n            elem.attachEvent( \"on\" + type, eventHandle );\n          }\n        }\n      }\n\n      if ( special.add ) {\n        special.add.call( elem, handleObj );\n\n        if ( !handleObj.handler.guid ) {\n          handleObj.handler.guid = handler.guid;\n        }\n      }\n\n      // Add to the element's handler list, delegates in front\n      if ( selector ) {\n        handlers.splice( handlers.delegateCount++, 0, handleObj );\n      } else {\n        handlers.push( handleObj );\n      }\n\n      // Keep track of which events have ever been used, for event optimization\n      jQuery.event.global[ type ] = true;\n    }\n\n    // Nullify elem to prevent memory leaks in IE\n    elem = null;\n  },\n\n  global: {},\n\n  // Detach an event or set of events from an element\n  remove: function( elem, types, handler, selector, mappedTypes ) {\n\n    var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n      t, tns, type, origType, namespaces, origCount,\n      j, events, special, handle, eventType, handleObj;\n\n    if ( !elemData || !(events = elemData.events) ) {\n      return;\n    }\n\n    // Once for each type.namespace in types; type may be omitted\n    types = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n    for ( t = 0; t < types.length; t++ ) {\n      tns = rtypenamespace.exec( types[t] ) || [];\n      type = origType = tns[1];\n      namespaces = tns[2];\n\n      // Unbind all events (on this namespace, if provided) for the element\n      if ( !type ) {\n        for ( type in events ) {\n          jQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n        }\n        continue;\n      }\n\n      special = jQuery.event.special[ type ] || {};\n      type = ( selector? special.delegateType : special.bindType ) || type;\n      eventType = events[ type ] || [];\n      origCount = eventType.length;\n      namespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n      // Remove matching events\n      for ( j = 0; j < eventType.length; j++ ) {\n        handleObj = eventType[ j ];\n\n        if ( ( mappedTypes || origType === handleObj.origType ) &&\n           ( !handler || handler.guid === handleObj.guid ) &&\n           ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n           ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n          eventType.splice( j--, 1 );\n\n          if ( handleObj.selector ) {\n            eventType.delegateCount--;\n          }\n          if ( special.remove ) {\n            special.remove.call( elem, handleObj );\n          }\n        }\n      }\n\n      // Remove generic event handler if we removed something and no more handlers exist\n      // (avoids potential for endless recursion during removal of special event handlers)\n      if ( eventType.length === 0 && origCount !== eventType.length ) {\n        if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n          jQuery.removeEvent( elem, type, elemData.handle );\n        }\n\n        delete events[ type ];\n      }\n    }\n\n    // Remove the expando if it's no longer used\n    if ( jQuery.isEmptyObject( events ) ) {\n      handle = elemData.handle;\n      if ( handle ) {\n        handle.elem = null;\n      }\n\n      // removeData also checks for emptiness and clears the expando if empty\n      // so use it instead of delete\n      jQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n    }\n  },\n\n  // Events that are safe to short-circuit if no handlers are attached.\n  // Native DOM events should not be added, they may have inline handlers.\n  customEvent: {\n    \"getData\": true,\n    \"setData\": true,\n    \"changeData\": true\n  },\n\n  trigger: function( event, data, elem, onlyHandlers ) {\n    // Don't do events on text and comment nodes\n    if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n      return;\n    }\n\n    // Event object or event type\n    var type = event.type || event,\n      namespaces = [],\n      cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n    // focus/blur morphs to focusin/out; ensure we're not firing them right now\n    if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n      return;\n    }\n\n    if ( type.indexOf( \"!\" ) >= 0 ) {\n      // Exclusive events trigger only for the exact event (no namespaces)\n      type = type.slice(0, -1);\n      exclusive = true;\n    }\n\n    if ( type.indexOf( \".\" ) >= 0 ) {\n      // Namespaced trigger; create a regexp to match event type in handle()\n      namespaces = type.split(\".\");\n      type = namespaces.shift();\n      namespaces.sort();\n    }\n\n    if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n      // No jQuery handlers for this event type, and it can't have inline handlers\n      return;\n    }\n\n    // Caller can pass in an Event, Object, or just an event type string\n    event = typeof event === \"object\" ?\n      // jQuery.Event object\n      event[ jQuery.expando ] ? event :\n      // Object literal\n      new jQuery.Event( type, event ) :\n      // Just the event type (string)\n      new jQuery.Event( type );\n\n    event.type = type;\n    event.isTrigger = true;\n    event.exclusive = exclusive;\n    event.namespace = namespaces.join( \".\" );\n    event.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n    ontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n    // Handle a global trigger\n    if ( !elem ) {\n\n      // TODO: Stop taunting the data cache; remove global events and always attach to document\n      cache = jQuery.cache;\n      for ( i in cache ) {\n        if ( cache[ i ].events && cache[ i ].events[ type ] ) {\n          jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n        }\n      }\n      return;\n    }\n\n    // Clean up the event in case it is being reused\n    event.result = undefined;\n    if ( !event.target ) {\n      event.target = elem;\n    }\n\n    // Clone any incoming data and prepend the event, creating the handler arg list\n    data = data != null ? jQuery.makeArray( data ) : [];\n    data.unshift( event );\n\n    // Allow special events to draw outside the lines\n    special = jQuery.event.special[ type ] || {};\n    if ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n      return;\n    }\n\n    // Determine event propagation path in advance, per W3C events spec (#9951)\n    // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n    eventPath = [[ elem, special.bindType || type ]];\n    if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n      bubbleType = special.delegateType || type;\n      cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n      old = null;\n      for ( ; cur; cur = cur.parentNode ) {\n        eventPath.push([ cur, bubbleType ]);\n        old = cur;\n      }\n\n      // Only add window if we got to document (e.g., not plain obj or detached DOM)\n      if ( old && old === elem.ownerDocument ) {\n        eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n      }\n    }\n\n    // Fire handlers on the event path\n    for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n      cur = eventPath[i][0];\n      event.type = eventPath[i][1];\n\n      handle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n      if ( handle ) {\n        handle.apply( cur, data );\n      }\n      // Note that this is a bare JS function and not a jQuery handler\n      handle = ontype && cur[ ontype ];\n      if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n        event.preventDefault();\n      }\n    }\n    event.type = type;\n\n    // If nobody prevented the default action, do it now\n    if ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n      if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n        !(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n        // Call a native DOM method on the target with the same name name as the event.\n        // Can't use an .isFunction() check here because IE6/7 fails that test.\n        // Don't do default actions on window, that's where global variables be (#6170)\n        // IE<9 dies on focus/blur to hidden element (#1486)\n        if ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n          // Don't re-trigger an onFOO event when we call its FOO() method\n          old = elem[ ontype ];\n\n          if ( old ) {\n            elem[ ontype ] = null;\n          }\n\n          // Prevent re-triggering of the same event, since we already bubbled it above\n          jQuery.event.triggered = type;\n          elem[ type ]();\n          jQuery.event.triggered = undefined;\n\n          if ( old ) {\n            elem[ ontype ] = old;\n          }\n        }\n      }\n    }\n\n    return event.result;\n  },\n\n  dispatch: function( event ) {\n\n    // Make a writable jQuery.Event from the native event object\n    event = jQuery.event.fix( event || window.event );\n\n    var handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n      delegateCount = handlers.delegateCount,\n      args = [].slice.call( arguments, 0 ),\n      run_all = !event.exclusive && !event.namespace,\n      special = jQuery.event.special[ event.type ] || {},\n      handlerQueue = [],\n      i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n    // Use the fix-ed jQuery.Event rather than the (read-only) native event\n    args[0] = event;\n    event.delegateTarget = this;\n\n    // Call the preDispatch hook for the mapped type, and let it bail if desired\n    if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n      return;\n    }\n\n    // Determine handlers that should run if there are delegated events\n    // Avoid non-left-click bubbling in Firefox (#3861)\n    if ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n      // Pregenerate a single jQuery object for reuse with .is()\n      jqcur = jQuery(this);\n      jqcur.context = this.ownerDocument || this;\n\n      for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n        // Don't process events on disabled elements (#6911, #8165)\n        if ( cur.disabled !== true ) {\n          selMatch = {};\n          matches = [];\n          jqcur[0] = cur;\n          for ( i = 0; i < delegateCount; i++ ) {\n            handleObj = handlers[ i ];\n            sel = handleObj.selector;\n\n            if ( selMatch[ sel ] === undefined ) {\n              selMatch[ sel ] = (\n                handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n              );\n            }\n            if ( selMatch[ sel ] ) {\n              matches.push( handleObj );\n            }\n          }\n          if ( matches.length ) {\n            handlerQueue.push({ elem: cur, matches: matches });\n          }\n        }\n      }\n    }\n\n    // Add the remaining (directly-bound) handlers\n    if ( handlers.length > delegateCount ) {\n      handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n    }\n\n    // Run delegates first; they may want to stop propagation beneath us\n    for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n      matched = handlerQueue[ i ];\n      event.currentTarget = matched.elem;\n\n      for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n        handleObj = matched.matches[ j ];\n\n        // Triggered event must either 1) be non-exclusive and have no namespace, or\n        // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n        if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n          event.data = handleObj.data;\n          event.handleObj = handleObj;\n\n          ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n              .apply( matched.elem, args );\n\n          if ( ret !== undefined ) {\n            event.result = ret;\n            if ( ret === false ) {\n              event.preventDefault();\n              event.stopPropagation();\n            }\n          }\n        }\n      }\n    }\n\n    // Call the postDispatch hook for the mapped type\n    if ( special.postDispatch ) {\n      special.postDispatch.call( this, event );\n    }\n\n    return event.result;\n  },\n\n  // Includes some event props shared by KeyEvent and MouseEvent\n  // *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n  props: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n  fixHooks: {},\n\n  keyHooks: {\n    props: \"char charCode key keyCode\".split(\" \"),\n    filter: function( event, original ) {\n\n      // Add which for key events\n      if ( event.which == null ) {\n        event.which = original.charCode != null ? original.charCode : original.keyCode;\n      }\n\n      return event;\n    }\n  },\n\n  mouseHooks: {\n    props: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n    filter: function( event, original ) {\n      var eventDoc, doc, body,\n        button = original.button,\n        fromElement = original.fromElement;\n\n      // Calculate pageX/Y if missing and clientX/Y available\n      if ( event.pageX == null && original.clientX != null ) {\n        eventDoc = event.target.ownerDocument || document;\n        doc = eventDoc.documentElement;\n        body = eventDoc.body;\n\n        event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n        event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n      }\n\n      // Add relatedTarget, if necessary\n      if ( !event.relatedTarget && fromElement ) {\n        event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n      }\n\n      // Add which for click: 1 === left; 2 === middle; 3 === right\n      // Note: button is not normalized, so don't use it\n      if ( !event.which && button !== undefined ) {\n        event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n      }\n\n      return event;\n    }\n  },\n\n  fix: function( event ) {\n    if ( event[ jQuery.expando ] ) {\n      return event;\n    }\n\n    // Create a writable copy of the event object and normalize some properties\n    var i, prop,\n      originalEvent = event,\n      fixHook = jQuery.event.fixHooks[ event.type ] || {},\n      copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n    event = jQuery.Event( originalEvent );\n\n    for ( i = copy.length; i; ) {\n      prop = copy[ --i ];\n      event[ prop ] = originalEvent[ prop ];\n    }\n\n    // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n    if ( !event.target ) {\n      event.target = originalEvent.srcElement || document;\n    }\n\n    // Target should not be a text node (#504, Safari)\n    if ( event.target.nodeType === 3 ) {\n      event.target = event.target.parentNode;\n    }\n\n    // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n    if ( event.metaKey === undefined ) {\n      event.metaKey = event.ctrlKey;\n    }\n\n    return fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n  },\n\n  special: {\n    ready: {\n      // Make sure the ready event is setup\n      setup: jQuery.bindReady\n    },\n\n    load: {\n      // Prevent triggered image.load events from bubbling to window.load\n      noBubble: true\n    },\n\n    focus: {\n      delegateType: \"focusin\"\n    },\n    blur: {\n      delegateType: \"focusout\"\n    },\n\n    beforeunload: {\n      setup: function( data, namespaces, eventHandle ) {\n        // We only want to do this special case on windows\n        if ( jQuery.isWindow( this ) ) {\n          this.onbeforeunload = eventHandle;\n        }\n      },\n\n      teardown: function( namespaces, eventHandle ) {\n        if ( this.onbeforeunload === eventHandle ) {\n          this.onbeforeunload = null;\n        }\n      }\n    }\n  },\n\n  simulate: function( type, elem, event, bubble ) {\n    // Piggyback on a donor event to simulate a different one.\n    // Fake originalEvent to avoid donor's stopPropagation, but if the\n    // simulated event prevents default then we do the same on the donor.\n    var e = jQuery.extend(\n      new jQuery.Event(),\n      event,\n      { type: type,\n        isSimulated: true,\n        originalEvent: {}\n      }\n    );\n    if ( bubble ) {\n      jQuery.event.trigger( e, null, elem );\n    } else {\n      jQuery.event.dispatch.call( elem, e );\n    }\n    if ( e.isDefaultPrevented() ) {\n      event.preventDefault();\n    }\n  }\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n  function( elem, type, handle ) {\n    if ( elem.removeEventListener ) {\n      elem.removeEventListener( type, handle, false );\n    }\n  } :\n  function( elem, type, handle ) {\n    if ( elem.detachEvent ) {\n      elem.detachEvent( \"on\" + type, handle );\n    }\n  };\n\njQuery.Event = function( src, props ) {\n  // Allow instantiation without the 'new' keyword\n  if ( !(this instanceof jQuery.Event) ) {\n    return new jQuery.Event( src, props );\n  }\n\n  // Event object\n  if ( src && src.type ) {\n    this.originalEvent = src;\n    this.type = src.type;\n\n    // Events bubbling up the document may have been marked as prevented\n    // by a handler lower down the tree; reflect the correct value.\n    this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n      src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n  // Event type\n  } else {\n    this.type = src;\n  }\n\n  // Put explicitly provided properties onto the event object\n  if ( props ) {\n    jQuery.extend( this, props );\n  }\n\n  // Create a timestamp if incoming event doesn't have one\n  this.timeStamp = src && src.timeStamp || jQuery.now();\n\n  // Mark it as fixed\n  this[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n  return false;\n}\nfunction returnTrue() {\n  return true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n  preventDefault: function() {\n    this.isDefaultPrevented = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n\n    // if preventDefault exists run it on the original event\n    if ( e.preventDefault ) {\n      e.preventDefault();\n\n    // otherwise set the returnValue property of the original event to false (IE)\n    } else {\n      e.returnValue = false;\n    }\n  },\n  stopPropagation: function() {\n    this.isPropagationStopped = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n    // if stopPropagation exists run it on the original event\n    if ( e.stopPropagation ) {\n      e.stopPropagation();\n    }\n    // otherwise set the cancelBubble property of the original event to true (IE)\n    e.cancelBubble = true;\n  },\n  stopImmediatePropagation: function() {\n    this.isImmediatePropagationStopped = returnTrue;\n    this.stopPropagation();\n  },\n  isDefaultPrevented: returnFalse,\n  isPropagationStopped: returnFalse,\n  isImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n  mouseenter: \"mouseover\",\n  mouseleave: \"mouseout\"\n}, function( orig, fix ) {\n  jQuery.event.special[ orig ] = {\n    delegateType: fix,\n    bindType: fix,\n\n    handle: function( event ) {\n      var target = this,\n        related = event.relatedTarget,\n        handleObj = event.handleObj,\n        selector = handleObj.selector,\n        ret;\n\n      // For mousenter/leave call the handler if related is outside the target.\n      // NB: No relatedTarget if the mouse left/entered the browser window\n      if ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n        event.type = handleObj.origType;\n        ret = handleObj.handler.apply( this, arguments );\n        event.type = fix;\n      }\n      return ret;\n    }\n  };\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n  jQuery.event.special.submit = {\n    setup: function() {\n      // Only need this for delegated form submit events\n      if ( jQuery.nodeName( this, \"form\" ) ) {\n        return false;\n      }\n\n      // Lazy-add a submit handler when a descendant form may potentially be submitted\n      jQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n        // Node name check avoids a VML-related crash in IE (#9807)\n        var elem = e.target,\n          form = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n        if ( form && !form._submit_attached ) {\n          jQuery.event.add( form, \"submit._submit\", function( event ) {\n            event._submit_bubble = true;\n          });\n          form._submit_attached = true;\n        }\n      });\n      // return undefined since we don't need an event listener\n    },\n\n    postDispatch: function( event ) {\n      // If form was submitted by the user, bubble the event up the tree\n      if ( event._submit_bubble ) {\n        delete event._submit_bubble;\n        if ( this.parentNode && !event.isTrigger ) {\n          jQuery.event.simulate( \"submit\", this.parentNode, event, true );\n        }\n      }\n    },\n\n    teardown: function() {\n      // Only need this for delegated form submit events\n      if ( jQuery.nodeName( this, \"form\" ) ) {\n        return false;\n      }\n\n      // Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n      jQuery.event.remove( this, \"._submit\" );\n    }\n  };\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n  jQuery.event.special.change = {\n\n    setup: function() {\n\n      if ( rformElems.test( this.nodeName ) ) {\n        // IE doesn't fire change on a check/radio until blur; trigger it on click\n        // after a propertychange. Eat the blur-change in special.change.handle.\n        // This still fires onchange a second time for check/radio after blur.\n        if ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n          jQuery.event.add( this, \"propertychange._change\", function( event ) {\n            if ( event.originalEvent.propertyName === \"checked\" ) {\n              this._just_changed = true;\n            }\n          });\n          jQuery.event.add( this, \"click._change\", function( event ) {\n            if ( this._just_changed && !event.isTrigger ) {\n              this._just_changed = false;\n              jQuery.event.simulate( \"change\", this, event, true );\n            }\n          });\n        }\n        return false;\n      }\n      // Delegated event; lazy-add a change handler on descendant inputs\n      jQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n        var elem = e.target;\n\n        if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n          jQuery.event.add( elem, \"change._change\", function( event ) {\n            if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n              jQuery.event.simulate( \"change\", this.parentNode, event, true );\n            }\n          });\n          elem._change_attached = true;\n        }\n      });\n    },\n\n    handle: function( event ) {\n      var elem = event.target;\n\n      // Swallow native change events from checkbox/radio, we already triggered them above\n      if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n        return event.handleObj.handler.apply( this, arguments );\n      }\n    },\n\n    teardown: function() {\n      jQuery.event.remove( this, \"._change\" );\n\n      return rformElems.test( this.nodeName );\n    }\n  };\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n  jQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n    // Attach a single capturing handler while someone wants focusin/focusout\n    var attaches = 0,\n      handler = function( event ) {\n        jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n      };\n\n    jQuery.event.special[ fix ] = {\n      setup: function() {\n        if ( attaches++ === 0 ) {\n          document.addEventListener( orig, handler, true );\n        }\n      },\n      teardown: function() {\n        if ( --attaches === 0 ) {\n          document.removeEventListener( orig, handler, true );\n        }\n      }\n    };\n  });\n}\n\njQuery.fn.extend({\n\n  on: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n    var origFn, type;\n\n    // Types can be a map of types/handlers\n    if ( typeof types === \"object\" ) {\n      // ( types-Object, selector, data )\n      if ( typeof selector !== \"string\" ) { // && selector != null\n        // ( types-Object, data )\n        data = data || selector;\n        selector = undefined;\n      }\n      for ( type in types ) {\n        this.on( type, selector, data, types[ type ], one );\n      }\n      return this;\n    }\n\n    if ( data == null && fn == null ) {\n      // ( types, fn )\n      fn = selector;\n      data = selector = undefined;\n    } else if ( fn == null ) {\n      if ( typeof selector === \"string\" ) {\n        // ( types, selector, fn )\n        fn = data;\n        data = undefined;\n      } else {\n        // ( types, data, fn )\n        fn = data;\n        data = selector;\n        selector = undefined;\n      }\n    }\n    if ( fn === false ) {\n      fn = returnFalse;\n    } else if ( !fn ) {\n      return this;\n    }\n\n    if ( one === 1 ) {\n      origFn = fn;\n      fn = function( event ) {\n        // Can use an empty set, since event contains the info\n        jQuery().off( event );\n        return origFn.apply( this, arguments );\n      };\n      // Use same guid so caller can remove using origFn\n      fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n    }\n    return this.each( function() {\n      jQuery.event.add( this, types, fn, data, selector );\n    });\n  },\n  one: function( types, selector, data, fn ) {\n    return this.on( types, selector, data, fn, 1 );\n  },\n  off: function( types, selector, fn ) {\n    if ( types && types.preventDefault && types.handleObj ) {\n      // ( event )  dispatched jQuery.Event\n      var handleObj = types.handleObj;\n      jQuery( types.delegateTarget ).off(\n        handleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n        handleObj.selector,\n        handleObj.handler\n      );\n      return this;\n    }\n    if ( typeof types === \"object\" ) {\n      // ( types-object [, selector] )\n      for ( var type in types ) {\n        this.off( type, selector, types[ type ] );\n      }\n      return this;\n    }\n    if ( selector === false || typeof selector === \"function\" ) {\n      // ( types [, fn] )\n      fn = selector;\n      selector = undefined;\n    }\n    if ( fn === false ) {\n      fn = returnFalse;\n    }\n    return this.each(function() {\n      jQuery.event.remove( this, types, fn, selector );\n    });\n  },\n\n  bind: function( types, data, fn ) {\n    return this.on( types, null, data, fn );\n  },\n  unbind: function( types, fn ) {\n    return this.off( types, null, fn );\n  },\n\n  live: function( types, data, fn ) {\n    jQuery( this.context ).on( types, this.selector, data, fn );\n    return this;\n  },\n  die: function( types, fn ) {\n    jQuery( this.context ).off( types, this.selector || \"**\", fn );\n    return this;\n  },\n\n  delegate: function( selector, types, data, fn ) {\n    return this.on( types, selector, data, fn );\n  },\n  undelegate: function( selector, types, fn ) {\n    // ( namespace ) or ( selector, types [, fn] )\n    return arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n  },\n\n  trigger: function( type, data ) {\n    return this.each(function() {\n      jQuery.event.trigger( type, data, this );\n    });\n  },\n  triggerHandler: function( type, data ) {\n    if ( this[0] ) {\n      return jQuery.event.trigger( type, data, this[0], true );\n    }\n  },\n\n  toggle: function( fn ) {\n    // Save reference to arguments for access in closure\n    var args = arguments,\n      guid = fn.guid || jQuery.guid++,\n      i = 0,\n      toggler = function( event ) {\n        // Figure out which function to execute\n        var lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n        jQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n        // Make sure that clicks stop\n        event.preventDefault();\n\n        // and execute the function\n        return args[ lastToggle ].apply( this, arguments ) || false;\n      };\n\n    // link all the functions, so any of them can unbind this click handler\n    toggler.guid = guid;\n    while ( i < args.length ) {\n      args[ i++ ].guid = guid;\n    }\n\n    return this.click( toggler );\n  },\n\n  hover: function( fnOver, fnOut ) {\n    return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n  }\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n  \"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n  \"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n  // Handle event binding\n  jQuery.fn[ name ] = function( data, fn ) {\n    if ( fn == null ) {\n      fn = data;\n      data = null;\n    }\n\n    return arguments.length > 0 ?\n      this.on( name, null, data, fn ) :\n      this.trigger( name );\n  };\n\n  if ( jQuery.attrFn ) {\n    jQuery.attrFn[ name ] = true;\n  }\n\n  if ( rkeyEvent.test( name ) ) {\n    jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n  }\n\n  if ( rmouseEvent.test( name ) ) {\n    jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n  }\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n  expando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n  done = 0,\n  toString = Object.prototype.toString,\n  hasDuplicate = false,\n  baseHasDuplicate = true,\n  rBackslash = /\\\\/g,\n  rReturn = /\\r\\n/g,\n  rNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n  baseHasDuplicate = false;\n  return 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n  results = results || [];\n  context = context || document;\n\n  var origContext = context;\n\n  if ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n    return [];\n  }\n\n  if ( !selector || typeof selector !== \"string\" ) {\n    return results;\n  }\n\n  var m, set, checkSet, extra, ret, cur, pop, i,\n    prune = true,\n    contextXML = Sizzle.isXML( context ),\n    parts = [],\n    soFar = selector;\n\n  // Reset the position of the chunker regexp (start from head)\n  do {\n    chunker.exec( \"\" );\n    m = chunker.exec( soFar );\n\n    if ( m ) {\n      soFar = m[3];\n\n      parts.push( m[1] );\n\n      if ( m[2] ) {\n        extra = m[3];\n        break;\n      }\n    }\n  } while ( m );\n\n  if ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n    if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n      set = posProcess( parts[0] + parts[1], context, seed );\n\n    } else {\n      set = Expr.relative[ parts[0] ] ?\n        [ context ] :\n        Sizzle( parts.shift(), context );\n\n      while ( parts.length ) {\n        selector = parts.shift();\n\n        if ( Expr.relative[ selector ] ) {\n          selector += parts.shift();\n        }\n\n        set = posProcess( selector, set, seed );\n      }\n    }\n\n  } else {\n    // Take a shortcut and set the context if the root selector is an ID\n    // (but not if it'll be faster if the inner selector is an ID)\n    if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n        Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n      ret = Sizzle.find( parts.shift(), context, contextXML );\n      context = ret.expr ?\n        Sizzle.filter( ret.expr, ret.set )[0] :\n        ret.set[0];\n    }\n\n    if ( context ) {\n      ret = seed ?\n        { expr: parts.pop(), set: makeArray(seed) } :\n        Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n      set = ret.expr ?\n        Sizzle.filter( ret.expr, ret.set ) :\n        ret.set;\n\n      if ( parts.length > 0 ) {\n        checkSet = makeArray( set );\n\n      } else {\n        prune = false;\n      }\n\n      while ( parts.length ) {\n        cur = parts.pop();\n        pop = cur;\n\n        if ( !Expr.relative[ cur ] ) {\n          cur = \"\";\n        } else {\n          pop = parts.pop();\n        }\n\n        if ( pop == null ) {\n          pop = context;\n        }\n\n        Expr.relative[ cur ]( checkSet, pop, contextXML );\n      }\n\n    } else {\n      checkSet = parts = [];\n    }\n  }\n\n  if ( !checkSet ) {\n    checkSet = set;\n  }\n\n  if ( !checkSet ) {\n    Sizzle.error( cur || selector );\n  }\n\n  if ( toString.call(checkSet) === \"[object Array]\" ) {\n    if ( !prune ) {\n      results.push.apply( results, checkSet );\n\n    } else if ( context && context.nodeType === 1 ) {\n      for ( i = 0; checkSet[i] != null; i++ ) {\n        if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n          results.push( set[i] );\n        }\n      }\n\n    } else {\n      for ( i = 0; checkSet[i] != null; i++ ) {\n        if ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n          results.push( set[i] );\n        }\n      }\n    }\n\n  } else {\n    makeArray( checkSet, results );\n  }\n\n  if ( extra ) {\n    Sizzle( extra, origContext, results, seed );\n    Sizzle.uniqueSort( results );\n  }\n\n  return results;\n};\n\nSizzle.uniqueSort = function( results ) {\n  if ( sortOrder ) {\n    hasDuplicate = baseHasDuplicate;\n    results.sort( sortOrder );\n\n    if ( hasDuplicate ) {\n      for ( var i = 1; i < results.length; i++ ) {\n        if ( results[i] === results[ i - 1 ] ) {\n          results.splice( i--, 1 );\n        }\n      }\n    }\n  }\n\n  return results;\n};\n\nSizzle.matches = function( expr, set ) {\n  return Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n  return Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n  var set, i, len, match, type, left;\n\n  if ( !expr ) {\n    return [];\n  }\n\n  for ( i = 0, len = Expr.order.length; i < len; i++ ) {\n    type = Expr.order[i];\n\n    if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n      left = match[1];\n      match.splice( 1, 1 );\n\n      if ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n        match[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n        set = Expr.find[ type ]( match, context, isXML );\n\n        if ( set != null ) {\n          expr = expr.replace( Expr.match[ type ], \"\" );\n          break;\n        }\n      }\n    }\n  }\n\n  if ( !set ) {\n    set = typeof context.getElementsByTagName !== \"undefined\" ?\n      context.getElementsByTagName( \"*\" ) :\n      [];\n  }\n\n  return { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n  var match, anyFound,\n    type, found, item, filter, left,\n    i, pass,\n    old = expr,\n    result = [],\n    curLoop = set,\n    isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n  while ( expr && set.length ) {\n    for ( type in Expr.filter ) {\n      if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n        filter = Expr.filter[ type ];\n        left = match[1];\n\n        anyFound = false;\n\n        match.splice(1,1);\n\n        if ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n          continue;\n        }\n\n        if ( curLoop === result ) {\n          result = [];\n        }\n\n        if ( Expr.preFilter[ type ] ) {\n          match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n          if ( !match ) {\n            anyFound = found = true;\n\n          } else if ( match === true ) {\n            continue;\n          }\n        }\n\n        if ( match ) {\n          for ( i = 0; (item = curLoop[i]) != null; i++ ) {\n            if ( item ) {\n              found = filter( item, match, i, curLoop );\n              pass = not ^ found;\n\n              if ( inplace && found != null ) {\n                if ( pass ) {\n                  anyFound = true;\n\n                } else {\n                  curLoop[i] = false;\n                }\n\n              } else if ( pass ) {\n                result.push( item );\n                anyFound = true;\n              }\n            }\n          }\n        }\n\n        if ( found !== undefined ) {\n          if ( !inplace ) {\n            curLoop = result;\n          }\n\n          expr = expr.replace( Expr.match[ type ], \"\" );\n\n          if ( !anyFound ) {\n            return [];\n          }\n\n          break;\n        }\n      }\n    }\n\n    // Improper expression\n    if ( expr === old ) {\n      if ( anyFound == null ) {\n        Sizzle.error( expr );\n\n      } else {\n        break;\n      }\n    }\n\n    old = expr;\n  }\n\n  return curLoop;\n};\n\nSizzle.error = function( msg ) {\n  throw new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n    nodeType = elem.nodeType,\n    ret = \"\";\n\n  if ( nodeType ) {\n    if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n      // Use textContent || innerText for elements\n      if ( typeof elem.textContent === 'string' ) {\n        return elem.textContent;\n      } else if ( typeof elem.innerText === 'string' ) {\n        // Replace IE's carriage returns\n        return elem.innerText.replace( rReturn, '' );\n      } else {\n        // Traverse it's children\n        for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n          ret += getText( elem );\n        }\n      }\n    } else if ( nodeType === 3 || nodeType === 4 ) {\n      return elem.nodeValue;\n    }\n  } else {\n\n    // If no nodeType, this is expected to be an array\n    for ( i = 0; (node = elem[i]); i++ ) {\n      // Do not traverse comment nodes\n      if ( node.nodeType !== 8 ) {\n        ret += getText( node );\n      }\n    }\n  }\n  return ret;\n};\n\nvar Expr = Sizzle.selectors = {\n  order: [ \"ID\", \"NAME\", \"TAG\" ],\n\n  match: {\n    ID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n    CLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n    NAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n    ATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n    TAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n    CHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n    POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n    PSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n  },\n\n  leftMatch: {},\n\n  attrMap: {\n    \"class\": \"className\",\n    \"for\": \"htmlFor\"\n  },\n\n  attrHandle: {\n    href: function( elem ) {\n      return elem.getAttribute( \"href\" );\n    },\n    type: function( elem ) {\n      return elem.getAttribute( \"type\" );\n    }\n  },\n\n  relative: {\n    \"+\": function(checkSet, part){\n      var isPartStr = typeof part === \"string\",\n        isTag = isPartStr && !rNonWord.test( part ),\n        isPartStrNotTag = isPartStr && !isTag;\n\n      if ( isTag ) {\n        part = part.toLowerCase();\n      }\n\n      for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n        if ( (elem = checkSet[i]) ) {\n          while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n          checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n            elem || false :\n            elem === part;\n        }\n      }\n\n      if ( isPartStrNotTag ) {\n        Sizzle.filter( part, checkSet, true );\n      }\n    },\n\n    \">\": function( checkSet, part ) {\n      var elem,\n        isPartStr = typeof part === \"string\",\n        i = 0,\n        l = checkSet.length;\n\n      if ( isPartStr && !rNonWord.test( part ) ) {\n        part = part.toLowerCase();\n\n        for ( ; i < l; i++ ) {\n          elem = checkSet[i];\n\n          if ( elem ) {\n            var parent = elem.parentNode;\n            checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n          }\n        }\n\n      } else {\n        for ( ; i < l; i++ ) {\n          elem = checkSet[i];\n\n          if ( elem ) {\n            checkSet[i] = isPartStr ?\n              elem.parentNode :\n              elem.parentNode === part;\n          }\n        }\n\n        if ( isPartStr ) {\n          Sizzle.filter( part, checkSet, true );\n        }\n      }\n    },\n\n    \"\": function(checkSet, part, isXML){\n      var nodeCheck,\n        doneName = done++,\n        checkFn = dirCheck;\n\n      if ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n        part = part.toLowerCase();\n        nodeCheck = part;\n        checkFn = dirNodeCheck;\n      }\n\n      checkFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n    },\n\n    \"~\": function( checkSet, part, isXML ) {\n      var nodeCheck,\n        doneName = done++,\n        checkFn = dirCheck;\n\n      if ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n        part = part.toLowerCase();\n        nodeCheck = part;\n        checkFn = dirNodeCheck;\n      }\n\n      checkFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n    }\n  },\n\n  find: {\n    ID: function( match, context, isXML ) {\n      if ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n        var m = context.getElementById(match[1]);\n        // Check parentNode to catch when Blackberry 4.6 returns\n        // nodes that are no longer in the document #6963\n        return m && m.parentNode ? [m] : [];\n      }\n    },\n\n    NAME: function( match, context ) {\n      if ( typeof context.getElementsByName !== \"undefined\" ) {\n        var ret = [],\n          results = context.getElementsByName( match[1] );\n\n        for ( var i = 0, l = results.length; i < l; i++ ) {\n          if ( results[i].getAttribute(\"name\") === match[1] ) {\n            ret.push( results[i] );\n          }\n        }\n\n        return ret.length === 0 ? null : ret;\n      }\n    },\n\n    TAG: function( match, context ) {\n      if ( typeof context.getElementsByTagName !== \"undefined\" ) {\n        return context.getElementsByTagName( match[1] );\n      }\n    }\n  },\n  preFilter: {\n    CLASS: function( match, curLoop, inplace, result, not, isXML ) {\n      match = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n      if ( isXML ) {\n        return match;\n      }\n\n      for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n        if ( elem ) {\n          if ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n            if ( !inplace ) {\n              result.push( elem );\n            }\n\n          } else if ( inplace ) {\n            curLoop[i] = false;\n          }\n        }\n      }\n\n      return false;\n    },\n\n    ID: function( match ) {\n      return match[1].replace( rBackslash, \"\" );\n    },\n\n    TAG: function( match, curLoop ) {\n      return match[1].replace( rBackslash, \"\" ).toLowerCase();\n    },\n\n    CHILD: function( match ) {\n      if ( match[1] === \"nth\" ) {\n        if ( !match[2] ) {\n          Sizzle.error( match[0] );\n        }\n\n        match[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n        // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n        var test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n          match[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n          !/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n        // calculate the numbers (first)n+(last) including if they are negative\n        match[2] = (test[1] + (test[2] || 1)) - 0;\n        match[3] = test[3] - 0;\n      }\n      else if ( match[2] ) {\n        Sizzle.error( match[0] );\n      }\n\n      // TODO: Move to normal caching system\n      match[0] = done++;\n\n      return match;\n    },\n\n    ATTR: function( match, curLoop, inplace, result, not, isXML ) {\n      var name = match[1] = match[1].replace( rBackslash, \"\" );\n\n      if ( !isXML && Expr.attrMap[name] ) {\n        match[1] = Expr.attrMap[name];\n      }\n\n      // Handle if an un-quoted value was used\n      match[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n      if ( match[2] === \"~=\" ) {\n        match[4] = \" \" + match[4] + \" \";\n      }\n\n      return match;\n    },\n\n    PSEUDO: function( match, curLoop, inplace, result, not ) {\n      if ( match[1] === \"not\" ) {\n        // If we're dealing with a complex expression, or a simple one\n        if ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n          match[3] = Sizzle(match[3], null, null, curLoop);\n\n        } else {\n          var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n          if ( !inplace ) {\n            result.push.apply( result, ret );\n          }\n\n          return false;\n        }\n\n      } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n        return true;\n      }\n\n      return match;\n    },\n\n    POS: function( match ) {\n      match.unshift( true );\n\n      return match;\n    }\n  },\n\n  filters: {\n    enabled: function( elem ) {\n      return elem.disabled === false && elem.type !== \"hidden\";\n    },\n\n    disabled: function( elem ) {\n      return elem.disabled === true;\n    },\n\n    checked: function( elem ) {\n      return elem.checked === true;\n    },\n\n    selected: function( elem ) {\n      // Accessing this property makes selected-by-default\n      // options in Safari work properly\n      if ( elem.parentNode ) {\n        elem.parentNode.selectedIndex;\n      }\n\n      return elem.selected === true;\n    },\n\n    parent: function( elem ) {\n      return !!elem.firstChild;\n    },\n\n    empty: function( elem ) {\n      return !elem.firstChild;\n    },\n\n    has: function( elem, i, match ) {\n      return !!Sizzle( match[3], elem ).length;\n    },\n\n    header: function( elem ) {\n      return (/h\\d/i).test( elem.nodeName );\n    },\n\n    text: function( elem ) {\n      var attr = elem.getAttribute( \"type\" ), type = elem.type;\n      // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n      // use getAttribute instead to test this case\n      return elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n    },\n\n    radio: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n    },\n\n    checkbox: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n    },\n\n    file: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n    },\n\n    password: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n    },\n\n    submit: function( elem ) {\n      var name = elem.nodeName.toLowerCase();\n      return (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n    },\n\n    image: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n    },\n\n    reset: function( elem ) {\n      var name = elem.nodeName.toLowerCase();\n      return (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n    },\n\n    button: function( elem ) {\n      var name = elem.nodeName.toLowerCase();\n      return name === \"input\" && \"button\" === elem.type || name === \"button\";\n    },\n\n    input: function( elem ) {\n      return (/input|select|textarea|button/i).test( elem.nodeName );\n    },\n\n    focus: function( elem ) {\n      return elem === elem.ownerDocument.activeElement;\n    }\n  },\n  setFilters: {\n    first: function( elem, i ) {\n      return i === 0;\n    },\n\n    last: function( elem, i, match, array ) {\n      return i === array.length - 1;\n    },\n\n    even: function( elem, i ) {\n      return i % 2 === 0;\n    },\n\n    odd: function( elem, i ) {\n      return i % 2 === 1;\n    },\n\n    lt: function( elem, i, match ) {\n      return i < match[3] - 0;\n    },\n\n    gt: function( elem, i, match ) {\n      return i > match[3] - 0;\n    },\n\n    nth: function( elem, i, match ) {\n      return match[3] - 0 === i;\n    },\n\n    eq: function( elem, i, match ) {\n      return match[3] - 0 === i;\n    }\n  },\n  filter: {\n    PSEUDO: function( elem, match, i, array ) {\n      var name = match[1],\n        filter = Expr.filters[ name ];\n\n      if ( filter ) {\n        return filter( elem, i, match, array );\n\n      } else if ( name === \"contains\" ) {\n        return (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n      } else if ( name === \"not\" ) {\n        var not = match[3];\n\n        for ( var j = 0, l = not.length; j < l; j++ ) {\n          if ( not[j] === elem ) {\n            return false;\n          }\n        }\n\n        return true;\n\n      } else {\n        Sizzle.error( name );\n      }\n    },\n\n    CHILD: function( elem, match ) {\n      var first, last,\n        doneName, parent, cache,\n        count, diff,\n        type = match[1],\n        node = elem;\n\n      switch ( type ) {\n        case \"only\":\n        case \"first\":\n          while ( (node = node.previousSibling) ) {\n            if ( node.nodeType === 1 ) {\n              return false;\n            }\n          }\n\n          if ( type === \"first\" ) {\n            return true;\n          }\n\n          node = elem;\n\n          /* falls through */\n        case \"last\":\n          while ( (node = node.nextSibling) ) {\n            if ( node.nodeType === 1 ) {\n              return false;\n            }\n          }\n\n          return true;\n\n        case \"nth\":\n          first = match[2];\n          last = match[3];\n\n          if ( first === 1 && last === 0 ) {\n            return true;\n          }\n\n          doneName = match[0];\n          parent = elem.parentNode;\n\n          if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n            count = 0;\n\n            for ( node = parent.firstChild; node; node = node.nextSibling ) {\n              if ( node.nodeType === 1 ) {\n                node.nodeIndex = ++count;\n              }\n            }\n\n            parent[ expando ] = doneName;\n          }\n\n          diff = elem.nodeIndex - last;\n\n          if ( first === 0 ) {\n            return diff === 0;\n\n          } else {\n            return ( diff % first === 0 && diff / first >= 0 );\n          }\n      }\n    },\n\n    ID: function( elem, match ) {\n      return elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n    },\n\n    TAG: function( elem, match ) {\n      return (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n    },\n\n    CLASS: function( elem, match ) {\n      return (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n        .indexOf( match ) > -1;\n    },\n\n    ATTR: function( elem, match ) {\n      var name = match[1],\n        result = Sizzle.attr ?\n          Sizzle.attr( elem, name ) :\n          Expr.attrHandle[ name ] ?\n          Expr.attrHandle[ name ]( elem ) :\n          elem[ name ] != null ?\n            elem[ name ] :\n            elem.getAttribute( name ),\n        value = result + \"\",\n        type = match[2],\n        check = match[4];\n\n      return result == null ?\n        type === \"!=\" :\n        !type && Sizzle.attr ?\n        result != null :\n        type === \"=\" ?\n        value === check :\n        type === \"*=\" ?\n        value.indexOf(check) >= 0 :\n        type === \"~=\" ?\n        (\" \" + value + \" \").indexOf(check) >= 0 :\n        !check ?\n        value && result !== false :\n        type === \"!=\" ?\n        value !== check :\n        type === \"^=\" ?\n        value.indexOf(check) === 0 :\n        type === \"$=\" ?\n        value.substr(value.length - check.length) === check :\n        type === \"|=\" ?\n        value === check || value.substr(0, check.length + 1) === check + \"-\" :\n        false;\n    },\n\n    POS: function( elem, match, i, array ) {\n      var name = match[2],\n        filter = Expr.setFilters[ name ];\n\n      if ( filter ) {\n        return filter( elem, i, match, array );\n      }\n    }\n  }\n};\n\nvar origPOS = Expr.match.POS,\n  fescape = function(all, num){\n    return \"\\\\\" + (num - 0 + 1);\n  };\n\nfor ( var type in Expr.match ) {\n  Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n  Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n  array = Array.prototype.slice.call( array, 0 );\n\n  if ( results ) {\n    results.push.apply( results, array );\n    return results;\n  }\n\n  return array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n  Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n  makeArray = function( array, results ) {\n    var i = 0,\n      ret = results || [];\n\n    if ( toString.call(array) === \"[object Array]\" ) {\n      Array.prototype.push.apply( ret, array );\n\n    } else {\n      if ( typeof array.length === \"number\" ) {\n        for ( var l = array.length; i < l; i++ ) {\n          ret.push( array[i] );\n        }\n\n      } else {\n        for ( ; array[i]; i++ ) {\n          ret.push( array[i] );\n        }\n      }\n    }\n\n    return ret;\n  };\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n  sortOrder = function( a, b ) {\n    if ( a === b ) {\n      hasDuplicate = true;\n      return 0;\n    }\n\n    if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n      return a.compareDocumentPosition ? -1 : 1;\n    }\n\n    return a.compareDocumentPosition(b) & 4 ? -1 : 1;\n  };\n\n} else {\n  sortOrder = function( a, b ) {\n    // The nodes are identical, we can exit early\n    if ( a === b ) {\n      hasDuplicate = true;\n      return 0;\n\n    // Fallback to using sourceIndex (in IE) if it's available on both nodes\n    } else if ( a.sourceIndex && b.sourceIndex ) {\n      return a.sourceIndex - b.sourceIndex;\n    }\n\n    var al, bl,\n      ap = [],\n      bp = [],\n      aup = a.parentNode,\n      bup = b.parentNode,\n      cur = aup;\n\n    // If the nodes are siblings (or identical) we can do a quick check\n    if ( aup === bup ) {\n      return siblingCheck( a, b );\n\n    // If no parents were found then the nodes are disconnected\n    } else if ( !aup ) {\n      return -1;\n\n    } else if ( !bup ) {\n      return 1;\n    }\n\n    // Otherwise they're somewhere else in the tree so we need\n    // to build up a full list of the parentNodes for comparison\n    while ( cur ) {\n      ap.unshift( cur );\n      cur = cur.parentNode;\n    }\n\n    cur = bup;\n\n    while ( cur ) {\n      bp.unshift( cur );\n      cur = cur.parentNode;\n    }\n\n    al = ap.length;\n    bl = bp.length;\n\n    // Start walking down the tree looking for a discrepancy\n    for ( var i = 0; i < al && i < bl; i++ ) {\n      if ( ap[i] !== bp[i] ) {\n        return siblingCheck( ap[i], bp[i] );\n      }\n    }\n\n    // We ended someplace up the tree so do a sibling check\n    return i === al ?\n      siblingCheck( a, bp[i], -1 ) :\n      siblingCheck( ap[i], b, 1 );\n  };\n\n  siblingCheck = function( a, b, ret ) {\n    if ( a === b ) {\n      return ret;\n    }\n\n    var cur = a.nextSibling;\n\n    while ( cur ) {\n      if ( cur === b ) {\n        return -1;\n      }\n\n      cur = cur.nextSibling;\n    }\n\n    return 1;\n  };\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n  // We're going to inject a fake input element with a specified name\n  var form = document.createElement(\"div\"),\n    id = \"script\" + (new Date()).getTime(),\n    root = document.documentElement;\n\n  form.innerHTML = \"<a name='\" + id + \"'/>\";\n\n  // Inject it into the root element, check its status, and remove it quickly\n  root.insertBefore( form, root.firstChild );\n\n  // The workaround has to do additional checks after a getElementById\n  // Which slows things down for other browsers (hence the branching)\n  if ( document.getElementById( id ) ) {\n    Expr.find.ID = function( match, context, isXML ) {\n      if ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n        var m = context.getElementById(match[1]);\n\n        return m ?\n          m.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n            [m] :\n            undefined :\n          [];\n      }\n    };\n\n    Expr.filter.ID = function( elem, match ) {\n      var node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n      return elem.nodeType === 1 && node && node.nodeValue === match;\n    };\n  }\n\n  root.removeChild( form );\n\n  // release memory in IE\n  root = form = null;\n})();\n\n(function(){\n  // Check to see if the browser returns only elements\n  // when doing getElementsByTagName(\"*\")\n\n  // Create a fake element\n  var div = document.createElement(\"div\");\n  div.appendChild( document.createComment(\"\") );\n\n  // Make sure no comments are found\n  if ( div.getElementsByTagName(\"*\").length > 0 ) {\n    Expr.find.TAG = function( match, context ) {\n      var results = context.getElementsByTagName( match[1] );\n\n      // Filter out possible comments\n      if ( match[1] === \"*\" ) {\n        var tmp = [];\n\n        for ( var i = 0; results[i]; i++ ) {\n          if ( results[i].nodeType === 1 ) {\n            tmp.push( results[i] );\n          }\n        }\n\n        results = tmp;\n      }\n\n      return results;\n    };\n  }\n\n  // Check to see if an attribute returns normalized href attributes\n  div.innerHTML = \"<a href='#'></a>\";\n\n  if ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n      div.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n    Expr.attrHandle.href = function( elem ) {\n      return elem.getAttribute( \"href\", 2 );\n    };\n  }\n\n  // release memory in IE\n  div = null;\n})();\n\nif ( document.querySelectorAll ) {\n  (function(){\n    var oldSizzle = Sizzle,\n      div = document.createElement(\"div\"),\n      id = \"__sizzle__\";\n\n    div.innerHTML = \"<p class='TEST'></p>\";\n\n    // Safari can't handle uppercase or unicode characters when\n    // in quirks mode.\n    if ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n      return;\n    }\n\n    Sizzle = function( query, context, extra, seed ) {\n      context = context || document;\n\n      // Only use querySelectorAll on non-XML documents\n      // (ID selectors don't work in non-HTML documents)\n      if ( !seed && !Sizzle.isXML(context) ) {\n        // See if we find a selector to speed up\n        var match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n        if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n          // Speed-up: Sizzle(\"TAG\")\n          if ( match[1] ) {\n            return makeArray( context.getElementsByTagName( query ), extra );\n\n          // Speed-up: Sizzle(\".CLASS\")\n          } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n            return makeArray( context.getElementsByClassName( match[2] ), extra );\n          }\n        }\n\n        if ( context.nodeType === 9 ) {\n          // Speed-up: Sizzle(\"body\")\n          // The body element only exists once, optimize finding it\n          if ( query === \"body\" && context.body ) {\n            return makeArray( [ context.body ], extra );\n\n          // Speed-up: Sizzle(\"#ID\")\n          } else if ( match && match[3] ) {\n            var elem = context.getElementById( match[3] );\n\n            // Check parentNode to catch when Blackberry 4.6 returns\n            // nodes that are no longer in the document #6963\n            if ( elem && elem.parentNode ) {\n              // Handle the case where IE and Opera return items\n              // by name instead of ID\n              if ( elem.id === match[3] ) {\n                return makeArray( [ elem ], extra );\n              }\n\n            } else {\n              return makeArray( [], extra );\n            }\n          }\n\n          try {\n            return makeArray( context.querySelectorAll(query), extra );\n          } catch(qsaError) {}\n\n        // qSA works strangely on Element-rooted queries\n        // We can work around this by specifying an extra ID on the root\n        // and working up from there (Thanks to Andrew Dupont for the technique)\n        // IE 8 doesn't work on object elements\n        } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n          var oldContext = context,\n            old = context.getAttribute( \"id\" ),\n            nid = old || id,\n            hasParent = context.parentNode,\n            relativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n          if ( !old ) {\n            context.setAttribute( \"id\", nid );\n          } else {\n            nid = nid.replace( /'/g, \"\\\\$&\" );\n          }\n          if ( relativeHierarchySelector && hasParent ) {\n            context = context.parentNode;\n          }\n\n          try {\n            if ( !relativeHierarchySelector || hasParent ) {\n              return makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n            }\n\n          } catch(pseudoError) {\n          } finally {\n            if ( !old ) {\n              oldContext.removeAttribute( \"id\" );\n            }\n          }\n        }\n      }\n\n      return oldSizzle(query, context, extra, seed);\n    };\n\n    for ( var prop in oldSizzle ) {\n      Sizzle[ prop ] = oldSizzle[ prop ];\n    }\n\n    // release memory in IE\n    div = null;\n  })();\n}\n\n(function(){\n  var html = document.documentElement,\n    matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n  if ( matches ) {\n    // Check to see if it's possible to do matchesSelector\n    // on a disconnected node (IE 9 fails this)\n    var disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n      pseudoWorks = false;\n\n    try {\n      // This should fail with an exception\n      // Gecko does not error, returns false instead\n      matches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n    } catch( pseudoError ) {\n      pseudoWorks = true;\n    }\n\n    Sizzle.matchesSelector = function( node, expr ) {\n      // Make sure that attribute selectors are quoted\n      expr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n      if ( !Sizzle.isXML( node ) ) {\n        try {\n          if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n            var ret = matches.call( node, expr );\n\n            // IE 9's matchesSelector returns false on disconnected nodes\n            if ( ret || !disconnectedMatch ||\n                // As well, disconnected nodes are said to be in a document\n                // fragment in IE 9, so check for that\n                node.document && node.document.nodeType !== 11 ) {\n              return ret;\n            }\n          }\n        } catch(e) {}\n      }\n\n      return Sizzle(expr, null, null, [node]).length > 0;\n    };\n  }\n})();\n\n(function(){\n  var div = document.createElement(\"div\");\n\n  div.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n  // Opera can't find a second classname (in 9.6)\n  // Also, make sure that getElementsByClassName actually exists\n  if ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n    return;\n  }\n\n  // Safari caches class attributes, doesn't catch changes (in 3.2)\n  div.lastChild.className = \"e\";\n\n  if ( div.getElementsByClassName(\"e\").length === 1 ) {\n    return;\n  }\n\n  Expr.order.splice(1, 0, \"CLASS\");\n  Expr.find.CLASS = function( match, context, isXML ) {\n    if ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n      return context.getElementsByClassName(match[1]);\n    }\n  };\n\n  // release memory in IE\n  div = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n  for ( var i = 0, l = checkSet.length; i < l; i++ ) {\n    var elem = checkSet[i];\n\n    if ( elem ) {\n      var match = false;\n\n      elem = elem[dir];\n\n      while ( elem ) {\n        if ( elem[ expando ] === doneName ) {\n          match = checkSet[elem.sizset];\n          break;\n        }\n\n        if ( elem.nodeType === 1 && !isXML ){\n          elem[ expando ] = doneName;\n          elem.sizset = i;\n        }\n\n        if ( elem.nodeName.toLowerCase() === cur ) {\n          match = elem;\n          break;\n        }\n\n        elem = elem[dir];\n      }\n\n      checkSet[i] = match;\n    }\n  }\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n  for ( var i = 0, l = checkSet.length; i < l; i++ ) {\n    var elem = checkSet[i];\n\n    if ( elem ) {\n      var match = false;\n\n      elem = elem[dir];\n\n      while ( elem ) {\n        if ( elem[ expando ] === doneName ) {\n          match = checkSet[elem.sizset];\n          break;\n        }\n\n        if ( elem.nodeType === 1 ) {\n          if ( !isXML ) {\n            elem[ expando ] = doneName;\n            elem.sizset = i;\n          }\n\n          if ( typeof cur !== \"string\" ) {\n            if ( elem === cur ) {\n              match = true;\n              break;\n            }\n\n          } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n            match = elem;\n            break;\n          }\n        }\n\n        elem = elem[dir];\n      }\n\n      checkSet[i] = match;\n    }\n  }\n}\n\nif ( document.documentElement.contains ) {\n  Sizzle.contains = function( a, b ) {\n    return a !== b && (a.contains ? a.contains(b) : true);\n  };\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n  Sizzle.contains = function( a, b ) {\n    return !!(a.compareDocumentPosition(b) & 16);\n  };\n\n} else {\n  Sizzle.contains = function() {\n    return false;\n  };\n}\n\nSizzle.isXML = function( elem ) {\n  // documentElement is verified for cases where it doesn't yet exist\n  // (such as loading iframes in IE - #4833)\n  var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n  return documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n  var match,\n    tmpSet = [],\n    later = \"\",\n    root = context.nodeType ? [context] : context;\n\n  // Position selectors must be done after the filter\n  // And so must :not(positional) so we move all PSEUDOs to the end\n  while ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n    later += match[0];\n    selector = selector.replace( Expr.match.PSEUDO, \"\" );\n  }\n\n  selector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n  for ( var i = 0, l = root.length; i < l; i++ ) {\n    Sizzle( selector, root[i], tmpSet, seed );\n  }\n\n  return Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n  rparentsprev = /^(?:parents|prevUntil|prevAll)/,\n  // Note: This RegExp should be improved, or likely pulled from Sizzle\n  rmultiselector = /,/,\n  isSimple = /^.[^:#\\[\\.,]*$/,\n  slice = Array.prototype.slice,\n  POS = jQuery.expr.match.globalPOS,\n  // methods guaranteed to produce a unique set when starting from a unique set\n  guaranteedUnique = {\n    children: true,\n    contents: true,\n    next: true,\n    prev: true\n  };\n\njQuery.fn.extend({\n  find: function( selector ) {\n    var self = this,\n      i, l;\n\n    if ( typeof selector !== \"string\" ) {\n      return jQuery( selector ).filter(function() {\n        for ( i = 0, l = self.length; i < l; i++ ) {\n          if ( jQuery.contains( self[ i ], this ) ) {\n            return true;\n          }\n        }\n      });\n    }\n\n    var ret = this.pushStack( \"\", \"find\", selector ),\n      length, n, r;\n\n    for ( i = 0, l = this.length; i < l; i++ ) {\n      length = ret.length;\n      jQuery.find( selector, this[i], ret );\n\n      if ( i > 0 ) {\n        // Make sure that the results are unique\n        for ( n = length; n < ret.length; n++ ) {\n          for ( r = 0; r < length; r++ ) {\n            if ( ret[r] === ret[n] ) {\n              ret.splice(n--, 1);\n              break;\n            }\n          }\n        }\n      }\n    }\n\n    return ret;\n  },\n\n  has: function( target ) {\n    var targets = jQuery( target );\n    return this.filter(function() {\n      for ( var i = 0, l = targets.length; i < l; i++ ) {\n        if ( jQuery.contains( this, targets[i] ) ) {\n          return true;\n        }\n      }\n    });\n  },\n\n  not: function( selector ) {\n    return this.pushStack( winnow(this, selector, false), \"not\", selector);\n  },\n\n  filter: function( selector ) {\n    return this.pushStack( winnow(this, selector, true), \"filter\", selector );\n  },\n\n  is: function( selector ) {\n    return !!selector && (\n      typeof selector === \"string\" ?\n        // If this is a positional selector, check membership in the returned set\n        // so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n        POS.test( selector ) ?\n          jQuery( selector, this.context ).index( this[0] ) >= 0 :\n          jQuery.filter( selector, this ).length > 0 :\n        this.filter( selector ).length > 0 );\n  },\n\n  closest: function( selectors, context ) {\n    var ret = [], i, l, cur = this[0];\n\n    // Array (deprecated as of jQuery 1.7)\n    if ( jQuery.isArray( selectors ) ) {\n      var level = 1;\n\n      while ( cur && cur.ownerDocument && cur !== context ) {\n        for ( i = 0; i < selectors.length; i++ ) {\n\n          if ( jQuery( cur ).is( selectors[ i ] ) ) {\n            ret.push({ selector: selectors[ i ], elem: cur, level: level });\n          }\n        }\n\n        cur = cur.parentNode;\n        level++;\n      }\n\n      return ret;\n    }\n\n    // String\n    var pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n        jQuery( selectors, context || this.context ) :\n        0;\n\n    for ( i = 0, l = this.length; i < l; i++ ) {\n      cur = this[i];\n\n      while ( cur ) {\n        if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n          ret.push( cur );\n          break;\n\n        } else {\n          cur = cur.parentNode;\n          if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n            break;\n          }\n        }\n      }\n    }\n\n    ret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n    return this.pushStack( ret, \"closest\", selectors );\n  },\n\n  // Determine the position of an element within\n  // the matched set of elements\n  index: function( elem ) {\n\n    // No argument, return index in parent\n    if ( !elem ) {\n      return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n    }\n\n    // index in selector\n    if ( typeof elem === \"string\" ) {\n      return jQuery.inArray( this[0], jQuery( elem ) );\n    }\n\n    // Locate the position of the desired element\n    return jQuery.inArray(\n      // If it receives a jQuery object, the first element is used\n      elem.jquery ? elem[0] : elem, this );\n  },\n\n  add: function( selector, context ) {\n    var set = typeof selector === \"string\" ?\n        jQuery( selector, context ) :\n        jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n      all = jQuery.merge( this.get(), set );\n\n    return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n      all :\n      jQuery.unique( all ) );\n  },\n\n  andSelf: function() {\n    return this.add( this.prevObject );\n  }\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n  return !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n  parent: function( elem ) {\n    var parent = elem.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n  parents: function( elem ) {\n    return jQuery.dir( elem, \"parentNode\" );\n  },\n  parentsUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"parentNode\", until );\n  },\n  next: function( elem ) {\n    return jQuery.nth( elem, 2, \"nextSibling\" );\n  },\n  prev: function( elem ) {\n    return jQuery.nth( elem, 2, \"previousSibling\" );\n  },\n  nextAll: function( elem ) {\n    return jQuery.dir( elem, \"nextSibling\" );\n  },\n  prevAll: function( elem ) {\n    return jQuery.dir( elem, \"previousSibling\" );\n  },\n  nextUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"nextSibling\", until );\n  },\n  prevUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"previousSibling\", until );\n  },\n  siblings: function( elem ) {\n    return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n  },\n  children: function( elem ) {\n    return jQuery.sibling( elem.firstChild );\n  },\n  contents: function( elem ) {\n    return jQuery.nodeName( elem, \"iframe\" ) ?\n      elem.contentDocument || elem.contentWindow.document :\n      jQuery.makeArray( elem.childNodes );\n  }\n}, function( name, fn ) {\n  jQuery.fn[ name ] = function( until, selector ) {\n    var ret = jQuery.map( this, fn, until );\n\n    if ( !runtil.test( name ) ) {\n      selector = until;\n    }\n\n    if ( selector && typeof selector === \"string\" ) {\n      ret = jQuery.filter( selector, ret );\n    }\n\n    ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n    if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n      ret = ret.reverse();\n    }\n\n    return this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n  };\n});\n\njQuery.extend({\n  filter: function( expr, elems, not ) {\n    if ( not ) {\n      expr = \":not(\" + expr + \")\";\n    }\n\n    return elems.length === 1 ?\n      jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n      jQuery.find.matches(expr, elems);\n  },\n\n  dir: function( elem, dir, until ) {\n    var matched = [],\n      cur = elem[ dir ];\n\n    while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n      if ( cur.nodeType === 1 ) {\n        matched.push( cur );\n      }\n      cur = cur[dir];\n    }\n    return matched;\n  },\n\n  nth: function( cur, result, dir, elem ) {\n    result = result || 1;\n    var num = 0;\n\n    for ( ; cur; cur = cur[dir] ) {\n      if ( cur.nodeType === 1 && ++num === result ) {\n        break;\n      }\n    }\n\n    return cur;\n  },\n\n  sibling: function( n, elem ) {\n    var r = [];\n\n    for ( ; n; n = n.nextSibling ) {\n      if ( n.nodeType === 1 && n !== elem ) {\n        r.push( n );\n      }\n    }\n\n    return r;\n  }\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n  // Can't pass null or undefined to indexOf in Firefox 4\n  // Set to 0 to skip string check\n  qualifier = qualifier || 0;\n\n  if ( jQuery.isFunction( qualifier ) ) {\n    return jQuery.grep(elements, function( elem, i ) {\n      var retVal = !!qualifier.call( elem, i, elem );\n      return retVal === keep;\n    });\n\n  } else if ( qualifier.nodeType ) {\n    return jQuery.grep(elements, function( elem, i ) {\n      return ( elem === qualifier ) === keep;\n    });\n\n  } else if ( typeof qualifier === \"string\" ) {\n    var filtered = jQuery.grep(elements, function( elem ) {\n      return elem.nodeType === 1;\n    });\n\n    if ( isSimple.test( qualifier ) ) {\n      return jQuery.filter(qualifier, filtered, !keep);\n    } else {\n      qualifier = jQuery.filter( qualifier, filtered );\n    }\n  }\n\n  return jQuery.grep(elements, function( elem, i ) {\n    return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n  });\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n  var list = nodeNames.split( \"|\" ),\n  safeFrag = document.createDocumentFragment();\n\n  if ( safeFrag.createElement ) {\n    while ( list.length ) {\n      safeFrag.createElement(\n        list.pop()\n      );\n    }\n  }\n  return safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n    \"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n  rinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n  rleadingWhitespace = /^\\s+/,\n  rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n  rtagName = /<([\\w:]+)/,\n  rtbody = /<tbody/i,\n  rhtml = /<|&#?\\w+;/,\n  rnoInnerhtml = /<(?:script|style)/i,\n  rnocache = /<(?:script|object|embed|option|style)/i,\n  rnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n  // checked=\"checked\" or checked\n  rchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n  rscriptType = /\\/(java|ecma)script/i,\n  rcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n  wrapMap = {\n    option: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n    legend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n    thead: [ 1, \"<table>\", \"</table>\" ],\n    tr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n    td: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n    col: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n    area: [ 1, \"<map>\", \"</map>\" ],\n    _default: [ 0, \"\", \"\" ]\n  },\n  safeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n  wrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n  text: function( value ) {\n    return jQuery.access( this, function( value ) {\n      return value === undefined ?\n        jQuery.text( this ) :\n        this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n    }, null, value, arguments.length );\n  },\n\n  wrapAll: function( html ) {\n    if ( jQuery.isFunction( html ) ) {\n      return this.each(function(i) {\n        jQuery(this).wrapAll( html.call(this, i) );\n      });\n    }\n\n    if ( this[0] ) {\n      // The elements to wrap the target around\n      var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n      if ( this[0].parentNode ) {\n        wrap.insertBefore( this[0] );\n      }\n\n      wrap.map(function() {\n        var elem = this;\n\n        while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n          elem = elem.firstChild;\n        }\n\n        return elem;\n      }).append( this );\n    }\n\n    return this;\n  },\n\n  wrapInner: function( html ) {\n    if ( jQuery.isFunction( html ) ) {\n      return this.each(function(i) {\n        jQuery(this).wrapInner( html.call(this, i) );\n      });\n    }\n\n    return this.each(function() {\n      var self = jQuery( this ),\n        contents = self.contents();\n\n      if ( contents.length ) {\n        contents.wrapAll( html );\n\n      } else {\n        self.append( html );\n      }\n    });\n  },\n\n  wrap: function( html ) {\n    var isFunction = jQuery.isFunction( html );\n\n    return this.each(function(i) {\n      jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n    });\n  },\n\n  unwrap: function() {\n    return this.parent().each(function() {\n      if ( !jQuery.nodeName( this, \"body\" ) ) {\n        jQuery( this ).replaceWith( this.childNodes );\n      }\n    }).end();\n  },\n\n  append: function() {\n    return this.domManip(arguments, true, function( elem ) {\n      if ( this.nodeType === 1 ) {\n        this.appendChild( elem );\n      }\n    });\n  },\n\n  prepend: function() {\n    return this.domManip(arguments, true, function( elem ) {\n      if ( this.nodeType === 1 ) {\n        this.insertBefore( elem, this.firstChild );\n      }\n    });\n  },\n\n  before: function() {\n    if ( this[0] && this[0].parentNode ) {\n      return this.domManip(arguments, false, function( elem ) {\n        this.parentNode.insertBefore( elem, this );\n      });\n    } else if ( arguments.length ) {\n      var set = jQuery.clean( arguments );\n      set.push.apply( set, this.toArray() );\n      return this.pushStack( set, \"before\", arguments );\n    }\n  },\n\n  after: function() {\n    if ( this[0] && this[0].parentNode ) {\n      return this.domManip(arguments, false, function( elem ) {\n        this.parentNode.insertBefore( elem, this.nextSibling );\n      });\n    } else if ( arguments.length ) {\n      var set = this.pushStack( this, \"after\", arguments );\n      set.push.apply( set, jQuery.clean(arguments) );\n      return set;\n    }\n  },\n\n  // keepData is for internal use only--do not document\n  remove: function( selector, keepData ) {\n    for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n      if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n        if ( !keepData && elem.nodeType === 1 ) {\n          jQuery.cleanData( elem.getElementsByTagName(\"*\") );\n          jQuery.cleanData( [ elem ] );\n        }\n\n        if ( elem.parentNode ) {\n          elem.parentNode.removeChild( elem );\n        }\n      }\n    }\n\n    return this;\n  },\n\n  empty: function() {\n    for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n      // Remove element nodes and prevent memory leaks\n      if ( elem.nodeType === 1 ) {\n        jQuery.cleanData( elem.getElementsByTagName(\"*\") );\n      }\n\n      // Remove any remaining nodes\n      while ( elem.firstChild ) {\n        elem.removeChild( elem.firstChild );\n      }\n    }\n\n    return this;\n  },\n\n  clone: function( dataAndEvents, deepDataAndEvents ) {\n    dataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n    deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n    return this.map( function () {\n      return jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n    });\n  },\n\n  html: function( value ) {\n    return jQuery.access( this, function( value ) {\n      var elem = this[0] || {},\n        i = 0,\n        l = this.length;\n\n      if ( value === undefined ) {\n        return elem.nodeType === 1 ?\n          elem.innerHTML.replace( rinlinejQuery, \"\" ) :\n          null;\n      }\n\n\n      if ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n        ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n        !wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n        value = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n        try {\n          for (; i < l; i++ ) {\n            // Remove element nodes and prevent memory leaks\n            elem = this[i] || {};\n            if ( elem.nodeType === 1 ) {\n              jQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n              elem.innerHTML = value;\n            }\n          }\n\n          elem = 0;\n\n        // If using innerHTML throws an exception, use the fallback method\n        } catch(e) {}\n      }\n\n      if ( elem ) {\n        this.empty().append( value );\n      }\n    }, null, value, arguments.length );\n  },\n\n  replaceWith: function( value ) {\n    if ( this[0] && this[0].parentNode ) {\n      // Make sure that the elements are removed from the DOM before they are inserted\n      // this can help fix replacing a parent with child elements\n      if ( jQuery.isFunction( value ) ) {\n        return this.each(function(i) {\n          var self = jQuery(this), old = self.html();\n          self.replaceWith( value.call( this, i, old ) );\n        });\n      }\n\n      if ( typeof value !== \"string\" ) {\n        value = jQuery( value ).detach();\n      }\n\n      return this.each(function() {\n        var next = this.nextSibling,\n          parent = this.parentNode;\n\n        jQuery( this ).remove();\n\n        if ( next ) {\n          jQuery(next).before( value );\n        } else {\n          jQuery(parent).append( value );\n        }\n      });\n    } else {\n      return this.length ?\n        this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n        this;\n    }\n  },\n\n  detach: function( selector ) {\n    return this.remove( selector, true );\n  },\n\n  domManip: function( args, table, callback ) {\n    var results, first, fragment, parent,\n      value = args[0],\n      scripts = [];\n\n    // We can't cloneNode fragments that contain checked, in WebKit\n    if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n      return this.each(function() {\n        jQuery(this).domManip( args, table, callback, true );\n      });\n    }\n\n    if ( jQuery.isFunction(value) ) {\n      return this.each(function(i) {\n        var self = jQuery(this);\n        args[0] = value.call(this, i, table ? self.html() : undefined);\n        self.domManip( args, table, callback );\n      });\n    }\n\n    if ( this[0] ) {\n      parent = value && value.parentNode;\n\n      // If we're in a fragment, just use that instead of building a new one\n      if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n        results = { fragment: parent };\n\n      } else {\n        results = jQuery.buildFragment( args, this, scripts );\n      }\n\n      fragment = results.fragment;\n\n      if ( fragment.childNodes.length === 1 ) {\n        first = fragment = fragment.firstChild;\n      } else {\n        first = fragment.firstChild;\n      }\n\n      if ( first ) {\n        table = table && jQuery.nodeName( first, \"tr\" );\n\n        for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n          callback.call(\n            table ?\n              root(this[i], first) :\n              this[i],\n            // Make sure that we do not leak memory by inadvertently discarding\n            // the original fragment (which might have attached data) instead of\n            // using it; in addition, use the original fragment object for the last\n            // item instead of first because it can end up being emptied incorrectly\n            // in certain situations (Bug #8070).\n            // Fragments from the fragment cache must always be cloned and never used\n            // in place.\n            results.cacheable || ( l > 1 && i < lastIndex ) ?\n              jQuery.clone( fragment, true, true ) :\n              fragment\n          );\n        }\n      }\n\n      if ( scripts.length ) {\n        jQuery.each( scripts, function( i, elem ) {\n          if ( elem.src ) {\n            jQuery.ajax({\n              type: \"GET\",\n              global: false,\n              url: elem.src,\n              async: false,\n              dataType: \"script\"\n            });\n          } else {\n            jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n          }\n\n          if ( elem.parentNode ) {\n            elem.parentNode.removeChild( elem );\n          }\n        });\n      }\n    }\n\n    return this;\n  }\n});\n\nfunction root( elem, cur ) {\n  return jQuery.nodeName(elem, \"table\") ?\n    (elem.getElementsByTagName(\"tbody\")[0] ||\n    elem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n    elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n  if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n    return;\n  }\n\n  var type, i, l,\n    oldData = jQuery._data( src ),\n    curData = jQuery._data( dest, oldData ),\n    events = oldData.events;\n\n  if ( events ) {\n    delete curData.handle;\n    curData.events = {};\n\n    for ( type in events ) {\n      for ( i = 0, l = events[ type ].length; i < l; i++ ) {\n        jQuery.event.add( dest, type, events[ type ][ i ] );\n      }\n    }\n  }\n\n  // make the cloned public data object a copy from the original\n  if ( curData.data ) {\n    curData.data = jQuery.extend( {}, curData.data );\n  }\n}\n\nfunction cloneFixAttributes( src, dest ) {\n  var nodeName;\n\n  // We do not need to do anything for non-Elements\n  if ( dest.nodeType !== 1 ) {\n    return;\n  }\n\n  // clearAttributes removes the attributes, which we don't want,\n  // but also removes the attachEvent events, which we *do* want\n  if ( dest.clearAttributes ) {\n    dest.clearAttributes();\n  }\n\n  // mergeAttributes, in contrast, only merges back on the\n  // original attributes, not the events\n  if ( dest.mergeAttributes ) {\n    dest.mergeAttributes( src );\n  }\n\n  nodeName = dest.nodeName.toLowerCase();\n\n  // IE6-8 fail to clone children inside object elements that use\n  // the proprietary classid attribute value (rather than the type\n  // attribute) to identify the type of content to display\n  if ( nodeName === \"object\" ) {\n    dest.outerHTML = src.outerHTML;\n\n  } else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n    // IE6-8 fails to persist the checked state of a cloned checkbox\n    // or radio button. Worse, IE6-7 fail to give the cloned element\n    // a checked appearance if the defaultChecked value isn't also set\n    if ( src.checked ) {\n      dest.defaultChecked = dest.checked = src.checked;\n    }\n\n    // IE6-7 get confused and end up setting the value of a cloned\n    // checkbox/radio button to an empty string instead of \"on\"\n    if ( dest.value !== src.value ) {\n      dest.value = src.value;\n    }\n\n  // IE6-8 fails to return the selected option to the default selected\n  // state when cloning options\n  } else if ( nodeName === \"option\" ) {\n    dest.selected = src.defaultSelected;\n\n  // IE6-8 fails to set the defaultValue to the correct value when\n  // cloning other types of input fields\n  } else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n    dest.defaultValue = src.defaultValue;\n\n  // IE blanks contents when cloning scripts\n  } else if ( nodeName === \"script\" && dest.text !== src.text ) {\n    dest.text = src.text;\n  }\n\n  // Event data gets referenced instead of copied if the expando\n  // gets copied too\n  dest.removeAttribute( jQuery.expando );\n\n  // Clear flags for bubbling special change/submit events, they must\n  // be reattached when the newly cloned events are first activated\n  dest.removeAttribute( \"_submit_attached\" );\n  dest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n  var fragment, cacheable, cacheresults, doc,\n  first = args[ 0 ];\n\n  // nodes may contain either an explicit document object,\n  // a jQuery collection or context object.\n  // If nodes[0] contains a valid object to assign to doc\n  if ( nodes && nodes[0] ) {\n    doc = nodes[0].ownerDocument || nodes[0];\n  }\n\n  // Ensure that an attr object doesn't incorrectly stand in as a document object\n  // Chrome and Firefox seem to allow this to occur and will throw exception\n  // Fixes #8950\n  if ( !doc.createDocumentFragment ) {\n    doc = document;\n  }\n\n  // Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n  // Cloning options loses the selected state, so don't cache them\n  // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n  // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n  // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n  if ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n    first.charAt(0) === \"<\" && !rnocache.test( first ) &&\n    (jQuery.support.checkClone || !rchecked.test( first )) &&\n    (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n    cacheable = true;\n\n    cacheresults = jQuery.fragments[ first ];\n    if ( cacheresults && cacheresults !== 1 ) {\n      fragment = cacheresults;\n    }\n  }\n\n  if ( !fragment ) {\n    fragment = doc.createDocumentFragment();\n    jQuery.clean( args, doc, fragment, scripts );\n  }\n\n  if ( cacheable ) {\n    jQuery.fragments[ first ] = cacheresults ? fragment : 1;\n  }\n\n  return { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n  appendTo: \"append\",\n  prependTo: \"prepend\",\n  insertBefore: \"before\",\n  insertAfter: \"after\",\n  replaceAll: \"replaceWith\"\n}, function( name, original ) {\n  jQuery.fn[ name ] = function( selector ) {\n    var ret = [],\n      insert = jQuery( selector ),\n      parent = this.length === 1 && this[0].parentNode;\n\n    if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n      insert[ original ]( this[0] );\n      return this;\n\n    } else {\n      for ( var i = 0, l = insert.length; i < l; i++ ) {\n        var elems = ( i > 0 ? this.clone(true) : this ).get();\n        jQuery( insert[i] )[ original ]( elems );\n        ret = ret.concat( elems );\n      }\n\n      return this.pushStack( ret, name, insert.selector );\n    }\n  };\n});\n\nfunction getAll( elem ) {\n  if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n    return elem.getElementsByTagName( \"*\" );\n\n  } else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n    return elem.querySelectorAll( \"*\" );\n\n  } else {\n    return [];\n  }\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n  if ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n    elem.defaultChecked = elem.checked;\n  }\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n  var nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n  if ( nodeName === \"input\" ) {\n    fixDefaultChecked( elem );\n  // Skip scripts, get other children\n  } else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n    jQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n  }\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n  var div = document.createElement( \"div\" );\n  safeFragment.appendChild( div );\n\n  div.innerHTML = elem.outerHTML;\n  return div.firstChild;\n}\n\njQuery.extend({\n  clone: function( elem, dataAndEvents, deepDataAndEvents ) {\n    var srcElements,\n      destElements,\n      i,\n      // IE<=8 does not properly clone detached, unknown element nodes\n      clone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n        elem.cloneNode( true ) :\n        shimCloneNode( elem );\n\n    if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n        (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n      // IE copies events bound via attachEvent when using cloneNode.\n      // Calling detachEvent on the clone will also remove the events\n      // from the original. In order to get around this, we use some\n      // proprietary methods to clear the events. Thanks to MooTools\n      // guys for this hotness.\n\n      cloneFixAttributes( elem, clone );\n\n      // Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n      srcElements = getAll( elem );\n      destElements = getAll( clone );\n\n      // Weird iteration because IE will replace the length property\n      // with an element if you are cloning the body and one of the\n      // elements on the page has a name or id of \"length\"\n      for ( i = 0; srcElements[i]; ++i ) {\n        // Ensure that the destination node is not null; Fixes #9587\n        if ( destElements[i] ) {\n          cloneFixAttributes( srcElements[i], destElements[i] );\n        }\n      }\n    }\n\n    // Copy the events from the original to the clone\n    if ( dataAndEvents ) {\n      cloneCopyEvent( elem, clone );\n\n      if ( deepDataAndEvents ) {\n        srcElements = getAll( elem );\n        destElements = getAll( clone );\n\n        for ( i = 0; srcElements[i]; ++i ) {\n          cloneCopyEvent( srcElements[i], destElements[i] );\n        }\n      }\n    }\n\n    srcElements = destElements = null;\n\n    // Return the cloned set\n    return clone;\n  },\n\n  clean: function( elems, context, fragment, scripts ) {\n    var checkScriptType, script, j,\n        ret = [];\n\n    context = context || document;\n\n    // !context.createElement fails in IE with an error but returns typeof 'object'\n    if ( typeof context.createElement === \"undefined\" ) {\n      context = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n    }\n\n    for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n      if ( typeof elem === \"number\" ) {\n        elem += \"\";\n      }\n\n      if ( !elem ) {\n        continue;\n      }\n\n      // Convert html string into DOM nodes\n      if ( typeof elem === \"string\" ) {\n        if ( !rhtml.test( elem ) ) {\n          elem = context.createTextNode( elem );\n        } else {\n          // Fix \"XHTML\"-style tags in all browsers\n          elem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n          // Trim whitespace, otherwise indexOf won't work as expected\n          var tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n            wrap = wrapMap[ tag ] || wrapMap._default,\n            depth = wrap[0],\n            div = context.createElement(\"div\"),\n            safeChildNodes = safeFragment.childNodes,\n            remove;\n\n          // Append wrapper element to unknown element safe doc fragment\n          if ( context === document ) {\n            // Use the fragment we've already created for this document\n            safeFragment.appendChild( div );\n          } else {\n            // Use a fragment created with the owner document\n            createSafeFragment( context ).appendChild( div );\n          }\n\n          // Go to html and back, then peel off extra wrappers\n          div.innerHTML = wrap[1] + elem + wrap[2];\n\n          // Move to the right depth\n          while ( depth-- ) {\n            div = div.lastChild;\n          }\n\n          // Remove IE's autoinserted <tbody> from table fragments\n          if ( !jQuery.support.tbody ) {\n\n            // String was a <table>, *may* have spurious <tbody>\n            var hasBody = rtbody.test(elem),\n              tbody = tag === \"table\" && !hasBody ?\n                div.firstChild && div.firstChild.childNodes :\n\n                // String was a bare <thead> or <tfoot>\n                wrap[1] === \"<table>\" && !hasBody ?\n                  div.childNodes :\n                  [];\n\n            for ( j = tbody.length - 1; j >= 0 ; --j ) {\n              if ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n                tbody[ j ].parentNode.removeChild( tbody[ j ] );\n              }\n            }\n          }\n\n          // IE completely kills leading whitespace when innerHTML is used\n          if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n            div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n          }\n\n          elem = div.childNodes;\n\n          // Clear elements from DocumentFragment (safeFragment or otherwise)\n          // to avoid hoarding elements. Fixes #11356\n          if ( div ) {\n            div.parentNode.removeChild( div );\n\n            // Guard against -1 index exceptions in FF3.6\n            if ( safeChildNodes.length > 0 ) {\n              remove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n              if ( remove && remove.parentNode ) {\n                remove.parentNode.removeChild( remove );\n              }\n            }\n          }\n        }\n      }\n\n      // Resets defaultChecked for any radios and checkboxes\n      // about to be appended to the DOM in IE 6/7 (#8060)\n      var len;\n      if ( !jQuery.support.appendChecked ) {\n        if ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n          for ( j = 0; j < len; j++ ) {\n            findInputs( elem[j] );\n          }\n        } else {\n          findInputs( elem );\n        }\n      }\n\n      if ( elem.nodeType ) {\n        ret.push( elem );\n      } else {\n        ret = jQuery.merge( ret, elem );\n      }\n    }\n\n    if ( fragment ) {\n      checkScriptType = function( elem ) {\n        return !elem.type || rscriptType.test( elem.type );\n      };\n      for ( i = 0; ret[i]; i++ ) {\n        script = ret[i];\n        if ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n          scripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n        } else {\n          if ( script.nodeType === 1 ) {\n            var jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n            ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n          }\n          fragment.appendChild( script );\n        }\n      }\n    }\n\n    return ret;\n  },\n\n  cleanData: function( elems ) {\n    var data, id,\n      cache = jQuery.cache,\n      special = jQuery.event.special,\n      deleteExpando = jQuery.support.deleteExpando;\n\n    for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n      if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n        continue;\n      }\n\n      id = elem[ jQuery.expando ];\n\n      if ( id ) {\n        data = cache[ id ];\n\n        if ( data && data.events ) {\n          for ( var type in data.events ) {\n            if ( special[ type ] ) {\n              jQuery.event.remove( elem, type );\n\n            // This is a shortcut to avoid jQuery.event.remove's overhead\n            } else {\n              jQuery.removeEvent( elem, type, data.handle );\n            }\n          }\n\n          // Null the DOM reference to avoid IE6/7/8 leak (#7054)\n          if ( data.handle ) {\n            data.handle.elem = null;\n          }\n        }\n\n        if ( deleteExpando ) {\n          delete elem[ jQuery.expando ];\n\n        } else if ( elem.removeAttribute ) {\n          elem.removeAttribute( jQuery.expando );\n        }\n\n        delete cache[ id ];\n      }\n    }\n  }\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n  ropacity = /opacity=([^)]*)/,\n  // fixed for IE9, see #8346\n  rupper = /([A-Z]|^ms)/g,\n  rnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n  rnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n  rrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n  rmargin = /^margin/,\n\n  cssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n  // order is important!\n  cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n  curCSS,\n\n  getComputedStyle,\n  currentStyle;\n\njQuery.fn.css = function( name, value ) {\n  return jQuery.access( this, function( elem, name, value ) {\n    return value !== undefined ?\n      jQuery.style( elem, name, value ) :\n      jQuery.css( elem, name );\n  }, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n  // Add in style property hooks for overriding the default\n  // behavior of getting and setting a style property\n  cssHooks: {\n    opacity: {\n      get: function( elem, computed ) {\n        if ( computed ) {\n          // We should always get a number back from opacity\n          var ret = curCSS( elem, \"opacity\" );\n          return ret === \"\" ? \"1\" : ret;\n\n        } else {\n          return elem.style.opacity;\n        }\n      }\n    }\n  },\n\n  // Exclude the following css properties to add px\n  cssNumber: {\n    \"fillOpacity\": true,\n    \"fontWeight\": true,\n    \"lineHeight\": true,\n    \"opacity\": true,\n    \"orphans\": true,\n    \"widows\": true,\n    \"zIndex\": true,\n    \"zoom\": true\n  },\n\n  // Add in properties whose names you wish to fix before\n  // setting or getting the value\n  cssProps: {\n    // normalize float css property\n    \"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n  },\n\n  // Get and set the style property on a DOM Node\n  style: function( elem, name, value, extra ) {\n    // Don't set styles on text and comment nodes\n    if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n      return;\n    }\n\n    // Make sure that we're working with the right name\n    var ret, type, origName = jQuery.camelCase( name ),\n      style = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n    name = jQuery.cssProps[ origName ] || origName;\n\n    // Check if we're setting a value\n    if ( value !== undefined ) {\n      type = typeof value;\n\n      // convert relative number strings (+= or -=) to relative numbers. #7345\n      if ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n        value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n        // Fixes bug #9237\n        type = \"number\";\n      }\n\n      // Make sure that NaN and null values aren't set. See: #7116\n      if ( value == null || type === \"number\" && isNaN( value ) ) {\n        return;\n      }\n\n      // If a number was passed in, add 'px' to the (except for certain CSS properties)\n      if ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n        value += \"px\";\n      }\n\n      // If a hook was provided, use that value, otherwise just set the specified value\n      if ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n        // Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n        // Fixes bug #5509\n        try {\n          style[ name ] = value;\n        } catch(e) {}\n      }\n\n    } else {\n      // If a hook was provided get the non-computed value from there\n      if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n        return ret;\n      }\n\n      // Otherwise just get the value from the style object\n      return style[ name ];\n    }\n  },\n\n  css: function( elem, name, extra ) {\n    var ret, hooks;\n\n    // Make sure that we're working with the right name\n    name = jQuery.camelCase( name );\n    hooks = jQuery.cssHooks[ name ];\n    name = jQuery.cssProps[ name ] || name;\n\n    // cssFloat needs a special treatment\n    if ( name === \"cssFloat\" ) {\n      name = \"float\";\n    }\n\n    // If a hook was provided get the computed value from there\n    if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n      return ret;\n\n    // Otherwise, if a way to get the computed value exists, use that\n    } else if ( curCSS ) {\n      return curCSS( elem, name );\n    }\n  },\n\n  // A method for quickly swapping in/out CSS properties to get correct calculations\n  swap: function( elem, options, callback ) {\n    var old = {},\n      ret, name;\n\n    // Remember the old values, and insert the new ones\n    for ( name in options ) {\n      old[ name ] = elem.style[ name ];\n      elem.style[ name ] = options[ name ];\n    }\n\n    ret = callback.call( elem );\n\n    // Revert the old values\n    for ( name in options ) {\n      elem.style[ name ] = old[ name ];\n    }\n\n    return ret;\n  }\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n  getComputedStyle = function( elem, name ) {\n    var ret, defaultView, computedStyle, width,\n      style = elem.style;\n\n    name = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n    if ( (defaultView = elem.ownerDocument.defaultView) &&\n        (computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n      ret = computedStyle.getPropertyValue( name );\n      if ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n        ret = jQuery.style( elem, name );\n      }\n    }\n\n    // A tribute to the \"awesome hack by Dean Edwards\"\n    // WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n    // which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n    if ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n      width = style.width;\n      style.width = ret;\n      ret = computedStyle.width;\n      style.width = width;\n    }\n\n    return ret;\n  };\n}\n\nif ( document.documentElement.currentStyle ) {\n  currentStyle = function( elem, name ) {\n    var left, rsLeft, uncomputed,\n      ret = elem.currentStyle && elem.currentStyle[ name ],\n      style = elem.style;\n\n    // Avoid setting ret to empty string here\n    // so we don't default to auto\n    if ( ret == null && style && (uncomputed = style[ name ]) ) {\n      ret = uncomputed;\n    }\n\n    // From the awesome hack by Dean Edwards\n    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n    // If we're not dealing with a regular pixel number\n    // but a number that has a weird ending, we need to convert it to pixels\n    if ( rnumnonpx.test( ret ) ) {\n\n      // Remember the original values\n      left = style.left;\n      rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n      // Put in the new values to get a computed value out\n      if ( rsLeft ) {\n        elem.runtimeStyle.left = elem.currentStyle.left;\n      }\n      style.left = name === \"fontSize\" ? \"1em\" : ret;\n      ret = style.pixelLeft + \"px\";\n\n      // Revert the changed values\n      style.left = left;\n      if ( rsLeft ) {\n        elem.runtimeStyle.left = rsLeft;\n      }\n    }\n\n    return ret === \"\" ? \"auto\" : ret;\n  };\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n  // Start with offset property\n  var val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n    i = name === \"width\" ? 1 : 0,\n    len = 4;\n\n  if ( val > 0 ) {\n    if ( extra !== \"border\" ) {\n      for ( ; i < len; i += 2 ) {\n        if ( !extra ) {\n          val -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n        }\n        if ( extra === \"margin\" ) {\n          val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n        } else {\n          val -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n        }\n      }\n    }\n\n    return val + \"px\";\n  }\n\n  // Fall back to computed then uncomputed css if necessary\n  val = curCSS( elem, name );\n  if ( val < 0 || val == null ) {\n    val = elem.style[ name ];\n  }\n\n  // Computed unit is not pixels. Stop here and return.\n  if ( rnumnonpx.test(val) ) {\n    return val;\n  }\n\n  // Normalize \"\", auto, and prepare for extra\n  val = parseFloat( val ) || 0;\n\n  // Add padding, border, margin\n  if ( extra ) {\n    for ( ; i < len; i += 2 ) {\n      val += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n      if ( extra !== \"padding\" ) {\n        val += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n      }\n      if ( extra === \"margin\" ) {\n        val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n      }\n    }\n  }\n\n  return val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n  jQuery.cssHooks[ name ] = {\n    get: function( elem, computed, extra ) {\n      if ( computed ) {\n        if ( elem.offsetWidth !== 0 ) {\n          return getWidthOrHeight( elem, name, extra );\n        } else {\n          return jQuery.swap( elem, cssShow, function() {\n            return getWidthOrHeight( elem, name, extra );\n          });\n        }\n      }\n    },\n\n    set: function( elem, value ) {\n      return rnum.test( value ) ?\n        value + \"px\" :\n        value;\n    }\n  };\n});\n\nif ( !jQuery.support.opacity ) {\n  jQuery.cssHooks.opacity = {\n    get: function( elem, computed ) {\n      // IE uses filters for opacity\n      return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n        ( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n        computed ? \"1\" : \"\";\n    },\n\n    set: function( elem, value ) {\n      var style = elem.style,\n        currentStyle = elem.currentStyle,\n        opacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n        filter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n      // IE has trouble with opacity if it does not have layout\n      // Force it by setting the zoom level\n      style.zoom = 1;\n\n      // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n      if ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n        // Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n        // if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n        // style.removeAttribute is IE Only, but so apparently is this code path...\n        style.removeAttribute( \"filter\" );\n\n        // if there there is no filter style applied in a css rule, we are done\n        if ( currentStyle && !currentStyle.filter ) {\n          return;\n        }\n      }\n\n      // otherwise, set new filter values\n      style.filter = ralpha.test( filter ) ?\n        filter.replace( ralpha, opacity ) :\n        filter + \" \" + opacity;\n    }\n  };\n}\n\njQuery(function() {\n  // This hook cannot be added until DOM ready because the support test\n  // for it is not run until after DOM ready\n  if ( !jQuery.support.reliableMarginRight ) {\n    jQuery.cssHooks.marginRight = {\n      get: function( elem, computed ) {\n        // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n        // Work around by temporarily setting element display to inline-block\n        return jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n          if ( computed ) {\n            return curCSS( elem, \"margin-right\" );\n          } else {\n            return elem.style.marginRight;\n          }\n        });\n      }\n    };\n  }\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n  jQuery.expr.filters.hidden = function( elem ) {\n    var width = elem.offsetWidth,\n      height = elem.offsetHeight;\n\n    return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n  };\n\n  jQuery.expr.filters.visible = function( elem ) {\n    return !jQuery.expr.filters.hidden( elem );\n  };\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n  margin: \"\",\n  padding: \"\",\n  border: \"Width\"\n}, function( prefix, suffix ) {\n\n  jQuery.cssHooks[ prefix + suffix ] = {\n    expand: function( value ) {\n      var i,\n\n        // assumes a single number if not a string\n        parts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n        expanded = {};\n\n      for ( i = 0; i < 4; i++ ) {\n        expanded[ prefix + cssExpand[ i ] + suffix ] =\n          parts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n      }\n\n      return expanded;\n    }\n  };\n});\n\n\n\n\nvar r20 = /%20/g,\n  rbracket = /\\[\\]$/,\n  rCRLF = /\\r?\\n/g,\n  rhash = /#.*$/,\n  rheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n  rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n  // #7653, #8125, #8152: local protocol detection\n  rlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n  rnoContent = /^(?:GET|HEAD)$/,\n  rprotocol = /^\\/\\//,\n  rquery = /\\?/,\n  rscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n  rselectTextarea = /^(?:select|textarea)/i,\n  rspacesAjax = /\\s+/,\n  rts = /([?&])_=[^&]*/,\n  rurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n  // Keep a copy of the old load method\n  _load = jQuery.fn.load,\n\n  /* Prefilters\n   * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n   * 2) These are called:\n   *    - BEFORE asking for a transport\n   *    - AFTER param serialization (s.data is a string if s.processData is true)\n   * 3) key is the dataType\n   * 4) the catchall symbol \"*\" can be used\n   * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n   */\n  prefilters = {},\n\n  /* Transports bindings\n   * 1) key is the dataType\n   * 2) the catchall symbol \"*\" can be used\n   * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n   */\n  transports = {},\n\n  // Document location\n  ajaxLocation,\n\n  // Document location segments\n  ajaxLocParts,\n\n  // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n  allTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n  ajaxLocation = location.href;\n} catch( e ) {\n  // Use the href attribute of an A element\n  // since IE will modify it given document.location\n  ajaxLocation = document.createElement( \"a\" );\n  ajaxLocation.href = \"\";\n  ajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n  // dataTypeExpression is optional and defaults to \"*\"\n  return function( dataTypeExpression, func ) {\n\n    if ( typeof dataTypeExpression !== \"string\" ) {\n      func = dataTypeExpression;\n      dataTypeExpression = \"*\";\n    }\n\n    if ( jQuery.isFunction( func ) ) {\n      var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n        i = 0,\n        length = dataTypes.length,\n        dataType,\n        list,\n        placeBefore;\n\n      // For each dataType in the dataTypeExpression\n      for ( ; i < length; i++ ) {\n        dataType = dataTypes[ i ];\n        // We control if we're asked to add before\n        // any existing element\n        placeBefore = /^\\+/.test( dataType );\n        if ( placeBefore ) {\n          dataType = dataType.substr( 1 ) || \"*\";\n        }\n        list = structure[ dataType ] = structure[ dataType ] || [];\n        // then we add to the structure accordingly\n        list[ placeBefore ? \"unshift\" : \"push\" ]( func );\n      }\n    }\n  };\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n    dataType /* internal */, inspected /* internal */ ) {\n\n  dataType = dataType || options.dataTypes[ 0 ];\n  inspected = inspected || {};\n\n  inspected[ dataType ] = true;\n\n  var list = structure[ dataType ],\n    i = 0,\n    length = list ? list.length : 0,\n    executeOnly = ( structure === prefilters ),\n    selection;\n\n  for ( ; i < length && ( executeOnly || !selection ); i++ ) {\n    selection = list[ i ]( options, originalOptions, jqXHR );\n    // If we got redirected to another dataType\n    // we try there if executing only and not done already\n    if ( typeof selection === \"string\" ) {\n      if ( !executeOnly || inspected[ selection ] ) {\n        selection = undefined;\n      } else {\n        options.dataTypes.unshift( selection );\n        selection = inspectPrefiltersOrTransports(\n            structure, options, originalOptions, jqXHR, selection, inspected );\n      }\n    }\n  }\n  // If we're only executing or nothing was selected\n  // we try the catchall dataType if not done already\n  if ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n    selection = inspectPrefiltersOrTransports(\n        structure, options, originalOptions, jqXHR, \"*\", inspected );\n  }\n  // unnecessary when only executing (prefilters)\n  // but it'll be ignored by the caller in that case\n  return selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n  var key, deep,\n    flatOptions = jQuery.ajaxSettings.flatOptions || {};\n  for ( key in src ) {\n    if ( src[ key ] !== undefined ) {\n      ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n    }\n  }\n  if ( deep ) {\n    jQuery.extend( true, target, deep );\n  }\n}\n\njQuery.fn.extend({\n  load: function( url, params, callback ) {\n    if ( typeof url !== \"string\" && _load ) {\n      return _load.apply( this, arguments );\n\n    // Don't do a request if no elements are being requested\n    } else if ( !this.length ) {\n      return this;\n    }\n\n    var off = url.indexOf( \" \" );\n    if ( off >= 0 ) {\n      var selector = url.slice( off, url.length );\n      url = url.slice( 0, off );\n    }\n\n    // Default to a GET request\n    var type = \"GET\";\n\n    // If the second parameter was provided\n    if ( params ) {\n      // If it's a function\n      if ( jQuery.isFunction( params ) ) {\n        // We assume that it's the callback\n        callback = params;\n        params = undefined;\n\n      // Otherwise, build a param string\n      } else if ( typeof params === \"object\" ) {\n        params = jQuery.param( params, jQuery.ajaxSettings.traditional );\n        type = \"POST\";\n      }\n    }\n\n    var self = this;\n\n    // Request the remote document\n    jQuery.ajax({\n      url: url,\n      type: type,\n      dataType: \"html\",\n      data: params,\n      // Complete callback (responseText is used internally)\n      complete: function( jqXHR, status, responseText ) {\n        // Store the response as specified by the jqXHR object\n        responseText = jqXHR.responseText;\n        // If successful, inject the HTML into all the matched elements\n        if ( jqXHR.isResolved() ) {\n          // #4825: Get the actual response in case\n          // a dataFilter is present in ajaxSettings\n          jqXHR.done(function( r ) {\n            responseText = r;\n          });\n          // See if a selector was specified\n          self.html( selector ?\n            // Create a dummy div to hold the results\n            jQuery(\"<div>\")\n              // inject the contents of the document in, removing the scripts\n              // to avoid any 'Permission Denied' errors in IE\n              .append(responseText.replace(rscript, \"\"))\n\n              // Locate the specified elements\n              .find(selector) :\n\n            // If not, just inject the full result\n            responseText );\n        }\n\n        if ( callback ) {\n          self.each( callback, [ responseText, status, jqXHR ] );\n        }\n      }\n    });\n\n    return this;\n  },\n\n  serialize: function() {\n    return jQuery.param( this.serializeArray() );\n  },\n\n  serializeArray: function() {\n    return this.map(function(){\n      return this.elements ? jQuery.makeArray( this.elements ) : this;\n    })\n    .filter(function(){\n      return this.name && !this.disabled &&\n        ( this.checked || rselectTextarea.test( this.nodeName ) ||\n          rinput.test( this.type ) );\n    })\n    .map(function( i, elem ){\n      var val = jQuery( this ).val();\n\n      return val == null ?\n        null :\n        jQuery.isArray( val ) ?\n          jQuery.map( val, function( val, i ){\n            return { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n          }) :\n          { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n    }).get();\n  }\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n  jQuery.fn[ o ] = function( f ){\n    return this.on( o, f );\n  };\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n  jQuery[ method ] = function( url, data, callback, type ) {\n    // shift arguments if data argument was omitted\n    if ( jQuery.isFunction( data ) ) {\n      type = type || callback;\n      callback = data;\n      data = undefined;\n    }\n\n    return jQuery.ajax({\n      type: method,\n      url: url,\n      data: data,\n      success: callback,\n      dataType: type\n    });\n  };\n});\n\njQuery.extend({\n\n  getScript: function( url, callback ) {\n    return jQuery.get( url, undefined, callback, \"script\" );\n  },\n\n  getJSON: function( url, data, callback ) {\n    return jQuery.get( url, data, callback, \"json\" );\n  },\n\n  // Creates a full fledged settings object into target\n  // with both ajaxSettings and settings fields.\n  // If target is omitted, writes into ajaxSettings.\n  ajaxSetup: function( target, settings ) {\n    if ( settings ) {\n      // Building a settings object\n      ajaxExtend( target, jQuery.ajaxSettings );\n    } else {\n      // Extending ajaxSettings\n      settings = target;\n      target = jQuery.ajaxSettings;\n    }\n    ajaxExtend( target, settings );\n    return target;\n  },\n\n  ajaxSettings: {\n    url: ajaxLocation,\n    isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n    global: true,\n    type: \"GET\",\n    contentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n    processData: true,\n    async: true,\n    /*\n    timeout: 0,\n    data: null,\n    dataType: null,\n    username: null,\n    password: null,\n    cache: null,\n    traditional: false,\n    headers: {},\n    */\n\n    accepts: {\n      xml: \"application/xml, text/xml\",\n      html: \"text/html\",\n      text: \"text/plain\",\n      json: \"application/json, text/javascript\",\n      \"*\": allTypes\n    },\n\n    contents: {\n      xml: /xml/,\n      html: /html/,\n      json: /json/\n    },\n\n    responseFields: {\n      xml: \"responseXML\",\n      text: \"responseText\"\n    },\n\n    // List of data converters\n    // 1) key format is \"source_type destination_type\" (a single space in-between)\n    // 2) the catchall symbol \"*\" can be used for source_type\n    converters: {\n\n      // Convert anything to text\n      \"* text\": window.String,\n\n      // Text to html (true = no transformation)\n      \"text html\": true,\n\n      // Evaluate text as a json expression\n      \"text json\": jQuery.parseJSON,\n\n      // Parse text as xml\n      \"text xml\": jQuery.parseXML\n    },\n\n    // For options that shouldn't be deep extended:\n    // you can add your own custom options here if\n    // and when you create one that shouldn't be\n    // deep extended (see ajaxExtend)\n    flatOptions: {\n      context: true,\n      url: true\n    }\n  },\n\n  ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n  ajaxTransport: addToPrefiltersOrTransports( transports ),\n\n  // Main method\n  ajax: function( url, options ) {\n\n    // If url is an object, simulate pre-1.5 signature\n    if ( typeof url === \"object\" ) {\n      options = url;\n      url = undefined;\n    }\n\n    // Force options to be an object\n    options = options || {};\n\n    var // Create the final options object\n      s = jQuery.ajaxSetup( {}, options ),\n      // Callbacks context\n      callbackContext = s.context || s,\n      // Context for global events\n      // It's the callbackContext if one was provided in the options\n      // and if it's a DOM node or a jQuery collection\n      globalEventContext = callbackContext !== s &&\n        ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n            jQuery( callbackContext ) : jQuery.event,\n      // Deferreds\n      deferred = jQuery.Deferred(),\n      completeDeferred = jQuery.Callbacks( \"once memory\" ),\n      // Status-dependent callbacks\n      statusCode = s.statusCode || {},\n      // ifModified key\n      ifModifiedKey,\n      // Headers (they are sent all at once)\n      requestHeaders = {},\n      requestHeadersNames = {},\n      // Response headers\n      responseHeadersString,\n      responseHeaders,\n      // transport\n      transport,\n      // timeout handle\n      timeoutTimer,\n      // Cross-domain detection vars\n      parts,\n      // The jqXHR state\n      state = 0,\n      // To know if global events are to be dispatched\n      fireGlobals,\n      // Loop variable\n      i,\n      // Fake xhr\n      jqXHR = {\n\n        readyState: 0,\n\n        // Caches the header\n        setRequestHeader: function( name, value ) {\n          if ( !state ) {\n            var lname = name.toLowerCase();\n            name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n            requestHeaders[ name ] = value;\n          }\n          return this;\n        },\n\n        // Raw string\n        getAllResponseHeaders: function() {\n          return state === 2 ? responseHeadersString : null;\n        },\n\n        // Builds headers hashtable if needed\n        getResponseHeader: function( key ) {\n          var match;\n          if ( state === 2 ) {\n            if ( !responseHeaders ) {\n              responseHeaders = {};\n              while( ( match = rheaders.exec( responseHeadersString ) ) ) {\n                responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n              }\n            }\n            match = responseHeaders[ key.toLowerCase() ];\n          }\n          return match === undefined ? null : match;\n        },\n\n        // Overrides response content-type header\n        overrideMimeType: function( type ) {\n          if ( !state ) {\n            s.mimeType = type;\n          }\n          return this;\n        },\n\n        // Cancel the request\n        abort: function( statusText ) {\n          statusText = statusText || \"abort\";\n          if ( transport ) {\n            transport.abort( statusText );\n          }\n          done( 0, statusText );\n          return this;\n        }\n      };\n\n    // Callback for when everything is done\n    // It is defined here because jslint complains if it is declared\n    // at the end of the function (which would be more logical and readable)\n    function done( status, nativeStatusText, responses, headers ) {\n\n      // Called once\n      if ( state === 2 ) {\n        return;\n      }\n\n      // State is \"done\" now\n      state = 2;\n\n      // Clear timeout if it exists\n      if ( timeoutTimer ) {\n        clearTimeout( timeoutTimer );\n      }\n\n      // Dereference transport for early garbage collection\n      // (no matter how long the jqXHR object will be used)\n      transport = undefined;\n\n      // Cache response headers\n      responseHeadersString = headers || \"\";\n\n      // Set readyState\n      jqXHR.readyState = status > 0 ? 4 : 0;\n\n      var isSuccess,\n        success,\n        error,\n        statusText = nativeStatusText,\n        response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n        lastModified,\n        etag;\n\n      // If successful, handle type chaining\n      if ( status >= 200 && status < 300 || status === 304 ) {\n\n        // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n        if ( s.ifModified ) {\n\n          if ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n            jQuery.lastModified[ ifModifiedKey ] = lastModified;\n          }\n          if ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n            jQuery.etag[ ifModifiedKey ] = etag;\n          }\n        }\n\n        // If not modified\n        if ( status === 304 ) {\n\n          statusText = \"notmodified\";\n          isSuccess = true;\n\n        // If we have data\n        } else {\n\n          try {\n            success = ajaxConvert( s, response );\n            statusText = \"success\";\n            isSuccess = true;\n          } catch(e) {\n            // We have a parsererror\n            statusText = \"parsererror\";\n            error = e;\n          }\n        }\n      } else {\n        // We extract error from statusText\n        // then normalize statusText and status for non-aborts\n        error = statusText;\n        if ( !statusText || status ) {\n          statusText = \"error\";\n          if ( status < 0 ) {\n            status = 0;\n          }\n        }\n      }\n\n      // Set data for the fake xhr object\n      jqXHR.status = status;\n      jqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n      // Success/Error\n      if ( isSuccess ) {\n        deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n      } else {\n        deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n      }\n\n      // Status-dependent callbacks\n      jqXHR.statusCode( statusCode );\n      statusCode = undefined;\n\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n            [ jqXHR, s, isSuccess ? success : error ] );\n      }\n\n      // Complete\n      completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n        // Handle the global AJAX counter\n        if ( !( --jQuery.active ) ) {\n          jQuery.event.trigger( \"ajaxStop\" );\n        }\n      }\n    }\n\n    // Attach deferreds\n    deferred.promise( jqXHR );\n    jqXHR.success = jqXHR.done;\n    jqXHR.error = jqXHR.fail;\n    jqXHR.complete = completeDeferred.add;\n\n    // Status-dependent callbacks\n    jqXHR.statusCode = function( map ) {\n      if ( map ) {\n        var tmp;\n        if ( state < 2 ) {\n          for ( tmp in map ) {\n            statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n          }\n        } else {\n          tmp = map[ jqXHR.status ];\n          jqXHR.then( tmp, tmp );\n        }\n      }\n      return this;\n    };\n\n    // Remove hash character (#7531: and string promotion)\n    // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n    // We also use the url parameter if available\n    s.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n    // Extract dataTypes list\n    s.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n    // Determine if a cross-domain request is in order\n    if ( s.crossDomain == null ) {\n      parts = rurl.exec( s.url.toLowerCase() );\n      s.crossDomain = !!( parts &&\n        ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n          ( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n            ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n      );\n    }\n\n    // Convert data if not already a string\n    if ( s.data && s.processData && typeof s.data !== \"string\" ) {\n      s.data = jQuery.param( s.data, s.traditional );\n    }\n\n    // Apply prefilters\n    inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n    // If request was aborted inside a prefilter, stop there\n    if ( state === 2 ) {\n      return false;\n    }\n\n    // We can fire global events as of now if asked to\n    fireGlobals = s.global;\n\n    // Uppercase the type\n    s.type = s.type.toUpperCase();\n\n    // Determine if request has content\n    s.hasContent = !rnoContent.test( s.type );\n\n    // Watch for a new set of requests\n    if ( fireGlobals && jQuery.active++ === 0 ) {\n      jQuery.event.trigger( \"ajaxStart\" );\n    }\n\n    // More options handling for requests with no content\n    if ( !s.hasContent ) {\n\n      // If data is available, append data to url\n      if ( s.data ) {\n        s.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n        // #9682: remove data so that it's not used in an eventual retry\n        delete s.data;\n      }\n\n      // Get ifModifiedKey before adding the anti-cache parameter\n      ifModifiedKey = s.url;\n\n      // Add anti-cache in url if needed\n      if ( s.cache === false ) {\n\n        var ts = jQuery.now(),\n          // try replacing _= if it is there\n          ret = s.url.replace( rts, \"$1_=\" + ts );\n\n        // if nothing was replaced, add timestamp to the end\n        s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n      }\n    }\n\n    // Set the correct header, if data is being sent\n    if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n      jqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n    }\n\n    // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n    if ( s.ifModified ) {\n      ifModifiedKey = ifModifiedKey || s.url;\n      if ( jQuery.lastModified[ ifModifiedKey ] ) {\n        jqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n      }\n      if ( jQuery.etag[ ifModifiedKey ] ) {\n        jqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n      }\n    }\n\n    // Set the Accepts header for the server, depending on the dataType\n    jqXHR.setRequestHeader(\n      \"Accept\",\n      s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n        s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n        s.accepts[ \"*\" ]\n    );\n\n    // Check for headers option\n    for ( i in s.headers ) {\n      jqXHR.setRequestHeader( i, s.headers[ i ] );\n    }\n\n    // Allow custom headers/mimetypes and early abort\n    if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n        // Abort if not done already\n        jqXHR.abort();\n        return false;\n\n    }\n\n    // Install callbacks on deferreds\n    for ( i in { success: 1, error: 1, complete: 1 } ) {\n      jqXHR[ i ]( s[ i ] );\n    }\n\n    // Get transport\n    transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n    // If no transport, we auto-abort\n    if ( !transport ) {\n      done( -1, \"No Transport\" );\n    } else {\n      jqXHR.readyState = 1;\n      // Send global event\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n      }\n      // Timeout\n      if ( s.async && s.timeout > 0 ) {\n        timeoutTimer = setTimeout( function(){\n          jqXHR.abort( \"timeout\" );\n        }, s.timeout );\n      }\n\n      try {\n        state = 1;\n        transport.send( requestHeaders, done );\n      } catch (e) {\n        // Propagate exception as error if not done\n        if ( state < 2 ) {\n          done( -1, e );\n        // Simply rethrow otherwise\n        } else {\n          throw e;\n        }\n      }\n    }\n\n    return jqXHR;\n  },\n\n  // Serialize an array of form elements or a set of\n  // key/values into a query string\n  param: function( a, traditional ) {\n    var s = [],\n      add = function( key, value ) {\n        // If value is a function, invoke it and return its value\n        value = jQuery.isFunction( value ) ? value() : value;\n        s[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n      };\n\n    // Set traditional to true for jQuery <= 1.3.2 behavior.\n    if ( traditional === undefined ) {\n      traditional = jQuery.ajaxSettings.traditional;\n    }\n\n    // If an array was passed in, assume that it is an array of form elements.\n    if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n      // Serialize the form elements\n      jQuery.each( a, function() {\n        add( this.name, this.value );\n      });\n\n    } else {\n      // If traditional, encode the \"old\" way (the way 1.3.2 or older\n      // did it), otherwise encode params recursively.\n      for ( var prefix in a ) {\n        buildParams( prefix, a[ prefix ], traditional, add );\n      }\n    }\n\n    // Return the resulting serialization\n    return s.join( \"&\" ).replace( r20, \"+\" );\n  }\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n  if ( jQuery.isArray( obj ) ) {\n    // Serialize array item.\n    jQuery.each( obj, function( i, v ) {\n      if ( traditional || rbracket.test( prefix ) ) {\n        // Treat each array item as a scalar.\n        add( prefix, v );\n\n      } else {\n        // If array item is non-scalar (array or object), encode its\n        // numeric index to resolve deserialization ambiguity issues.\n        // Note that rack (as of 1.0.0) can't currently deserialize\n        // nested arrays properly, and attempting to do so may cause\n        // a server error. Possible fixes are to modify rack's\n        // deserialization algorithm or to provide an option or flag\n        // to force array serialization to be shallow.\n        buildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n      }\n    });\n\n  } else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n    // Serialize object item.\n    for ( var name in obj ) {\n      buildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n    }\n\n  } else {\n    // Serialize scalar item.\n    add( prefix, obj );\n  }\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n  // Counter for holding the number of active queries\n  active: 0,\n\n  // Last-Modified header cache for next request\n  lastModified: {},\n  etag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n  var contents = s.contents,\n    dataTypes = s.dataTypes,\n    responseFields = s.responseFields,\n    ct,\n    type,\n    finalDataType,\n    firstDataType;\n\n  // Fill responseXXX fields\n  for ( type in responseFields ) {\n    if ( type in responses ) {\n      jqXHR[ responseFields[type] ] = responses[ type ];\n    }\n  }\n\n  // Remove auto dataType and get content-type in the process\n  while( dataTypes[ 0 ] === \"*\" ) {\n    dataTypes.shift();\n    if ( ct === undefined ) {\n      ct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n    }\n  }\n\n  // Check if we're dealing with a known content-type\n  if ( ct ) {\n    for ( type in contents ) {\n      if ( contents[ type ] && contents[ type ].test( ct ) ) {\n        dataTypes.unshift( type );\n        break;\n      }\n    }\n  }\n\n  // Check to see if we have a response for the expected dataType\n  if ( dataTypes[ 0 ] in responses ) {\n    finalDataType = dataTypes[ 0 ];\n  } else {\n    // Try convertible dataTypes\n    for ( type in responses ) {\n      if ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n        finalDataType = type;\n        break;\n      }\n      if ( !firstDataType ) {\n        firstDataType = type;\n      }\n    }\n    // Or just use first one\n    finalDataType = finalDataType || firstDataType;\n  }\n\n  // If we found a dataType\n  // We add the dataType to the list if needed\n  // and return the corresponding response\n  if ( finalDataType ) {\n    if ( finalDataType !== dataTypes[ 0 ] ) {\n      dataTypes.unshift( finalDataType );\n    }\n    return responses[ finalDataType ];\n  }\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n  // Apply the dataFilter if provided\n  if ( s.dataFilter ) {\n    response = s.dataFilter( response, s.dataType );\n  }\n\n  var dataTypes = s.dataTypes,\n    converters = {},\n    i,\n    key,\n    length = dataTypes.length,\n    tmp,\n    // Current and previous dataTypes\n    current = dataTypes[ 0 ],\n    prev,\n    // Conversion expression\n    conversion,\n    // Conversion function\n    conv,\n    // Conversion functions (transitive conversion)\n    conv1,\n    conv2;\n\n  // For each dataType in the chain\n  for ( i = 1; i < length; i++ ) {\n\n    // Create converters map\n    // with lowercased keys\n    if ( i === 1 ) {\n      for ( key in s.converters ) {\n        if ( typeof key === \"string\" ) {\n          converters[ key.toLowerCase() ] = s.converters[ key ];\n        }\n      }\n    }\n\n    // Get the dataTypes\n    prev = current;\n    current = dataTypes[ i ];\n\n    // If current is auto dataType, update it to prev\n    if ( current === \"*\" ) {\n      current = prev;\n    // If no auto and dataTypes are actually different\n    } else if ( prev !== \"*\" && prev !== current ) {\n\n      // Get the converter\n      conversion = prev + \" \" + current;\n      conv = converters[ conversion ] || converters[ \"* \" + current ];\n\n      // If there is no direct converter, search transitively\n      if ( !conv ) {\n        conv2 = undefined;\n        for ( conv1 in converters ) {\n          tmp = conv1.split( \" \" );\n          if ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n            conv2 = converters[ tmp[1] + \" \" + current ];\n            if ( conv2 ) {\n              conv1 = converters[ conv1 ];\n              if ( conv1 === true ) {\n                conv = conv2;\n              } else if ( conv2 === true ) {\n                conv = conv1;\n              }\n              break;\n            }\n          }\n        }\n      }\n      // If we found no converter, dispatch an error\n      if ( !( conv || conv2 ) ) {\n        jQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n      }\n      // If found converter is not an equivalence\n      if ( conv !== true ) {\n        // Convert with 1 or 2 converters accordingly\n        response = conv ? conv( response ) : conv2( conv1(response) );\n      }\n    }\n  }\n  return response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n  jsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n  jsonp: \"callback\",\n  jsonpCallback: function() {\n    return jQuery.expando + \"_\" + ( jsc++ );\n  }\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n  var inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n  if ( s.dataTypes[ 0 ] === \"jsonp\" ||\n    s.jsonp !== false && ( jsre.test( s.url ) ||\n        inspectData && jsre.test( s.data ) ) ) {\n\n    var responseContainer,\n      jsonpCallback = s.jsonpCallback =\n        jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n      previous = window[ jsonpCallback ],\n      url = s.url,\n      data = s.data,\n      replace = \"$1\" + jsonpCallback + \"$2\";\n\n    if ( s.jsonp !== false ) {\n      url = url.replace( jsre, replace );\n      if ( s.url === url ) {\n        if ( inspectData ) {\n          data = data.replace( jsre, replace );\n        }\n        if ( s.data === data ) {\n          // Add callback manually\n          url += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n        }\n      }\n    }\n\n    s.url = url;\n    s.data = data;\n\n    // Install callback\n    window[ jsonpCallback ] = function( response ) {\n      responseContainer = [ response ];\n    };\n\n    // Clean-up function\n    jqXHR.always(function() {\n      // Set callback back to previous value\n      window[ jsonpCallback ] = previous;\n      // Call if it was a function and we have a response\n      if ( responseContainer && jQuery.isFunction( previous ) ) {\n        window[ jsonpCallback ]( responseContainer[ 0 ] );\n      }\n    });\n\n    // Use data converter to retrieve json after script execution\n    s.converters[\"script json\"] = function() {\n      if ( !responseContainer ) {\n        jQuery.error( jsonpCallback + \" was not called\" );\n      }\n      return responseContainer[ 0 ];\n    };\n\n    // force json dataType\n    s.dataTypes[ 0 ] = \"json\";\n\n    // Delegate to script\n    return \"script\";\n  }\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n  accepts: {\n    script: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n  },\n  contents: {\n    script: /javascript|ecmascript/\n  },\n  converters: {\n    \"text script\": function( text ) {\n      jQuery.globalEval( text );\n      return text;\n    }\n  }\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n  if ( s.cache === undefined ) {\n    s.cache = false;\n  }\n  if ( s.crossDomain ) {\n    s.type = \"GET\";\n    s.global = false;\n  }\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n  // This transport only deals with cross domain requests\n  if ( s.crossDomain ) {\n\n    var script,\n      head = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n    return {\n\n      send: function( _, callback ) {\n\n        script = document.createElement( \"script\" );\n\n        script.async = \"async\";\n\n        if ( s.scriptCharset ) {\n          script.charset = s.scriptCharset;\n        }\n\n        script.src = s.url;\n\n        // Attach handlers for all browsers\n        script.onload = script.onreadystatechange = function( _, isAbort ) {\n\n          if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n            // Handle memory leak in IE\n            script.onload = script.onreadystatechange = null;\n\n            // Remove the script\n            if ( head && script.parentNode ) {\n              head.removeChild( script );\n            }\n\n            // Dereference the script\n            script = undefined;\n\n            // Callback if not abort\n            if ( !isAbort ) {\n              callback( 200, \"success\" );\n            }\n          }\n        };\n        // Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n        // This arises when a base node is used (#2709 and #4378).\n        head.insertBefore( script, head.firstChild );\n      },\n\n      abort: function() {\n        if ( script ) {\n          script.onload( 0, 1 );\n        }\n      }\n    };\n  }\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n  xhrOnUnloadAbort = window.ActiveXObject ? function() {\n    // Abort all pending requests\n    for ( var key in xhrCallbacks ) {\n      xhrCallbacks[ key ]( 0, 1 );\n    }\n  } : false,\n  xhrId = 0,\n  xhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n  try {\n    return new window.XMLHttpRequest();\n  } catch( e ) {}\n}\n\nfunction createActiveXHR() {\n  try {\n    return new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n  } catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n  /* Microsoft failed to properly\n   * implement the XMLHttpRequest in IE7 (can't request local files),\n   * so we use the ActiveXObject when it is available\n   * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n   * we need a fallback.\n   */\n  function() {\n    return !this.isLocal && createStandardXHR() || createActiveXHR();\n  } :\n  // For all other browsers, use the standard XMLHttpRequest object\n  createStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n  jQuery.extend( jQuery.support, {\n    ajax: !!xhr,\n    cors: !!xhr && ( \"withCredentials\" in xhr )\n  });\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n  jQuery.ajaxTransport(function( s ) {\n    // Cross domain only allowed if supported through XMLHttpRequest\n    if ( !s.crossDomain || jQuery.support.cors ) {\n\n      var callback;\n\n      return {\n        send: function( headers, complete ) {\n\n          // Get a new xhr\n          var xhr = s.xhr(),\n            handle,\n            i;\n\n          // Open the socket\n          // Passing null username, generates a login popup on Opera (#2865)\n          if ( s.username ) {\n            xhr.open( s.type, s.url, s.async, s.username, s.password );\n          } else {\n            xhr.open( s.type, s.url, s.async );\n          }\n\n          // Apply custom fields if provided\n          if ( s.xhrFields ) {\n            for ( i in s.xhrFields ) {\n              xhr[ i ] = s.xhrFields[ i ];\n            }\n          }\n\n          // Override mime type if needed\n          if ( s.mimeType && xhr.overrideMimeType ) {\n            xhr.overrideMimeType( s.mimeType );\n          }\n\n          // X-Requested-With header\n          // For cross-domain requests, seeing as conditions for a preflight are\n          // akin to a jigsaw puzzle, we simply never set it to be sure.\n          // (it can always be set on a per-request basis or even using ajaxSetup)\n          // For same-domain requests, won't change header if already provided.\n          if ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n            headers[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n          }\n\n          // Need an extra try/catch for cross domain requests in Firefox 3\n          try {\n            for ( i in headers ) {\n              xhr.setRequestHeader( i, headers[ i ] );\n            }\n          } catch( _ ) {}\n\n          // Do send the request\n          // This may raise an exception which is actually\n          // handled in jQuery.ajax (so no try/catch here)\n          xhr.send( ( s.hasContent && s.data ) || null );\n\n          // Listener\n          callback = function( _, isAbort ) {\n\n            var status,\n              statusText,\n              responseHeaders,\n              responses,\n              xml;\n\n            // Firefox throws exceptions when accessing properties\n            // of an xhr when a network error occured\n            // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n            try {\n\n              // Was never called and is aborted or complete\n              if ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n                // Only called once\n                callback = undefined;\n\n                // Do not keep as active anymore\n                if ( handle ) {\n                  xhr.onreadystatechange = jQuery.noop;\n                  if ( xhrOnUnloadAbort ) {\n                    delete xhrCallbacks[ handle ];\n                  }\n                }\n\n                // If it's an abort\n                if ( isAbort ) {\n                  // Abort it manually if needed\n                  if ( xhr.readyState !== 4 ) {\n                    xhr.abort();\n                  }\n                } else {\n                  status = xhr.status;\n                  responseHeaders = xhr.getAllResponseHeaders();\n                  responses = {};\n                  xml = xhr.responseXML;\n\n                  // Construct response list\n                  if ( xml && xml.documentElement /* #4958 */ ) {\n                    responses.xml = xml;\n                  }\n\n                  // When requesting binary data, IE6-9 will throw an exception\n                  // on any attempt to access responseText (#11426)\n                  try {\n                    responses.text = xhr.responseText;\n                  } catch( _ ) {\n                  }\n\n                  // Firefox throws an exception when accessing\n                  // statusText for faulty cross-domain requests\n                  try {\n                    statusText = xhr.statusText;\n                  } catch( e ) {\n                    // We normalize with Webkit giving an empty statusText\n                    statusText = \"\";\n                  }\n\n                  // Filter status for non standard behaviors\n\n                  // If the request is local and we have data: assume a success\n                  // (success with no data won't get notified, that's the best we\n                  // can do given current implementations)\n                  if ( !status && s.isLocal && !s.crossDomain ) {\n                    status = responses.text ? 200 : 404;\n                  // IE - #1450: sometimes returns 1223 when it should be 204\n                  } else if ( status === 1223 ) {\n                    status = 204;\n                  }\n                }\n              }\n            } catch( firefoxAccessException ) {\n              if ( !isAbort ) {\n                complete( -1, firefoxAccessException );\n              }\n            }\n\n            // Call complete if needed\n            if ( responses ) {\n              complete( status, statusText, responses, responseHeaders );\n            }\n          };\n\n          // if we're in sync mode or it's in cache\n          // and has been retrieved directly (IE6 & IE7)\n          // we need to manually fire the callback\n          if ( !s.async || xhr.readyState === 4 ) {\n            callback();\n          } else {\n            handle = ++xhrId;\n            if ( xhrOnUnloadAbort ) {\n              // Create the active xhrs callbacks list if needed\n              // and attach the unload handler\n              if ( !xhrCallbacks ) {\n                xhrCallbacks = {};\n                jQuery( window ).unload( xhrOnUnloadAbort );\n              }\n              // Add to list of active xhrs callbacks\n              xhrCallbacks[ handle ] = callback;\n            }\n            xhr.onreadystatechange = callback;\n          }\n        },\n\n        abort: function() {\n          if ( callback ) {\n            callback(0,1);\n          }\n        }\n      };\n    }\n  });\n}\n\n\n\n\nvar elemdisplay = {},\n  iframe, iframeDoc,\n  rfxtypes = /^(?:toggle|show|hide)$/,\n  rfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n  timerId,\n  fxAttrs = [\n    // height animations\n    [ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n    // width animations\n    [ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n    // opacity animations\n    [ \"opacity\" ]\n  ],\n  fxNow;\n\njQuery.fn.extend({\n  show: function( speed, easing, callback ) {\n    var elem, display;\n\n    if ( speed || speed === 0 ) {\n      return this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n    } else {\n      for ( var i = 0, j = this.length; i < j; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.style ) {\n          display = elem.style.display;\n\n          // Reset the inline display of this element to learn if it is\n          // being hidden by cascaded rules or not\n          if ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n            display = elem.style.display = \"\";\n          }\n\n          // Set elements which have been overridden with display: none\n          // in a stylesheet to whatever the default browser style is\n          // for such an element\n          if ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n            !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n            jQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n          }\n        }\n      }\n\n      // Set the display of most of the elements in a second loop\n      // to avoid the constant reflow\n      for ( i = 0; i < j; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.style ) {\n          display = elem.style.display;\n\n          if ( display === \"\" || display === \"none\" ) {\n            elem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n          }\n        }\n      }\n\n      return this;\n    }\n  },\n\n  hide: function( speed, easing, callback ) {\n    if ( speed || speed === 0 ) {\n      return this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n    } else {\n      var elem, display,\n        i = 0,\n        j = this.length;\n\n      for ( ; i < j; i++ ) {\n        elem = this[i];\n        if ( elem.style ) {\n          display = jQuery.css( elem, \"display\" );\n\n          if ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n            jQuery._data( elem, \"olddisplay\", display );\n          }\n        }\n      }\n\n      // Set the display of the elements in a second loop\n      // to avoid the constant reflow\n      for ( i = 0; i < j; i++ ) {\n        if ( this[i].style ) {\n          this[i].style.display = \"none\";\n        }\n      }\n\n      return this;\n    }\n  },\n\n  // Save the old toggle function\n  _toggle: jQuery.fn.toggle,\n\n  toggle: function( fn, fn2, callback ) {\n    var bool = typeof fn === \"boolean\";\n\n    if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n      this._toggle.apply( this, arguments );\n\n    } else if ( fn == null || bool ) {\n      this.each(function() {\n        var state = bool ? fn : jQuery(this).is(\":hidden\");\n        jQuery(this)[ state ? \"show\" : \"hide\" ]();\n      });\n\n    } else {\n      this.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n    }\n\n    return this;\n  },\n\n  fadeTo: function( speed, to, easing, callback ) {\n    return this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n          .animate({opacity: to}, speed, easing, callback);\n  },\n\n  animate: function( prop, speed, easing, callback ) {\n    var optall = jQuery.speed( speed, easing, callback );\n\n    if ( jQuery.isEmptyObject( prop ) ) {\n      return this.each( optall.complete, [ false ] );\n    }\n\n    // Do not change referenced properties as per-property easing will be lost\n    prop = jQuery.extend( {}, prop );\n\n    function doAnimation() {\n      // XXX 'this' does not always have a nodeName when running the\n      // test suite\n\n      if ( optall.queue === false ) {\n        jQuery._mark( this );\n      }\n\n      var opt = jQuery.extend( {}, optall ),\n        isElement = this.nodeType === 1,\n        hidden = isElement && jQuery(this).is(\":hidden\"),\n        name, val, p, e, hooks, replace,\n        parts, start, end, unit,\n        method;\n\n      // will store per property easing and be used to determine when an animation is complete\n      opt.animatedProperties = {};\n\n      // first pass over propertys to expand / normalize\n      for ( p in prop ) {\n        name = jQuery.camelCase( p );\n        if ( p !== name ) {\n          prop[ name ] = prop[ p ];\n          delete prop[ p ];\n        }\n\n        if ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n          replace = hooks.expand( prop[ name ] );\n          delete prop[ name ];\n\n          // not quite $.extend, this wont overwrite keys already present.\n          // also - reusing 'p' from above because we have the correct \"name\"\n          for ( p in replace ) {\n            if ( ! ( p in prop ) ) {\n              prop[ p ] = replace[ p ];\n            }\n          }\n        }\n      }\n\n      for ( name in prop ) {\n        val = prop[ name ];\n        // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n        if ( jQuery.isArray( val ) ) {\n          opt.animatedProperties[ name ] = val[ 1 ];\n          val = prop[ name ] = val[ 0 ];\n        } else {\n          opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n        }\n\n        if ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n          return opt.complete.call( this );\n        }\n\n        if ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n          // Make sure that nothing sneaks out\n          // Record all 3 overflow attributes because IE does not\n          // change the overflow attribute when overflowX and\n          // overflowY are set to the same value\n          opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n          // Set display property to inline-block for height/width\n          // animations on inline elements that are having width/height animated\n          if ( jQuery.css( this, \"display\" ) === \"inline\" &&\n              jQuery.css( this, \"float\" ) === \"none\" ) {\n\n            // inline-level elements accept inline-block;\n            // block-level elements need to be inline with layout\n            if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n              this.style.display = \"inline-block\";\n\n            } else {\n              this.style.zoom = 1;\n            }\n          }\n        }\n      }\n\n      if ( opt.overflow != null ) {\n        this.style.overflow = \"hidden\";\n      }\n\n      for ( p in prop ) {\n        e = new jQuery.fx( this, opt, p );\n        val = prop[ p ];\n\n        if ( rfxtypes.test( val ) ) {\n\n          // Tracks whether to show or hide based on private\n          // data attached to the element\n          method = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n          if ( method ) {\n            jQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n            e[ method ]();\n          } else {\n            e[ val ]();\n          }\n\n        } else {\n          parts = rfxnum.exec( val );\n          start = e.cur();\n\n          if ( parts ) {\n            end = parseFloat( parts[2] );\n            unit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n            // We need to compute starting value\n            if ( unit !== \"px\" ) {\n              jQuery.style( this, p, (end || 1) + unit);\n              start = ( (end || 1) / e.cur() ) * start;\n              jQuery.style( this, p, start + unit);\n            }\n\n            // If a +=/-= token was provided, we're doing a relative animation\n            if ( parts[1] ) {\n              end = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n            }\n\n            e.custom( start, end, unit );\n\n          } else {\n            e.custom( start, val, \"\" );\n          }\n        }\n      }\n\n      // For JS strict compliance\n      return true;\n    }\n\n    return optall.queue === false ?\n      this.each( doAnimation ) :\n      this.queue( optall.queue, doAnimation );\n  },\n\n  stop: function( type, clearQueue, gotoEnd ) {\n    if ( typeof type !== \"string\" ) {\n      gotoEnd = clearQueue;\n      clearQueue = type;\n      type = undefined;\n    }\n    if ( clearQueue && type !== false ) {\n      this.queue( type || \"fx\", [] );\n    }\n\n    return this.each(function() {\n      var index,\n        hadTimers = false,\n        timers = jQuery.timers,\n        data = jQuery._data( this );\n\n      // clear marker counters if we know they won't be\n      if ( !gotoEnd ) {\n        jQuery._unmark( true, this );\n      }\n\n      function stopQueue( elem, data, index ) {\n        var hooks = data[ index ];\n        jQuery.removeData( elem, index, true );\n        hooks.stop( gotoEnd );\n      }\n\n      if ( type == null ) {\n        for ( index in data ) {\n          if ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n            stopQueue( this, data, index );\n          }\n        }\n      } else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n        stopQueue( this, data, index );\n      }\n\n      for ( index = timers.length; index--; ) {\n        if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n          if ( gotoEnd ) {\n\n            // force the next step to be the last\n            timers[ index ]( true );\n          } else {\n            timers[ index ].saveState();\n          }\n          hadTimers = true;\n          timers.splice( index, 1 );\n        }\n      }\n\n      // start the next in the queue if the last step wasn't forced\n      // timers currently will call their complete callbacks, which will dequeue\n      // but only if they were gotoEnd\n      if ( !( gotoEnd && hadTimers ) ) {\n        jQuery.dequeue( this, type );\n      }\n    });\n  }\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n  setTimeout( clearFxNow, 0 );\n  return ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n  fxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n  var obj = {};\n\n  jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n    obj[ this ] = type;\n  });\n\n  return obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n  slideDown: genFx( \"show\", 1 ),\n  slideUp: genFx( \"hide\", 1 ),\n  slideToggle: genFx( \"toggle\", 1 ),\n  fadeIn: { opacity: \"show\" },\n  fadeOut: { opacity: \"hide\" },\n  fadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n  jQuery.fn[ name ] = function( speed, easing, callback ) {\n    return this.animate( props, speed, easing, callback );\n  };\n});\n\njQuery.extend({\n  speed: function( speed, easing, fn ) {\n    var opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n      complete: fn || !fn && easing ||\n        jQuery.isFunction( speed ) && speed,\n      duration: speed,\n      easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n    };\n\n    opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n      opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n    // normalize opt.queue - true/undefined/null -> \"fx\"\n    if ( opt.queue == null || opt.queue === true ) {\n      opt.queue = \"fx\";\n    }\n\n    // Queueing\n    opt.old = opt.complete;\n\n    opt.complete = function( noUnmark ) {\n      if ( jQuery.isFunction( opt.old ) ) {\n        opt.old.call( this );\n      }\n\n      if ( opt.queue ) {\n        jQuery.dequeue( this, opt.queue );\n      } else if ( noUnmark !== false ) {\n        jQuery._unmark( this );\n      }\n    };\n\n    return opt;\n  },\n\n  easing: {\n    linear: function( p ) {\n      return p;\n    },\n    swing: function( p ) {\n      return ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n    }\n  },\n\n  timers: [],\n\n  fx: function( elem, options, prop ) {\n    this.options = options;\n    this.elem = elem;\n    this.prop = prop;\n\n    options.orig = options.orig || {};\n  }\n\n});\n\njQuery.fx.prototype = {\n  // Simple function for setting a style value\n  update: function() {\n    if ( this.options.step ) {\n      this.options.step.call( this.elem, this.now, this );\n    }\n\n    ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n  },\n\n  // Get the current size\n  cur: function() {\n    if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n      return this.elem[ this.prop ];\n    }\n\n    var parsed,\n      r = jQuery.css( this.elem, this.prop );\n    // Empty strings, null, undefined and \"auto\" are converted to 0,\n    // complex values such as \"rotate(1rad)\" are returned as is,\n    // simple values such as \"10px\" are parsed to Float.\n    return isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n  },\n\n  // Start an animation from one number to another\n  custom: function( from, to, unit ) {\n    var self = this,\n      fx = jQuery.fx;\n\n    this.startTime = fxNow || createFxNow();\n    this.end = to;\n    this.now = this.start = from;\n    this.pos = this.state = 0;\n    this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n    function t( gotoEnd ) {\n      return self.step( gotoEnd );\n    }\n\n    t.queue = this.options.queue;\n    t.elem = this.elem;\n    t.saveState = function() {\n      if ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n        if ( self.options.hide ) {\n          jQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n        } else if ( self.options.show ) {\n          jQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n        }\n      }\n    };\n\n    if ( t() && jQuery.timers.push(t) && !timerId ) {\n      timerId = setInterval( fx.tick, fx.interval );\n    }\n  },\n\n  // Simple 'show' function\n  show: function() {\n    var dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n    // Remember where we started, so that we can go back to it later\n    this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n    this.options.show = true;\n\n    // Begin the animation\n    // Make sure that we start at a small width/height to avoid any flash of content\n    if ( dataShow !== undefined ) {\n      // This show is picking up where a previous hide or show left off\n      this.custom( this.cur(), dataShow );\n    } else {\n      this.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n    }\n\n    // Start by showing the element\n    jQuery( this.elem ).show();\n  },\n\n  // Simple 'hide' function\n  hide: function() {\n    // Remember where we started, so that we can go back to it later\n    this.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n    this.options.hide = true;\n\n    // Begin the animation\n    this.custom( this.cur(), 0 );\n  },\n\n  // Each step of an animation\n  step: function( gotoEnd ) {\n    var p, n, complete,\n      t = fxNow || createFxNow(),\n      done = true,\n      elem = this.elem,\n      options = this.options;\n\n    if ( gotoEnd || t >= options.duration + this.startTime ) {\n      this.now = this.end;\n      this.pos = this.state = 1;\n      this.update();\n\n      options.animatedProperties[ this.prop ] = true;\n\n      for ( p in options.animatedProperties ) {\n        if ( options.animatedProperties[ p ] !== true ) {\n          done = false;\n        }\n      }\n\n      if ( done ) {\n        // Reset the overflow\n        if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n          jQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n            elem.style[ \"overflow\" + value ] = options.overflow[ index ];\n          });\n        }\n\n        // Hide the element if the \"hide\" operation was done\n        if ( options.hide ) {\n          jQuery( elem ).hide();\n        }\n\n        // Reset the properties, if the item has been hidden or shown\n        if ( options.hide || options.show ) {\n          for ( p in options.animatedProperties ) {\n            jQuery.style( elem, p, options.orig[ p ] );\n            jQuery.removeData( elem, \"fxshow\" + p, true );\n            // Toggle data is no longer needed\n            jQuery.removeData( elem, \"toggle\" + p, true );\n          }\n        }\n\n        // Execute the complete function\n        // in the event that the complete function throws an exception\n        // we must ensure it won't be called twice. #5684\n\n        complete = options.complete;\n        if ( complete ) {\n\n          options.complete = false;\n          complete.call( elem );\n        }\n      }\n\n      return false;\n\n    } else {\n      // classical easing cannot be used with an Infinity duration\n      if ( options.duration == Infinity ) {\n        this.now = t;\n      } else {\n        n = t - this.startTime;\n        this.state = n / options.duration;\n\n        // Perform the easing function, defaults to swing\n        this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n        this.now = this.start + ( (this.end - this.start) * this.pos );\n      }\n      // Perform the next step of the animation\n      this.update();\n    }\n\n    return true;\n  }\n};\n\njQuery.extend( jQuery.fx, {\n  tick: function() {\n    var timer,\n      timers = jQuery.timers,\n      i = 0;\n\n    for ( ; i < timers.length; i++ ) {\n      timer = timers[ i ];\n      // Checks the timer has not already been removed\n      if ( !timer() && timers[ i ] === timer ) {\n        timers.splice( i--, 1 );\n      }\n    }\n\n    if ( !timers.length ) {\n      jQuery.fx.stop();\n    }\n  },\n\n  interval: 13,\n\n  stop: function() {\n    clearInterval( timerId );\n    timerId = null;\n  },\n\n  speeds: {\n    slow: 600,\n    fast: 200,\n    // Default speed\n    _default: 400\n  },\n\n  step: {\n    opacity: function( fx ) {\n      jQuery.style( fx.elem, \"opacity\", fx.now );\n    },\n\n    _default: function( fx ) {\n      if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n        fx.elem.style[ fx.prop ] = fx.now + fx.unit;\n      } else {\n        fx.elem[ fx.prop ] = fx.now;\n      }\n    }\n  }\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n  // exclude marginTop, marginLeft, marginBottom and marginRight from this list\n  if ( prop.indexOf( \"margin\" ) ) {\n    jQuery.fx.step[ prop ] = function( fx ) {\n      jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n    };\n  }\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n  jQuery.expr.filters.animated = function( elem ) {\n    return jQuery.grep(jQuery.timers, function( fn ) {\n      return elem === fn.elem;\n    }).length;\n  };\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n  if ( !elemdisplay[ nodeName ] ) {\n\n    var body = document.body,\n      elem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n      display = elem.css( \"display\" );\n    elem.remove();\n\n    // If the simple way fails,\n    // get element's real default display by attaching it to a temp iframe\n    if ( display === \"none\" || display === \"\" ) {\n      // No iframe to use yet, so create it\n      if ( !iframe ) {\n        iframe = document.createElement( \"iframe\" );\n        iframe.frameBorder = iframe.width = iframe.height = 0;\n      }\n\n      body.appendChild( iframe );\n\n      // Create a cacheable copy of the iframe document on first call.\n      // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n      // document to it; WebKit & Firefox won't allow reusing the iframe document.\n      if ( !iframeDoc || !iframe.createElement ) {\n        iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n        iframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n        iframeDoc.close();\n      }\n\n      elem = iframeDoc.createElement( nodeName );\n\n      iframeDoc.body.appendChild( elem );\n\n      display = jQuery.css( elem, \"display\" );\n      body.removeChild( iframe );\n    }\n\n    // Store the correct default display\n    elemdisplay[ nodeName ] = display;\n  }\n\n  return elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n  rtable = /^t(?:able|d|h)$/i,\n  rroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n  getOffset = function( elem, doc, docElem, box ) {\n    try {\n      box = elem.getBoundingClientRect();\n    } catch(e) {}\n\n    // Make sure we're not dealing with a disconnected DOM node\n    if ( !box || !jQuery.contains( docElem, elem ) ) {\n      return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n    }\n\n    var body = doc.body,\n      win = getWindow( doc ),\n      clientTop  = docElem.clientTop  || body.clientTop  || 0,\n      clientLeft = docElem.clientLeft || body.clientLeft || 0,\n      scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n      scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n      top  = box.top  + scrollTop  - clientTop,\n      left = box.left + scrollLeft - clientLeft;\n\n    return { top: top, left: left };\n  };\n\n} else {\n  getOffset = function( elem, doc, docElem ) {\n    var computedStyle,\n      offsetParent = elem.offsetParent,\n      prevOffsetParent = elem,\n      body = doc.body,\n      defaultView = doc.defaultView,\n      prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n      top = elem.offsetTop,\n      left = elem.offsetLeft;\n\n    while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n      if ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n        break;\n      }\n\n      computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n      top  -= elem.scrollTop;\n      left -= elem.scrollLeft;\n\n      if ( elem === offsetParent ) {\n        top  += elem.offsetTop;\n        left += elem.offsetLeft;\n\n        if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n          top  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n          left += parseFloat( computedStyle.borderLeftWidth ) || 0;\n        }\n\n        prevOffsetParent = offsetParent;\n        offsetParent = elem.offsetParent;\n      }\n\n      if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n        top  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n        left += parseFloat( computedStyle.borderLeftWidth ) || 0;\n      }\n\n      prevComputedStyle = computedStyle;\n    }\n\n    if ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n      top  += body.offsetTop;\n      left += body.offsetLeft;\n    }\n\n    if ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n      top  += Math.max( docElem.scrollTop, body.scrollTop );\n      left += Math.max( docElem.scrollLeft, body.scrollLeft );\n    }\n\n    return { top: top, left: left };\n  };\n}\n\njQuery.fn.offset = function( options ) {\n  if ( arguments.length ) {\n    return options === undefined ?\n      this :\n      this.each(function( i ) {\n        jQuery.offset.setOffset( this, options, i );\n      });\n  }\n\n  var elem = this[0],\n    doc = elem && elem.ownerDocument;\n\n  if ( !doc ) {\n    return null;\n  }\n\n  if ( elem === doc.body ) {\n    return jQuery.offset.bodyOffset( elem );\n  }\n\n  return getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n  bodyOffset: function( body ) {\n    var top = body.offsetTop,\n      left = body.offsetLeft;\n\n    if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n      top  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n      left += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n    }\n\n    return { top: top, left: left };\n  },\n\n  setOffset: function( elem, options, i ) {\n    var position = jQuery.css( elem, \"position\" );\n\n    // set position first, in-case top/left are set even on static elem\n    if ( position === \"static\" ) {\n      elem.style.position = \"relative\";\n    }\n\n    var curElem = jQuery( elem ),\n      curOffset = curElem.offset(),\n      curCSSTop = jQuery.css( elem, \"top\" ),\n      curCSSLeft = jQuery.css( elem, \"left\" ),\n      calculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n      props = {}, curPosition = {}, curTop, curLeft;\n\n    // need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n    if ( calculatePosition ) {\n      curPosition = curElem.position();\n      curTop = curPosition.top;\n      curLeft = curPosition.left;\n    } else {\n      curTop = parseFloat( curCSSTop ) || 0;\n      curLeft = parseFloat( curCSSLeft ) || 0;\n    }\n\n    if ( jQuery.isFunction( options ) ) {\n      options = options.call( elem, i, curOffset );\n    }\n\n    if ( options.top != null ) {\n      props.top = ( options.top - curOffset.top ) + curTop;\n    }\n    if ( options.left != null ) {\n      props.left = ( options.left - curOffset.left ) + curLeft;\n    }\n\n    if ( \"using\" in options ) {\n      options.using.call( elem, props );\n    } else {\n      curElem.css( props );\n    }\n  }\n};\n\n\njQuery.fn.extend({\n\n  position: function() {\n    if ( !this[0] ) {\n      return null;\n    }\n\n    var elem = this[0],\n\n    // Get *real* offsetParent\n    offsetParent = this.offsetParent(),\n\n    // Get correct offsets\n    offset       = this.offset(),\n    parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n    // Subtract element margins\n    // note: when an element has margin: auto the offsetLeft and marginLeft\n    // are the same in Safari causing offset.left to incorrectly be 0\n    offset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n    offset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n    // Add offsetParent borders\n    parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n    parentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n    // Subtract the two offsets\n    return {\n      top:  offset.top  - parentOffset.top,\n      left: offset.left - parentOffset.left\n    };\n  },\n\n  offsetParent: function() {\n    return this.map(function() {\n      var offsetParent = this.offsetParent || document.body;\n      while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent;\n    });\n  }\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n  var top = /Y/.test( prop );\n\n  jQuery.fn[ method ] = function( val ) {\n    return jQuery.access( this, function( elem, method, val ) {\n      var win = getWindow( elem );\n\n      if ( val === undefined ) {\n        return win ? (prop in win) ? win[ prop ] :\n          jQuery.support.boxModel && win.document.documentElement[ method ] ||\n            win.document.body[ method ] :\n          elem[ method ];\n      }\n\n      if ( win ) {\n        win.scrollTo(\n          !top ? val : jQuery( win ).scrollLeft(),\n           top ? val : jQuery( win ).scrollTop()\n        );\n\n      } else {\n        elem[ method ] = val;\n      }\n    }, method, val, arguments.length, null );\n  };\n});\n\nfunction getWindow( elem ) {\n  return jQuery.isWindow( elem ) ?\n    elem :\n    elem.nodeType === 9 ?\n      elem.defaultView || elem.parentWindow :\n      false;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n  var clientProp = \"client\" + name,\n    scrollProp = \"scroll\" + name,\n    offsetProp = \"offset\" + name;\n\n  // innerHeight and innerWidth\n  jQuery.fn[ \"inner\" + name ] = function() {\n    var elem = this[0];\n    return elem ?\n      elem.style ?\n      parseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n      this[ type ]() :\n      null;\n  };\n\n  // outerHeight and outerWidth\n  jQuery.fn[ \"outer\" + name ] = function( margin ) {\n    var elem = this[0];\n    return elem ?\n      elem.style ?\n      parseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n      this[ type ]() :\n      null;\n  };\n\n  jQuery.fn[ type ] = function( value ) {\n    return jQuery.access( this, function( elem, type, value ) {\n      var doc, docElemProp, orig, ret;\n\n      if ( jQuery.isWindow( elem ) ) {\n        // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n        doc = elem.document;\n        docElemProp = doc.documentElement[ clientProp ];\n        return jQuery.support.boxModel && docElemProp ||\n          doc.body && doc.body[ clientProp ] || docElemProp;\n      }\n\n      // Get document width or height\n      if ( elem.nodeType === 9 ) {\n        // Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n        doc = elem.documentElement;\n\n        // when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n        // so we can't use max, as it'll choose the incorrect offset[Width/Height]\n        // instead we use the correct client[Width/Height]\n        // support:IE6\n        if ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n          return doc[ clientProp ];\n        }\n\n        return Math.max(\n          elem.body[ scrollProp ], doc[ scrollProp ],\n          elem.body[ offsetProp ], doc[ offsetProp ]\n        );\n      }\n\n      // Get width or height on the element\n      if ( value === undefined ) {\n        orig = jQuery.css( elem, type );\n        ret = parseFloat( orig );\n        return jQuery.isNumeric( ret ) ? ret : orig;\n      }\n\n      // Set the width or height on the element\n      jQuery( elem ).css( type, value );\n    }, type, value, arguments.length, null );\n  };\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n  define( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/resources/static/js/jquery.validate.js",
    "content": "/**\n * jQuery Validation Plugin @VERSION\n *\n * http://bassistance.de/jquery-plugins/jquery-plugin-validation/\n * http://docs.jquery.com/Plugins/Validation\n *\n * Copyright (c) 2012 JÃ¶rn Zaefferer\n *\n * Dual licensed under the MIT and GPL licenses:\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n */\n\n(function($) {\n\n$.extend($.fn, {\n  // http://docs.jquery.com/Plugins/Validation/validate\n  validate: function( options ) {\n\n    // if nothing is selected, return nothing; can't chain anyway\n    if (!this.length) {\n      if (options && options.debug && window.console) {\n        console.warn( \"nothing selected, can't validate, returning nothing\" );\n      }\n      return;\n    }\n\n    // check if a validator for this form was already created\n    var validator = $.data(this[0], 'validator');\n    if ( validator ) {\n      return validator;\n    }\n\n    // Add novalidate tag if HTML5.\n    this.attr('novalidate', 'novalidate');\n\n    validator = new $.validator( options, this[0] );\n    $.data(this[0], 'validator', validator);\n\n    if ( validator.settings.onsubmit ) {\n\n      this.validateDelegate( \":submit\", \"click\", function(ev) {\n        if ( validator.settings.submitHandler ) {\n          validator.submitButton = ev.target;\n        }\n        // allow suppressing validation by adding a cancel class to the submit button\n        if ( $(ev.target).hasClass('cancel') ) {\n          validator.cancelSubmit = true;\n        }\n      });\n\n      // validate the form on submit\n      this.submit( function( event ) {\n        if ( validator.settings.debug ) {\n          // prevent form submit to be able to see console output\n          event.preventDefault();\n        }\n        function handle() {\n          var hidden;\n          if ( validator.settings.submitHandler ) {\n            if (validator.submitButton) {\n              // insert a hidden input as a replacement for the missing submit button\n              hidden = $(\"<input type='hidden'/>\").attr(\"name\", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);\n            }\n            validator.settings.submitHandler.call( validator, validator.currentForm, event );\n            if (validator.submitButton) {\n              // and clean up afterwards; thanks to no-block-scope, hidden can be referenced\n              hidden.remove();\n            }\n            return false;\n          }\n          return true;\n        }\n\n        // prevent submit for invalid forms or custom submit handlers\n        if ( validator.cancelSubmit ) {\n          validator.cancelSubmit = false;\n          return handle();\n        }\n        if ( validator.form() ) {\n          if ( validator.pendingRequest ) {\n            validator.formSubmitted = true;\n            return false;\n          }\n          return handle();\n        } else {\n          validator.focusInvalid();\n          return false;\n        }\n      });\n    }\n\n    return validator;\n  },\n  // http://docs.jquery.com/Plugins/Validation/valid\n  valid: function() {\n    if ( $(this[0]).is('form')) {\n      return this.validate().form();\n    } else {\n      var valid = true;\n      var validator = $(this[0].form).validate();\n      this.each(function() {\n        valid &= validator.element(this);\n      });\n      return valid;\n    }\n  },\n  // attributes: space seperated list of attributes to retrieve and remove\n  removeAttrs: function(attributes) {\n    var result = {},\n      $element = this;\n    $.each(attributes.split(/\\s/), function(index, value) {\n      result[value] = $element.attr(value);\n      $element.removeAttr(value);\n    });\n    return result;\n  },\n  // http://docs.jquery.com/Plugins/Validation/rules\n  rules: function(command, argument) {\n    var element = this[0];\n\n    if (command) {\n      var settings = $.data(element.form, 'validator').settings;\n      var staticRules = settings.rules;\n      var existingRules = $.validator.staticRules(element);\n      switch(command) {\n      case \"add\":\n        $.extend(existingRules, $.validator.normalizeRule(argument));\n        staticRules[element.name] = existingRules;\n        if (argument.messages) {\n          settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );\n        }\n        break;\n      case \"remove\":\n        if (!argument) {\n          delete staticRules[element.name];\n          return existingRules;\n        }\n        var filtered = {};\n        $.each(argument.split(/\\s/), function(index, method) {\n          filtered[method] = existingRules[method];\n          delete existingRules[method];\n        });\n        return filtered;\n      }\n    }\n\n    var data = $.validator.normalizeRules(\n    $.extend(\n      {},\n      $.validator.metadataRules(element),\n      $.validator.classRules(element),\n      $.validator.attributeRules(element),\n      $.validator.staticRules(element)\n    ), element);\n\n    // make sure required is at front\n    if (data.required) {\n      var param = data.required;\n      delete data.required;\n      data = $.extend({required: param}, data);\n    }\n\n    return data;\n  }\n});\n\n// Custom selectors\n$.extend($.expr[\":\"], {\n  // http://docs.jquery.com/Plugins/Validation/blank\n  blank: function(a) {return !$.trim(\"\" + a.value);},\n  // http://docs.jquery.com/Plugins/Validation/filled\n  filled: function(a) {return !!$.trim(\"\" + a.value);},\n  // http://docs.jquery.com/Plugins/Validation/unchecked\n  unchecked: function(a) {return !a.checked;}\n});\n\n// constructor for validator\n$.validator = function( options, form ) {\n  this.settings = $.extend( true, {}, $.validator.defaults, options );\n  this.currentForm = form;\n  this.init();\n};\n\n$.validator.format = function(source, params) {\n  if ( arguments.length === 1 ) {\n    return function() {\n      var args = $.makeArray(arguments);\n      args.unshift(source);\n      return $.validator.format.apply( this, args );\n    };\n  }\n  if ( arguments.length > 2 && params.constructor !== Array  ) {\n    params = $.makeArray(arguments).slice(1);\n  }\n  if ( params.constructor !== Array ) {\n    params = [ params ];\n  }\n  $.each(params, function(i, n) {\n    source = source.replace(new RegExp(\"\\\\{\" + i + \"\\\\}\", \"g\"), n);\n  });\n  return source;\n};\n\n$.extend($.validator, {\n\n  defaults: {\n    messages: {},\n    groups: {},\n    rules: {},\n    errorClass: \"error\",\n    validClass: \"valid\",\n    errorElement: \"label\",\n    focusInvalid: true,\n    errorContainer: $( [] ),\n    errorLabelContainer: $( [] ),\n    onsubmit: true,\n    ignore: \":hidden\",\n    ignoreTitle: false,\n    onfocusin: function(element, event) {\n      this.lastActive = element;\n\n      // hide error label and remove error class on focus if enabled\n      if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {\n        if ( this.settings.unhighlight ) {\n          this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );\n        }\n        this.addWrapper(this.errorsFor(element)).hide();\n      }\n    },\n    onfocusout: function(element, event) {\n      if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {\n        this.element(element);\n      }\n    },\n    onkeyup: function(element, event) {\n      if ( element.name in this.submitted || element === this.lastElement ) {\n        this.element(element);\n      }\n    },\n    onclick: function(element, event) {\n      // click on selects, radiobuttons and checkboxes\n      if ( element.name in this.submitted ) {\n        this.element(element);\n      }\n      // or option elements, check parent select in that case\n      else if (element.parentNode.name in this.submitted) {\n        this.element(element.parentNode);\n      }\n    },\n    highlight: function(element, errorClass, validClass) {\n      if (element.type === 'radio') {\n        this.findByName(element.name).addClass(errorClass).removeClass(validClass);\n      } else {\n        $(element).addClass(errorClass).removeClass(validClass);\n      }\n    },\n    unhighlight: function(element, errorClass, validClass) {\n      if (element.type === 'radio') {\n        this.findByName(element.name).removeClass(errorClass).addClass(validClass);\n      } else {\n        $(element).removeClass(errorClass).addClass(validClass);\n      }\n    }\n  },\n\n  // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults\n  setDefaults: function(settings) {\n    $.extend( $.validator.defaults, settings );\n  },\n\n  messages: {\n    required: \"This field is required.\",\n    remote: \"Please fix this field.\",\n    email: \"Please enter a valid email address.\",\n    url: \"Please enter a valid URL.\",\n    date: \"Please enter a valid date.\",\n    dateISO: \"Please enter a valid date (ISO).\",\n    number: \"Please enter a valid number.\",\n    digits: \"Please enter only digits.\",\n    creditcard: \"Please enter a valid credit card number.\",\n    equalTo: \"Please enter the same value again.\",\n    accept: \"Please enter a value with a valid extension.\",\n    maxlength: $.validator.format(\"Please enter no more than {0} characters.\"),\n    minlength: $.validator.format(\"Please enter at least {0} characters.\"),\n    rangelength: $.validator.format(\"Please enter a value between {0} and {1} characters long.\"),\n    range: $.validator.format(\"Please enter a value between {0} and {1}.\"),\n    max: $.validator.format(\"Please enter a value less than or equal to {0}.\"),\n    min: $.validator.format(\"Please enter a value greater than or equal to {0}.\")\n  },\n\n  autoCreateRanges: false,\n\n  prototype: {\n\n    init: function() {\n      this.labelContainer = $(this.settings.errorLabelContainer);\n      this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);\n      this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );\n      this.submitted = {};\n      this.valueCache = {};\n      this.pendingRequest = 0;\n      this.pending = {};\n      this.invalid = {};\n      this.reset();\n\n      var groups = (this.groups = {});\n      $.each(this.settings.groups, function(key, value) {\n        $.each(value.split(/\\s/), function(index, name) {\n          groups[name] = key;\n        });\n      });\n      var rules = this.settings.rules;\n      $.each(rules, function(key, value) {\n        rules[key] = $.validator.normalizeRule(value);\n      });\n\n      function delegate(event) {\n        var validator = $.data(this[0].form, \"validator\"),\n          eventType = \"on\" + event.type.replace(/^validate/, \"\");\n        if (validator.settings[eventType]) {\n          validator.settings[eventType].call(validator, this[0], event);\n        }\n      }\n      $(this.currentForm)\n        .validateDelegate(\"[type='text'], [type='password'], [type='file'], select, textarea, \" +\n          \"[type='number'], [type='search'] ,[type='tel'], [type='url'], \" +\n          \"[type='email'], [type='datetime'], [type='date'], [type='month'], \" +\n          \"[type='week'], [type='time'], [type='datetime-local'], \" +\n          \"[type='range'], [type='color'] \",\n          \"focusin focusout keyup\", delegate)\n        .validateDelegate(\"[type='radio'], [type='checkbox'], select, option\", \"click\", delegate);\n\n      if (this.settings.invalidHandler) {\n        $(this.currentForm).bind(\"invalid-form.validate\", this.settings.invalidHandler);\n      }\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Validator/form\n    form: function() {\n      this.checkForm();\n      $.extend(this.submitted, this.errorMap);\n      this.invalid = $.extend({}, this.errorMap);\n      if (!this.valid()) {\n        $(this.currentForm).triggerHandler(\"invalid-form\", [this]);\n      }\n      this.showErrors();\n      return this.valid();\n    },\n\n    checkForm: function() {\n      this.prepareForm();\n      for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {\n        this.check( elements[i] );\n      }\n      return this.valid();\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Validator/element\n    element: function( element ) {\n      element = this.validationTargetFor( this.clean( element ) );\n      this.lastElement = element;\n      this.prepareElement( element );\n      this.currentElements = $(element);\n      var result = this.check( element ) !== false;\n      if (result) {\n        delete this.invalid[element.name];\n      } else {\n        this.invalid[element.name] = true;\n      }\n      if ( !this.numberOfInvalids() ) {\n        // Hide error containers on last error\n        this.toHide = this.toHide.add( this.containers );\n      }\n      this.showErrors();\n      return result;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Validator/showErrors\n    showErrors: function(errors) {\n      if(errors) {\n        // add items to error list and map\n        $.extend( this.errorMap, errors );\n        this.errorList = [];\n        for ( var name in errors ) {\n          this.errorList.push({\n            message: errors[name],\n            element: this.findByName(name)[0]\n          });\n        }\n        // remove items from success list\n        this.successList = $.grep( this.successList, function(element) {\n          return !(element.name in errors);\n        });\n      }\n      if (this.settings.showErrors) {\n        this.settings.showErrors.call( this, this.errorMap, this.errorList );\n      } else {\n        this.defaultShowErrors();\n      }\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Validator/resetForm\n    resetForm: function() {\n      if ( $.fn.resetForm ) {\n        $( this.currentForm ).resetForm();\n      }\n      this.submitted = {};\n      this.lastElement = null;\n      this.prepareForm();\n      this.hideErrors();\n      this.elements().removeClass( this.settings.errorClass );\n    },\n\n    numberOfInvalids: function() {\n      return this.objectLength(this.invalid);\n    },\n\n    objectLength: function( obj ) {\n      var count = 0;\n      for ( var i in obj ) {\n        count++;\n      }\n      return count;\n    },\n\n    hideErrors: function() {\n      this.addWrapper( this.toHide ).hide();\n    },\n\n    valid: function() {\n      return this.size() === 0;\n    },\n\n    size: function() {\n      return this.errorList.length;\n    },\n\n    focusInvalid: function() {\n      if( this.settings.focusInvalid ) {\n        try {\n          $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])\n          .filter(\":visible\")\n          .focus()\n          // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find\n          .trigger(\"focusin\");\n        } catch(e) {\n          // ignore IE throwing errors when focusing hidden elements\n        }\n      }\n    },\n\n    findLastActive: function() {\n      var lastActive = this.lastActive;\n      return lastActive && $.grep(this.errorList, function(n) {\n        return n.element.name === lastActive.name;\n      }).length === 1 && lastActive;\n    },\n\n    elements: function() {\n      var validator = this,\n        rulesCache = {};\n\n      // select all valid inputs inside the form (no submit or reset buttons)\n      return $(this.currentForm)\n      .find(\"input, select, textarea\")\n      .not(\":submit, :reset, :image, [disabled]\")\n      .not( this.settings.ignore )\n      .filter(function() {\n        if ( !this.name && validator.settings.debug && window.console ) {\n          console.error( \"%o has no name assigned\", this);\n        }\n\n        // select only the first element for each name, and only those with rules specified\n        if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) {\n          return false;\n        }\n\n        rulesCache[this.name] = true;\n        return true;\n      });\n    },\n\n    clean: function( selector ) {\n      return $( selector )[0];\n    },\n\n    errors: function() {\n      var errorClass = this.settings.errorClass.replace(' ', '.');\n      return $( this.settings.errorElement + \".\" + errorClass, this.errorContext );\n    },\n\n    reset: function() {\n      this.successList = [];\n      this.errorList = [];\n      this.errorMap = {};\n      this.toShow = $([]);\n      this.toHide = $([]);\n      this.currentElements = $([]);\n    },\n\n    prepareForm: function() {\n      this.reset();\n      this.toHide = this.errors().add( this.containers );\n    },\n\n    prepareElement: function( element ) {\n      this.reset();\n      this.toHide = this.errorsFor(element);\n    },\n\n    elementValue: function( element ) {\n      var val = $(element).val();\n      if( typeof val === 'string' ) {\n        return val.replace(/\\r/g, \"\");\n      }\n      return val;\n    },\n\n    check: function( element ) {\n      element = this.validationTargetFor( this.clean( element ) );\n\n      var rules = $(element).rules();\n      var dependencyMismatch = false;\n      var val = this.elementValue(element);\n      var result;\n\n      for (var method in rules ) {\n        var rule = { method: method, parameters: rules[method] };\n        try {\n\n          result = $.validator.methods[method].call( this, val, element, rule.parameters );\n\n          // if a method indicates that the field is optional and therefore valid,\n          // don't mark it as valid when there are no other rules\n          if ( result === \"dependency-mismatch\" ) {\n            dependencyMismatch = true;\n            continue;\n          }\n          dependencyMismatch = false;\n\n          if ( result === \"pending\" ) {\n            this.toHide = this.toHide.not( this.errorsFor(element) );\n            return;\n          }\n\n          if( !result ) {\n            this.formatAndAdd( element, rule );\n            return false;\n          }\n        } catch(e) {\n          if ( this.settings.debug && window.console ) {\n            console.log(\"exception occured when checking element \" + element.id + \", check the '\" + rule.method + \"' method\", e);\n          }\n          throw e;\n        }\n      }\n      if (dependencyMismatch) {\n        return;\n      }\n      if ( this.objectLength(rules) ) {\n        this.successList.push(element);\n      }\n      return true;\n    },\n\n    // return the custom message for the given element and validation method\n    // specified in the element's \"messages\" metadata\n    customMetaMessage: function(element, method) {\n      if (!$.metadata) {\n        return;\n      }\n      var meta = this.settings.meta ? $(element).metadata()[this.settings.meta] : $(element).metadata();\n      return meta && meta.messages && meta.messages[method];\n    },\n\n    // return the custom message for the given element name and validation method\n    customMessage: function( name, method ) {\n      var m = this.settings.messages[name];\n      return m && (m.constructor === String ? m : m[method]);\n    },\n\n    // return the first defined argument, allowing empty strings\n    findDefined: function() {\n      for(var i = 0; i < arguments.length; i++) {\n        if (arguments[i] !== undefined) {\n          return arguments[i];\n        }\n      }\n      return undefined;\n    },\n\n    defaultMessage: function( element, method) {\n      return this.findDefined(\n        this.customMessage( element.name, method ),\n        this.customMetaMessage( element, method ),\n        // title is never undefined, so handle empty string as undefined\n        !this.settings.ignoreTitle && element.title || undefined,\n        $.validator.messages[method],\n        \"<strong>Warning: No message defined for \" + element.name + \"</strong>\"\n      );\n    },\n\n    formatAndAdd: function( element, rule ) {\n      var message = this.defaultMessage( element, rule.method ),\n        theregex = /\\$?\\{(\\d+)\\}/g;\n      if ( typeof message === \"function\" ) {\n        message = message.call(this, rule.parameters, element);\n      } else if (theregex.test(message)) {\n        message = $.validator.format(message.replace(theregex, '{$1}'), rule.parameters);\n      }\n      this.errorList.push({\n        message: message,\n        element: element\n      });\n\n      this.errorMap[element.name] = message;\n      this.submitted[element.name] = message;\n    },\n\n    addWrapper: function(toToggle) {\n      if ( this.settings.wrapper ) {\n        toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );\n      }\n      return toToggle;\n    },\n\n    defaultShowErrors: function() {\n      var i, elements;\n      for ( i = 0; this.errorList[i]; i++ ) {\n        var error = this.errorList[i];\n        if ( this.settings.highlight ) {\n          this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );\n        }\n        this.showLabel( error.element, error.message );\n      }\n      if( this.errorList.length ) {\n        this.toShow = this.toShow.add( this.containers );\n      }\n      if (this.settings.success) {\n        for ( i = 0; this.successList[i]; i++ ) {\n          this.showLabel( this.successList[i] );\n        }\n      }\n      if (this.settings.unhighlight) {\n        for ( i = 0, elements = this.validElements(); elements[i]; i++ ) {\n          this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );\n        }\n      }\n      this.toHide = this.toHide.not( this.toShow );\n      this.hideErrors();\n      this.addWrapper( this.toShow ).show();\n    },\n\n    validElements: function() {\n      return this.currentElements.not(this.invalidElements());\n    },\n\n    invalidElements: function() {\n      return $(this.errorList).map(function() {\n        return this.element;\n      });\n    },\n\n    showLabel: function(element, message) {\n      var label = this.errorsFor( element );\n      if ( label.length ) {\n        // refresh error/success class\n        label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );\n\n        // check if we have a generated label, replace the message then\n        if ( label.attr(\"generated\") ) {\n          label.html(message);\n        }\n      } else {\n        // create label\n        label = $(\"<\" + this.settings.errorElement + \"/>\")\n          .attr({\"for\":  this.idOrName(element), generated: true})\n          .addClass(this.settings.errorClass)\n          .html(message || \"\");\n        if ( this.settings.wrapper ) {\n          // make sure the element is visible, even in IE\n          // actually showing the wrapped element is handled elsewhere\n          label = label.hide().show().wrap(\"<\" + this.settings.wrapper + \"/>\").parent();\n        }\n        if ( !this.labelContainer.append(label).length ) {\n          if ( this.settings.errorPlacement ) {\n            this.settings.errorPlacement(label, $(element) );\n          } else {\n          label.insertAfter(element);\n          }\n        }\n      }\n      if ( !message && this.settings.success ) {\n        label.text(\"\");\n        if ( typeof this.settings.success === \"string\" ) {\n          label.addClass( this.settings.success );\n        } else {\n          this.settings.success( label );\n        }\n      }\n      this.toShow = this.toShow.add(label);\n    },\n\n    errorsFor: function(element) {\n      var name = this.idOrName(element);\n      return this.errors().filter(function() {\n        return $(this).attr('for') === name;\n      });\n    },\n\n    idOrName: function(element) {\n      return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);\n    },\n\n    validationTargetFor: function(element) {\n      // if radio/checkbox, validate first element in group instead\n      if (this.checkable(element)) {\n        element = this.findByName( element.name ).not(this.settings.ignore)[0];\n      }\n      return element;\n    },\n\n    checkable: function( element ) {\n      return (/radio|checkbox/i).test(element.type);\n    },\n\n    findByName: function( name ) {\n      // select by name and filter by form for performance over form.find(\"[name=...]\")\n      var form = this.currentForm;\n      return $(document.getElementsByName(name)).map(function(index, element) {\n        return element.form === form && element.name === name && element  || null;\n      });\n    },\n\n    getLength: function(value, element) {\n      switch( element.nodeName.toLowerCase() ) {\n      case 'select':\n        return $(\"option:selected\", element).length;\n      case 'input':\n        if( this.checkable( element) ) {\n          return this.findByName(element.name).filter(':checked').length;\n        }\n      }\n      return value.length;\n    },\n\n    depend: function(param, element) {\n      return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true;\n    },\n\n    dependTypes: {\n      \"boolean\": function(param, element) {\n        return param;\n      },\n      \"string\": function(param, element) {\n        return !!$(param, element.form).length;\n      },\n      \"function\": function(param, element) {\n        return param(element);\n      }\n    },\n\n    optional: function(element) {\n      var val = this.elementValue(element);\n      return !$.validator.methods.required.call(this, val, element) && \"dependency-mismatch\";\n    },\n\n    startRequest: function(element) {\n      if (!this.pending[element.name]) {\n        this.pendingRequest++;\n        this.pending[element.name] = true;\n      }\n    },\n\n    stopRequest: function(element, valid) {\n      this.pendingRequest--;\n      // sometimes synchronization fails, make sure pendingRequest is never < 0\n      if (this.pendingRequest < 0) {\n        this.pendingRequest = 0;\n      }\n      delete this.pending[element.name];\n      if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {\n        $(this.currentForm).submit();\n        this.formSubmitted = false;\n      } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) {\n        $(this.currentForm).triggerHandler(\"invalid-form\", [this]);\n        this.formSubmitted = false;\n      }\n    },\n\n    previousValue: function(element) {\n      return $.data(element, \"previousValue\") || $.data(element, \"previousValue\", {\n        old: null,\n        valid: true,\n        message: this.defaultMessage( element, \"remote\" )\n      });\n    }\n\n  },\n\n  classRuleSettings: {\n    required: {required: true},\n    email: {email: true},\n    url: {url: true},\n    date: {date: true},\n    dateISO: {dateISO: true},\n    number: {number: true},\n    digits: {digits: true},\n    creditcard: {creditcard: true}\n  },\n\n  addClassRules: function(className, rules) {\n    if ( className.constructor === String ) {\n      this.classRuleSettings[className] = rules;\n    } else {\n      $.extend(this.classRuleSettings, className);\n    }\n  },\n\n  classRules: function(element) {\n    var rules = {};\n    var classes = $(element).attr('class');\n    if ( classes ) {\n      $.each(classes.split(' '), function() {\n        if (this in $.validator.classRuleSettings) {\n          $.extend(rules, $.validator.classRuleSettings[this]);\n        }\n      });\n    }\n    return rules;\n  },\n\n  attributeRules: function(element) {\n    var rules = {};\n    var $element = $(element);\n\n    for (var method in $.validator.methods) {\n      var value;\n\n      // support for <input required> in both html5 and older browsers\n      if (method === 'required') {\n        value = $element.get(0).getAttribute(method);\n        // Some browsers return an empty string for the required attribute\n        // and non-HTML5 browsers might have required=\"\" markup\n        if (value === \"\") {\n          value = true;\n        } else if (value === \"false\") {\n          value = false;\n        }\n        // force non-HTML5 browsers to return bool\n        value = !!value;\n      } else {\n        value = $element.attr(method);\n      }\n\n      if (value) {\n        rules[method] = value;\n      } else if ($element[0].getAttribute(\"type\") === method) {\n        rules[method] = true;\n      }\n    }\n\n    // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs\n    if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {\n      delete rules.maxlength;\n    }\n\n    return rules;\n  },\n\n  metadataRules: function(element) {\n    if (!$.metadata) {\n      return {};\n    }\n\n    var meta = $.data(element.form, 'validator').settings.meta;\n    return meta ?\n      $(element).metadata()[meta] :\n      $(element).metadata();\n  },\n\n  staticRules: function(element) {\n    var rules = {};\n    var validator = $.data(element.form, 'validator');\n    if (validator.settings.rules) {\n      rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};\n    }\n    return rules;\n  },\n\n  normalizeRules: function(rules, element) {\n    // handle dependency check\n    $.each(rules, function(prop, val) {\n      // ignore rule when param is explicitly false, eg. required:false\n      if (val === false) {\n        delete rules[prop];\n        return;\n      }\n      if (val.param || val.depends) {\n        var keepRule = true;\n        switch (typeof val.depends) {\n          case \"string\":\n            keepRule = !!$(val.depends, element.form).length;\n            break;\n          case \"function\":\n            keepRule = val.depends.call(element, element);\n            break;\n        }\n        if (keepRule) {\n          rules[prop] = val.param !== undefined ? val.param : true;\n        } else {\n          delete rules[prop];\n        }\n      }\n    });\n\n    // evaluate parameters\n    $.each(rules, function(rule, parameter) {\n      rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;\n    });\n\n    // clean number parameters\n    $.each(['minlength', 'maxlength', 'min', 'max'], function() {\n      if (rules[this]) {\n        rules[this] = Number(rules[this]);\n      }\n    });\n    $.each(['rangelength', 'range'], function() {\n      if (rules[this]) {\n        rules[this] = [Number(rules[this][0]), Number(rules[this][1])];\n      }\n    });\n\n    if ($.validator.autoCreateRanges) {\n      // auto-create ranges\n      if (rules.min && rules.max) {\n        rules.range = [rules.min, rules.max];\n        delete rules.min;\n        delete rules.max;\n      }\n      if (rules.minlength && rules.maxlength) {\n        rules.rangelength = [rules.minlength, rules.maxlength];\n        delete rules.minlength;\n        delete rules.maxlength;\n      }\n    }\n\n    // To support custom messages in metadata ignore rule methods titled \"messages\"\n    if (rules.messages) {\n      delete rules.messages;\n    }\n\n    return rules;\n  },\n\n  // Converts a simple string to a {string: true} rule, e.g., \"required\" to {required:true}\n  normalizeRule: function(data) {\n    if( typeof data === \"string\" ) {\n      var transformed = {};\n      $.each(data.split(/\\s/), function() {\n        transformed[this] = true;\n      });\n      data = transformed;\n    }\n    return data;\n  },\n\n  // http://docs.jquery.com/Plugins/Validation/Validator/addMethod\n  addMethod: function(name, method, message) {\n    $.validator.methods[name] = method;\n    $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];\n    if (method.length < 3) {\n      $.validator.addClassRules(name, $.validator.normalizeRule(name));\n    }\n  },\n\n  methods: {\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/required\n    required: function(value, element, param) {\n      // check if dependency is met\n      if ( !this.depend(param, element) ) {\n        return \"dependency-mismatch\";\n      }\n      if ( element.nodeName.toLowerCase() === \"select\" ) {\n        // could be an array for select-multiple or a string, both are fine this way\n        var val = $(element).val();\n        return val && val.length > 0;\n      }\n      if ( this.checkable(element) ) {\n        return this.getLength(value, element) > 0;\n      }\n      return $.trim(value).length > 0;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/remote\n    remote: function(value, element, param) {\n      if ( this.optional(element) ) {\n        return \"dependency-mismatch\";\n      }\n\n      var previous = this.previousValue(element);\n      if (!this.settings.messages[element.name] ) {\n        this.settings.messages[element.name] = {};\n      }\n      previous.originalMessage = this.settings.messages[element.name].remote;\n      this.settings.messages[element.name].remote = previous.message;\n\n      param = typeof param === \"string\" && {url:param} || param;\n\n      if ( this.pending[element.name] ) {\n        return \"pending\";\n      }\n      if ( previous.old === value ) {\n        return previous.valid;\n      }\n\n      previous.old = value;\n      var validator = this;\n      this.startRequest(element);\n      var data = {};\n      data[element.name] = value;\n      $.ajax($.extend(true, {\n        url: param,\n        mode: \"abort\",\n        port: \"validate\" + element.name,\n        dataType: \"json\",\n        data: data,\n        success: function(response) {\n          validator.settings.messages[element.name].remote = previous.originalMessage;\n          var valid = response === true;\n          if ( valid ) {\n            var submitted = validator.formSubmitted;\n            validator.prepareElement(element);\n            validator.formSubmitted = submitted;\n            validator.successList.push(element);\n            validator.showErrors();\n          } else {\n            var errors = {};\n            var message = response || validator.defaultMessage( element, \"remote\" );\n            errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;\n            validator.showErrors(errors);\n          }\n          previous.valid = valid;\n          validator.stopRequest(element, valid);\n        }\n      }, param));\n      return \"pending\";\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/minlength\n    minlength: function(value, element, param) {\n      var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);\n      return this.optional(element) || length >= param;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/maxlength\n    maxlength: function(value, element, param) {\n      var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);\n      return this.optional(element) || length <= param;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/rangelength\n    rangelength: function(value, element, param) {\n      var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);\n      return this.optional(element) || ( length >= param[0] && length <= param[1] );\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/min\n    min: function( value, element, param ) {\n      return this.optional(element) || value >= param;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/max\n    max: function( value, element, param ) {\n      return this.optional(element) || value <= param;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/range\n    range: function( value, element, param ) {\n      return this.optional(element) || ( value >= param[0] && value <= param[1] );\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/email\n    email: function(value, element) {\n      // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/\n      return this.optional(element) || /^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$/i.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/url\n    url: function(value, element) {\n      // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/\n      return this.optional(element) || /^(https?|ftp):\\/\\/(((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/date\n    date: function(value, element) {\n      return this.optional(element) || !/Invalid|NaN/.test(new Date(value));\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/dateISO\n    dateISO: function(value, element) {\n      return this.optional(element) || /^\\d{4}[\\/\\-]\\d{1,2}[\\/\\-]\\d{1,2}$/.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/number\n    number: function(value, element) {\n      return this.optional(element) || /^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$/.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/digits\n    digits: function(value, element) {\n      return this.optional(element) || /^\\d+$/.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/creditcard\n    // based on http://en.wikipedia.org/wiki/Luhn\n    creditcard: function(value, element) {\n      if ( this.optional(element) ) {\n        return \"dependency-mismatch\";\n      }\n      // accept only spaces, digits and dashes\n      if (/[^0-9 \\-]+/.test(value)) {\n        return false;\n      }\n      var nCheck = 0,\n        nDigit = 0,\n        bEven = false;\n\n      value = value.replace(/\\D/g, \"\");\n\n      for (var n = value.length - 1; n >= 0; n--) {\n        var cDigit = value.charAt(n);\n        nDigit = parseInt(cDigit, 10);\n        if (bEven) {\n          if ((nDigit *= 2) > 9) {\n            nDigit -= 9;\n          }\n        }\n        nCheck += nDigit;\n        bEven = !bEven;\n      }\n\n      return (nCheck % 10) === 0;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/accept\n    accept: function(value, element, param) {\n      param = typeof param === \"string\" ? param.replace(/,/g, '|') : \"png|jpe?g|gif\";\n      return this.optional(element) || value.match(new RegExp(\".(\" + param + \")$\", \"i\"));\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/equalTo\n    equalTo: function(value, element, param) {\n      // bind to the blur event of the target in order to revalidate whenever the target field is updated\n      // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead\n      var target = $(param).unbind(\".validate-equalTo\").bind(\"blur.validate-equalTo\", function() {\n        $(element).valid();\n      });\n      return value === target.val();\n    }\n\n  }\n\n});\n\n// deprecated, use $.validator.format instead\n$.format = $.validator.format;\n\n}(jQuery));\n\n// ajax mode: abort\n// usage: $.ajax({ mode: \"abort\"[, port: \"uniqueport\"]});\n// if mode:\"abort\" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()\n(function($) {\n  var pendingRequests = {};\n  // Use a prefilter if available (1.5+)\n  if ( $.ajaxPrefilter ) {\n    $.ajaxPrefilter(function(settings, _, xhr) {\n      var port = settings.port;\n      if (settings.mode === \"abort\") {\n        if ( pendingRequests[port] ) {\n          pendingRequests[port].abort();\n        }\n        pendingRequests[port] = xhr;\n      }\n    });\n  } else {\n    // Proxy ajax\n    var ajax = $.ajax;\n    $.ajax = function(settings) {\n      var mode = ( \"mode\" in settings ? settings : $.ajaxSettings ).mode,\n        port = ( \"port\" in settings ? settings : $.ajaxSettings ).port;\n      if (mode === \"abort\") {\n        if ( pendingRequests[port] ) {\n          pendingRequests[port].abort();\n        }\n        return (pendingRequests[port] = ajax.apply(this, arguments));\n      }\n      return ajax.apply(this, arguments);\n    };\n  }\n}(jQuery));\n\n// provides cross-browser focusin and focusout events\n// IE has native support, in other browsers, use event caputuring (neither bubbles)\n\n// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation\n// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target\n(function($) {\n  // only implement if not provided by jQuery core (since 1.4)\n  // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs\n  if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {\n    $.each({\n      focus: 'focusin',\n      blur: 'focusout'\n    }, function( original, fix ){\n      $.event.special[fix] = {\n        setup:function() {\n          this.addEventListener( original, handler, true );\n        },\n        teardown:function() {\n          this.removeEventListener( original, handler, true );\n        },\n        handler: function(e) {\n          var args = arguments;\n          args[0] = $.event.fix(e);\n          args[0].type = fix;\n          return $.event.handle.apply(this, args);\n        }\n      };\n      function handler(e) {\n        e = $.event.fix(e);\n        e.type = fix;\n        return $.event.handle.call(this, e);\n      }\n    });\n  }\n  $.extend($.fn, {\n    validateDelegate: function(delegate, type, handler) {\n      return this.bind(type, function(event) {\n        var target = $(event.target);\n        if (target.is(delegate)) {\n          return handler.apply(target, arguments);\n        }\n      });\n    }\n  });\n}(jQuery));"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/resources/templates/layout.tpl",
    "content": "html {\n  head {\n    title(title)\n    link(rel:'stylesheet', href:'/css/bootstrap.min.css')\n  }\n  body {\n    div(class:'container') {\n      div(class:'navbar') {\n        div(class:'navbar-inner') {\n          a(class:'brand',\n              href:'http://beta.groovy-lang.org/docs/groovy-2.3.0/html/documentation/markup-template-engine.html') {\n              yield 'Groovy - Layout'\n          }\n          ul(class:'nav') {\n            li {\n              a(href:'/') {\n                yield 'Messages'\n              }\n            }\n          }\n        }\n      }\n      h1(title)\n      div { content() }\n    }\n  }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/resources/templates/messages/form.tpl",
    "content": "layout 'layout.tpl', title: 'Messages : Create',\n  content: contents {\n    div (class:'container') {\n      form (id:'messageForm', action:'/', method:'post') {\n      \tif (formErrors) {\n          div(class:'alert alert-error') {\n            formErrors.each { error ->\n              p error.defaultMessage\n            }\n          }\n        }\n        div (class:'pull-right') {\n          a (href:'/', 'Messages')\n        }\n        label (for:'summary', 'Summary')\n        input (name:'summary', type:'text', value:message.summary?:'',\n            class:fieldErrors?.summary ? 'field-error' : 'none')\n        label (for:'text', 'Message')\n        textarea (name:'text', class:fieldErrors?.text ? 'field-error' : 'none', message.text?:'')\n        div (class:'form-actions') {\n          input (type:'submit', value:'Create')\n        }\n      }\n    }\n  }"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/resources/templates/messages/list.tpl",
    "content": "layout 'layout.tpl', title: 'Messages : View all',\n  content: contents {\n    div(class:'container') {\n      div(class:'pull-right') {\n        a(href:'/?form', 'Create Message')\n      }\n      table(class:'table table-bordered table-striped') {\n        thead {\n          tr {\n            td 'ID'\n            td 'Created'\n            td 'Summary'\n          }\n        }\n        tbody {\n          if (messages.empty) { tr { td(colspan:'3', 'No Messages' ) } }\n          messages.each { message ->\n            tr { \n              td message.id\n              td \"${message.created}\"\n              td {\n                a(href:\"/${message.id}\") {\n                  yield message.summary\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/resources/templates/messages/view.tpl",
    "content": "layout 'layout.tpl', title:'Messages : View',\n  content: contents {\n    div(class:'container') {\n      if (globalMessage) {\n        div (class:'alert alert-success', globalMessage)\n      }\n      div(class:'pull-right') {\n        a(href:'/', 'Messages')\n      }\n      dl {\n        dt 'ID'\n        dd(id:'id', message.id)\n        dt 'Date'\n        dd(id:'created', \"${message.created}\")\n        dt 'Summary'\n        dd(id:'summary', message.summary)\n        dt 'Message'\n        dd(id:'text', message.text)\n      }\n    }\n  }"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/test/java/comsat/sample/ui/SampleGroovyTemplateApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport co.paralleluniverse.test.categories.CI;\nimport java.net.URI;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.experimental.categories.Category;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleGroovyTemplateApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleGroovyTemplateApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body (title doesn't match):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"<title>Messages\"));\n        assertFalse(\"Wrong body (found layout:fragment):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"layout:fragment\"));\n    }\n\n    @Test\n    public void testCreate() throws Exception {\n        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();\n        map.set(\"text\", \"FOO text\");\n        map.set(\"summary\", \"FOO\");\n        URI location = new TestRestTemplate().postForLocation(\"http://localhost:\"\n                + this.port, map);\n        assertTrue(\"Wrong location:\\n\" + location,\n                location.toString().contains(\"localhost:\" + this.port));\n    }\n\n    @Test\n    public void testCreateValidation() throws Exception {\n        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();\n        map.set(\"text\", \"\");\n        map.set(\"summary\", \"\");\n        ResponseEntity<String> entity = new TestRestTemplate().postForEntity(\"http://localhost:\"\n                + this.port, map, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body ('required' validation error doesn't match):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"is required\"));\n    }\n\n    @Test\n    public void testCss() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/css/bootstrap.min.css\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"body\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-jsp/build.gradle",
    "content": "dependencies {\n    compile \"org.apache.tomcat.embed:tomcat-embed-jasper:$tomcatVer\"\n    compile \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    provided(\"javax.servlet:jstl:$jstlVer\")\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-jsp/src/main/java/comsat/sample/jsp/SampleWebJspApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.boot.context.web.SpringBootServletInitializer;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleWebJspApplication extends SpringBootServletInitializer {\n    @Override\n    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {\n        return application.sources(SampleWebJspApplication.class);\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleWebJspApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-jsp/src/main/java/comsat/sample/jsp/WelcomeController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@Controller\npublic class WelcomeController {\n\n    @Value(\"${application.message:Hello World}\")\n    private String message = \"Hello World\";\n\n    @RequestMapping(\"/\")\n    public String welcome(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"time\", new Date());\n        model.put(\"message\", this.message);\n        return \"welcome\";\n    }\n\n    @RequestMapping(\"/foo\")\n    public String foo(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new RuntimeException(\"Foo\");\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-jsp/src/main/resources/application.properties",
    "content": "spring.mvc.view.prefix: /WEB-INF/jsp/\nspring.mvc.view.suffix: .jsp\napplication.message: Hello Phil"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-jsp/src/main/webapp/WEB-INF/jsp/welcome.jsp",
    "content": "<!DOCTYPE html>\n\n<%@ taglib prefix=\"spring\" uri=\"http://www.springframework.org/tags\"%>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\n\n<html lang=\"en\">\n\n<body>\n\t<c:url value=\"/resources/text.txt\" var=\"url\"/>\n\t<spring:url value=\"/resources/text.txt\" htmlEscape=\"true\" var=\"springUrl\" />\n\tSpring URL: ${springUrl} at ${time}\n\t<br>\n\tJSTL URL: ${url}\n\t<br>\n\tMessage: ${message}\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-jsp/src/test/java/comsat/sample/jsp/SampleWebJspApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Phillip Webb.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.jsp;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for JSP application.\n *\n * @author Phillip Webb\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebJspApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleWebJspApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testJspWithEl() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(),\n                entity.getBody().contains(\"/resources/text.txt\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-method-security/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-security:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-boot-security\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-method-security/src/main/java/comsat/sample/ui/method/SampleMethodSecurityApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.method;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.security.access.annotation.Secured;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.web.util.matcher.AntPathRequestMatcher;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\nimport co.paralleluniverse.springframework.boot.security.autoconfigure.web.FiberSecureSpringBootApplication;\n\n@FiberSecureSpringBootApplication // This will enable fiber-blocking\n@EnableGlobalMethodSecurity(securedEnabled = true)\npublic class SampleMethodSecurityApplication extends WebMvcConfigurerAdapter {\n    @Controller\n    protected static class HomeController {\n        // Unfortunately Spring method security proxies classes in such a way that declared exceptions\n        // get a generated, specific catch block which, for SuspendExecution prevents Quasar from instrumenting;\n        // this means the exception has to be catched and the method annotated in this special case\n        @RequestMapping(\"/\")\n        @Secured(\"ROLE_ADMIN\")\n        @Suspendable\n        public String home(Map<String, Object> model) throws InterruptedException {\n            try {\n                Fiber.sleep(10);\n            } catch (SuspendExecution se) {\n                throw new AssertionError(se);\n            }\n            model.put(\"message\", \"Hello World\");\n            model.put(\"title\", \"Hello Home\");\n            model.put(\"date\", new Date());\n            return \"home\";\n        }\n    }\n\n    public static void main(String[] args) throws Exception {\n        new SpringApplicationBuilder(SampleMethodSecurityApplication.class).run(args);\n    }\n\n    @Override\n    public void addViewControllers(ViewControllerRegistry registry) {\n        registry.addViewController(\"/login\").setViewName(\"login\");\n        registry.addViewController(\"/access\").setViewName(\"access\");\n    }\n\n    @Bean\n    public ApplicationSecurity applicationSecurity() {\n        return new ApplicationSecurity();\n    }\n\n    @Order(Ordered.HIGHEST_PRECEDENCE)\n    @Configuration\n    protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {\n        @Override\n        public void init(AuthenticationManagerBuilder auth) throws Exception {\n            // @formatter:off\n            auth.inMemoryAuthentication().withUser(\"admin\").password(\"admin\")\n                    .roles(\"ADMIN\", \"USER\").and().withUser(\"user\").password(\"user\")\n                    .roles(\"USER\");\n            // @formatter:on\n        }\n    }\n\n    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)\n    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {\n        @Override\n        protected void configure(HttpSecurity http) throws Exception {\n            // @formatter:off\n            http.authorizeRequests().antMatchers(\"/login\").permitAll().anyRequest()\n                    .fullyAuthenticated().and().formLogin().loginPage(\"/login\")\n                    .failureUrl(\"/login?error\").and().logout()\n                    .logoutRequestMatcher(new AntPathRequestMatcher(\"/logout\")).and()\n                    .exceptionHandling().accessDeniedPage(\"/access?error\");\n            // @formatter:on\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-method-security/src/main/resources/application.properties",
    "content": "spring.thymeleaf.cache: false\nlogging.level.org.springframework.security: INFO"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-method-security/src/main/resources/templates/access.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Error</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<p class=\"alert alert-error\">Access denied:\n\t\t\tyou do not have permission for that resource</p>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div>Please contact the operator with the above information.</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-method-security/src/main/resources/templates/error.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Error</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<div id=\"created\" th:text=\"${#dates.format(timestamp)}\">July 11,\n\t\t\t2012 2:17:16 PM CDT</div>\n\t\t<div>\n\t\t\tThere was an unexpected error (type=<span th:text=\"${error}\">Bad</span>, status=<span th:text=\"${status}\">500</span>).\n\t\t</div>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div>\n\t\t\tPlease contact the operator with the above information.\n\t\t</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-method-security/src/main/resources/templates/home.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title th:text=\"${title}\">Title</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div id=\"created\" th:text=\"${#dates.format(date)}\">July 11,\n\t\t\t2012 2:17:16 PM CDT</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-method-security/src/main/resources/templates/login.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Login</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body onload=\"document.f.username.focus();\">\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"content\">\n\t\t\t<p th:if=\"${param.logout}\" class=\"alert\">You have been logged out</p>\n\t\t\t<p th:if=\"${param.error}\" class=\"alert alert-error\">There was an error, please try again</p>\n\t\t\t<h2>Login with Username and Password</h2>\n\t\t\t<form name=\"form\" th:action=\"@{/login}\" action=\"/login\" method=\"POST\">\n\t\t\t\t<fieldset>\n\t\t\t\t\t<input type=\"text\" name=\"username\" value=\"\" placeholder=\"Username\" />\n\t\t\t\t\t<input type=\"password\" name=\"password\" placeholder=\"Password\" />\n\t\t\t\t</fieldset>\n\t\t\t\t<input type=\"submit\" id=\"login\" value=\"Login\"\n\t\t\t\t\tclass=\"btn btn-primary\" />\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</body>\n</html>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-method-security/src/test/java/comsat/sample/ui/method/SampleMethodSecurityApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.method;\n\nimport co.paralleluniverse.test.categories.CI;\nimport java.util.Arrays;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.experimental.categories.Category;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@Category(CI.class)\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleMethodSecurityApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleMethodSecurityApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port, HttpMethod.GET, new HttpEntity<Void>(\n                        headers), String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body (title doesn't match):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"<title>Login\"));\n    }\n\n    @Test\n    public void testLogin() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();\n        form.set(\"username\", \"admin\");\n        form.set(\"password\", \"admin\");\n        getCsrf(form, headers);\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/login\", HttpMethod.POST,\n                new HttpEntity<MultiValueMap<String, String>>(form, headers),\n                String.class);\n        assertEquals(HttpStatus.FOUND, entity.getStatusCode());\n        assertEquals(\"http://localhost:\" + this.port + \"/\", entity.getHeaders()\n                .getLocation().toString());\n    }\n\n    @Test\n    public void testDenied() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();\n        form.set(\"username\", \"user\");\n        form.set(\"password\", \"user\");\n        getCsrf(form, headers);\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/login\", HttpMethod.POST,\n                new HttpEntity<MultiValueMap<String, String>>(form, headers),\n                String.class);\n        assertEquals(HttpStatus.FOUND, entity.getStatusCode());\n        String cookie = entity.getHeaders().getFirst(\"Set-Cookie\");\n        headers.set(\"Cookie\", cookie);\n        ResponseEntity<String> page = new TestRestTemplate().exchange(entity.getHeaders()\n                .getLocation(), HttpMethod.GET, new HttpEntity<Void>(headers),\n                String.class);\n        assertEquals(HttpStatus.FORBIDDEN, page.getStatusCode());\n        assertTrue(\"Wrong body (message doesn't match):\\n\" + entity.getBody(), page\n                .getBody().contains(\"Access denied\"));\n    }\n\n    @Test\n    public void testManagementProtected() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/beans\", String.class);\n        assertEquals(HttpStatus.UNAUTHORIZED, entity.getStatusCode());\n    }\n\n    @Test\n    public void testManagementAuthorizedAccess() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate(\"admin\", \"admin\")\n                .getForEntity(\"http://localhost:\" + this.port + \"/beans\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n    }\n\n    @Test\n    public void testManagementUnauthorizedAccess() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate(\"user\", \"user\")\n                .getForEntity(\"http://localhost:\" + this.port + \"/beans\", String.class);\n        assertEquals(HttpStatus.FORBIDDEN, entity.getStatusCode());\n    }\n\n    private void getCsrf(MultiValueMap<String, String> form, HttpHeaders headers) {\n        ResponseEntity<String> page = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/login\", String.class);\n        String cookie = page.getHeaders().getFirst(\"Set-Cookie\");\n        headers.set(\"Cookie\", cookie);\n        String body = page.getBody();\n        Matcher matcher = Pattern.compile(\"(?s).*name=\\\"_csrf\\\".*?value=\\\"([^\\\"]+).*\")\n                .matcher(body);\n        matcher.find();\n        form.set(\"_csrf\", matcher.group(1));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-mustache/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-mustache:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-mustache/src/main/java/comsat/sample/mustache/SampleWebMustacheApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.mustache;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleWebMustacheApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleWebMustacheApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-mustache/src/main/java/comsat/sample/mustache/WelcomeController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.mustache;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@Controller\n@ConfigurationProperties\npublic class WelcomeController {\n    @Value(\"${application.message:Hello World}\")\n    private String message = \"Hello World\";\n\n    @RequestMapping(\"/\")\n    public String welcome(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"time\", new Date());\n        model.put(\"message\", this.message);\n        return \"welcome\";\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-mustache/src/main/resources/application.properties",
    "content": "application.message: Hello, Andy"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-mustache/src/main/resources/templates/error.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<body>\n\tSomething went wrong: {{status}} {{error}}\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-mustache/src/main/resources/templates/welcome.html",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<body>\n\tDate: {{time.date}}\n\t<br>\n\tTime: {{time.time}}\n\t<br>\n\tMessage: {{message}}\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-mustache/src/test/java/comsat/sample/mustache/SampleWebMustacheApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.mustache;\n\nimport java.util.Arrays;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for Mustache application.\n *\n * @author Phillip Webb\n * @author Andy Wilkinson\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebMustacheApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleWebMustacheApplicationTests {\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testMustacheTemplate() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"Hello, Andy\"));\n    }\n\n    @Test\n    public void testMustacheErrorTemplate() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        HttpEntity<String> requestEntity = new HttpEntity<String>(headers);\n\n        ResponseEntity<String> responseEntity = new TestRestTemplate().exchange(\"http://localhost:\" + this.port + \"/does-not-exist\", HttpMethod.GET, requestEntity, String.class);\n\n        assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + responseEntity.getBody(), responseEntity.getBody().contains(\"Something went wrong: 404 Not Found\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-security:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVer\"\n    compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n    compile project(\":comsat-spring:comsat-spring-boot-security\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure/src/main/java/comsat/sample/ui/secure/SampleWebSecureApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.secure;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.springframework.boot.security.autoconfigure.web.FiberSecureSpringBootApplication;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\nimport org.springframework.stereotype.Controller;\n\n@FiberSecureSpringBootApplication // This will enable fiber-blocking\n@Controller\npublic class SampleWebSecureApplication extends WebMvcConfigurerAdapter {\n    @RequestMapping(\"/\")\n    public String home(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"message\", \"Hello World\");\n        model.put(\"title\", \"Hello Home\");\n        model.put(\"date\", new Date());\n        return \"home\";\n    }\n\n    @RequestMapping(\"/foo\")\n    public String foo() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new RuntimeException(\"Expected exception in controller\");\n    }\n\n    public static void main(String[] args) throws Exception {\n        new SpringApplicationBuilder(SampleWebSecureApplication.class).run(args);\n    }\n\n    @Override\n    public void addViewControllers(ViewControllerRegistry registry) {\n        registry.addViewController(\"/login\").setViewName(\"login\");\n    }\n\n    @Configuration\n    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)\n    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {\n        @Autowired\n        private SecurityProperties security;\n\n        @Override\n        protected void configure(HttpSecurity http) throws Exception {\n            http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()\n                    .loginPage(\"/login\").failureUrl(\"/login?error\").permitAll();\n        }\n\n        @Override\n        public void configure(AuthenticationManagerBuilder auth) throws Exception {\n            auth.inMemoryAuthentication().withUser(\"admin\").password(\"admin\")\n                    .roles(\"ADMIN\", \"USER\").and().withUser(\"user\").password(\"user\")\n                    .roles(\"USER\");\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure/src/main/resources/application.properties",
    "content": "spring.thymeleaf.cache: false\nsecurity.basic.enabled: false\n# demo only:\nsecurity.user.password: password\nlogging.level.org.springframework.security: INFO"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure/src/main/resources/schema.sql",
    "content": "create table users (\n  username varchar(256),\n  password varchar(256),\n  enabled boolean\n);\n\ncreate table authorities (\n  username varchar(256),\n  authority varchar(256)\n);"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure/src/main/resources/templates/error.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Error</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<div id=\"created\" th:text=\"${#dates.format(timestamp)}\">July 11,\n\t\t\t2012 2:17:16 PM CDT</div>\n\t\t<div>\n\t\t\tThere was an unexpected error (type=<span th:text=\"${error}\">Bad</span>, status=<span th:text=\"${status}\">500</span>).\n\t\t</div>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div>\n\t\t\tPlease contact the operator with the above information.\n\t\t</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure/src/main/resources/templates/home.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title th:text=\"${title}\">Title</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div id=\"created\" th:text=\"${#dates.format(date)}\">July 11,\n\t\t\t2012 2:17:16 PM CDT</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure/src/main/resources/templates/login.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Login</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body onload=\"document.f.username.focus();\">\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"content\">\n\t\t\t<p th:if=\"${param.logout}\" class=\"alert\">You have been logged out</p>\n\t\t\t<p th:if=\"${param.error}\" class=\"alert alert-error\">There was an error, please try again</p>\n\t\t\t<h2>Login with Username and Password</h2>\n\t\t\t<form name=\"form\" th:action=\"@{/login}\" action=\"/login\" method=\"POST\">\n\t\t\t\t<fieldset>\n\t\t\t\t\t<input type=\"text\" name=\"username\" value=\"\" placeholder=\"Username\" />\n\t\t\t\t\t<input type=\"password\" name=\"password\" placeholder=\"Password\" />\n\t\t\t\t</fieldset>\n\t\t\t\t<input type=\"submit\" id=\"login\" value=\"Login\"\n\t\t\t\t\tclass=\"btn btn-primary\" />\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</body>\n</html>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure/src/test/java/comsat/sample/ui/secure/SampleSecureApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.secure;\n\nimport java.util.Arrays;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebSecureApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleSecureApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port, HttpMethod.GET, new HttpEntity<Void>(\n                        headers), String.class);\n        assertEquals(HttpStatus.FOUND, entity.getStatusCode());\n        assertTrue(\"Wrong location:\\n\" + entity.getHeaders(), entity.getHeaders()\n                .getLocation().toString().endsWith(port + \"/login\"));\n    }\n\n    @Test\n    public void testLoginPage() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/login\", HttpMethod.GET,\n                new HttpEntity<Void>(headers), String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong content:\\n\" + entity.getBody(),\n                entity.getBody().contains(\"_csrf\"));\n    }\n\n    @Test\n    public void testLogin() throws Exception {\n        HttpHeaders headers = getHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);\n        MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();\n        form.set(\"username\", \"user\");\n        form.set(\"password\", \"user\");\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/login\", HttpMethod.POST,\n                new HttpEntity<MultiValueMap<String, String>>(form, headers),\n                String.class);\n        assertEquals(HttpStatus.FOUND, entity.getStatusCode());\n        assertTrue(\"Wrong location:\\n\" + entity.getHeaders(), entity.getHeaders()\n                .getLocation().toString().endsWith(port + \"/\"));\n        assertNotNull(\"Missing cookie:\\n\" + entity.getHeaders(),\n                entity.getHeaders().get(\"Set-Cookie\"));\n    }\n\n    private HttpHeaders getHeaders() {\n        HttpHeaders headers = new HttpHeaders();\n        ResponseEntity<String> page = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/login\", String.class);\n        assertEquals(HttpStatus.OK, page.getStatusCode());\n        String cookie = page.getHeaders().getFirst(\"Set-Cookie\");\n        headers.set(\"Cookie\", cookie);\n        Matcher matcher = Pattern.compile(\"(?s).*name=\\\"_csrf\\\".*?value=\\\"([^\\\"]+).*\")\n                .matcher(page.getBody());\n        assertTrue(\"No csrf token: \" + page.getBody(), matcher.matches());\n        headers.set(\"X-CSRF-TOKEN\", matcher.group(1));\n        return headers;\n    }\n\n    @Test\n    public void testCss() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/css/bootstrap.min.css\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"body\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-custom/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-security:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVer\"\n    compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n    compile project(\":comsat-spring:comsat-spring-boot-security\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-custom/src/main/java/comsat/sample/ui/secure/SampleWebSecureCustomApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.secure;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.springframework.boot.security.autoconfigure.web.FiberSecureSpringBootApplication;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\n\n@FiberSecureSpringBootApplication // This will enable fiber-blocking\n@Controller\npublic class SampleWebSecureCustomApplication extends WebMvcConfigurerAdapter {\n    @RequestMapping(\"/\")\n    public String home(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"message\", \"Hello World\");\n        model.put(\"title\", \"Hello Home\");\n        model.put(\"date\", new Date());\n        return \"home\";\n    }\n\n    @RequestMapping(\"/foo\")\n    public String foo() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new RuntimeException(\"Expected exception in controller\");\n    }\n\n    public static void main(String[] args) throws Exception {\n        new SpringApplicationBuilder(SampleWebSecureCustomApplication.class).run(args);\n    }\n\n    @Override\n    public void addViewControllers(ViewControllerRegistry registry) {\n        registry.addViewController(\"/login\").setViewName(\"login\");\n    }\n\n    @Bean\n    public ApplicationSecurity applicationSecurity() {\n        return new ApplicationSecurity();\n    }\n\n    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)\n    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {\n        @Autowired\n        private SecurityProperties security;\n\n        @Override\n        protected void configure(HttpSecurity http) throws Exception {\n            http.authorizeRequests().antMatchers(\"/css/**\").permitAll().anyRequest()\n                    .fullyAuthenticated().and().formLogin().loginPage(\"/login\")\n                    .failureUrl(\"/login?error\").permitAll();\n        }\n\n        @Override\n        public void configure(AuthenticationManagerBuilder auth) throws Exception {\n            auth.inMemoryAuthentication().withUser(\"user\").password(\"user\").roles(\"USER\");\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-custom/src/main/resources/application.properties",
    "content": "spring.thymeleaf.cache: false\nsecurity.basic.enabled: false\nlogging.level.org.springframework.security: INFO"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-custom/src/main/resources/templates/error.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Error</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<div id=\"created\" th:text=\"${#dates.format(timestamp)}\">July 11,\n\t\t\t2012 2:17:16 PM CDT</div>\n\t\t<div>\n\t\t\tThere was an unexpected error (type=<span th:text=\"${error}\">Bad</span>, status=<span th:text=\"${status}\">500</span>).\n\t\t</div>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div>\n\t\t\tPlease contact the operator with the above information.\n\t\t</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-custom/src/main/resources/templates/home.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title th:text=\"${title}\">Title</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div id=\"created\" th:text=\"${#dates.format(date)}\">July 11,\n\t\t\t2012 2:17:16 PM CDT</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-custom/src/main/resources/templates/login.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Login</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body onload=\"document.f.username.focus();\">\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"content\">\n\t\t\t<p th:if=\"${param.logout}\" class=\"alert\">You have been logged out</p>\n\t\t\t<p th:if=\"${param.error}\" class=\"alert alert-error\">There was an error, please try again</p>\n\t\t\t<h2>Login with Username and Password</h2>\n\t\t\t<form name=\"form\" th:action=\"@{/login}\" action=\"/login\" method=\"POST\">\n\t\t\t\t<fieldset>\n\t\t\t\t\t<input type=\"text\" name=\"username\" value=\"\" placeholder=\"Username\" />\n\t\t\t\t\t<input type=\"password\" name=\"password\" placeholder=\"Password\" />\n\t\t\t\t</fieldset>\n\t\t\t\t<input type=\"submit\" id=\"login\" value=\"Login\"\n\t\t\t\t\tclass=\"btn btn-primary\" />\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</body>\n</html>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-custom/src/test/java/comsat/sample/ui/secure/SampleWebSecureCustomApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.secure;\n\nimport java.util.Arrays;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebSecureCustomApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleWebSecureCustomApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port, HttpMethod.GET, new HttpEntity<Void>(\n                        headers), String.class);\n        assertEquals(HttpStatus.FOUND, entity.getStatusCode());\n        assertTrue(\"Wrong location:\\n\" + entity.getHeaders(), entity.getHeaders()\n                .getLocation().toString().endsWith(port + \"/login\"));\n    }\n\n    @Test\n    public void testLoginPage() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/login\", HttpMethod.GET,\n                new HttpEntity<Void>(headers), String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong content:\\n\" + entity.getBody(),\n                entity.getBody().contains(\"_csrf\"));\n    }\n\n    @Test\n    public void testLogin() throws Exception {\n        HttpHeaders headers = getHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);\n        MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();\n        form.set(\"username\", \"user\");\n        form.set(\"password\", \"user\");\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/login\", HttpMethod.POST,\n                new HttpEntity<MultiValueMap<String, String>>(form, headers),\n                String.class);\n        assertEquals(HttpStatus.FOUND, entity.getStatusCode());\n        assertTrue(\"Wrong location:\\n\" + entity.getHeaders(), entity.getHeaders()\n                .getLocation().toString().endsWith(port + \"/\"));\n        assertNotNull(\"Missing cookie:\\n\" + entity.getHeaders(),\n                entity.getHeaders().get(\"Set-Cookie\"));\n    }\n\n    private HttpHeaders getHeaders() {\n        HttpHeaders headers = new HttpHeaders();\n        ResponseEntity<String> page = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/login\", String.class);\n        assertEquals(HttpStatus.OK, page.getStatusCode());\n        String cookie = page.getHeaders().getFirst(\"Set-Cookie\");\n        headers.set(\"Cookie\", cookie);\n        Matcher matcher = Pattern.compile(\"(?s).*name=\\\"_csrf\\\".*?value=\\\"([^\\\"]+).*\")\n                .matcher(page.getBody());\n        assertTrue(\"No csrf token: \" + page.getBody(), matcher.matches());\n        headers.set(\"X-CSRF-TOKEN\", matcher.group(1));\n        return headers;\n    }\n\n    @Test\n    public void testCss() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/css/bootstrap.min.css\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"body\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-security:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-jdbc:$springBootVer\"\n    compile \"org.apache.httpcomponents:httpclient:$httpClientVer\"\n    compile \"com.h2database:h2:$h2Ver\"\n    compile project(\":comsat-spring:comsat-spring-boot-security\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/src/main/java/comsat/sample/ui/secure/SampleWebSecureCustomApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.secure;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.springframework.boot.security.autoconfigure.web.FiberSecureSpringBootApplication;\nimport java.util.Date;\nimport java.util.Map;\n\nimport javax.sql.DataSource;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.autoconfigure.security.SecurityProperties;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\n\n@FiberSecureSpringBootApplication // This will enable fiber-blocking\n@Controller\npublic class SampleWebSecureCustomApplication extends WebMvcConfigurerAdapter {\n    @RequestMapping(\"/\")\n    public String home(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"message\", \"Hello World\");\n        model.put(\"title\", \"Hello Home\");\n        model.put(\"date\", new Date());\n        return \"home\";\n    }\n\n    @RequestMapping(\"/foo\")\n    public String foo() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new RuntimeException(\"Expected exception in controller\");\n    }\n\n    public static void main(String[] args) throws Exception {\n        new SpringApplicationBuilder(SampleWebSecureCustomApplication.class).run(args);\n    }\n\n    @Override\n    public void addViewControllers(ViewControllerRegistry registry) {\n        registry.addViewController(\"/login\").setViewName(\"login\");\n    }\n\n    @Bean\n    public ApplicationSecurity applicationSecurity() {\n        return new ApplicationSecurity();\n    }\n\n    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)\n    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {\n        @Autowired\n        private SecurityProperties security;\n\n        @Autowired\n        private DataSource dataSource;\n\n        @Override\n        protected void configure(HttpSecurity http) throws Exception {\n            http.authorizeRequests().antMatchers(\"/css/**\").permitAll().anyRequest()\n                    .fullyAuthenticated().and().formLogin().loginPage(\"/login\")\n                    .failureUrl(\"/login?error\").permitAll();\n        }\n\n        @Override\n        public void configure(AuthenticationManagerBuilder auth) throws Exception {\n            auth.jdbcAuthentication().dataSource(this.dataSource);\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/src/main/resources/application.properties",
    "content": "debug: true\nspring.thymeleaf.cache: false\nsecurity.basic.enabled: false\nlogging.level.org.springframework.security: INFO"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/src/main/resources/data.sql",
    "content": "insert into users (username, password, enabled) values ('user', 'user', true);\n\ninsert into authorities (username, authority) values ('user', 'ROLE_ADMIN');"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/src/main/resources/schema.sql",
    "content": "create table users (\n  username varchar(256),\n  password varchar(256),\n  enabled boolean\n);\n\ncreate table authorities (\n  username varchar(256),\n  authority varchar(256)\n);"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/src/main/resources/templates/error.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Error</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<div id=\"created\" th:text=\"${#dates.format(timestamp)}\">July 11,\n\t\t\t2012 2:17:16 PM CDT</div>\n\t\t<div>\n\t\t\tThere was an unexpected error (type=<span th:text=\"${error}\">Bad</span>, status=<span th:text=\"${status}\">500</span>).\n\t\t</div>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div>\n\t\t\tPlease contact the operator with the above information.\n\t\t</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/src/main/resources/templates/home.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title th:text=\"${title}\">Title</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body>\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t\t<li><a th:href=\"@{/logout}\" href=\"logout\"> Logout </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<h1 th:text=\"${title}\">Title</h1>\n\t\t<div th:text=\"${message}\">Fake content</div>\n\t\t<div id=\"created\" th:text=\"${#dates.format(date)}\">July 11,\n\t\t\t2012 2:17:16 PM CDT</div>\n\t</div>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/src/main/resources/templates/login.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n<title>Login</title>\n<link rel=\"stylesheet\" th:href=\"@{/css/bootstrap.min.css}\"\n\thref=\"../../css/bootstrap.min.css\" />\n</head>\n<body onload=\"document.f.username.focus();\">\n\t<div class=\"container\">\n\t\t<div class=\"navbar\">\n\t\t\t<div class=\"navbar-inner\">\n\t\t\t\t<a class=\"brand\" href=\"http://www.thymeleaf.org\"> Thymeleaf -\n\t\t\t\t\tPlain </a>\n\t\t\t\t<ul class=\"nav\">\n\t\t\t\t\t<li><a th:href=\"@{/}\" href=\"home.html\"> Home </a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"content\">\n\t\t\t<p th:if=\"${param.logout}\" class=\"alert\">You have been logged out</p>\n\t\t\t<p th:if=\"${param.error}\" class=\"alert alert-error\">There was an error, please try again</p>\n\t\t\t<h2>Login with Username and Password</h2>\n\t\t\t<form name=\"form\" th:action=\"@{/login}\" action=\"/login\" method=\"POST\">\n\t\t\t\t<fieldset>\n\t\t\t\t\t<input type=\"text\" name=\"username\" value=\"\" placeholder=\"Username\" />\n\t\t\t\t\t<input type=\"password\" name=\"password\" placeholder=\"Password\" />\n\t\t\t\t</fieldset>\n\t\t\t\t<input type=\"submit\" id=\"login\" value=\"Login\"\n\t\t\t\t\tclass=\"btn btn-primary\" />\n\t\t\t</form>\n\t\t</div>\n\t</div>\n</body>\n</html>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-secure-jdbc/src/test/java/comsat/sample/ui/secure/SampleWebSecureCustomApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.secure;\n\nimport java.util.Arrays;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebSecureCustomApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleWebSecureCustomApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port, HttpMethod.GET, new HttpEntity<Void>(\n                        headers), String.class);\n        assertEquals(HttpStatus.FOUND, entity.getStatusCode());\n        assertTrue(\"Wrong location:\\n\" + entity.getHeaders(), entity.getHeaders()\n                .getLocation().toString().endsWith(port + \"/login\"));\n    }\n\n    @Test\n    public void testLoginPage() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/login\", HttpMethod.GET,\n                new HttpEntity<Void>(headers), String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong content:\\n\" + entity.getBody(),\n                entity.getBody().contains(\"_csrf\"));\n    }\n\n    @Test\n    public void testLogin() throws Exception {\n        HttpHeaders headers = getHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);\n        MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();\n        form.set(\"username\", \"user\");\n        form.set(\"password\", \"user\");\n        ResponseEntity<String> entity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/login\", HttpMethod.POST,\n                new HttpEntity<MultiValueMap<String, String>>(form, headers),\n                String.class);\n        assertEquals(HttpStatus.FOUND, entity.getStatusCode());\n        assertTrue(\"Wrong location:\\n\" + entity.getHeaders(), entity.getHeaders()\n                .getLocation().toString().endsWith(port + \"/\"));\n        assertNotNull(\"Missing cookie:\\n\" + entity.getHeaders(),\n                entity.getHeaders().get(\"Set-Cookie\"));\n    }\n\n    private HttpHeaders getHeaders() {\n        HttpHeaders headers = new HttpHeaders();\n        ResponseEntity<String> page = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/login\", String.class);\n        assertEquals(HttpStatus.OK, page.getStatusCode());\n        String cookie = page.getHeaders().getFirst(\"Set-Cookie\");\n        headers.set(\"Cookie\", cookie);\n        Matcher matcher = Pattern.compile(\"(?s).*name=\\\"_csrf\\\".*?value=\\\"([^\\\"]+).*\")\n                .matcher(page.getBody());\n        assertTrue(\"No csrf token: \" + page.getBody(), matcher.matches());\n        headers.set(\"X-CSRF-TOKEN\", matcher.group(1));\n        return headers;\n    }\n\n    @Test\n    public void testCss() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/css/bootstrap.min.css\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"body\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-static/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n    compile \"org.springframework.boot:spring-boot-starter-actuator:$springBootVer\"\n    compile \"org.webjars:bootstrap:$bootstrapVer\"\n    compile \"org.webjars:jquery:$jqueryVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-static/src/main/java/comsat/sample/ui/SampleWebStaticApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.boot.context.web.SpringBootServletInitializer;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleWebStaticApplication extends SpringBootServletInitializer {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleWebStaticApplication.class, args);\n    }\n\n    @Override\n    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {\n        return application.sources(SampleWebStaticApplication.class);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-static/src/main/webapp/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<title>Static</title>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<link rel=\"stylesheet\" type=\"text/css\"\n\thref=\"/webjars/bootstrap/3.0.3/css/bootstrap.min.css\" />\n</head>\n<body>\n\t<script type=\"text/javascript\"\n\t\tsrc=\"/webjars/jquery/2.0.3/jquery.min.js\"></script>\n\t<div id=\"navbar\" class=\"navbar navbar-default\" role=\"navigation\">\n\t\t<div class=\"navbar-header\">\n\t\t\t<button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\"\n\t\t\t\tdata-target=\".navbar-collapse\">\n\t\t\t\t<span class=\"icon-bar\"></span> <span class=\"icon-bar\"></span> <span\n\t\t\t\t\tclass=\"icon-bar\"></span>\n\t\t\t</button>\n\t\t\t<a class=\"navbar-brand\"\n\t\t\t\thref=\"https://github.com/spring-projects/spring-boot\"> Spring Boot\n\t\t\t</a>\n\t\t</div>\n\t\t<div class=\"navbar-collapse collapse\">\n\t\t\t<ul class=\"nav navbar-nav\">\n\t\t\t\t<li><a href=\"/\"> Home </a></li>\n\t\t\t</ul>\n\t\t</div>\n\t</div>\n\t<div class=\"jumbotron\">\n\t\t<h1>Home</h1>\n\t\t<p>Some static content</p>\n\t\t<p>\n          <a class=\"btn btn-lg btn-primary\" href=\"#navbar\" role=\"button\">Go &raquo;</a>\n        </p>\n\t</div>\n\t<script type=\"text/javascript\"\n\t\tsrc=\"/webjars/bootstrap/3.0.3/js/bootstrap.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-static/src/test/java/comsat/sample/ui/SampleWebStaticApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport comsat.sample.ui.SampleWebStaticApplication;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebStaticApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleWebStaticApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port = 0;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body (title doesn't match):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"<title>Static\"));\n    }\n\n    @Test\n    public void testCss() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port\n                + \"/webjars/bootstrap/3.3.5/css/bootstrap.min.css\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"body\"));\n        assertEquals(\"Wrong content type:\\n\" + entity.getHeaders().getContentType(),\n                MediaType.valueOf(\"text/css;charset=UTF-8\"), entity.getHeaders().getContentType());\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVer\"\n    compile \"org.hibernate:hibernate-validator:$hibernateValidatorVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/java/comsat/sample/ui/InMemoryMessageRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Dave Syer.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * @author Dave Syer\n */\npublic class InMemoryMessageRepository implements MessageRepository {\n\n    private static AtomicLong counter = new AtomicLong();\n\n    private final ConcurrentMap<Long, Message> messages = new ConcurrentHashMap<Long, Message>();\n\n    @Override\n    public Iterable<Message> findAll() {\n        return this.messages.values();\n    }\n\n    @Override\n    public Message save(Message message) {\n        Long id = message.getId();\n        if (id == null) {\n            id = counter.incrementAndGet();\n            message.setId(id);\n        }\n        this.messages.put(id, message);\n        return message;\n    }\n\n    @Override\n    public Message findMessage(Long id) {\n        return this.messages.get(id);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/java/comsat/sample/ui/Message.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Rob Winch.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport java.util.Calendar;\n\nimport org.hibernate.validator.constraints.NotEmpty;\n\n/**\n * @author Rob Winch\n */\npublic class Message {\n\n    private Long id;\n\n    @NotEmpty(message = \"Message is required.\")\n    private String text;\n\n    @NotEmpty(message = \"Summary is required.\")\n    private String summary;\n\n    private Calendar created = Calendar.getInstance();\n\n    public Long getId() {\n        return this.id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public Calendar getCreated() {\n        return this.created;\n    }\n\n    public void setCreated(Calendar created) {\n        this.created = created;\n    }\n\n    public String getText() {\n        return this.text;\n    }\n\n    public void setText(String text) {\n        this.text = text;\n    }\n\n    public String getSummary() {\n        return this.summary;\n    }\n\n    public void setSummary(String summary) {\n        this.summary = summary;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/java/comsat/sample/ui/MessageRepository.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Rob Winch.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\n/**\n * @author Rob Winch\n */\npublic interface MessageRepository {\n\n    Iterable<Message> findAll();\n\n    Message save(Message message);\n\n    Message findMessage(Long id);\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/java/comsat/sample/ui/SampleWebUiApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Rob Winch.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.core.convert.converter.Converter;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleWebUiApplication {\n    @Bean\n    public MessageRepository messageRepository() {\n        return new InMemoryMessageRepository();\n    }\n\n    @Bean\n    public Converter<String, Message> messageConverter() {\n        return new Converter<String, Message>() {\n            @Override\n            public Message convert(String id) {\n                return messageRepository().findMessage(Long.valueOf(id));\n            }\n        };\n    }\n\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleWebUiApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/java/comsat/sample/ui/mvc/MessageController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author Rob Winch.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui.mvc;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport javax.validation.Valid;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.validation.BindingResult;\nimport org.springframework.web.bind.annotation.ModelAttribute;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.servlet.mvc.support.RedirectAttributes;\n\nimport comsat.sample.ui.Message;\nimport comsat.sample.ui.MessageRepository;\n\n/**\n * @author Rob Winch\n */\n@Controller\n@RequestMapping(\"/\")\npublic class MessageController {\n\n    private final MessageRepository messageRepository;\n\n    @Autowired\n    public MessageController(MessageRepository messageRepository) {\n        this.messageRepository = messageRepository;\n    }\n\n    @RequestMapping\n    public ModelAndView list() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        Iterable<Message> messages = this.messageRepository.findAll();\n        return new ModelAndView(\"messages/list\", \"messages\", messages);\n    }\n\n    @RequestMapping(\"{id}\")\n    public ModelAndView view(@PathVariable(\"id\") Message message) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return new ModelAndView(\"messages/view\", \"message\", message);\n    }\n\n    @RequestMapping(params = \"form\", method = RequestMethod.GET)\n    public String createForm(@ModelAttribute Message message) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        return \"messages/form\";\n    }\n\n    @RequestMapping(method = RequestMethod.POST)\n    public ModelAndView create(@Valid Message message, BindingResult result,\n            RedirectAttributes redirect) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        if (result.hasErrors()) {\n            return new ModelAndView(\"messages/form\", \"formErrors\", result.getAllErrors());\n        }\n        message = this.messageRepository.save(message);\n        redirect.addFlashAttribute(\"globalMessage\", \"Successfully created a new message\");\n        return new ModelAndView(\"redirect:/{message.id}\", \"message.id\", message.getId());\n    }\n\n    @RequestMapping(\"foo\")\n    public String foo() throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        throw new RuntimeException(\"Expected exception in controller\");\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/resources/application.properties",
    "content": "# Allow Thymeleaf templates to be reloaded at dev time\nspring.thymeleaf.cache: false\nserver.tomcat.access_log_enabled: true\nserver.tomcat.basedir: target/tomcat"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/resources/logback.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n\n\t<include resource=\"org/springframework/boot/logging/logback/base.xml\"/>\n\n\t<!-- logger name=\"org.springframework\" level=\"DEBUG\"/-->\n\n</configuration>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/resources/static/js/jquery-1.7.2.js",
    "content": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under the MIT or GPL Version 2 licenses.\n * http://jquery.org/license\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n * Copyright 2011, The Dojo Foundation\n * Released under the MIT, BSD, and GPL Licenses.\n *\n * Date: Wed Mar 21 12:46:34 2012 -0700\n */\n(function( window, undefined ) {\n\n// Use the correct document accordingly with window argument (sandbox)\nvar document = window.document,\n  navigator = window.navigator,\n  location = window.location;\nvar jQuery = (function() {\n\n// Define a local copy of jQuery\nvar jQuery = function( selector, context ) {\n    // The jQuery object is actually just the init constructor 'enhanced'\n    return new jQuery.fn.init( selector, context, rootjQuery );\n  },\n\n  // Map over jQuery in case of overwrite\n  _jQuery = window.jQuery,\n\n  // Map over the $ in case of overwrite\n  _$ = window.$,\n\n  // A central reference to the root jQuery(document)\n  rootjQuery,\n\n  // A simple way to check for HTML strings or ID strings\n  // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n  quickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n  // Check if a string has a non-whitespace character in it\n  rnotwhite = /\\S/,\n\n  // Used for trimming whitespace\n  trimLeft = /^\\s+/,\n  trimRight = /\\s+$/,\n\n  // Match a standalone tag\n  rsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,\n\n  // JSON RegExp\n  rvalidchars = /^[\\],:{}\\s]*$/,\n  rvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\n  rvalidtokens = /\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\n  rvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\n  // Useragent RegExp\n  rwebkit = /(webkit)[ \\/]([\\w.]+)/,\n  ropera = /(opera)(?:.*version)?[ \\/]([\\w.]+)/,\n  rmsie = /(msie) ([\\w.]+)/,\n  rmozilla = /(mozilla)(?:.*? rv:([\\w.]+))?/,\n\n  // Matches dashed string for camelizing\n  rdashAlpha = /-([a-z]|[0-9])/ig,\n  rmsPrefix = /^-ms-/,\n\n  // Used by jQuery.camelCase as callback to replace()\n  fcamelCase = function( all, letter ) {\n    return ( letter + \"\" ).toUpperCase();\n  },\n\n  // Keep a UserAgent string for use with jQuery.browser\n  userAgent = navigator.userAgent,\n\n  // For matching the engine and version of the browser\n  browserMatch,\n\n  // The deferred used on DOM ready\n  readyList,\n\n  // The ready event handler\n  DOMContentLoaded,\n\n  // Save a reference to some core methods\n  toString = Object.prototype.toString,\n  hasOwn = Object.prototype.hasOwnProperty,\n  push = Array.prototype.push,\n  slice = Array.prototype.slice,\n  trim = String.prototype.trim,\n  indexOf = Array.prototype.indexOf,\n\n  // [[Class]] -> type pairs\n  class2type = {};\n\njQuery.fn = jQuery.prototype = {\n  constructor: jQuery,\n  init: function( selector, context, rootjQuery ) {\n    var match, elem, ret, doc;\n\n    // Handle $(\"\"), $(null), or $(undefined)\n    if ( !selector ) {\n      return this;\n    }\n\n    // Handle $(DOMElement)\n    if ( selector.nodeType ) {\n      this.context = this[0] = selector;\n      this.length = 1;\n      return this;\n    }\n\n    // The body element only exists once, optimize finding it\n    if ( selector === \"body\" && !context && document.body ) {\n      this.context = document;\n      this[0] = document.body;\n      this.selector = selector;\n      this.length = 1;\n      return this;\n    }\n\n    // Handle HTML strings\n    if ( typeof selector === \"string\" ) {\n      // Are we dealing with HTML string or an ID?\n      if ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n        // Assume that strings that start and end with <> are HTML and skip the regex check\n        match = [ null, selector, null ];\n\n      } else {\n        match = quickExpr.exec( selector );\n      }\n\n      // Verify a match, and that no context was specified for #id\n      if ( match && (match[1] || !context) ) {\n\n        // HANDLE: $(html) -> $(array)\n        if ( match[1] ) {\n          context = context instanceof jQuery ? context[0] : context;\n          doc = ( context ? context.ownerDocument || context : document );\n\n          // If a single string is passed in and it's a single tag\n          // just do a createElement and skip the rest\n          ret = rsingleTag.exec( selector );\n\n          if ( ret ) {\n            if ( jQuery.isPlainObject( context ) ) {\n              selector = [ document.createElement( ret[1] ) ];\n              jQuery.fn.attr.call( selector, context, true );\n\n            } else {\n              selector = [ doc.createElement( ret[1] ) ];\n            }\n\n          } else {\n            ret = jQuery.buildFragment( [ match[1] ], [ doc ] );\n            selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;\n          }\n\n          return jQuery.merge( this, selector );\n\n        // HANDLE: $(\"#id\")\n        } else {\n          elem = document.getElementById( match[2] );\n\n          // Check parentNode to catch when Blackberry 4.6 returns\n          // nodes that are no longer in the document #6963\n          if ( elem && elem.parentNode ) {\n            // Handle the case where IE and Opera return items\n            // by name instead of ID\n            if ( elem.id !== match[2] ) {\n              return rootjQuery.find( selector );\n            }\n\n            // Otherwise, we inject the element directly into the jQuery object\n            this.length = 1;\n            this[0] = elem;\n          }\n\n          this.context = document;\n          this.selector = selector;\n          return this;\n        }\n\n      // HANDLE: $(expr, $(...))\n      } else if ( !context || context.jquery ) {\n        return ( context || rootjQuery ).find( selector );\n\n      // HANDLE: $(expr, context)\n      // (which is just equivalent to: $(context).find(expr)\n      } else {\n        return this.constructor( context ).find( selector );\n      }\n\n    // HANDLE: $(function)\n    // Shortcut for document ready\n    } else if ( jQuery.isFunction( selector ) ) {\n      return rootjQuery.ready( selector );\n    }\n\n    if ( selector.selector !== undefined ) {\n      this.selector = selector.selector;\n      this.context = selector.context;\n    }\n\n    return jQuery.makeArray( selector, this );\n  },\n\n  // Start with an empty selector\n  selector: \"\",\n\n  // The current version of jQuery being used\n  jquery: \"1.7.2\",\n\n  // The default length of a jQuery object is 0\n  length: 0,\n\n  // The number of elements contained in the matched element set\n  size: function() {\n    return this.length;\n  },\n\n  toArray: function() {\n    return slice.call( this, 0 );\n  },\n\n  // Get the Nth element in the matched element set OR\n  // Get the whole matched element set as a clean array\n  get: function( num ) {\n    return num == null ?\n\n      // Return a 'clean' array\n      this.toArray() :\n\n      // Return just the object\n      ( num < 0 ? this[ this.length + num ] : this[ num ] );\n  },\n\n  // Take an array of elements and push it onto the stack\n  // (returning the new matched element set)\n  pushStack: function( elems, name, selector ) {\n    // Build a new jQuery matched element set\n    var ret = this.constructor();\n\n    if ( jQuery.isArray( elems ) ) {\n      push.apply( ret, elems );\n\n    } else {\n      jQuery.merge( ret, elems );\n    }\n\n    // Add the old object onto the stack (as a reference)\n    ret.prevObject = this;\n\n    ret.context = this.context;\n\n    if ( name === \"find\" ) {\n      ret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n    } else if ( name ) {\n      ret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n    }\n\n    // Return the newly-formed element set\n    return ret;\n  },\n\n  // Execute a callback for every element in the matched set.\n  // (You can seed the arguments with an array of args, but this is\n  // only used internally.)\n  each: function( callback, args ) {\n    return jQuery.each( this, callback, args );\n  },\n\n  ready: function( fn ) {\n    // Attach the listeners\n    jQuery.bindReady();\n\n    // Add the callback\n    readyList.add( fn );\n\n    return this;\n  },\n\n  eq: function( i ) {\n    i = +i;\n    return i === -1 ?\n      this.slice( i ) :\n      this.slice( i, i + 1 );\n  },\n\n  first: function() {\n    return this.eq( 0 );\n  },\n\n  last: function() {\n    return this.eq( -1 );\n  },\n\n  slice: function() {\n    return this.pushStack( slice.apply( this, arguments ),\n      \"slice\", slice.call(arguments).join(\",\") );\n  },\n\n  map: function( callback ) {\n    return this.pushStack( jQuery.map(this, function( elem, i ) {\n      return callback.call( elem, i, elem );\n    }));\n  },\n\n  end: function() {\n    return this.prevObject || this.constructor(null);\n  },\n\n  // For internal use only.\n  // Behaves like an Array's method, not like a jQuery method.\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n  var options, name, src, copy, copyIsArray, clone,\n    target = arguments[0] || {},\n    i = 1,\n    length = arguments.length,\n    deep = false;\n\n  // Handle a deep copy situation\n  if ( typeof target === \"boolean\" ) {\n    deep = target;\n    target = arguments[1] || {};\n    // skip the boolean and the target\n    i = 2;\n  }\n\n  // Handle case when target is a string or something (possible in deep copy)\n  if ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n    target = {};\n  }\n\n  // extend jQuery itself if only one argument is passed\n  if ( length === i ) {\n    target = this;\n    --i;\n  }\n\n  for ( ; i < length; i++ ) {\n    // Only deal with non-null/undefined values\n    if ( (options = arguments[ i ]) != null ) {\n      // Extend the base object\n      for ( name in options ) {\n        src = target[ name ];\n        copy = options[ name ];\n\n        // Prevent never-ending loop\n        if ( target === copy ) {\n          continue;\n        }\n\n        // Recurse if we're merging plain objects or arrays\n        if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n          if ( copyIsArray ) {\n            copyIsArray = false;\n            clone = src && jQuery.isArray(src) ? src : [];\n\n          } else {\n            clone = src && jQuery.isPlainObject(src) ? src : {};\n          }\n\n          // Never move original objects, clone them\n          target[ name ] = jQuery.extend( deep, clone, copy );\n\n        // Don't bring in undefined values\n        } else if ( copy !== undefined ) {\n          target[ name ] = copy;\n        }\n      }\n    }\n  }\n\n  // Return the modified object\n  return target;\n};\n\njQuery.extend({\n  noConflict: function( deep ) {\n    if ( window.$ === jQuery ) {\n      window.$ = _$;\n    }\n\n    if ( deep && window.jQuery === jQuery ) {\n      window.jQuery = _jQuery;\n    }\n\n    return jQuery;\n  },\n\n  // Is the DOM ready to be used? Set to true once it occurs.\n  isReady: false,\n\n  // A counter to track how many items to wait for before\n  // the ready event fires. See #6781\n  readyWait: 1,\n\n  // Hold (or release) the ready event\n  holdReady: function( hold ) {\n    if ( hold ) {\n      jQuery.readyWait++;\n    } else {\n      jQuery.ready( true );\n    }\n  },\n\n  // Handle when the DOM is ready\n  ready: function( wait ) {\n    // Either a released hold or an DOMready/load event and not yet ready\n    if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {\n      // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n      if ( !document.body ) {\n        return setTimeout( jQuery.ready, 1 );\n      }\n\n      // Remember that the DOM is ready\n      jQuery.isReady = true;\n\n      // If a normal DOM Ready event fired, decrement, and wait if need be\n      if ( wait !== true && --jQuery.readyWait > 0 ) {\n        return;\n      }\n\n      // If there are functions bound, to execute\n      readyList.fireWith( document, [ jQuery ] );\n\n      // Trigger any bound ready events\n      if ( jQuery.fn.trigger ) {\n        jQuery( document ).trigger( \"ready\" ).off( \"ready\" );\n      }\n    }\n  },\n\n  bindReady: function() {\n    if ( readyList ) {\n      return;\n    }\n\n    readyList = jQuery.Callbacks( \"once memory\" );\n\n    // Catch cases where $(document).ready() is called after the\n    // browser event has already occurred.\n    if ( document.readyState === \"complete\" ) {\n      // Handle it asynchronously to allow scripts the opportunity to delay ready\n      return setTimeout( jQuery.ready, 1 );\n    }\n\n    // Mozilla, Opera and webkit nightlies currently support this event\n    if ( document.addEventListener ) {\n      // Use the handy event callback\n      document.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n      // A fallback to window.onload, that will always work\n      window.addEventListener( \"load\", jQuery.ready, false );\n\n    // If IE event model is used\n    } else if ( document.attachEvent ) {\n      // ensure firing before onload,\n      // maybe late but safe also for iframes\n      document.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n      // A fallback to window.onload, that will always work\n      window.attachEvent( \"onload\", jQuery.ready );\n\n      // If IE and not a frame\n      // continually check to see if the document is ready\n      var toplevel = false;\n\n      try {\n        toplevel = window.frameElement == null;\n      } catch(e) {}\n\n      if ( document.documentElement.doScroll && toplevel ) {\n        doScrollCheck();\n      }\n    }\n  },\n\n  // See test/unit/core.js for details concerning isFunction.\n  // Since version 1.3, DOM methods and functions like alert\n  // aren't supported. They return false on IE (#2968).\n  isFunction: function( obj ) {\n    return jQuery.type(obj) === \"function\";\n  },\n\n  isArray: Array.isArray || function( obj ) {\n    return jQuery.type(obj) === \"array\";\n  },\n\n  isWindow: function( obj ) {\n    return obj != null && obj == obj.window;\n  },\n\n  isNumeric: function( obj ) {\n    return !isNaN( parseFloat(obj) ) && isFinite( obj );\n  },\n\n  type: function( obj ) {\n    return obj == null ?\n      String( obj ) :\n      class2type[ toString.call(obj) ] || \"object\";\n  },\n\n  isPlainObject: function( obj ) {\n    // Must be an Object.\n    // Because of IE, we also have to check the presence of the constructor property.\n    // Make sure that DOM nodes and window objects don't pass through, as well\n    if ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n      return false;\n    }\n\n    try {\n      // Not own constructor property must be Object\n      if ( obj.constructor &&\n        !hasOwn.call(obj, \"constructor\") &&\n        !hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n        return false;\n      }\n    } catch ( e ) {\n      // IE8,9 Will throw exceptions on certain host objects #9897\n      return false;\n    }\n\n    // Own properties are enumerated firstly, so to speed up,\n    // if last one is own, then all properties are own.\n\n    var key;\n    for ( key in obj ) {}\n\n    return key === undefined || hasOwn.call( obj, key );\n  },\n\n  isEmptyObject: function( obj ) {\n    for ( var name in obj ) {\n      return false;\n    }\n    return true;\n  },\n\n  error: function( msg ) {\n    throw new Error( msg );\n  },\n\n  parseJSON: function( data ) {\n    if ( typeof data !== \"string\" || !data ) {\n      return null;\n    }\n\n    // Make sure leading/trailing whitespace is removed (IE can't handle it)\n    data = jQuery.trim( data );\n\n    // Attempt to parse using the native JSON parser first\n    if ( window.JSON && window.JSON.parse ) {\n      return window.JSON.parse( data );\n    }\n\n    // Make sure the incoming data is actual JSON\n    // Logic borrowed from http://json.org/json2.js\n    if ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n      .replace( rvalidtokens, \"]\" )\n      .replace( rvalidbraces, \"\")) ) {\n\n      return ( new Function( \"return \" + data ) )();\n\n    }\n    jQuery.error( \"Invalid JSON: \" + data );\n  },\n\n  // Cross-browser xml parsing\n  parseXML: function( data ) {\n    if ( typeof data !== \"string\" || !data ) {\n      return null;\n    }\n    var xml, tmp;\n    try {\n      if ( window.DOMParser ) { // Standard\n        tmp = new DOMParser();\n        xml = tmp.parseFromString( data , \"text/xml\" );\n      } else { // IE\n        xml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n        xml.async = \"false\";\n        xml.loadXML( data );\n      }\n    } catch( e ) {\n      xml = undefined;\n    }\n    if ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n      jQuery.error( \"Invalid XML: \" + data );\n    }\n    return xml;\n  },\n\n  noop: function() {},\n\n  // Evaluates a script in a global context\n  // Workarounds based on findings by Jim Driscoll\n  // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n  globalEval: function( data ) {\n    if ( data && rnotwhite.test( data ) ) {\n      // We use execScript on Internet Explorer\n      // We use an anonymous function so that context is window\n      // rather than jQuery in Firefox\n      ( window.execScript || function( data ) {\n        window[ \"eval\" ].call( window, data );\n      } )( data );\n    }\n  },\n\n  // Convert dashed to camelCase; used by the css and data modules\n  // Microsoft forgot to hump their vendor prefix (#9572)\n  camelCase: function( string ) {\n    return string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n  },\n\n  nodeName: function( elem, name ) {\n    return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();\n  },\n\n  // args is for internal usage only\n  each: function( object, callback, args ) {\n    var name, i = 0,\n      length = object.length,\n      isObj = length === undefined || jQuery.isFunction( object );\n\n    if ( args ) {\n      if ( isObj ) {\n        for ( name in object ) {\n          if ( callback.apply( object[ name ], args ) === false ) {\n            break;\n          }\n        }\n      } else {\n        for ( ; i < length; ) {\n          if ( callback.apply( object[ i++ ], args ) === false ) {\n            break;\n          }\n        }\n      }\n\n    // A special, fast, case for the most common use of each\n    } else {\n      if ( isObj ) {\n        for ( name in object ) {\n          if ( callback.call( object[ name ], name, object[ name ] ) === false ) {\n            break;\n          }\n        }\n      } else {\n        for ( ; i < length; ) {\n          if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {\n            break;\n          }\n        }\n      }\n    }\n\n    return object;\n  },\n\n  // Use native String.trim function wherever possible\n  trim: trim ?\n    function( text ) {\n      return text == null ?\n        \"\" :\n        trim.call( text );\n    } :\n\n    // Otherwise use our own trimming functionality\n    function( text ) {\n      return text == null ?\n        \"\" :\n        text.toString().replace( trimLeft, \"\" ).replace( trimRight, \"\" );\n    },\n\n  // results is for internal usage only\n  makeArray: function( array, results ) {\n    var ret = results || [];\n\n    if ( array != null ) {\n      // The window, strings (and functions) also have 'length'\n      // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n      var type = jQuery.type( array );\n\n      if ( array.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( array ) ) {\n        push.call( ret, array );\n      } else {\n        jQuery.merge( ret, array );\n      }\n    }\n\n    return ret;\n  },\n\n  inArray: function( elem, array, i ) {\n    var len;\n\n    if ( array ) {\n      if ( indexOf ) {\n        return indexOf.call( array, elem, i );\n      }\n\n      len = array.length;\n      i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n      for ( ; i < len; i++ ) {\n        // Skip accessing in sparse arrays\n        if ( i in array && array[ i ] === elem ) {\n          return i;\n        }\n      }\n    }\n\n    return -1;\n  },\n\n  merge: function( first, second ) {\n    var i = first.length,\n      j = 0;\n\n    if ( typeof second.length === \"number\" ) {\n      for ( var l = second.length; j < l; j++ ) {\n        first[ i++ ] = second[ j ];\n      }\n\n    } else {\n      while ( second[j] !== undefined ) {\n        first[ i++ ] = second[ j++ ];\n      }\n    }\n\n    first.length = i;\n\n    return first;\n  },\n\n  grep: function( elems, callback, inv ) {\n    var ret = [], retVal;\n    inv = !!inv;\n\n    // Go through the array, only saving the items\n    // that pass the validator function\n    for ( var i = 0, length = elems.length; i < length; i++ ) {\n      retVal = !!callback( elems[ i ], i );\n      if ( inv !== retVal ) {\n        ret.push( elems[ i ] );\n      }\n    }\n\n    return ret;\n  },\n\n  // arg is for internal usage only\n  map: function( elems, callback, arg ) {\n    var value, key, ret = [],\n      i = 0,\n      length = elems.length,\n      // jquery objects are treated as arrays\n      isArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n    // Go through the array, translating each of the items to their\n    if ( isArray ) {\n      for ( ; i < length; i++ ) {\n        value = callback( elems[ i ], i, arg );\n\n        if ( value != null ) {\n          ret[ ret.length ] = value;\n        }\n      }\n\n    // Go through every key on the object,\n    } else {\n      for ( key in elems ) {\n        value = callback( elems[ key ], key, arg );\n\n        if ( value != null ) {\n          ret[ ret.length ] = value;\n        }\n      }\n    }\n\n    // Flatten any nested arrays\n    return ret.concat.apply( [], ret );\n  },\n\n  // A global GUID counter for objects\n  guid: 1,\n\n  // Bind a function to a context, optionally partially applying any\n  // arguments.\n  proxy: function( fn, context ) {\n    if ( typeof context === \"string\" ) {\n      var tmp = fn[ context ];\n      context = fn;\n      fn = tmp;\n    }\n\n    // Quick check to determine if target is callable, in the spec\n    // this throws a TypeError, but we will just return undefined.\n    if ( !jQuery.isFunction( fn ) ) {\n      return undefined;\n    }\n\n    // Simulated bind\n    var args = slice.call( arguments, 2 ),\n      proxy = function() {\n        return fn.apply( context, args.concat( slice.call( arguments ) ) );\n      };\n\n    // Set the guid of unique handler to the same of original handler, so it can be removed\n    proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;\n\n    return proxy;\n  },\n\n  // Mutifunctional method to get and set values to a collection\n  // The value/s can optionally be executed if it's a function\n  access: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n    var exec,\n      bulk = key == null,\n      i = 0,\n      length = elems.length;\n\n    // Sets many values\n    if ( key && typeof key === \"object\" ) {\n      for ( i in key ) {\n        jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n      }\n      chainable = 1;\n\n    // Sets one value\n    } else if ( value !== undefined ) {\n      // Optionally, function values get executed if exec is true\n      exec = pass === undefined && jQuery.isFunction( value );\n\n      if ( bulk ) {\n        // Bulk operations only iterate when executing function values\n        if ( exec ) {\n          exec = fn;\n          fn = function( elem, key, value ) {\n            return exec.call( jQuery( elem ), value );\n          };\n\n        // Otherwise they run against the entire set\n        } else {\n          fn.call( elems, value );\n          fn = null;\n        }\n      }\n\n      if ( fn ) {\n        for (; i < length; i++ ) {\n          fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n        }\n      }\n\n      chainable = 1;\n    }\n\n    return chainable ?\n      elems :\n\n      // Gets\n      bulk ?\n        fn.call( elems ) :\n        length ? fn( elems[0], key ) : emptyGet;\n  },\n\n  now: function() {\n    return ( new Date() ).getTime();\n  },\n\n  // Use of jQuery.browser is frowned upon.\n  // More details: http://docs.jquery.com/Utilities/jQuery.browser\n  uaMatch: function( ua ) {\n    ua = ua.toLowerCase();\n\n    var match = rwebkit.exec( ua ) ||\n      ropera.exec( ua ) ||\n      rmsie.exec( ua ) ||\n      ua.indexOf(\"compatible\") < 0 && rmozilla.exec( ua ) ||\n      [];\n\n    return { browser: match[1] || \"\", version: match[2] || \"0\" };\n  },\n\n  sub: function() {\n    function jQuerySub( selector, context ) {\n      return new jQuerySub.fn.init( selector, context );\n    }\n    jQuery.extend( true, jQuerySub, this );\n    jQuerySub.superclass = this;\n    jQuerySub.fn = jQuerySub.prototype = this();\n    jQuerySub.fn.constructor = jQuerySub;\n    jQuerySub.sub = this.sub;\n    jQuerySub.fn.init = function init( selector, context ) {\n      if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n        context = jQuerySub( context );\n      }\n\n      return jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n    };\n    jQuerySub.fn.init.prototype = jQuerySub.fn;\n    var rootjQuerySub = jQuerySub(document);\n    return jQuerySub;\n  },\n\n  browser: {}\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n  class2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nbrowserMatch = jQuery.uaMatch( userAgent );\nif ( browserMatch.browser ) {\n  jQuery.browser[ browserMatch.browser ] = true;\n  jQuery.browser.version = browserMatch.version;\n}\n\n// Deprecated, use jQuery.browser.webkit instead\nif ( jQuery.browser.webkit ) {\n  jQuery.browser.safari = true;\n}\n\n// IE doesn't match non-breaking spaces with \\s\nif ( rnotwhite.test( \"\\xA0\" ) ) {\n  trimLeft = /^[\\s\\xA0]+/;\n  trimRight = /[\\s\\xA0]+$/;\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n\n// Cleanup functions for the document ready method\nif ( document.addEventListener ) {\n  DOMContentLoaded = function() {\n    document.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n    jQuery.ready();\n  };\n\n} else if ( document.attachEvent ) {\n  DOMContentLoaded = function() {\n    // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n    if ( document.readyState === \"complete\" ) {\n      document.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n      jQuery.ready();\n    }\n  };\n}\n\n// The DOM ready check for Internet Explorer\nfunction doScrollCheck() {\n  if ( jQuery.isReady ) {\n    return;\n  }\n\n  try {\n    // If IE is used, use the trick by Diego Perini\n    // http://javascript.nwbox.com/IEContentLoaded/\n    document.documentElement.doScroll(\"left\");\n  } catch(e) {\n    setTimeout( doScrollCheck, 1 );\n    return;\n  }\n\n  // and execute any waiting functions\n  jQuery.ready();\n}\n\nreturn jQuery;\n\n})();\n\n\n// String to Object flags format cache\nvar flagsCache = {};\n\n// Convert String-formatted flags into Object-formatted ones and store in cache\nfunction createFlags( flags ) {\n  var object = flagsCache[ flags ] = {},\n    i, length;\n  flags = flags.split( /\\s+/ );\n  for ( i = 0, length = flags.length; i < length; i++ ) {\n    object[ flags[i] ] = true;\n  }\n  return object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\tflags:\tan optional list of space-separated flags that will change how\n *\t\t\tthe callback list behaves\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible flags:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( flags ) {\n\n  // Convert flags from String-formatted to Object-formatted\n  // (we check in cache first)\n  flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};\n\n  var // Actual callback list\n    list = [],\n    // Stack of fire calls for repeatable lists\n    stack = [],\n    // Last fire value (for non-forgettable lists)\n    memory,\n    // Flag to know if list was already fired\n    fired,\n    // Flag to know if list is currently firing\n    firing,\n    // First callback to fire (used internally by add and fireWith)\n    firingStart,\n    // End of the loop when firing\n    firingLength,\n    // Index of currently firing callback (modified by remove if needed)\n    firingIndex,\n    // Add one or several callbacks to the list\n    add = function( args ) {\n      var i,\n        length,\n        elem,\n        type,\n        actual;\n      for ( i = 0, length = args.length; i < length; i++ ) {\n        elem = args[ i ];\n        type = jQuery.type( elem );\n        if ( type === \"array\" ) {\n          // Inspect recursively\n          add( elem );\n        } else if ( type === \"function\" ) {\n          // Add if not in unique mode and callback is not in\n          if ( !flags.unique || !self.has( elem ) ) {\n            list.push( elem );\n          }\n        }\n      }\n    },\n    // Fire callbacks\n    fire = function( context, args ) {\n      args = args || [];\n      memory = !flags.memory || [ context, args ];\n      fired = true;\n      firing = true;\n      firingIndex = firingStart || 0;\n      firingStart = 0;\n      firingLength = list.length;\n      for ( ; list && firingIndex < firingLength; firingIndex++ ) {\n        if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {\n          memory = true; // Mark as halted\n          break;\n        }\n      }\n      firing = false;\n      if ( list ) {\n        if ( !flags.once ) {\n          if ( stack && stack.length ) {\n            memory = stack.shift();\n            self.fireWith( memory[ 0 ], memory[ 1 ] );\n          }\n        } else if ( memory === true ) {\n          self.disable();\n        } else {\n          list = [];\n        }\n      }\n    },\n    // Actual Callbacks object\n    self = {\n      // Add a callback or a collection of callbacks to the list\n      add: function() {\n        if ( list ) {\n          var length = list.length;\n          add( arguments );\n          // Do we need to add the callbacks to the\n          // current firing batch?\n          if ( firing ) {\n            firingLength = list.length;\n          // With memory, if we're not firing then\n          // we should call right away, unless previous\n          // firing was halted (stopOnFalse)\n          } else if ( memory && memory !== true ) {\n            firingStart = length;\n            fire( memory[ 0 ], memory[ 1 ] );\n          }\n        }\n        return this;\n      },\n      // Remove a callback from the list\n      remove: function() {\n        if ( list ) {\n          var args = arguments,\n            argIndex = 0,\n            argLength = args.length;\n          for ( ; argIndex < argLength ; argIndex++ ) {\n            for ( var i = 0; i < list.length; i++ ) {\n              if ( args[ argIndex ] === list[ i ] ) {\n                // Handle firingIndex and firingLength\n                if ( firing ) {\n                  if ( i <= firingLength ) {\n                    firingLength--;\n                    if ( i <= firingIndex ) {\n                      firingIndex--;\n                    }\n                  }\n                }\n                // Remove the element\n                list.splice( i--, 1 );\n                // If we have some unicity property then\n                // we only need to do this once\n                if ( flags.unique ) {\n                  break;\n                }\n              }\n            }\n          }\n        }\n        return this;\n      },\n      // Control if a given callback is in the list\n      has: function( fn ) {\n        if ( list ) {\n          var i = 0,\n            length = list.length;\n          for ( ; i < length; i++ ) {\n            if ( fn === list[ i ] ) {\n              return true;\n            }\n          }\n        }\n        return false;\n      },\n      // Remove all callbacks from the list\n      empty: function() {\n        list = [];\n        return this;\n      },\n      // Have the list do nothing anymore\n      disable: function() {\n        list = stack = memory = undefined;\n        return this;\n      },\n      // Is it disabled?\n      disabled: function() {\n        return !list;\n      },\n      // Lock the list in its current state\n      lock: function() {\n        stack = undefined;\n        if ( !memory || memory === true ) {\n          self.disable();\n        }\n        return this;\n      },\n      // Is it locked?\n      locked: function() {\n        return !stack;\n      },\n      // Call all callbacks with the given context and arguments\n      fireWith: function( context, args ) {\n        if ( stack ) {\n          if ( firing ) {\n            if ( !flags.once ) {\n              stack.push( [ context, args ] );\n            }\n          } else if ( !( flags.once && memory ) ) {\n            fire( context, args );\n          }\n        }\n        return this;\n      },\n      // Call all the callbacks with the given arguments\n      fire: function() {\n        self.fireWith( this, arguments );\n        return this;\n      },\n      // To know if the callbacks have already been called at least once\n      fired: function() {\n        return !!fired;\n      }\n    };\n\n  return self;\n};\n\n\n\n\nvar // Static reference to slice\n  sliceDeferred = [].slice;\n\njQuery.extend({\n\n  Deferred: function( func ) {\n    var doneList = jQuery.Callbacks( \"once memory\" ),\n      failList = jQuery.Callbacks( \"once memory\" ),\n      progressList = jQuery.Callbacks( \"memory\" ),\n      state = \"pending\",\n      lists = {\n        resolve: doneList,\n        reject: failList,\n        notify: progressList\n      },\n      promise = {\n        done: doneList.add,\n        fail: failList.add,\n        progress: progressList.add,\n\n        state: function() {\n          return state;\n        },\n\n        // Deprecated\n        isResolved: doneList.fired,\n        isRejected: failList.fired,\n\n        then: function( doneCallbacks, failCallbacks, progressCallbacks ) {\n          deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );\n          return this;\n        },\n        always: function() {\n          deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );\n          return this;\n        },\n        pipe: function( fnDone, fnFail, fnProgress ) {\n          return jQuery.Deferred(function( newDefer ) {\n            jQuery.each( {\n              done: [ fnDone, \"resolve\" ],\n              fail: [ fnFail, \"reject\" ],\n              progress: [ fnProgress, \"notify\" ]\n            }, function( handler, data ) {\n              var fn = data[ 0 ],\n                action = data[ 1 ],\n                returned;\n              if ( jQuery.isFunction( fn ) ) {\n                deferred[ handler ](function() {\n                  returned = fn.apply( this, arguments );\n                  if ( returned && jQuery.isFunction( returned.promise ) ) {\n                    returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );\n                  } else {\n                    newDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n                  }\n                });\n              } else {\n                deferred[ handler ]( newDefer[ action ] );\n              }\n            });\n          }).promise();\n        },\n        // Get a promise for this deferred\n        // If obj is provided, the promise aspect is added to the object\n        promise: function( obj ) {\n          if ( obj == null ) {\n            obj = promise;\n          } else {\n            for ( var key in promise ) {\n              obj[ key ] = promise[ key ];\n            }\n          }\n          return obj;\n        }\n      },\n      deferred = promise.promise({}),\n      key;\n\n    for ( key in lists ) {\n      deferred[ key ] = lists[ key ].fire;\n      deferred[ key + \"With\" ] = lists[ key ].fireWith;\n    }\n\n    // Handle state\n    deferred.done( function() {\n      state = \"resolved\";\n    }, failList.disable, progressList.lock ).fail( function() {\n      state = \"rejected\";\n    }, doneList.disable, progressList.lock );\n\n    // Call given func if any\n    if ( func ) {\n      func.call( deferred, deferred );\n    }\n\n    // All done!\n    return deferred;\n  },\n\n  // Deferred helper\n  when: function( firstParam ) {\n    var args = sliceDeferred.call( arguments, 0 ),\n      i = 0,\n      length = args.length,\n      pValues = new Array( length ),\n      count = length,\n      pCount = length,\n      deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?\n        firstParam :\n        jQuery.Deferred(),\n      promise = deferred.promise();\n    function resolveFunc( i ) {\n      return function( value ) {\n        args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n        if ( !( --count ) ) {\n          deferred.resolveWith( deferred, args );\n        }\n      };\n    }\n    function progressFunc( i ) {\n      return function( value ) {\n        pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;\n        deferred.notifyWith( promise, pValues );\n      };\n    }\n    if ( length > 1 ) {\n      for ( ; i < length; i++ ) {\n        if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {\n          args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );\n        } else {\n          --count;\n        }\n      }\n      if ( !count ) {\n        deferred.resolveWith( deferred, args );\n      }\n    } else if ( deferred !== firstParam ) {\n      deferred.resolveWith( deferred, length ? [ firstParam ] : [] );\n    }\n    return promise;\n  }\n});\n\n\n\n\njQuery.support = (function() {\n\n  var support,\n    all,\n    a,\n    select,\n    opt,\n    input,\n    fragment,\n    tds,\n    events,\n    eventName,\n    i,\n    isSupported,\n    div = document.createElement( \"div\" ),\n    documentElement = document.documentElement;\n\n  // Preliminary tests\n  div.setAttribute(\"className\", \"t\");\n  div.innerHTML = \"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\";\n\n  all = div.getElementsByTagName( \"*\" );\n  a = div.getElementsByTagName( \"a\" )[ 0 ];\n\n  // Can't get basic test support\n  if ( !all || !all.length || !a ) {\n    return {};\n  }\n\n  // First batch of supports tests\n  select = document.createElement( \"select\" );\n  opt = select.appendChild( document.createElement(\"option\") );\n  input = div.getElementsByTagName( \"input\" )[ 0 ];\n\n  support = {\n    // IE strips leading whitespace when .innerHTML is used\n    leadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n    // Make sure that tbody elements aren't automatically inserted\n    // IE will insert them into empty tables\n    tbody: !div.getElementsByTagName(\"tbody\").length,\n\n    // Make sure that link elements get serialized correctly by innerHTML\n    // This requires a wrapper element in IE\n    htmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n    // Get the style information from getAttribute\n    // (IE uses .cssText instead)\n    style: /top/.test( a.getAttribute(\"style\") ),\n\n    // Make sure that URLs aren't manipulated\n    // (IE normalizes it by default)\n    hrefNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n    // Make sure that element opacity exists\n    // (IE uses filter instead)\n    // Use a regex to work around a WebKit issue. See #5145\n    opacity: /^0.55/.test( a.style.opacity ),\n\n    // Verify style float existence\n    // (IE uses styleFloat instead of cssFloat)\n    cssFloat: !!a.style.cssFloat,\n\n    // Make sure that if no value is specified for a checkbox\n    // that it defaults to \"on\".\n    // (WebKit defaults to \"\" instead)\n    checkOn: ( input.value === \"on\" ),\n\n    // Make sure that a selected-by-default option has a working selected property.\n    // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n    optSelected: opt.selected,\n\n    // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n    getSetAttribute: div.className !== \"t\",\n\n    // Tests for enctype support on a form(#6743)\n    enctype: !!document.createElement(\"form\").enctype,\n\n    // Makes sure cloning an html5 element does not cause problems\n    // Where outerHTML is undefined, this still works\n    html5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n    // Will be defined later\n    submitBubbles: true,\n    changeBubbles: true,\n    focusinBubbles: false,\n    deleteExpando: true,\n    noCloneEvent: true,\n    inlineBlockNeedsLayout: false,\n    shrinkWrapBlocks: false,\n    reliableMarginRight: true,\n    pixelMargin: true\n  };\n\n  // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead\n  jQuery.boxModel = support.boxModel = (document.compatMode === \"CSS1Compat\");\n\n  // Make sure checked status is properly cloned\n  input.checked = true;\n  support.noCloneChecked = input.cloneNode( true ).checked;\n\n  // Make sure that the options inside disabled selects aren't marked as disabled\n  // (WebKit marks them as disabled)\n  select.disabled = true;\n  support.optDisabled = !opt.disabled;\n\n  // Test to see if it's possible to delete an expando from an element\n  // Fails in Internet Explorer\n  try {\n    delete div.test;\n  } catch( e ) {\n    support.deleteExpando = false;\n  }\n\n  if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n    div.attachEvent( \"onclick\", function() {\n      // Cloning a node shouldn't copy over any\n      // bound event handlers (IE does this)\n      support.noCloneEvent = false;\n    });\n    div.cloneNode( true ).fireEvent( \"onclick\" );\n  }\n\n  // Check if a radio maintains its value\n  // after being appended to the DOM\n  input = document.createElement(\"input\");\n  input.value = \"t\";\n  input.setAttribute(\"type\", \"radio\");\n  support.radioValue = input.value === \"t\";\n\n  input.setAttribute(\"checked\", \"checked\");\n\n  // #11217 - WebKit loses check when the name is after the checked attribute\n  input.setAttribute( \"name\", \"t\" );\n\n  div.appendChild( input );\n  fragment = document.createDocumentFragment();\n  fragment.appendChild( div.lastChild );\n\n  // WebKit doesn't clone checked state correctly in fragments\n  support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n  // Check if a disconnected checkbox will retain its checked\n  // value of true after appended to the DOM (IE6/7)\n  support.appendChecked = input.checked;\n\n  fragment.removeChild( input );\n  fragment.appendChild( div );\n\n  // Technique from Juriy Zaytsev\n  // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n  // We only care about the case where non-standard event systems\n  // are used, namely in IE. Short-circuiting here helps us to\n  // avoid an eval call (in setAttribute) which can cause CSP\n  // to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n  if ( div.attachEvent ) {\n    for ( i in {\n      submit: 1,\n      change: 1,\n      focusin: 1\n    }) {\n      eventName = \"on\" + i;\n      isSupported = ( eventName in div );\n      if ( !isSupported ) {\n        div.setAttribute( eventName, \"return;\" );\n        isSupported = ( typeof div[ eventName ] === \"function\" );\n      }\n      support[ i + \"Bubbles\" ] = isSupported;\n    }\n  }\n\n  fragment.removeChild( div );\n\n  // Null elements to avoid leaks in IE\n  fragment = select = opt = div = input = null;\n\n  // Run tests that need a body at doc ready\n  jQuery(function() {\n    var container, outer, inner, table, td, offsetSupport,\n      marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,\n      paddingMarginBorderVisibility, paddingMarginBorder,\n      body = document.getElementsByTagName(\"body\")[0];\n\n    if ( !body ) {\n      // Return for frameset docs that don't have a body\n      return;\n    }\n\n    conMarginTop = 1;\n    paddingMarginBorder = \"padding:0;margin:0;border:\";\n    positionTopLeftWidthHeight = \"position:absolute;top:0;left:0;width:1px;height:1px;\";\n    paddingMarginBorderVisibility = paddingMarginBorder + \"0;visibility:hidden;\";\n    style = \"style='\" + positionTopLeftWidthHeight + paddingMarginBorder + \"5px solid #000;\";\n    html = \"<div \" + style + \"display:block;'><div style='\" + paddingMarginBorder + \"0;display:block;overflow:hidden;'></div></div>\" +\n      \"<table \" + style + \"' cellpadding='0' cellspacing='0'>\" +\n      \"<tr><td></td></tr></table>\";\n\n    container = document.createElement(\"div\");\n    container.style.cssText = paddingMarginBorderVisibility + \"width:0;height:0;position:static;top:0;margin-top:\" + conMarginTop + \"px\";\n    body.insertBefore( container, body.firstChild );\n\n    // Construct the test element\n    div = document.createElement(\"div\");\n    container.appendChild( div );\n\n    // Check if table cells still have offsetWidth/Height when they are set\n    // to display:none and there are still other visible table cells in a\n    // table row; if so, offsetWidth/Height are not reliable for use when\n    // determining if an element has been hidden directly using\n    // display:none (it is still safe to use offsets if a parent element is\n    // hidden; don safety goggles and see bug #4512 for more information).\n    // (only IE 8 fails this test)\n    div.innerHTML = \"<table><tr><td style='\" + paddingMarginBorder + \"0;display:none'></td><td>t</td></tr></table>\";\n    tds = div.getElementsByTagName( \"td\" );\n    isSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n    tds[ 0 ].style.display = \"\";\n    tds[ 1 ].style.display = \"none\";\n\n    // Check if empty table cells still have offsetWidth/Height\n    // (IE <= 8 fail this test)\n    support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n    // Check if div with explicit width and no margin-right incorrectly\n    // gets computed margin-right based on width of container. For more\n    // info see bug #3333\n    // Fails in WebKit before Feb 2011 nightlies\n    // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n    if ( window.getComputedStyle ) {\n      div.innerHTML = \"\";\n      marginDiv = document.createElement( \"div\" );\n      marginDiv.style.width = \"0\";\n      marginDiv.style.marginRight = \"0\";\n      div.style.width = \"2px\";\n      div.appendChild( marginDiv );\n      support.reliableMarginRight =\n        ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;\n    }\n\n    if ( typeof div.style.zoom !== \"undefined\" ) {\n      // Check if natively block-level elements act like inline-block\n      // elements when setting their display to 'inline' and giving\n      // them layout\n      // (IE < 8 does this)\n      div.innerHTML = \"\";\n      div.style.width = div.style.padding = \"1px\";\n      div.style.border = 0;\n      div.style.overflow = \"hidden\";\n      div.style.display = \"inline\";\n      div.style.zoom = 1;\n      support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n      // Check if elements with layout shrink-wrap their children\n      // (IE 6 does this)\n      div.style.display = \"block\";\n      div.style.overflow = \"visible\";\n      div.innerHTML = \"<div style='width:5px;'></div>\";\n      support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n    }\n\n    div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;\n    div.innerHTML = html;\n\n    outer = div.firstChild;\n    inner = outer.firstChild;\n    td = outer.nextSibling.firstChild.firstChild;\n\n    offsetSupport = {\n      doesNotAddBorder: ( inner.offsetTop !== 5 ),\n      doesAddBorderForTableAndCells: ( td.offsetTop === 5 )\n    };\n\n    inner.style.position = \"fixed\";\n    inner.style.top = \"20px\";\n\n    // safari subtracts parent border width here which is 5px\n    offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );\n    inner.style.position = inner.style.top = \"\";\n\n    outer.style.overflow = \"hidden\";\n    outer.style.position = \"relative\";\n\n    offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );\n    offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );\n\n    if ( window.getComputedStyle ) {\n      div.style.marginTop = \"1%\";\n      support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== \"1%\";\n    }\n\n    if ( typeof container.style.zoom !== \"undefined\" ) {\n      container.style.zoom = 1;\n    }\n\n    body.removeChild( container );\n    marginDiv = div = container = null;\n\n    jQuery.extend( support, offsetSupport );\n  });\n\n  return support;\n})();\n\n\n\n\nvar rbrace = /^(?:\\{.*\\}|\\[.*\\])$/,\n  rmultiDash = /([A-Z])/g;\n\njQuery.extend({\n  cache: {},\n\n  // Please use with caution\n  uuid: 0,\n\n  // Unique for each copy of jQuery on the page\n  // Non-digits removed to match rinlinejQuery\n  expando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n  // The following elements throw uncatchable exceptions if you\n  // attempt to add expando properties to them.\n  noData: {\n    \"embed\": true,\n    // Ban all objects except for Flash (which handle expandos)\n    \"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n    \"applet\": true\n  },\n\n  hasData: function( elem ) {\n    elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n    return !!elem && !isEmptyDataObject( elem );\n  },\n\n  data: function( elem, name, data, pvt /* Internal Use Only */ ) {\n    if ( !jQuery.acceptData( elem ) ) {\n      return;\n    }\n\n    var privateCache, thisCache, ret,\n      internalKey = jQuery.expando,\n      getByName = typeof name === \"string\",\n\n      // We have to handle DOM nodes and JS objects differently because IE6-7\n      // can't GC object references properly across the DOM-JS boundary\n      isNode = elem.nodeType,\n\n      // Only DOM nodes need the global jQuery cache; JS object data is\n      // attached directly to the object so GC can occur automatically\n      cache = isNode ? jQuery.cache : elem,\n\n      // Only defining an ID for JS objects if its cache already exists allows\n      // the code to shortcut on the same path as a DOM node with no cache\n      id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,\n      isEvents = name === \"events\";\n\n    // Avoid doing any more work than we need to when trying to get data on an\n    // object that has no data at all\n    if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {\n      return;\n    }\n\n    if ( !id ) {\n      // Only DOM nodes need a new unique ID for each element since their data\n      // ends up in the global cache\n      if ( isNode ) {\n        elem[ internalKey ] = id = ++jQuery.uuid;\n      } else {\n        id = internalKey;\n      }\n    }\n\n    if ( !cache[ id ] ) {\n      cache[ id ] = {};\n\n      // Avoids exposing jQuery metadata on plain JS objects when the object\n      // is serialized using JSON.stringify\n      if ( !isNode ) {\n        cache[ id ].toJSON = jQuery.noop;\n      }\n    }\n\n    // An object can be passed to jQuery.data instead of a key/value pair; this gets\n    // shallow copied over onto the existing cache\n    if ( typeof name === \"object\" || typeof name === \"function\" ) {\n      if ( pvt ) {\n        cache[ id ] = jQuery.extend( cache[ id ], name );\n      } else {\n        cache[ id ].data = jQuery.extend( cache[ id ].data, name );\n      }\n    }\n\n    privateCache = thisCache = cache[ id ];\n\n    // jQuery data() is stored in a separate object inside the object's internal data\n    // cache in order to avoid key collisions between internal data and user-defined\n    // data.\n    if ( !pvt ) {\n      if ( !thisCache.data ) {\n        thisCache.data = {};\n      }\n\n      thisCache = thisCache.data;\n    }\n\n    if ( data !== undefined ) {\n      thisCache[ jQuery.camelCase( name ) ] = data;\n    }\n\n    // Users should not attempt to inspect the internal events object using jQuery.data,\n    // it is undocumented and subject to change. But does anyone listen? No.\n    if ( isEvents && !thisCache[ name ] ) {\n      return privateCache.events;\n    }\n\n    // Check for both converted-to-camel and non-converted data property names\n    // If a data property was specified\n    if ( getByName ) {\n\n      // First Try to find as-is property data\n      ret = thisCache[ name ];\n\n      // Test for null|undefined property data\n      if ( ret == null ) {\n\n        // Try to find the camelCased property\n        ret = thisCache[ jQuery.camelCase( name ) ];\n      }\n    } else {\n      ret = thisCache;\n    }\n\n    return ret;\n  },\n\n  removeData: function( elem, name, pvt /* Internal Use Only */ ) {\n    if ( !jQuery.acceptData( elem ) ) {\n      return;\n    }\n\n    var thisCache, i, l,\n\n      // Reference to internal data cache key\n      internalKey = jQuery.expando,\n\n      isNode = elem.nodeType,\n\n      // See jQuery.data for more information\n      cache = isNode ? jQuery.cache : elem,\n\n      // See jQuery.data for more information\n      id = isNode ? elem[ internalKey ] : internalKey;\n\n    // If there is already no cache entry for this object, there is no\n    // purpose in continuing\n    if ( !cache[ id ] ) {\n      return;\n    }\n\n    if ( name ) {\n\n      thisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n      if ( thisCache ) {\n\n        // Support array or space separated string names for data keys\n        if ( !jQuery.isArray( name ) ) {\n\n          // try the string as a key before any manipulation\n          if ( name in thisCache ) {\n            name = [ name ];\n          } else {\n\n            // split the camel cased version by spaces unless a key with the spaces exists\n            name = jQuery.camelCase( name );\n            if ( name in thisCache ) {\n              name = [ name ];\n            } else {\n              name = name.split( \" \" );\n            }\n          }\n        }\n\n        for ( i = 0, l = name.length; i < l; i++ ) {\n          delete thisCache[ name[i] ];\n        }\n\n        // If there is no data left in the cache, we want to continue\n        // and let the cache object itself get destroyed\n        if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n          return;\n        }\n      }\n    }\n\n    // See jQuery.data for more information\n    if ( !pvt ) {\n      delete cache[ id ].data;\n\n      // Don't destroy the parent cache unless the internal data object\n      // had been the only thing left in it\n      if ( !isEmptyDataObject(cache[ id ]) ) {\n        return;\n      }\n    }\n\n    // Browsers that fail expando deletion also refuse to delete expandos on\n    // the window, but it will allow it on all other JS objects; other browsers\n    // don't care\n    // Ensure that `cache` is not a window object #10080\n    if ( jQuery.support.deleteExpando || !cache.setInterval ) {\n      delete cache[ id ];\n    } else {\n      cache[ id ] = null;\n    }\n\n    // We destroyed the cache and need to eliminate the expando on the node to avoid\n    // false lookups in the cache for entries that no longer exist\n    if ( isNode ) {\n      // IE does not allow us to delete expando properties from nodes,\n      // nor does it have a removeAttribute function on Document nodes;\n      // we must handle all of these cases\n      if ( jQuery.support.deleteExpando ) {\n        delete elem[ internalKey ];\n      } else if ( elem.removeAttribute ) {\n        elem.removeAttribute( internalKey );\n      } else {\n        elem[ internalKey ] = null;\n      }\n    }\n  },\n\n  // For internal use only.\n  _data: function( elem, name, data ) {\n    return jQuery.data( elem, name, data, true );\n  },\n\n  // A method for determining if a DOM node can handle the data expando\n  acceptData: function( elem ) {\n    if ( elem.nodeName ) {\n      var match = jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n      if ( match ) {\n        return !(match === true || elem.getAttribute(\"classid\") !== match);\n      }\n    }\n\n    return true;\n  }\n});\n\njQuery.fn.extend({\n  data: function( key, value ) {\n    var parts, part, attr, name, l,\n      elem = this[0],\n      i = 0,\n      data = null;\n\n    // Gets all values\n    if ( key === undefined ) {\n      if ( this.length ) {\n        data = jQuery.data( elem );\n\n        if ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n          attr = elem.attributes;\n          for ( l = attr.length; i < l; i++ ) {\n            name = attr[i].name;\n\n            if ( name.indexOf( \"data-\" ) === 0 ) {\n              name = jQuery.camelCase( name.substring(5) );\n\n              dataAttr( elem, name, data[ name ] );\n            }\n          }\n          jQuery._data( elem, \"parsedAttrs\", true );\n        }\n      }\n\n      return data;\n    }\n\n    // Sets multiple values\n    if ( typeof key === \"object\" ) {\n      return this.each(function() {\n        jQuery.data( this, key );\n      });\n    }\n\n    parts = key.split( \".\", 2 );\n    parts[1] = parts[1] ? \".\" + parts[1] : \"\";\n    part = parts[1] + \"!\";\n\n    return jQuery.access( this, function( value ) {\n\n      if ( value === undefined ) {\n        data = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n        // Try to fetch any internally stored data first\n        if ( data === undefined && elem ) {\n          data = jQuery.data( elem, key );\n          data = dataAttr( elem, key, data );\n        }\n\n        return data === undefined && parts[1] ?\n          this.data( parts[0] ) :\n          data;\n      }\n\n      parts[1] = value;\n      this.each(function() {\n        var self = jQuery( this );\n\n        self.triggerHandler( \"setData\" + part, parts );\n        jQuery.data( this, key, value );\n        self.triggerHandler( \"changeData\" + part, parts );\n      });\n    }, null, value, arguments.length > 1, null, false );\n  },\n\n  removeData: function( key ) {\n    return this.each(function() {\n      jQuery.removeData( this, key );\n    });\n  }\n});\n\nfunction dataAttr( elem, key, data ) {\n  // If nothing was found internally, try to fetch any\n  // data from the HTML5 data-* attribute\n  if ( data === undefined && elem.nodeType === 1 ) {\n\n    var name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n    data = elem.getAttribute( name );\n\n    if ( typeof data === \"string\" ) {\n      try {\n        data = data === \"true\" ? true :\n        data === \"false\" ? false :\n        data === \"null\" ? null :\n        jQuery.isNumeric( data ) ? +data :\n          rbrace.test( data ) ? jQuery.parseJSON( data ) :\n          data;\n      } catch( e ) {}\n\n      // Make sure we set the data so it isn't changed later\n      jQuery.data( elem, key, data );\n\n    } else {\n      data = undefined;\n    }\n  }\n\n  return data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n  for ( var name in obj ) {\n\n    // if the public data object is empty, the private is still empty\n    if ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n      continue;\n    }\n    if ( name !== \"toJSON\" ) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n\n\n\nfunction handleQueueMarkDefer( elem, type, src ) {\n  var deferDataKey = type + \"defer\",\n    queueDataKey = type + \"queue\",\n    markDataKey = type + \"mark\",\n    defer = jQuery._data( elem, deferDataKey );\n  if ( defer &&\n    ( src === \"queue\" || !jQuery._data(elem, queueDataKey) ) &&\n    ( src === \"mark\" || !jQuery._data(elem, markDataKey) ) ) {\n    // Give room for hard-coded callbacks to fire first\n    // and eventually mark/queue something else on the element\n    setTimeout( function() {\n      if ( !jQuery._data( elem, queueDataKey ) &&\n        !jQuery._data( elem, markDataKey ) ) {\n        jQuery.removeData( elem, deferDataKey, true );\n        defer.fire();\n      }\n    }, 0 );\n  }\n}\n\njQuery.extend({\n\n  _mark: function( elem, type ) {\n    if ( elem ) {\n      type = ( type || \"fx\" ) + \"mark\";\n      jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );\n    }\n  },\n\n  _unmark: function( force, elem, type ) {\n    if ( force !== true ) {\n      type = elem;\n      elem = force;\n      force = false;\n    }\n    if ( elem ) {\n      type = type || \"fx\";\n      var key = type + \"mark\",\n        count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );\n      if ( count ) {\n        jQuery._data( elem, key, count );\n      } else {\n        jQuery.removeData( elem, key, true );\n        handleQueueMarkDefer( elem, type, \"mark\" );\n      }\n    }\n  },\n\n  queue: function( elem, type, data ) {\n    var q;\n    if ( elem ) {\n      type = ( type || \"fx\" ) + \"queue\";\n      q = jQuery._data( elem, type );\n\n      // Speed up dequeue by getting out quickly if this is just a lookup\n      if ( data ) {\n        if ( !q || jQuery.isArray(data) ) {\n          q = jQuery._data( elem, type, jQuery.makeArray(data) );\n        } else {\n          q.push( data );\n        }\n      }\n      return q || [];\n    }\n  },\n\n  dequeue: function( elem, type ) {\n    type = type || \"fx\";\n\n    var queue = jQuery.queue( elem, type ),\n      fn = queue.shift(),\n      hooks = {};\n\n    // If the fx queue is dequeued, always remove the progress sentinel\n    if ( fn === \"inprogress\" ) {\n      fn = queue.shift();\n    }\n\n    if ( fn ) {\n      // Add a progress sentinel to prevent the fx queue from being\n      // automatically dequeued\n      if ( type === \"fx\" ) {\n        queue.unshift( \"inprogress\" );\n      }\n\n      jQuery._data( elem, type + \".run\", hooks );\n      fn.call( elem, function() {\n        jQuery.dequeue( elem, type );\n      }, hooks );\n    }\n\n    if ( !queue.length ) {\n      jQuery.removeData( elem, type + \"queue \" + type + \".run\", true );\n      handleQueueMarkDefer( elem, type, \"queue\" );\n    }\n  }\n});\n\njQuery.fn.extend({\n  queue: function( type, data ) {\n    var setter = 2;\n\n    if ( typeof type !== \"string\" ) {\n      data = type;\n      type = \"fx\";\n      setter--;\n    }\n\n    if ( arguments.length < setter ) {\n      return jQuery.queue( this[0], type );\n    }\n\n    return data === undefined ?\n      this :\n      this.each(function() {\n        var queue = jQuery.queue( this, type, data );\n\n        if ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n          jQuery.dequeue( this, type );\n        }\n      });\n  },\n  dequeue: function( type ) {\n    return this.each(function() {\n      jQuery.dequeue( this, type );\n    });\n  },\n  // Based off of the plugin by Clint Helfers, with permission.\n  // http://blindsignals.com/index.php/2009/07/jquery-delay/\n  delay: function( time, type ) {\n    time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n    type = type || \"fx\";\n\n    return this.queue( type, function( next, hooks ) {\n      var timeout = setTimeout( next, time );\n      hooks.stop = function() {\n        clearTimeout( timeout );\n      };\n    });\n  },\n  clearQueue: function( type ) {\n    return this.queue( type || \"fx\", [] );\n  },\n  // Get a promise resolved when queues of a certain type\n  // are emptied (fx is the type by default)\n  promise: function( type, object ) {\n    if ( typeof type !== \"string\" ) {\n      object = type;\n      type = undefined;\n    }\n    type = type || \"fx\";\n    var defer = jQuery.Deferred(),\n      elements = this,\n      i = elements.length,\n      count = 1,\n      deferDataKey = type + \"defer\",\n      queueDataKey = type + \"queue\",\n      markDataKey = type + \"mark\",\n      tmp;\n    function resolve() {\n      if ( !( --count ) ) {\n        defer.resolveWith( elements, [ elements ] );\n      }\n    }\n    while( i-- ) {\n      if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||\n          ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||\n            jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&\n          jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( \"once memory\" ), true ) )) {\n        count++;\n        tmp.add( resolve );\n      }\n    }\n    resolve();\n    return defer.promise( object );\n  }\n});\n\n\n\n\nvar rclass = /[\\n\\t\\r]/g,\n  rspace = /\\s+/,\n  rreturn = /\\r/g,\n  rtype = /^(?:button|input)$/i,\n  rfocusable = /^(?:button|input|object|select|textarea)$/i,\n  rclickable = /^a(?:rea)?$/i,\n  rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n  getSetAttribute = jQuery.support.getSetAttribute,\n  nodeHook, boolHook, fixSpecified;\n\njQuery.fn.extend({\n  attr: function( name, value ) {\n    return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n  },\n\n  removeAttr: function( name ) {\n    return this.each(function() {\n      jQuery.removeAttr( this, name );\n    });\n  },\n\n  prop: function( name, value ) {\n    return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n  },\n\n  removeProp: function( name ) {\n    name = jQuery.propFix[ name ] || name;\n    return this.each(function() {\n      // try/catch handles cases where IE balks (such as removing a property on window)\n      try {\n        this[ name ] = undefined;\n        delete this[ name ];\n      } catch( e ) {}\n    });\n  },\n\n  addClass: function( value ) {\n    var classNames, i, l, elem,\n      setClass, c, cl;\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( j ) {\n        jQuery( this ).addClass( value.call(this, j, this.className) );\n      });\n    }\n\n    if ( value && typeof value === \"string\" ) {\n      classNames = value.split( rspace );\n\n      for ( i = 0, l = this.length; i < l; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.nodeType === 1 ) {\n          if ( !elem.className && classNames.length === 1 ) {\n            elem.className = value;\n\n          } else {\n            setClass = \" \" + elem.className + \" \";\n\n            for ( c = 0, cl = classNames.length; c < cl; c++ ) {\n              if ( !~setClass.indexOf( \" \" + classNames[ c ] + \" \" ) ) {\n                setClass += classNames[ c ] + \" \";\n              }\n            }\n            elem.className = jQuery.trim( setClass );\n          }\n        }\n      }\n    }\n\n    return this;\n  },\n\n  removeClass: function( value ) {\n    var classNames, i, l, elem, className, c, cl;\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( j ) {\n        jQuery( this ).removeClass( value.call(this, j, this.className) );\n      });\n    }\n\n    if ( (value && typeof value === \"string\") || value === undefined ) {\n      classNames = ( value || \"\" ).split( rspace );\n\n      for ( i = 0, l = this.length; i < l; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.nodeType === 1 && elem.className ) {\n          if ( value ) {\n            className = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n            for ( c = 0, cl = classNames.length; c < cl; c++ ) {\n              className = className.replace(\" \" + classNames[ c ] + \" \", \" \");\n            }\n            elem.className = jQuery.trim( className );\n\n          } else {\n            elem.className = \"\";\n          }\n        }\n      }\n    }\n\n    return this;\n  },\n\n  toggleClass: function( value, stateVal ) {\n    var type = typeof value,\n      isBool = typeof stateVal === \"boolean\";\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( i ) {\n        jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n      });\n    }\n\n    return this.each(function() {\n      if ( type === \"string\" ) {\n        // toggle individual class names\n        var className,\n          i = 0,\n          self = jQuery( this ),\n          state = stateVal,\n          classNames = value.split( rspace );\n\n        while ( (className = classNames[ i++ ]) ) {\n          // check each className given, space seperated list\n          state = isBool ? state : !self.hasClass( className );\n          self[ state ? \"addClass\" : \"removeClass\" ]( className );\n        }\n\n      } else if ( type === \"undefined\" || type === \"boolean\" ) {\n        if ( this.className ) {\n          // store className if set\n          jQuery._data( this, \"__className__\", this.className );\n        }\n\n        // toggle whole className\n        this.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n      }\n    });\n  },\n\n  hasClass: function( selector ) {\n    var className = \" \" + selector + \" \",\n      i = 0,\n      l = this.length;\n    for ( ; i < l; i++ ) {\n      if ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) > -1 ) {\n        return true;\n      }\n    }\n\n    return false;\n  },\n\n  val: function( value ) {\n    var hooks, ret, isFunction,\n      elem = this[0];\n\n    if ( !arguments.length ) {\n      if ( elem ) {\n        hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n        if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n          return ret;\n        }\n\n        ret = elem.value;\n\n        return typeof ret === \"string\" ?\n          // handle most common string cases\n          ret.replace(rreturn, \"\") :\n          // handle cases where value is null/undef or number\n          ret == null ? \"\" : ret;\n      }\n\n      return;\n    }\n\n    isFunction = jQuery.isFunction( value );\n\n    return this.each(function( i ) {\n      var self = jQuery(this), val;\n\n      if ( this.nodeType !== 1 ) {\n        return;\n      }\n\n      if ( isFunction ) {\n        val = value.call( this, i, self.val() );\n      } else {\n        val = value;\n      }\n\n      // Treat null/undefined as \"\"; convert numbers to string\n      if ( val == null ) {\n        val = \"\";\n      } else if ( typeof val === \"number\" ) {\n        val += \"\";\n      } else if ( jQuery.isArray( val ) ) {\n        val = jQuery.map(val, function ( value ) {\n          return value == null ? \"\" : value + \"\";\n        });\n      }\n\n      hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n      // If set returns undefined, fall back to normal setting\n      if ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n        this.value = val;\n      }\n    });\n  }\n});\n\njQuery.extend({\n  valHooks: {\n    option: {\n      get: function( elem ) {\n        // attributes.value is undefined in Blackberry 4.7 but\n        // uses .value. See #6932\n        var val = elem.attributes.value;\n        return !val || val.specified ? elem.value : elem.text;\n      }\n    },\n    select: {\n      get: function( elem ) {\n        var value, i, max, option,\n          index = elem.selectedIndex,\n          values = [],\n          options = elem.options,\n          one = elem.type === \"select-one\";\n\n        // Nothing was selected\n        if ( index < 0 ) {\n          return null;\n        }\n\n        // Loop through all the selected options\n        i = one ? index : 0;\n        max = one ? index + 1 : options.length;\n        for ( ; i < max; i++ ) {\n          option = options[ i ];\n\n          // Don't return options that are disabled or in a disabled optgroup\n          if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n              (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n            // Get the specific value for the option\n            value = jQuery( option ).val();\n\n            // We don't need an array for one selects\n            if ( one ) {\n              return value;\n            }\n\n            // Multi-Selects return an array\n            values.push( value );\n          }\n        }\n\n        // Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n        if ( one && !values.length && options.length ) {\n          return jQuery( options[ index ] ).val();\n        }\n\n        return values;\n      },\n\n      set: function( elem, value ) {\n        var values = jQuery.makeArray( value );\n\n        jQuery(elem).find(\"option\").each(function() {\n          this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n        });\n\n        if ( !values.length ) {\n          elem.selectedIndex = -1;\n        }\n        return values;\n      }\n    }\n  },\n\n  attrFn: {\n    val: true,\n    css: true,\n    html: true,\n    text: true,\n    data: true,\n    width: true,\n    height: true,\n    offset: true\n  },\n\n  attr: function( elem, name, value, pass ) {\n    var ret, hooks, notxml,\n      nType = elem.nodeType;\n\n    // don't get/set attributes on text, comment and attribute nodes\n    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n      return;\n    }\n\n    if ( pass && name in jQuery.attrFn ) {\n      return jQuery( elem )[ name ]( value );\n    }\n\n    // Fallback to prop when attributes are not supported\n    if ( typeof elem.getAttribute === \"undefined\" ) {\n      return jQuery.prop( elem, name, value );\n    }\n\n    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n    // All attributes are lowercase\n    // Grab necessary hook if one is defined\n    if ( notxml ) {\n      name = name.toLowerCase();\n      hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n    }\n\n    if ( value !== undefined ) {\n\n      if ( value === null ) {\n        jQuery.removeAttr( elem, name );\n        return;\n\n      } else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n        return ret;\n\n      } else {\n        elem.setAttribute( name, \"\" + value );\n        return value;\n      }\n\n    } else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n      return ret;\n\n    } else {\n\n      ret = elem.getAttribute( name );\n\n      // Non-existent attributes return null, we normalize to undefined\n      return ret === null ?\n        undefined :\n        ret;\n    }\n  },\n\n  removeAttr: function( elem, value ) {\n    var propName, attrNames, name, l, isBool,\n      i = 0;\n\n    if ( value && elem.nodeType === 1 ) {\n      attrNames = value.toLowerCase().split( rspace );\n      l = attrNames.length;\n\n      for ( ; i < l; i++ ) {\n        name = attrNames[ i ];\n\n        if ( name ) {\n          propName = jQuery.propFix[ name ] || name;\n          isBool = rboolean.test( name );\n\n          // See #9699 for explanation of this approach (setting first, then removal)\n          // Do not do this for boolean attributes (see #10870)\n          if ( !isBool ) {\n            jQuery.attr( elem, name, \"\" );\n          }\n          elem.removeAttribute( getSetAttribute ? name : propName );\n\n          // Set corresponding property to false for boolean attributes\n          if ( isBool && propName in elem ) {\n            elem[ propName ] = false;\n          }\n        }\n      }\n    }\n  },\n\n  attrHooks: {\n    type: {\n      set: function( elem, value ) {\n        // We can't allow the type property to be changed (since it causes problems in IE)\n        if ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n          jQuery.error( \"type property can't be changed\" );\n        } else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n          // Setting the type on a radio button after the value resets the value in IE6-9\n          // Reset value to it's default in case type is set after value\n          // This is for element creation\n          var val = elem.value;\n          elem.setAttribute( \"type\", value );\n          if ( val ) {\n            elem.value = val;\n          }\n          return value;\n        }\n      }\n    },\n    // Use the value property for back compat\n    // Use the nodeHook for button elements in IE6/7 (#1954)\n    value: {\n      get: function( elem, name ) {\n        if ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n          return nodeHook.get( elem, name );\n        }\n        return name in elem ?\n          elem.value :\n          null;\n      },\n      set: function( elem, value, name ) {\n        if ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n          return nodeHook.set( elem, value, name );\n        }\n        // Does not return so that setAttribute is also used\n        elem.value = value;\n      }\n    }\n  },\n\n  propFix: {\n    tabindex: \"tabIndex\",\n    readonly: \"readOnly\",\n    \"for\": \"htmlFor\",\n    \"class\": \"className\",\n    maxlength: \"maxLength\",\n    cellspacing: \"cellSpacing\",\n    cellpadding: \"cellPadding\",\n    rowspan: \"rowSpan\",\n    colspan: \"colSpan\",\n    usemap: \"useMap\",\n    frameborder: \"frameBorder\",\n    contenteditable: \"contentEditable\"\n  },\n\n  prop: function( elem, name, value ) {\n    var ret, hooks, notxml,\n      nType = elem.nodeType;\n\n    // don't get/set properties on text, comment and attribute nodes\n    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n      return;\n    }\n\n    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n    if ( notxml ) {\n      // Fix name and attach hooks\n      name = jQuery.propFix[ name ] || name;\n      hooks = jQuery.propHooks[ name ];\n    }\n\n    if ( value !== undefined ) {\n      if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n        return ret;\n\n      } else {\n        return ( elem[ name ] = value );\n      }\n\n    } else {\n      if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n        return ret;\n\n      } else {\n        return elem[ name ];\n      }\n    }\n  },\n\n  propHooks: {\n    tabIndex: {\n      get: function( elem ) {\n        // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n        // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n        var attributeNode = elem.getAttributeNode(\"tabindex\");\n\n        return attributeNode && attributeNode.specified ?\n          parseInt( attributeNode.value, 10 ) :\n          rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n            0 :\n            undefined;\n      }\n    }\n  }\n});\n\n// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)\njQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;\n\n// Hook for boolean attributes\nboolHook = {\n  get: function( elem, name ) {\n    // Align boolean attributes with corresponding properties\n    // Fall back to attribute presence where some booleans are not supported\n    var attrNode,\n      property = jQuery.prop( elem, name );\n    return property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n      name.toLowerCase() :\n      undefined;\n  },\n  set: function( elem, value, name ) {\n    var propName;\n    if ( value === false ) {\n      // Remove boolean attributes when set to false\n      jQuery.removeAttr( elem, name );\n    } else {\n      // value is true since we know at this point it's type boolean and not false\n      // Set boolean attributes to the same name and set the DOM property\n      propName = jQuery.propFix[ name ] || name;\n      if ( propName in elem ) {\n        // Only set the IDL specifically if it already exists on the element\n        elem[ propName ] = true;\n      }\n\n      elem.setAttribute( name, name.toLowerCase() );\n    }\n    return name;\n  }\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n  fixSpecified = {\n    name: true,\n    id: true,\n    coords: true\n  };\n\n  // Use this for any attribute in IE6/7\n  // This fixes almost every IE6/7 issue\n  nodeHook = jQuery.valHooks.button = {\n    get: function( elem, name ) {\n      var ret;\n      ret = elem.getAttributeNode( name );\n      return ret && ( fixSpecified[ name ] ? ret.nodeValue !== \"\" : ret.specified ) ?\n        ret.nodeValue :\n        undefined;\n    },\n    set: function( elem, value, name ) {\n      // Set the existing or create a new attribute node\n      var ret = elem.getAttributeNode( name );\n      if ( !ret ) {\n        ret = document.createAttribute( name );\n        elem.setAttributeNode( ret );\n      }\n      return ( ret.nodeValue = value + \"\" );\n    }\n  };\n\n  // Apply the nodeHook to tabindex\n  jQuery.attrHooks.tabindex.set = nodeHook.set;\n\n  // Set width and height to auto instead of 0 on empty string( Bug #8150 )\n  // This is for removals\n  jQuery.each([ \"width\", \"height\" ], function( i, name ) {\n    jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n      set: function( elem, value ) {\n        if ( value === \"\" ) {\n          elem.setAttribute( name, \"auto\" );\n          return value;\n        }\n      }\n    });\n  });\n\n  // Set contenteditable to false on removals(#10429)\n  // Setting to empty string throws an error as an invalid value\n  jQuery.attrHooks.contenteditable = {\n    get: nodeHook.get,\n    set: function( elem, value, name ) {\n      if ( value === \"\" ) {\n        value = \"false\";\n      }\n      nodeHook.set( elem, value, name );\n    }\n  };\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n  jQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n    jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n      get: function( elem ) {\n        var ret = elem.getAttribute( name, 2 );\n        return ret === null ? undefined : ret;\n      }\n    });\n  });\n}\n\nif ( !jQuery.support.style ) {\n  jQuery.attrHooks.style = {\n    get: function( elem ) {\n      // Return undefined in the case of empty string\n      // Normalize to lowercase since IE uppercases css property names\n      return elem.style.cssText.toLowerCase() || undefined;\n    },\n    set: function( elem, value ) {\n      return ( elem.style.cssText = \"\" + value );\n    }\n  };\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n  jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n    get: function( elem ) {\n      var parent = elem.parentNode;\n\n      if ( parent ) {\n        parent.selectedIndex;\n\n        // Make sure that it also works with optgroups, see #5701\n        if ( parent.parentNode ) {\n          parent.parentNode.selectedIndex;\n        }\n      }\n      return null;\n    }\n  });\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n  jQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n  jQuery.each([ \"radio\", \"checkbox\" ], function() {\n    jQuery.valHooks[ this ] = {\n      get: function( elem ) {\n        // Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n        return elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n      }\n    };\n  });\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n  jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n    set: function( elem, value ) {\n      if ( jQuery.isArray( value ) ) {\n        return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n      }\n    }\n  });\n});\n\n\n\n\nvar rformElems = /^(?:textarea|input|select)$/i,\n  rtypenamespace = /^([^\\.]*)?(?:\\.(.+))?$/,\n  rhoverHack = /(?:^|\\s)hover(\\.\\S+)?\\b/,\n  rkeyEvent = /^key/,\n  rmouseEvent = /^(?:mouse|contextmenu)|click/,\n  rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n  rquickIs = /^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,\n  quickParse = function( selector ) {\n    var quick = rquickIs.exec( selector );\n    if ( quick ) {\n      //   0  1    2   3\n      // [ _, tag, id, class ]\n      quick[1] = ( quick[1] || \"\" ).toLowerCase();\n      quick[3] = quick[3] && new RegExp( \"(?:^|\\\\s)\" + quick[3] + \"(?:\\\\s|$)\" );\n    }\n    return quick;\n  },\n  quickIs = function( elem, m ) {\n    var attrs = elem.attributes || {};\n    return (\n      (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&\n      (!m[2] || (attrs.id || {}).value === m[2]) &&\n      (!m[3] || m[3].test( (attrs[ \"class\" ] || {}).value ))\n    );\n  },\n  hoverHack = function( events ) {\n    return jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n  };\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n  add: function( elem, types, handler, data, selector ) {\n\n    var elemData, eventHandle, events,\n      t, tns, type, namespaces, handleObj,\n      handleObjIn, quick, handlers, special;\n\n    // Don't attach events to noData or text/comment nodes (allow plain objects tho)\n    if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n      return;\n    }\n\n    // Caller can pass in an object of custom data in lieu of the handler\n    if ( handler.handler ) {\n      handleObjIn = handler;\n      handler = handleObjIn.handler;\n      selector = handleObjIn.selector;\n    }\n\n    // Make sure that the handler has a unique ID, used to find/remove it later\n    if ( !handler.guid ) {\n      handler.guid = jQuery.guid++;\n    }\n\n    // Init the element's event structure and main handler, if this is the first\n    events = elemData.events;\n    if ( !events ) {\n      elemData.events = events = {};\n    }\n    eventHandle = elemData.handle;\n    if ( !eventHandle ) {\n      elemData.handle = eventHandle = function( e ) {\n        // Discard the second event of a jQuery.event.trigger() and\n        // when an event is called after a page has unloaded\n        return typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n          jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n          undefined;\n      };\n      // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n      eventHandle.elem = elem;\n    }\n\n    // Handle multiple events separated by a space\n    // jQuery(...).bind(\"mouseover mouseout\", fn);\n    types = jQuery.trim( hoverHack(types) ).split( \" \" );\n    for ( t = 0; t < types.length; t++ ) {\n\n      tns = rtypenamespace.exec( types[t] ) || [];\n      type = tns[1];\n      namespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n      // If event changes its type, use the special event handlers for the changed type\n      special = jQuery.event.special[ type ] || {};\n\n      // If selector defined, determine special event api type, otherwise given type\n      type = ( selector ? special.delegateType : special.bindType ) || type;\n\n      // Update special based on newly reset type\n      special = jQuery.event.special[ type ] || {};\n\n      // handleObj is passed to all event handlers\n      handleObj = jQuery.extend({\n        type: type,\n        origType: tns[1],\n        data: data,\n        handler: handler,\n        guid: handler.guid,\n        selector: selector,\n        quick: selector && quickParse( selector ),\n        namespace: namespaces.join(\".\")\n      }, handleObjIn );\n\n      // Init the event handler queue if we're the first\n      handlers = events[ type ];\n      if ( !handlers ) {\n        handlers = events[ type ] = [];\n        handlers.delegateCount = 0;\n\n        // Only use addEventListener/attachEvent if the special events handler returns false\n        if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n          // Bind the global event handler to the element\n          if ( elem.addEventListener ) {\n            elem.addEventListener( type, eventHandle, false );\n\n          } else if ( elem.attachEvent ) {\n            elem.attachEvent( \"on\" + type, eventHandle );\n          }\n        }\n      }\n\n      if ( special.add ) {\n        special.add.call( elem, handleObj );\n\n        if ( !handleObj.handler.guid ) {\n          handleObj.handler.guid = handler.guid;\n        }\n      }\n\n      // Add to the element's handler list, delegates in front\n      if ( selector ) {\n        handlers.splice( handlers.delegateCount++, 0, handleObj );\n      } else {\n        handlers.push( handleObj );\n      }\n\n      // Keep track of which events have ever been used, for event optimization\n      jQuery.event.global[ type ] = true;\n    }\n\n    // Nullify elem to prevent memory leaks in IE\n    elem = null;\n  },\n\n  global: {},\n\n  // Detach an event or set of events from an element\n  remove: function( elem, types, handler, selector, mappedTypes ) {\n\n    var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),\n      t, tns, type, origType, namespaces, origCount,\n      j, events, special, handle, eventType, handleObj;\n\n    if ( !elemData || !(events = elemData.events) ) {\n      return;\n    }\n\n    // Once for each type.namespace in types; type may be omitted\n    types = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n    for ( t = 0; t < types.length; t++ ) {\n      tns = rtypenamespace.exec( types[t] ) || [];\n      type = origType = tns[1];\n      namespaces = tns[2];\n\n      // Unbind all events (on this namespace, if provided) for the element\n      if ( !type ) {\n        for ( type in events ) {\n          jQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n        }\n        continue;\n      }\n\n      special = jQuery.event.special[ type ] || {};\n      type = ( selector? special.delegateType : special.bindType ) || type;\n      eventType = events[ type ] || [];\n      origCount = eventType.length;\n      namespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n\n      // Remove matching events\n      for ( j = 0; j < eventType.length; j++ ) {\n        handleObj = eventType[ j ];\n\n        if ( ( mappedTypes || origType === handleObj.origType ) &&\n           ( !handler || handler.guid === handleObj.guid ) &&\n           ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n           ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n          eventType.splice( j--, 1 );\n\n          if ( handleObj.selector ) {\n            eventType.delegateCount--;\n          }\n          if ( special.remove ) {\n            special.remove.call( elem, handleObj );\n          }\n        }\n      }\n\n      // Remove generic event handler if we removed something and no more handlers exist\n      // (avoids potential for endless recursion during removal of special event handlers)\n      if ( eventType.length === 0 && origCount !== eventType.length ) {\n        if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {\n          jQuery.removeEvent( elem, type, elemData.handle );\n        }\n\n        delete events[ type ];\n      }\n    }\n\n    // Remove the expando if it's no longer used\n    if ( jQuery.isEmptyObject( events ) ) {\n      handle = elemData.handle;\n      if ( handle ) {\n        handle.elem = null;\n      }\n\n      // removeData also checks for emptiness and clears the expando if empty\n      // so use it instead of delete\n      jQuery.removeData( elem, [ \"events\", \"handle\" ], true );\n    }\n  },\n\n  // Events that are safe to short-circuit if no handlers are attached.\n  // Native DOM events should not be added, they may have inline handlers.\n  customEvent: {\n    \"getData\": true,\n    \"setData\": true,\n    \"changeData\": true\n  },\n\n  trigger: function( event, data, elem, onlyHandlers ) {\n    // Don't do events on text and comment nodes\n    if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n      return;\n    }\n\n    // Event object or event type\n    var type = event.type || event,\n      namespaces = [],\n      cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;\n\n    // focus/blur morphs to focusin/out; ensure we're not firing them right now\n    if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n      return;\n    }\n\n    if ( type.indexOf( \"!\" ) >= 0 ) {\n      // Exclusive events trigger only for the exact event (no namespaces)\n      type = type.slice(0, -1);\n      exclusive = true;\n    }\n\n    if ( type.indexOf( \".\" ) >= 0 ) {\n      // Namespaced trigger; create a regexp to match event type in handle()\n      namespaces = type.split(\".\");\n      type = namespaces.shift();\n      namespaces.sort();\n    }\n\n    if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n      // No jQuery handlers for this event type, and it can't have inline handlers\n      return;\n    }\n\n    // Caller can pass in an Event, Object, or just an event type string\n    event = typeof event === \"object\" ?\n      // jQuery.Event object\n      event[ jQuery.expando ] ? event :\n      // Object literal\n      new jQuery.Event( type, event ) :\n      // Just the event type (string)\n      new jQuery.Event( type );\n\n    event.type = type;\n    event.isTrigger = true;\n    event.exclusive = exclusive;\n    event.namespace = namespaces.join( \".\" );\n    event.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.)?\") + \"(\\\\.|$)\") : null;\n    ontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n    // Handle a global trigger\n    if ( !elem ) {\n\n      // TODO: Stop taunting the data cache; remove global events and always attach to document\n      cache = jQuery.cache;\n      for ( i in cache ) {\n        if ( cache[ i ].events && cache[ i ].events[ type ] ) {\n          jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n        }\n      }\n      return;\n    }\n\n    // Clean up the event in case it is being reused\n    event.result = undefined;\n    if ( !event.target ) {\n      event.target = elem;\n    }\n\n    // Clone any incoming data and prepend the event, creating the handler arg list\n    data = data != null ? jQuery.makeArray( data ) : [];\n    data.unshift( event );\n\n    // Allow special events to draw outside the lines\n    special = jQuery.event.special[ type ] || {};\n    if ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n      return;\n    }\n\n    // Determine event propagation path in advance, per W3C events spec (#9951)\n    // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n    eventPath = [[ elem, special.bindType || type ]];\n    if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n      bubbleType = special.delegateType || type;\n      cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n      old = null;\n      for ( ; cur; cur = cur.parentNode ) {\n        eventPath.push([ cur, bubbleType ]);\n        old = cur;\n      }\n\n      // Only add window if we got to document (e.g., not plain obj or detached DOM)\n      if ( old && old === elem.ownerDocument ) {\n        eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n      }\n    }\n\n    // Fire handlers on the event path\n    for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n      cur = eventPath[i][0];\n      event.type = eventPath[i][1];\n\n      handle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n      if ( handle ) {\n        handle.apply( cur, data );\n      }\n      // Note that this is a bare JS function and not a jQuery handler\n      handle = ontype && cur[ ontype ];\n      if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {\n        event.preventDefault();\n      }\n    }\n    event.type = type;\n\n    // If nobody prevented the default action, do it now\n    if ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n      if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n        !(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n        // Call a native DOM method on the target with the same name name as the event.\n        // Can't use an .isFunction() check here because IE6/7 fails that test.\n        // Don't do default actions on window, that's where global variables be (#6170)\n        // IE<9 dies on focus/blur to hidden element (#1486)\n        if ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n          // Don't re-trigger an onFOO event when we call its FOO() method\n          old = elem[ ontype ];\n\n          if ( old ) {\n            elem[ ontype ] = null;\n          }\n\n          // Prevent re-triggering of the same event, since we already bubbled it above\n          jQuery.event.triggered = type;\n          elem[ type ]();\n          jQuery.event.triggered = undefined;\n\n          if ( old ) {\n            elem[ ontype ] = old;\n          }\n        }\n      }\n    }\n\n    return event.result;\n  },\n\n  dispatch: function( event ) {\n\n    // Make a writable jQuery.Event from the native event object\n    event = jQuery.event.fix( event || window.event );\n\n    var handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n      delegateCount = handlers.delegateCount,\n      args = [].slice.call( arguments, 0 ),\n      run_all = !event.exclusive && !event.namespace,\n      special = jQuery.event.special[ event.type ] || {},\n      handlerQueue = [],\n      i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;\n\n    // Use the fix-ed jQuery.Event rather than the (read-only) native event\n    args[0] = event;\n    event.delegateTarget = this;\n\n    // Call the preDispatch hook for the mapped type, and let it bail if desired\n    if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n      return;\n    }\n\n    // Determine handlers that should run if there are delegated events\n    // Avoid non-left-click bubbling in Firefox (#3861)\n    if ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n      // Pregenerate a single jQuery object for reuse with .is()\n      jqcur = jQuery(this);\n      jqcur.context = this.ownerDocument || this;\n\n      for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n        // Don't process events on disabled elements (#6911, #8165)\n        if ( cur.disabled !== true ) {\n          selMatch = {};\n          matches = [];\n          jqcur[0] = cur;\n          for ( i = 0; i < delegateCount; i++ ) {\n            handleObj = handlers[ i ];\n            sel = handleObj.selector;\n\n            if ( selMatch[ sel ] === undefined ) {\n              selMatch[ sel ] = (\n                handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )\n              );\n            }\n            if ( selMatch[ sel ] ) {\n              matches.push( handleObj );\n            }\n          }\n          if ( matches.length ) {\n            handlerQueue.push({ elem: cur, matches: matches });\n          }\n        }\n      }\n    }\n\n    // Add the remaining (directly-bound) handlers\n    if ( handlers.length > delegateCount ) {\n      handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n    }\n\n    // Run delegates first; they may want to stop propagation beneath us\n    for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n      matched = handlerQueue[ i ];\n      event.currentTarget = matched.elem;\n\n      for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n        handleObj = matched.matches[ j ];\n\n        // Triggered event must either 1) be non-exclusive and have no namespace, or\n        // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n        if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n          event.data = handleObj.data;\n          event.handleObj = handleObj;\n\n          ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n              .apply( matched.elem, args );\n\n          if ( ret !== undefined ) {\n            event.result = ret;\n            if ( ret === false ) {\n              event.preventDefault();\n              event.stopPropagation();\n            }\n          }\n        }\n      }\n    }\n\n    // Call the postDispatch hook for the mapped type\n    if ( special.postDispatch ) {\n      special.postDispatch.call( this, event );\n    }\n\n    return event.result;\n  },\n\n  // Includes some event props shared by KeyEvent and MouseEvent\n  // *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n  props: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n  fixHooks: {},\n\n  keyHooks: {\n    props: \"char charCode key keyCode\".split(\" \"),\n    filter: function( event, original ) {\n\n      // Add which for key events\n      if ( event.which == null ) {\n        event.which = original.charCode != null ? original.charCode : original.keyCode;\n      }\n\n      return event;\n    }\n  },\n\n  mouseHooks: {\n    props: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n    filter: function( event, original ) {\n      var eventDoc, doc, body,\n        button = original.button,\n        fromElement = original.fromElement;\n\n      // Calculate pageX/Y if missing and clientX/Y available\n      if ( event.pageX == null && original.clientX != null ) {\n        eventDoc = event.target.ownerDocument || document;\n        doc = eventDoc.documentElement;\n        body = eventDoc.body;\n\n        event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n        event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n      }\n\n      // Add relatedTarget, if necessary\n      if ( !event.relatedTarget && fromElement ) {\n        event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n      }\n\n      // Add which for click: 1 === left; 2 === middle; 3 === right\n      // Note: button is not normalized, so don't use it\n      if ( !event.which && button !== undefined ) {\n        event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n      }\n\n      return event;\n    }\n  },\n\n  fix: function( event ) {\n    if ( event[ jQuery.expando ] ) {\n      return event;\n    }\n\n    // Create a writable copy of the event object and normalize some properties\n    var i, prop,\n      originalEvent = event,\n      fixHook = jQuery.event.fixHooks[ event.type ] || {},\n      copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n    event = jQuery.Event( originalEvent );\n\n    for ( i = copy.length; i; ) {\n      prop = copy[ --i ];\n      event[ prop ] = originalEvent[ prop ];\n    }\n\n    // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n    if ( !event.target ) {\n      event.target = originalEvent.srcElement || document;\n    }\n\n    // Target should not be a text node (#504, Safari)\n    if ( event.target.nodeType === 3 ) {\n      event.target = event.target.parentNode;\n    }\n\n    // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)\n    if ( event.metaKey === undefined ) {\n      event.metaKey = event.ctrlKey;\n    }\n\n    return fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n  },\n\n  special: {\n    ready: {\n      // Make sure the ready event is setup\n      setup: jQuery.bindReady\n    },\n\n    load: {\n      // Prevent triggered image.load events from bubbling to window.load\n      noBubble: true\n    },\n\n    focus: {\n      delegateType: \"focusin\"\n    },\n    blur: {\n      delegateType: \"focusout\"\n    },\n\n    beforeunload: {\n      setup: function( data, namespaces, eventHandle ) {\n        // We only want to do this special case on windows\n        if ( jQuery.isWindow( this ) ) {\n          this.onbeforeunload = eventHandle;\n        }\n      },\n\n      teardown: function( namespaces, eventHandle ) {\n        if ( this.onbeforeunload === eventHandle ) {\n          this.onbeforeunload = null;\n        }\n      }\n    }\n  },\n\n  simulate: function( type, elem, event, bubble ) {\n    // Piggyback on a donor event to simulate a different one.\n    // Fake originalEvent to avoid donor's stopPropagation, but if the\n    // simulated event prevents default then we do the same on the donor.\n    var e = jQuery.extend(\n      new jQuery.Event(),\n      event,\n      { type: type,\n        isSimulated: true,\n        originalEvent: {}\n      }\n    );\n    if ( bubble ) {\n      jQuery.event.trigger( e, null, elem );\n    } else {\n      jQuery.event.dispatch.call( elem, e );\n    }\n    if ( e.isDefaultPrevented() ) {\n      event.preventDefault();\n    }\n  }\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n  function( elem, type, handle ) {\n    if ( elem.removeEventListener ) {\n      elem.removeEventListener( type, handle, false );\n    }\n  } :\n  function( elem, type, handle ) {\n    if ( elem.detachEvent ) {\n      elem.detachEvent( \"on\" + type, handle );\n    }\n  };\n\njQuery.Event = function( src, props ) {\n  // Allow instantiation without the 'new' keyword\n  if ( !(this instanceof jQuery.Event) ) {\n    return new jQuery.Event( src, props );\n  }\n\n  // Event object\n  if ( src && src.type ) {\n    this.originalEvent = src;\n    this.type = src.type;\n\n    // Events bubbling up the document may have been marked as prevented\n    // by a handler lower down the tree; reflect the correct value.\n    this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n      src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n  // Event type\n  } else {\n    this.type = src;\n  }\n\n  // Put explicitly provided properties onto the event object\n  if ( props ) {\n    jQuery.extend( this, props );\n  }\n\n  // Create a timestamp if incoming event doesn't have one\n  this.timeStamp = src && src.timeStamp || jQuery.now();\n\n  // Mark it as fixed\n  this[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n  return false;\n}\nfunction returnTrue() {\n  return true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n  preventDefault: function() {\n    this.isDefaultPrevented = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n\n    // if preventDefault exists run it on the original event\n    if ( e.preventDefault ) {\n      e.preventDefault();\n\n    // otherwise set the returnValue property of the original event to false (IE)\n    } else {\n      e.returnValue = false;\n    }\n  },\n  stopPropagation: function() {\n    this.isPropagationStopped = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n    // if stopPropagation exists run it on the original event\n    if ( e.stopPropagation ) {\n      e.stopPropagation();\n    }\n    // otherwise set the cancelBubble property of the original event to true (IE)\n    e.cancelBubble = true;\n  },\n  stopImmediatePropagation: function() {\n    this.isImmediatePropagationStopped = returnTrue;\n    this.stopPropagation();\n  },\n  isDefaultPrevented: returnFalse,\n  isPropagationStopped: returnFalse,\n  isImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n  mouseenter: \"mouseover\",\n  mouseleave: \"mouseout\"\n}, function( orig, fix ) {\n  jQuery.event.special[ orig ] = {\n    delegateType: fix,\n    bindType: fix,\n\n    handle: function( event ) {\n      var target = this,\n        related = event.relatedTarget,\n        handleObj = event.handleObj,\n        selector = handleObj.selector,\n        ret;\n\n      // For mousenter/leave call the handler if related is outside the target.\n      // NB: No relatedTarget if the mouse left/entered the browser window\n      if ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n        event.type = handleObj.origType;\n        ret = handleObj.handler.apply( this, arguments );\n        event.type = fix;\n      }\n      return ret;\n    }\n  };\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n  jQuery.event.special.submit = {\n    setup: function() {\n      // Only need this for delegated form submit events\n      if ( jQuery.nodeName( this, \"form\" ) ) {\n        return false;\n      }\n\n      // Lazy-add a submit handler when a descendant form may potentially be submitted\n      jQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n        // Node name check avoids a VML-related crash in IE (#9807)\n        var elem = e.target,\n          form = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n        if ( form && !form._submit_attached ) {\n          jQuery.event.add( form, \"submit._submit\", function( event ) {\n            event._submit_bubble = true;\n          });\n          form._submit_attached = true;\n        }\n      });\n      // return undefined since we don't need an event listener\n    },\n\n    postDispatch: function( event ) {\n      // If form was submitted by the user, bubble the event up the tree\n      if ( event._submit_bubble ) {\n        delete event._submit_bubble;\n        if ( this.parentNode && !event.isTrigger ) {\n          jQuery.event.simulate( \"submit\", this.parentNode, event, true );\n        }\n      }\n    },\n\n    teardown: function() {\n      // Only need this for delegated form submit events\n      if ( jQuery.nodeName( this, \"form\" ) ) {\n        return false;\n      }\n\n      // Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n      jQuery.event.remove( this, \"._submit\" );\n    }\n  };\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n  jQuery.event.special.change = {\n\n    setup: function() {\n\n      if ( rformElems.test( this.nodeName ) ) {\n        // IE doesn't fire change on a check/radio until blur; trigger it on click\n        // after a propertychange. Eat the blur-change in special.change.handle.\n        // This still fires onchange a second time for check/radio after blur.\n        if ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n          jQuery.event.add( this, \"propertychange._change\", function( event ) {\n            if ( event.originalEvent.propertyName === \"checked\" ) {\n              this._just_changed = true;\n            }\n          });\n          jQuery.event.add( this, \"click._change\", function( event ) {\n            if ( this._just_changed && !event.isTrigger ) {\n              this._just_changed = false;\n              jQuery.event.simulate( \"change\", this, event, true );\n            }\n          });\n        }\n        return false;\n      }\n      // Delegated event; lazy-add a change handler on descendant inputs\n      jQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n        var elem = e.target;\n\n        if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {\n          jQuery.event.add( elem, \"change._change\", function( event ) {\n            if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n              jQuery.event.simulate( \"change\", this.parentNode, event, true );\n            }\n          });\n          elem._change_attached = true;\n        }\n      });\n    },\n\n    handle: function( event ) {\n      var elem = event.target;\n\n      // Swallow native change events from checkbox/radio, we already triggered them above\n      if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n        return event.handleObj.handler.apply( this, arguments );\n      }\n    },\n\n    teardown: function() {\n      jQuery.event.remove( this, \"._change\" );\n\n      return rformElems.test( this.nodeName );\n    }\n  };\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n  jQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n    // Attach a single capturing handler while someone wants focusin/focusout\n    var attaches = 0,\n      handler = function( event ) {\n        jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n      };\n\n    jQuery.event.special[ fix ] = {\n      setup: function() {\n        if ( attaches++ === 0 ) {\n          document.addEventListener( orig, handler, true );\n        }\n      },\n      teardown: function() {\n        if ( --attaches === 0 ) {\n          document.removeEventListener( orig, handler, true );\n        }\n      }\n    };\n  });\n}\n\njQuery.fn.extend({\n\n  on: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n    var origFn, type;\n\n    // Types can be a map of types/handlers\n    if ( typeof types === \"object\" ) {\n      // ( types-Object, selector, data )\n      if ( typeof selector !== \"string\" ) { // && selector != null\n        // ( types-Object, data )\n        data = data || selector;\n        selector = undefined;\n      }\n      for ( type in types ) {\n        this.on( type, selector, data, types[ type ], one );\n      }\n      return this;\n    }\n\n    if ( data == null && fn == null ) {\n      // ( types, fn )\n      fn = selector;\n      data = selector = undefined;\n    } else if ( fn == null ) {\n      if ( typeof selector === \"string\" ) {\n        // ( types, selector, fn )\n        fn = data;\n        data = undefined;\n      } else {\n        // ( types, data, fn )\n        fn = data;\n        data = selector;\n        selector = undefined;\n      }\n    }\n    if ( fn === false ) {\n      fn = returnFalse;\n    } else if ( !fn ) {\n      return this;\n    }\n\n    if ( one === 1 ) {\n      origFn = fn;\n      fn = function( event ) {\n        // Can use an empty set, since event contains the info\n        jQuery().off( event );\n        return origFn.apply( this, arguments );\n      };\n      // Use same guid so caller can remove using origFn\n      fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n    }\n    return this.each( function() {\n      jQuery.event.add( this, types, fn, data, selector );\n    });\n  },\n  one: function( types, selector, data, fn ) {\n    return this.on( types, selector, data, fn, 1 );\n  },\n  off: function( types, selector, fn ) {\n    if ( types && types.preventDefault && types.handleObj ) {\n      // ( event )  dispatched jQuery.Event\n      var handleObj = types.handleObj;\n      jQuery( types.delegateTarget ).off(\n        handleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n        handleObj.selector,\n        handleObj.handler\n      );\n      return this;\n    }\n    if ( typeof types === \"object\" ) {\n      // ( types-object [, selector] )\n      for ( var type in types ) {\n        this.off( type, selector, types[ type ] );\n      }\n      return this;\n    }\n    if ( selector === false || typeof selector === \"function\" ) {\n      // ( types [, fn] )\n      fn = selector;\n      selector = undefined;\n    }\n    if ( fn === false ) {\n      fn = returnFalse;\n    }\n    return this.each(function() {\n      jQuery.event.remove( this, types, fn, selector );\n    });\n  },\n\n  bind: function( types, data, fn ) {\n    return this.on( types, null, data, fn );\n  },\n  unbind: function( types, fn ) {\n    return this.off( types, null, fn );\n  },\n\n  live: function( types, data, fn ) {\n    jQuery( this.context ).on( types, this.selector, data, fn );\n    return this;\n  },\n  die: function( types, fn ) {\n    jQuery( this.context ).off( types, this.selector || \"**\", fn );\n    return this;\n  },\n\n  delegate: function( selector, types, data, fn ) {\n    return this.on( types, selector, data, fn );\n  },\n  undelegate: function( selector, types, fn ) {\n    // ( namespace ) or ( selector, types [, fn] )\n    return arguments.length == 1? this.off( selector, \"**\" ) : this.off( types, selector, fn );\n  },\n\n  trigger: function( type, data ) {\n    return this.each(function() {\n      jQuery.event.trigger( type, data, this );\n    });\n  },\n  triggerHandler: function( type, data ) {\n    if ( this[0] ) {\n      return jQuery.event.trigger( type, data, this[0], true );\n    }\n  },\n\n  toggle: function( fn ) {\n    // Save reference to arguments for access in closure\n    var args = arguments,\n      guid = fn.guid || jQuery.guid++,\n      i = 0,\n      toggler = function( event ) {\n        // Figure out which function to execute\n        var lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n        jQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n        // Make sure that clicks stop\n        event.preventDefault();\n\n        // and execute the function\n        return args[ lastToggle ].apply( this, arguments ) || false;\n      };\n\n    // link all the functions, so any of them can unbind this click handler\n    toggler.guid = guid;\n    while ( i < args.length ) {\n      args[ i++ ].guid = guid;\n    }\n\n    return this.click( toggler );\n  },\n\n  hover: function( fnOver, fnOut ) {\n    return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n  }\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n  \"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n  \"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n  // Handle event binding\n  jQuery.fn[ name ] = function( data, fn ) {\n    if ( fn == null ) {\n      fn = data;\n      data = null;\n    }\n\n    return arguments.length > 0 ?\n      this.on( name, null, data, fn ) :\n      this.trigger( name );\n  };\n\n  if ( jQuery.attrFn ) {\n    jQuery.attrFn[ name ] = true;\n  }\n\n  if ( rkeyEvent.test( name ) ) {\n    jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n  }\n\n  if ( rmouseEvent.test( name ) ) {\n    jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n  }\n});\n\n\n\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n  expando = \"sizcache\" + (Math.random() + '').replace('.', ''),\n  done = 0,\n  toString = Object.prototype.toString,\n  hasDuplicate = false,\n  baseHasDuplicate = true,\n  rBackslash = /\\\\/g,\n  rReturn = /\\r\\n/g,\n  rNonWord = /\\W/;\n\n// Here we check if the JavaScript engine is using some sort of\n// optimization where it does not always call our comparision\n// function. If that is the case, discard the hasDuplicate value.\n//   Thus far that includes Google Chrome.\n[0, 0].sort(function() {\n  baseHasDuplicate = false;\n  return 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n  results = results || [];\n  context = context || document;\n\n  var origContext = context;\n\n  if ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n    return [];\n  }\n\n  if ( !selector || typeof selector !== \"string\" ) {\n    return results;\n  }\n\n  var m, set, checkSet, extra, ret, cur, pop, i,\n    prune = true,\n    contextXML = Sizzle.isXML( context ),\n    parts = [],\n    soFar = selector;\n\n  // Reset the position of the chunker regexp (start from head)\n  do {\n    chunker.exec( \"\" );\n    m = chunker.exec( soFar );\n\n    if ( m ) {\n      soFar = m[3];\n\n      parts.push( m[1] );\n\n      if ( m[2] ) {\n        extra = m[3];\n        break;\n      }\n    }\n  } while ( m );\n\n  if ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n    if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n      set = posProcess( parts[0] + parts[1], context, seed );\n\n    } else {\n      set = Expr.relative[ parts[0] ] ?\n        [ context ] :\n        Sizzle( parts.shift(), context );\n\n      while ( parts.length ) {\n        selector = parts.shift();\n\n        if ( Expr.relative[ selector ] ) {\n          selector += parts.shift();\n        }\n\n        set = posProcess( selector, set, seed );\n      }\n    }\n\n  } else {\n    // Take a shortcut and set the context if the root selector is an ID\n    // (but not if it'll be faster if the inner selector is an ID)\n    if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n        Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n      ret = Sizzle.find( parts.shift(), context, contextXML );\n      context = ret.expr ?\n        Sizzle.filter( ret.expr, ret.set )[0] :\n        ret.set[0];\n    }\n\n    if ( context ) {\n      ret = seed ?\n        { expr: parts.pop(), set: makeArray(seed) } :\n        Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n      set = ret.expr ?\n        Sizzle.filter( ret.expr, ret.set ) :\n        ret.set;\n\n      if ( parts.length > 0 ) {\n        checkSet = makeArray( set );\n\n      } else {\n        prune = false;\n      }\n\n      while ( parts.length ) {\n        cur = parts.pop();\n        pop = cur;\n\n        if ( !Expr.relative[ cur ] ) {\n          cur = \"\";\n        } else {\n          pop = parts.pop();\n        }\n\n        if ( pop == null ) {\n          pop = context;\n        }\n\n        Expr.relative[ cur ]( checkSet, pop, contextXML );\n      }\n\n    } else {\n      checkSet = parts = [];\n    }\n  }\n\n  if ( !checkSet ) {\n    checkSet = set;\n  }\n\n  if ( !checkSet ) {\n    Sizzle.error( cur || selector );\n  }\n\n  if ( toString.call(checkSet) === \"[object Array]\" ) {\n    if ( !prune ) {\n      results.push.apply( results, checkSet );\n\n    } else if ( context && context.nodeType === 1 ) {\n      for ( i = 0; checkSet[i] != null; i++ ) {\n        if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n          results.push( set[i] );\n        }\n      }\n\n    } else {\n      for ( i = 0; checkSet[i] != null; i++ ) {\n        if ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n          results.push( set[i] );\n        }\n      }\n    }\n\n  } else {\n    makeArray( checkSet, results );\n  }\n\n  if ( extra ) {\n    Sizzle( extra, origContext, results, seed );\n    Sizzle.uniqueSort( results );\n  }\n\n  return results;\n};\n\nSizzle.uniqueSort = function( results ) {\n  if ( sortOrder ) {\n    hasDuplicate = baseHasDuplicate;\n    results.sort( sortOrder );\n\n    if ( hasDuplicate ) {\n      for ( var i = 1; i < results.length; i++ ) {\n        if ( results[i] === results[ i - 1 ] ) {\n          results.splice( i--, 1 );\n        }\n      }\n    }\n  }\n\n  return results;\n};\n\nSizzle.matches = function( expr, set ) {\n  return Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n  return Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n  var set, i, len, match, type, left;\n\n  if ( !expr ) {\n    return [];\n  }\n\n  for ( i = 0, len = Expr.order.length; i < len; i++ ) {\n    type = Expr.order[i];\n\n    if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n      left = match[1];\n      match.splice( 1, 1 );\n\n      if ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n        match[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n        set = Expr.find[ type ]( match, context, isXML );\n\n        if ( set != null ) {\n          expr = expr.replace( Expr.match[ type ], \"\" );\n          break;\n        }\n      }\n    }\n  }\n\n  if ( !set ) {\n    set = typeof context.getElementsByTagName !== \"undefined\" ?\n      context.getElementsByTagName( \"*\" ) :\n      [];\n  }\n\n  return { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n  var match, anyFound,\n    type, found, item, filter, left,\n    i, pass,\n    old = expr,\n    result = [],\n    curLoop = set,\n    isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n  while ( expr && set.length ) {\n    for ( type in Expr.filter ) {\n      if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n        filter = Expr.filter[ type ];\n        left = match[1];\n\n        anyFound = false;\n\n        match.splice(1,1);\n\n        if ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n          continue;\n        }\n\n        if ( curLoop === result ) {\n          result = [];\n        }\n\n        if ( Expr.preFilter[ type ] ) {\n          match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n          if ( !match ) {\n            anyFound = found = true;\n\n          } else if ( match === true ) {\n            continue;\n          }\n        }\n\n        if ( match ) {\n          for ( i = 0; (item = curLoop[i]) != null; i++ ) {\n            if ( item ) {\n              found = filter( item, match, i, curLoop );\n              pass = not ^ found;\n\n              if ( inplace && found != null ) {\n                if ( pass ) {\n                  anyFound = true;\n\n                } else {\n                  curLoop[i] = false;\n                }\n\n              } else if ( pass ) {\n                result.push( item );\n                anyFound = true;\n              }\n            }\n          }\n        }\n\n        if ( found !== undefined ) {\n          if ( !inplace ) {\n            curLoop = result;\n          }\n\n          expr = expr.replace( Expr.match[ type ], \"\" );\n\n          if ( !anyFound ) {\n            return [];\n          }\n\n          break;\n        }\n      }\n    }\n\n    // Improper expression\n    if ( expr === old ) {\n      if ( anyFound == null ) {\n        Sizzle.error( expr );\n\n      } else {\n        break;\n      }\n    }\n\n    old = expr;\n  }\n\n  return curLoop;\n};\n\nSizzle.error = function( msg ) {\n  throw new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Utility function for retreiving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\nvar getText = Sizzle.getText = function( elem ) {\n    var i, node,\n    nodeType = elem.nodeType,\n    ret = \"\";\n\n  if ( nodeType ) {\n    if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n      // Use textContent || innerText for elements\n      if ( typeof elem.textContent === 'string' ) {\n        return elem.textContent;\n      } else if ( typeof elem.innerText === 'string' ) {\n        // Replace IE's carriage returns\n        return elem.innerText.replace( rReturn, '' );\n      } else {\n        // Traverse it's children\n        for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {\n          ret += getText( elem );\n        }\n      }\n    } else if ( nodeType === 3 || nodeType === 4 ) {\n      return elem.nodeValue;\n    }\n  } else {\n\n    // If no nodeType, this is expected to be an array\n    for ( i = 0; (node = elem[i]); i++ ) {\n      // Do not traverse comment nodes\n      if ( node.nodeType !== 8 ) {\n        ret += getText( node );\n      }\n    }\n  }\n  return ret;\n};\n\nvar Expr = Sizzle.selectors = {\n  order: [ \"ID\", \"NAME\", \"TAG\" ],\n\n  match: {\n    ID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n    CLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n    NAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n    ATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n    TAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n    CHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n    POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n    PSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n  },\n\n  leftMatch: {},\n\n  attrMap: {\n    \"class\": \"className\",\n    \"for\": \"htmlFor\"\n  },\n\n  attrHandle: {\n    href: function( elem ) {\n      return elem.getAttribute( \"href\" );\n    },\n    type: function( elem ) {\n      return elem.getAttribute( \"type\" );\n    }\n  },\n\n  relative: {\n    \"+\": function(checkSet, part){\n      var isPartStr = typeof part === \"string\",\n        isTag = isPartStr && !rNonWord.test( part ),\n        isPartStrNotTag = isPartStr && !isTag;\n\n      if ( isTag ) {\n        part = part.toLowerCase();\n      }\n\n      for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n        if ( (elem = checkSet[i]) ) {\n          while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n          checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n            elem || false :\n            elem === part;\n        }\n      }\n\n      if ( isPartStrNotTag ) {\n        Sizzle.filter( part, checkSet, true );\n      }\n    },\n\n    \">\": function( checkSet, part ) {\n      var elem,\n        isPartStr = typeof part === \"string\",\n        i = 0,\n        l = checkSet.length;\n\n      if ( isPartStr && !rNonWord.test( part ) ) {\n        part = part.toLowerCase();\n\n        for ( ; i < l; i++ ) {\n          elem = checkSet[i];\n\n          if ( elem ) {\n            var parent = elem.parentNode;\n            checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n          }\n        }\n\n      } else {\n        for ( ; i < l; i++ ) {\n          elem = checkSet[i];\n\n          if ( elem ) {\n            checkSet[i] = isPartStr ?\n              elem.parentNode :\n              elem.parentNode === part;\n          }\n        }\n\n        if ( isPartStr ) {\n          Sizzle.filter( part, checkSet, true );\n        }\n      }\n    },\n\n    \"\": function(checkSet, part, isXML){\n      var nodeCheck,\n        doneName = done++,\n        checkFn = dirCheck;\n\n      if ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n        part = part.toLowerCase();\n        nodeCheck = part;\n        checkFn = dirNodeCheck;\n      }\n\n      checkFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n    },\n\n    \"~\": function( checkSet, part, isXML ) {\n      var nodeCheck,\n        doneName = done++,\n        checkFn = dirCheck;\n\n      if ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n        part = part.toLowerCase();\n        nodeCheck = part;\n        checkFn = dirNodeCheck;\n      }\n\n      checkFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n    }\n  },\n\n  find: {\n    ID: function( match, context, isXML ) {\n      if ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n        var m = context.getElementById(match[1]);\n        // Check parentNode to catch when Blackberry 4.6 returns\n        // nodes that are no longer in the document #6963\n        return m && m.parentNode ? [m] : [];\n      }\n    },\n\n    NAME: function( match, context ) {\n      if ( typeof context.getElementsByName !== \"undefined\" ) {\n        var ret = [],\n          results = context.getElementsByName( match[1] );\n\n        for ( var i = 0, l = results.length; i < l; i++ ) {\n          if ( results[i].getAttribute(\"name\") === match[1] ) {\n            ret.push( results[i] );\n          }\n        }\n\n        return ret.length === 0 ? null : ret;\n      }\n    },\n\n    TAG: function( match, context ) {\n      if ( typeof context.getElementsByTagName !== \"undefined\" ) {\n        return context.getElementsByTagName( match[1] );\n      }\n    }\n  },\n  preFilter: {\n    CLASS: function( match, curLoop, inplace, result, not, isXML ) {\n      match = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n      if ( isXML ) {\n        return match;\n      }\n\n      for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n        if ( elem ) {\n          if ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n            if ( !inplace ) {\n              result.push( elem );\n            }\n\n          } else if ( inplace ) {\n            curLoop[i] = false;\n          }\n        }\n      }\n\n      return false;\n    },\n\n    ID: function( match ) {\n      return match[1].replace( rBackslash, \"\" );\n    },\n\n    TAG: function( match, curLoop ) {\n      return match[1].replace( rBackslash, \"\" ).toLowerCase();\n    },\n\n    CHILD: function( match ) {\n      if ( match[1] === \"nth\" ) {\n        if ( !match[2] ) {\n          Sizzle.error( match[0] );\n        }\n\n        match[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n        // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'\n        var test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n          match[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n          !/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n        // calculate the numbers (first)n+(last) including if they are negative\n        match[2] = (test[1] + (test[2] || 1)) - 0;\n        match[3] = test[3] - 0;\n      }\n      else if ( match[2] ) {\n        Sizzle.error( match[0] );\n      }\n\n      // TODO: Move to normal caching system\n      match[0] = done++;\n\n      return match;\n    },\n\n    ATTR: function( match, curLoop, inplace, result, not, isXML ) {\n      var name = match[1] = match[1].replace( rBackslash, \"\" );\n\n      if ( !isXML && Expr.attrMap[name] ) {\n        match[1] = Expr.attrMap[name];\n      }\n\n      // Handle if an un-quoted value was used\n      match[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n      if ( match[2] === \"~=\" ) {\n        match[4] = \" \" + match[4] + \" \";\n      }\n\n      return match;\n    },\n\n    PSEUDO: function( match, curLoop, inplace, result, not ) {\n      if ( match[1] === \"not\" ) {\n        // If we're dealing with a complex expression, or a simple one\n        if ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n          match[3] = Sizzle(match[3], null, null, curLoop);\n\n        } else {\n          var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n          if ( !inplace ) {\n            result.push.apply( result, ret );\n          }\n\n          return false;\n        }\n\n      } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n        return true;\n      }\n\n      return match;\n    },\n\n    POS: function( match ) {\n      match.unshift( true );\n\n      return match;\n    }\n  },\n\n  filters: {\n    enabled: function( elem ) {\n      return elem.disabled === false && elem.type !== \"hidden\";\n    },\n\n    disabled: function( elem ) {\n      return elem.disabled === true;\n    },\n\n    checked: function( elem ) {\n      return elem.checked === true;\n    },\n\n    selected: function( elem ) {\n      // Accessing this property makes selected-by-default\n      // options in Safari work properly\n      if ( elem.parentNode ) {\n        elem.parentNode.selectedIndex;\n      }\n\n      return elem.selected === true;\n    },\n\n    parent: function( elem ) {\n      return !!elem.firstChild;\n    },\n\n    empty: function( elem ) {\n      return !elem.firstChild;\n    },\n\n    has: function( elem, i, match ) {\n      return !!Sizzle( match[3], elem ).length;\n    },\n\n    header: function( elem ) {\n      return (/h\\d/i).test( elem.nodeName );\n    },\n\n    text: function( elem ) {\n      var attr = elem.getAttribute( \"type\" ), type = elem.type;\n      // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n      // use getAttribute instead to test this case\n      return elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n    },\n\n    radio: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n    },\n\n    checkbox: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n    },\n\n    file: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n    },\n\n    password: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n    },\n\n    submit: function( elem ) {\n      var name = elem.nodeName.toLowerCase();\n      return (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n    },\n\n    image: function( elem ) {\n      return elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n    },\n\n    reset: function( elem ) {\n      var name = elem.nodeName.toLowerCase();\n      return (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n    },\n\n    button: function( elem ) {\n      var name = elem.nodeName.toLowerCase();\n      return name === \"input\" && \"button\" === elem.type || name === \"button\";\n    },\n\n    input: function( elem ) {\n      return (/input|select|textarea|button/i).test( elem.nodeName );\n    },\n\n    focus: function( elem ) {\n      return elem === elem.ownerDocument.activeElement;\n    }\n  },\n  setFilters: {\n    first: function( elem, i ) {\n      return i === 0;\n    },\n\n    last: function( elem, i, match, array ) {\n      return i === array.length - 1;\n    },\n\n    even: function( elem, i ) {\n      return i % 2 === 0;\n    },\n\n    odd: function( elem, i ) {\n      return i % 2 === 1;\n    },\n\n    lt: function( elem, i, match ) {\n      return i < match[3] - 0;\n    },\n\n    gt: function( elem, i, match ) {\n      return i > match[3] - 0;\n    },\n\n    nth: function( elem, i, match ) {\n      return match[3] - 0 === i;\n    },\n\n    eq: function( elem, i, match ) {\n      return match[3] - 0 === i;\n    }\n  },\n  filter: {\n    PSEUDO: function( elem, match, i, array ) {\n      var name = match[1],\n        filter = Expr.filters[ name ];\n\n      if ( filter ) {\n        return filter( elem, i, match, array );\n\n      } else if ( name === \"contains\" ) {\n        return (elem.textContent || elem.innerText || getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n      } else if ( name === \"not\" ) {\n        var not = match[3];\n\n        for ( var j = 0, l = not.length; j < l; j++ ) {\n          if ( not[j] === elem ) {\n            return false;\n          }\n        }\n\n        return true;\n\n      } else {\n        Sizzle.error( name );\n      }\n    },\n\n    CHILD: function( elem, match ) {\n      var first, last,\n        doneName, parent, cache,\n        count, diff,\n        type = match[1],\n        node = elem;\n\n      switch ( type ) {\n        case \"only\":\n        case \"first\":\n          while ( (node = node.previousSibling) ) {\n            if ( node.nodeType === 1 ) {\n              return false;\n            }\n          }\n\n          if ( type === \"first\" ) {\n            return true;\n          }\n\n          node = elem;\n\n          /* falls through */\n        case \"last\":\n          while ( (node = node.nextSibling) ) {\n            if ( node.nodeType === 1 ) {\n              return false;\n            }\n          }\n\n          return true;\n\n        case \"nth\":\n          first = match[2];\n          last = match[3];\n\n          if ( first === 1 && last === 0 ) {\n            return true;\n          }\n\n          doneName = match[0];\n          parent = elem.parentNode;\n\n          if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {\n            count = 0;\n\n            for ( node = parent.firstChild; node; node = node.nextSibling ) {\n              if ( node.nodeType === 1 ) {\n                node.nodeIndex = ++count;\n              }\n            }\n\n            parent[ expando ] = doneName;\n          }\n\n          diff = elem.nodeIndex - last;\n\n          if ( first === 0 ) {\n            return diff === 0;\n\n          } else {\n            return ( diff % first === 0 && diff / first >= 0 );\n          }\n      }\n    },\n\n    ID: function( elem, match ) {\n      return elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n    },\n\n    TAG: function( elem, match ) {\n      return (match === \"*\" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;\n    },\n\n    CLASS: function( elem, match ) {\n      return (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n        .indexOf( match ) > -1;\n    },\n\n    ATTR: function( elem, match ) {\n      var name = match[1],\n        result = Sizzle.attr ?\n          Sizzle.attr( elem, name ) :\n          Expr.attrHandle[ name ] ?\n          Expr.attrHandle[ name ]( elem ) :\n          elem[ name ] != null ?\n            elem[ name ] :\n            elem.getAttribute( name ),\n        value = result + \"\",\n        type = match[2],\n        check = match[4];\n\n      return result == null ?\n        type === \"!=\" :\n        !type && Sizzle.attr ?\n        result != null :\n        type === \"=\" ?\n        value === check :\n        type === \"*=\" ?\n        value.indexOf(check) >= 0 :\n        type === \"~=\" ?\n        (\" \" + value + \" \").indexOf(check) >= 0 :\n        !check ?\n        value && result !== false :\n        type === \"!=\" ?\n        value !== check :\n        type === \"^=\" ?\n        value.indexOf(check) === 0 :\n        type === \"$=\" ?\n        value.substr(value.length - check.length) === check :\n        type === \"|=\" ?\n        value === check || value.substr(0, check.length + 1) === check + \"-\" :\n        false;\n    },\n\n    POS: function( elem, match, i, array ) {\n      var name = match[2],\n        filter = Expr.setFilters[ name ];\n\n      if ( filter ) {\n        return filter( elem, i, match, array );\n      }\n    }\n  }\n};\n\nvar origPOS = Expr.match.POS,\n  fescape = function(all, num){\n    return \"\\\\\" + (num - 0 + 1);\n  };\n\nfor ( var type in Expr.match ) {\n  Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n  Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n// Expose origPOS\n// \"global\" as in regardless of relation to brackets/parens\nExpr.match.globalPOS = origPOS;\n\nvar makeArray = function( array, results ) {\n  array = Array.prototype.slice.call( array, 0 );\n\n  if ( results ) {\n    results.push.apply( results, array );\n    return results;\n  }\n\n  return array;\n};\n\n// Perform a simple check to determine if the browser is capable of\n// converting a NodeList to an array using builtin methods.\n// Also verifies that the returned array holds DOM nodes\n// (which is not the case in the Blackberry browser)\ntry {\n  Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n// Provide a fallback method if it does not work\n} catch( e ) {\n  makeArray = function( array, results ) {\n    var i = 0,\n      ret = results || [];\n\n    if ( toString.call(array) === \"[object Array]\" ) {\n      Array.prototype.push.apply( ret, array );\n\n    } else {\n      if ( typeof array.length === \"number\" ) {\n        for ( var l = array.length; i < l; i++ ) {\n          ret.push( array[i] );\n        }\n\n      } else {\n        for ( ; array[i]; i++ ) {\n          ret.push( array[i] );\n        }\n      }\n    }\n\n    return ret;\n  };\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n  sortOrder = function( a, b ) {\n    if ( a === b ) {\n      hasDuplicate = true;\n      return 0;\n    }\n\n    if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n      return a.compareDocumentPosition ? -1 : 1;\n    }\n\n    return a.compareDocumentPosition(b) & 4 ? -1 : 1;\n  };\n\n} else {\n  sortOrder = function( a, b ) {\n    // The nodes are identical, we can exit early\n    if ( a === b ) {\n      hasDuplicate = true;\n      return 0;\n\n    // Fallback to using sourceIndex (in IE) if it's available on both nodes\n    } else if ( a.sourceIndex && b.sourceIndex ) {\n      return a.sourceIndex - b.sourceIndex;\n    }\n\n    var al, bl,\n      ap = [],\n      bp = [],\n      aup = a.parentNode,\n      bup = b.parentNode,\n      cur = aup;\n\n    // If the nodes are siblings (or identical) we can do a quick check\n    if ( aup === bup ) {\n      return siblingCheck( a, b );\n\n    // If no parents were found then the nodes are disconnected\n    } else if ( !aup ) {\n      return -1;\n\n    } else if ( !bup ) {\n      return 1;\n    }\n\n    // Otherwise they're somewhere else in the tree so we need\n    // to build up a full list of the parentNodes for comparison\n    while ( cur ) {\n      ap.unshift( cur );\n      cur = cur.parentNode;\n    }\n\n    cur = bup;\n\n    while ( cur ) {\n      bp.unshift( cur );\n      cur = cur.parentNode;\n    }\n\n    al = ap.length;\n    bl = bp.length;\n\n    // Start walking down the tree looking for a discrepancy\n    for ( var i = 0; i < al && i < bl; i++ ) {\n      if ( ap[i] !== bp[i] ) {\n        return siblingCheck( ap[i], bp[i] );\n      }\n    }\n\n    // We ended someplace up the tree so do a sibling check\n    return i === al ?\n      siblingCheck( a, bp[i], -1 ) :\n      siblingCheck( ap[i], b, 1 );\n  };\n\n  siblingCheck = function( a, b, ret ) {\n    if ( a === b ) {\n      return ret;\n    }\n\n    var cur = a.nextSibling;\n\n    while ( cur ) {\n      if ( cur === b ) {\n        return -1;\n      }\n\n      cur = cur.nextSibling;\n    }\n\n    return 1;\n  };\n}\n\n// Check to see if the browser returns elements by name when\n// querying by getElementById (and provide a workaround)\n(function(){\n  // We're going to inject a fake input element with a specified name\n  var form = document.createElement(\"div\"),\n    id = \"script\" + (new Date()).getTime(),\n    root = document.documentElement;\n\n  form.innerHTML = \"<a name='\" + id + \"'/>\";\n\n  // Inject it into the root element, check its status, and remove it quickly\n  root.insertBefore( form, root.firstChild );\n\n  // The workaround has to do additional checks after a getElementById\n  // Which slows things down for other browsers (hence the branching)\n  if ( document.getElementById( id ) ) {\n    Expr.find.ID = function( match, context, isXML ) {\n      if ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n        var m = context.getElementById(match[1]);\n\n        return m ?\n          m.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n            [m] :\n            undefined :\n          [];\n      }\n    };\n\n    Expr.filter.ID = function( elem, match ) {\n      var node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n      return elem.nodeType === 1 && node && node.nodeValue === match;\n    };\n  }\n\n  root.removeChild( form );\n\n  // release memory in IE\n  root = form = null;\n})();\n\n(function(){\n  // Check to see if the browser returns only elements\n  // when doing getElementsByTagName(\"*\")\n\n  // Create a fake element\n  var div = document.createElement(\"div\");\n  div.appendChild( document.createComment(\"\") );\n\n  // Make sure no comments are found\n  if ( div.getElementsByTagName(\"*\").length > 0 ) {\n    Expr.find.TAG = function( match, context ) {\n      var results = context.getElementsByTagName( match[1] );\n\n      // Filter out possible comments\n      if ( match[1] === \"*\" ) {\n        var tmp = [];\n\n        for ( var i = 0; results[i]; i++ ) {\n          if ( results[i].nodeType === 1 ) {\n            tmp.push( results[i] );\n          }\n        }\n\n        results = tmp;\n      }\n\n      return results;\n    };\n  }\n\n  // Check to see if an attribute returns normalized href attributes\n  div.innerHTML = \"<a href='#'></a>\";\n\n  if ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n      div.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n    Expr.attrHandle.href = function( elem ) {\n      return elem.getAttribute( \"href\", 2 );\n    };\n  }\n\n  // release memory in IE\n  div = null;\n})();\n\nif ( document.querySelectorAll ) {\n  (function(){\n    var oldSizzle = Sizzle,\n      div = document.createElement(\"div\"),\n      id = \"__sizzle__\";\n\n    div.innerHTML = \"<p class='TEST'></p>\";\n\n    // Safari can't handle uppercase or unicode characters when\n    // in quirks mode.\n    if ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n      return;\n    }\n\n    Sizzle = function( query, context, extra, seed ) {\n      context = context || document;\n\n      // Only use querySelectorAll on non-XML documents\n      // (ID selectors don't work in non-HTML documents)\n      if ( !seed && !Sizzle.isXML(context) ) {\n        // See if we find a selector to speed up\n        var match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n        if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n          // Speed-up: Sizzle(\"TAG\")\n          if ( match[1] ) {\n            return makeArray( context.getElementsByTagName( query ), extra );\n\n          // Speed-up: Sizzle(\".CLASS\")\n          } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n            return makeArray( context.getElementsByClassName( match[2] ), extra );\n          }\n        }\n\n        if ( context.nodeType === 9 ) {\n          // Speed-up: Sizzle(\"body\")\n          // The body element only exists once, optimize finding it\n          if ( query === \"body\" && context.body ) {\n            return makeArray( [ context.body ], extra );\n\n          // Speed-up: Sizzle(\"#ID\")\n          } else if ( match && match[3] ) {\n            var elem = context.getElementById( match[3] );\n\n            // Check parentNode to catch when Blackberry 4.6 returns\n            // nodes that are no longer in the document #6963\n            if ( elem && elem.parentNode ) {\n              // Handle the case where IE and Opera return items\n              // by name instead of ID\n              if ( elem.id === match[3] ) {\n                return makeArray( [ elem ], extra );\n              }\n\n            } else {\n              return makeArray( [], extra );\n            }\n          }\n\n          try {\n            return makeArray( context.querySelectorAll(query), extra );\n          } catch(qsaError) {}\n\n        // qSA works strangely on Element-rooted queries\n        // We can work around this by specifying an extra ID on the root\n        // and working up from there (Thanks to Andrew Dupont for the technique)\n        // IE 8 doesn't work on object elements\n        } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n          var oldContext = context,\n            old = context.getAttribute( \"id\" ),\n            nid = old || id,\n            hasParent = context.parentNode,\n            relativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n          if ( !old ) {\n            context.setAttribute( \"id\", nid );\n          } else {\n            nid = nid.replace( /'/g, \"\\\\$&\" );\n          }\n          if ( relativeHierarchySelector && hasParent ) {\n            context = context.parentNode;\n          }\n\n          try {\n            if ( !relativeHierarchySelector || hasParent ) {\n              return makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n            }\n\n          } catch(pseudoError) {\n          } finally {\n            if ( !old ) {\n              oldContext.removeAttribute( \"id\" );\n            }\n          }\n        }\n      }\n\n      return oldSizzle(query, context, extra, seed);\n    };\n\n    for ( var prop in oldSizzle ) {\n      Sizzle[ prop ] = oldSizzle[ prop ];\n    }\n\n    // release memory in IE\n    div = null;\n  })();\n}\n\n(function(){\n  var html = document.documentElement,\n    matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n  if ( matches ) {\n    // Check to see if it's possible to do matchesSelector\n    // on a disconnected node (IE 9 fails this)\n    var disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n      pseudoWorks = false;\n\n    try {\n      // This should fail with an exception\n      // Gecko does not error, returns false instead\n      matches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n    } catch( pseudoError ) {\n      pseudoWorks = true;\n    }\n\n    Sizzle.matchesSelector = function( node, expr ) {\n      // Make sure that attribute selectors are quoted\n      expr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n      if ( !Sizzle.isXML( node ) ) {\n        try {\n          if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n            var ret = matches.call( node, expr );\n\n            // IE 9's matchesSelector returns false on disconnected nodes\n            if ( ret || !disconnectedMatch ||\n                // As well, disconnected nodes are said to be in a document\n                // fragment in IE 9, so check for that\n                node.document && node.document.nodeType !== 11 ) {\n              return ret;\n            }\n          }\n        } catch(e) {}\n      }\n\n      return Sizzle(expr, null, null, [node]).length > 0;\n    };\n  }\n})();\n\n(function(){\n  var div = document.createElement(\"div\");\n\n  div.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n  // Opera can't find a second classname (in 9.6)\n  // Also, make sure that getElementsByClassName actually exists\n  if ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n    return;\n  }\n\n  // Safari caches class attributes, doesn't catch changes (in 3.2)\n  div.lastChild.className = \"e\";\n\n  if ( div.getElementsByClassName(\"e\").length === 1 ) {\n    return;\n  }\n\n  Expr.order.splice(1, 0, \"CLASS\");\n  Expr.find.CLASS = function( match, context, isXML ) {\n    if ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n      return context.getElementsByClassName(match[1]);\n    }\n  };\n\n  // release memory in IE\n  div = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n  for ( var i = 0, l = checkSet.length; i < l; i++ ) {\n    var elem = checkSet[i];\n\n    if ( elem ) {\n      var match = false;\n\n      elem = elem[dir];\n\n      while ( elem ) {\n        if ( elem[ expando ] === doneName ) {\n          match = checkSet[elem.sizset];\n          break;\n        }\n\n        if ( elem.nodeType === 1 && !isXML ){\n          elem[ expando ] = doneName;\n          elem.sizset = i;\n        }\n\n        if ( elem.nodeName.toLowerCase() === cur ) {\n          match = elem;\n          break;\n        }\n\n        elem = elem[dir];\n      }\n\n      checkSet[i] = match;\n    }\n  }\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n  for ( var i = 0, l = checkSet.length; i < l; i++ ) {\n    var elem = checkSet[i];\n\n    if ( elem ) {\n      var match = false;\n\n      elem = elem[dir];\n\n      while ( elem ) {\n        if ( elem[ expando ] === doneName ) {\n          match = checkSet[elem.sizset];\n          break;\n        }\n\n        if ( elem.nodeType === 1 ) {\n          if ( !isXML ) {\n            elem[ expando ] = doneName;\n            elem.sizset = i;\n          }\n\n          if ( typeof cur !== \"string\" ) {\n            if ( elem === cur ) {\n              match = true;\n              break;\n            }\n\n          } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n            match = elem;\n            break;\n          }\n        }\n\n        elem = elem[dir];\n      }\n\n      checkSet[i] = match;\n    }\n  }\n}\n\nif ( document.documentElement.contains ) {\n  Sizzle.contains = function( a, b ) {\n    return a !== b && (a.contains ? a.contains(b) : true);\n  };\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n  Sizzle.contains = function( a, b ) {\n    return !!(a.compareDocumentPosition(b) & 16);\n  };\n\n} else {\n  Sizzle.contains = function() {\n    return false;\n  };\n}\n\nSizzle.isXML = function( elem ) {\n  // documentElement is verified for cases where it doesn't yet exist\n  // (such as loading iframes in IE - #4833)\n  var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n  return documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context, seed ) {\n  var match,\n    tmpSet = [],\n    later = \"\",\n    root = context.nodeType ? [context] : context;\n\n  // Position selectors must be done after the filter\n  // And so must :not(positional) so we move all PSEUDOs to the end\n  while ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n    later += match[0];\n    selector = selector.replace( Expr.match.PSEUDO, \"\" );\n  }\n\n  selector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n  for ( var i = 0, l = root.length; i < l; i++ ) {\n    Sizzle( selector, root[i], tmpSet, seed );\n  }\n\n  return Sizzle.filter( later, tmpSet );\n};\n\n// EXPOSE\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\nSizzle.selectors.attrMap = {};\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.filters;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})();\n\n\nvar runtil = /Until$/,\n  rparentsprev = /^(?:parents|prevUntil|prevAll)/,\n  // Note: This RegExp should be improved, or likely pulled from Sizzle\n  rmultiselector = /,/,\n  isSimple = /^.[^:#\\[\\.,]*$/,\n  slice = Array.prototype.slice,\n  POS = jQuery.expr.match.globalPOS,\n  // methods guaranteed to produce a unique set when starting from a unique set\n  guaranteedUnique = {\n    children: true,\n    contents: true,\n    next: true,\n    prev: true\n  };\n\njQuery.fn.extend({\n  find: function( selector ) {\n    var self = this,\n      i, l;\n\n    if ( typeof selector !== \"string\" ) {\n      return jQuery( selector ).filter(function() {\n        for ( i = 0, l = self.length; i < l; i++ ) {\n          if ( jQuery.contains( self[ i ], this ) ) {\n            return true;\n          }\n        }\n      });\n    }\n\n    var ret = this.pushStack( \"\", \"find\", selector ),\n      length, n, r;\n\n    for ( i = 0, l = this.length; i < l; i++ ) {\n      length = ret.length;\n      jQuery.find( selector, this[i], ret );\n\n      if ( i > 0 ) {\n        // Make sure that the results are unique\n        for ( n = length; n < ret.length; n++ ) {\n          for ( r = 0; r < length; r++ ) {\n            if ( ret[r] === ret[n] ) {\n              ret.splice(n--, 1);\n              break;\n            }\n          }\n        }\n      }\n    }\n\n    return ret;\n  },\n\n  has: function( target ) {\n    var targets = jQuery( target );\n    return this.filter(function() {\n      for ( var i = 0, l = targets.length; i < l; i++ ) {\n        if ( jQuery.contains( this, targets[i] ) ) {\n          return true;\n        }\n      }\n    });\n  },\n\n  not: function( selector ) {\n    return this.pushStack( winnow(this, selector, false), \"not\", selector);\n  },\n\n  filter: function( selector ) {\n    return this.pushStack( winnow(this, selector, true), \"filter\", selector );\n  },\n\n  is: function( selector ) {\n    return !!selector && (\n      typeof selector === \"string\" ?\n        // If this is a positional selector, check membership in the returned set\n        // so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n        POS.test( selector ) ?\n          jQuery( selector, this.context ).index( this[0] ) >= 0 :\n          jQuery.filter( selector, this ).length > 0 :\n        this.filter( selector ).length > 0 );\n  },\n\n  closest: function( selectors, context ) {\n    var ret = [], i, l, cur = this[0];\n\n    // Array (deprecated as of jQuery 1.7)\n    if ( jQuery.isArray( selectors ) ) {\n      var level = 1;\n\n      while ( cur && cur.ownerDocument && cur !== context ) {\n        for ( i = 0; i < selectors.length; i++ ) {\n\n          if ( jQuery( cur ).is( selectors[ i ] ) ) {\n            ret.push({ selector: selectors[ i ], elem: cur, level: level });\n          }\n        }\n\n        cur = cur.parentNode;\n        level++;\n      }\n\n      return ret;\n    }\n\n    // String\n    var pos = POS.test( selectors ) || typeof selectors !== \"string\" ?\n        jQuery( selectors, context || this.context ) :\n        0;\n\n    for ( i = 0, l = this.length; i < l; i++ ) {\n      cur = this[i];\n\n      while ( cur ) {\n        if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n          ret.push( cur );\n          break;\n\n        } else {\n          cur = cur.parentNode;\n          if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {\n            break;\n          }\n        }\n      }\n    }\n\n    ret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n    return this.pushStack( ret, \"closest\", selectors );\n  },\n\n  // Determine the position of an element within\n  // the matched set of elements\n  index: function( elem ) {\n\n    // No argument, return index in parent\n    if ( !elem ) {\n      return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n    }\n\n    // index in selector\n    if ( typeof elem === \"string\" ) {\n      return jQuery.inArray( this[0], jQuery( elem ) );\n    }\n\n    // Locate the position of the desired element\n    return jQuery.inArray(\n      // If it receives a jQuery object, the first element is used\n      elem.jquery ? elem[0] : elem, this );\n  },\n\n  add: function( selector, context ) {\n    var set = typeof selector === \"string\" ?\n        jQuery( selector, context ) :\n        jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n      all = jQuery.merge( this.get(), set );\n\n    return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n      all :\n      jQuery.unique( all ) );\n  },\n\n  andSelf: function() {\n    return this.add( this.prevObject );\n  }\n});\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n  return !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\njQuery.each({\n  parent: function( elem ) {\n    var parent = elem.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n  parents: function( elem ) {\n    return jQuery.dir( elem, \"parentNode\" );\n  },\n  parentsUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"parentNode\", until );\n  },\n  next: function( elem ) {\n    return jQuery.nth( elem, 2, \"nextSibling\" );\n  },\n  prev: function( elem ) {\n    return jQuery.nth( elem, 2, \"previousSibling\" );\n  },\n  nextAll: function( elem ) {\n    return jQuery.dir( elem, \"nextSibling\" );\n  },\n  prevAll: function( elem ) {\n    return jQuery.dir( elem, \"previousSibling\" );\n  },\n  nextUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"nextSibling\", until );\n  },\n  prevUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"previousSibling\", until );\n  },\n  siblings: function( elem ) {\n    return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n  },\n  children: function( elem ) {\n    return jQuery.sibling( elem.firstChild );\n  },\n  contents: function( elem ) {\n    return jQuery.nodeName( elem, \"iframe\" ) ?\n      elem.contentDocument || elem.contentWindow.document :\n      jQuery.makeArray( elem.childNodes );\n  }\n}, function( name, fn ) {\n  jQuery.fn[ name ] = function( until, selector ) {\n    var ret = jQuery.map( this, fn, until );\n\n    if ( !runtil.test( name ) ) {\n      selector = until;\n    }\n\n    if ( selector && typeof selector === \"string\" ) {\n      ret = jQuery.filter( selector, ret );\n    }\n\n    ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n    if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {\n      ret = ret.reverse();\n    }\n\n    return this.pushStack( ret, name, slice.call( arguments ).join(\",\") );\n  };\n});\n\njQuery.extend({\n  filter: function( expr, elems, not ) {\n    if ( not ) {\n      expr = \":not(\" + expr + \")\";\n    }\n\n    return elems.length === 1 ?\n      jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n      jQuery.find.matches(expr, elems);\n  },\n\n  dir: function( elem, dir, until ) {\n    var matched = [],\n      cur = elem[ dir ];\n\n    while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n      if ( cur.nodeType === 1 ) {\n        matched.push( cur );\n      }\n      cur = cur[dir];\n    }\n    return matched;\n  },\n\n  nth: function( cur, result, dir, elem ) {\n    result = result || 1;\n    var num = 0;\n\n    for ( ; cur; cur = cur[dir] ) {\n      if ( cur.nodeType === 1 && ++num === result ) {\n        break;\n      }\n    }\n\n    return cur;\n  },\n\n  sibling: function( n, elem ) {\n    var r = [];\n\n    for ( ; n; n = n.nextSibling ) {\n      if ( n.nodeType === 1 && n !== elem ) {\n        r.push( n );\n      }\n    }\n\n    return r;\n  }\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n  // Can't pass null or undefined to indexOf in Firefox 4\n  // Set to 0 to skip string check\n  qualifier = qualifier || 0;\n\n  if ( jQuery.isFunction( qualifier ) ) {\n    return jQuery.grep(elements, function( elem, i ) {\n      var retVal = !!qualifier.call( elem, i, elem );\n      return retVal === keep;\n    });\n\n  } else if ( qualifier.nodeType ) {\n    return jQuery.grep(elements, function( elem, i ) {\n      return ( elem === qualifier ) === keep;\n    });\n\n  } else if ( typeof qualifier === \"string\" ) {\n    var filtered = jQuery.grep(elements, function( elem ) {\n      return elem.nodeType === 1;\n    });\n\n    if ( isSimple.test( qualifier ) ) {\n      return jQuery.filter(qualifier, filtered, !keep);\n    } else {\n      qualifier = jQuery.filter( qualifier, filtered );\n    }\n  }\n\n  return jQuery.grep(elements, function( elem, i ) {\n    return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n  });\n}\n\n\n\n\nfunction createSafeFragment( document ) {\n  var list = nodeNames.split( \"|\" ),\n  safeFrag = document.createDocumentFragment();\n\n  if ( safeFrag.createElement ) {\n    while ( list.length ) {\n      safeFrag.createElement(\n        list.pop()\n      );\n    }\n  }\n  return safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n    \"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n  rinlinejQuery = / jQuery\\d+=\"(?:\\d+|null)\"/g,\n  rleadingWhitespace = /^\\s+/,\n  rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,\n  rtagName = /<([\\w:]+)/,\n  rtbody = /<tbody/i,\n  rhtml = /<|&#?\\w+;/,\n  rnoInnerhtml = /<(?:script|style)/i,\n  rnocache = /<(?:script|object|embed|option|style)/i,\n  rnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n  // checked=\"checked\" or checked\n  rchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n  rscriptType = /\\/(java|ecma)script/i,\n  rcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,\n  wrapMap = {\n    option: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n    legend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n    thead: [ 1, \"<table>\", \"</table>\" ],\n    tr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n    td: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n    col: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n    area: [ 1, \"<map>\", \"</map>\" ],\n    _default: [ 0, \"\", \"\" ]\n  },\n  safeFragment = createSafeFragment( document );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE can't serialize <link> and <script> tags normally\nif ( !jQuery.support.htmlSerialize ) {\n  wrapMap._default = [ 1, \"div<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n  text: function( value ) {\n    return jQuery.access( this, function( value ) {\n      return value === undefined ?\n        jQuery.text( this ) :\n        this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n    }, null, value, arguments.length );\n  },\n\n  wrapAll: function( html ) {\n    if ( jQuery.isFunction( html ) ) {\n      return this.each(function(i) {\n        jQuery(this).wrapAll( html.call(this, i) );\n      });\n    }\n\n    if ( this[0] ) {\n      // The elements to wrap the target around\n      var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n      if ( this[0].parentNode ) {\n        wrap.insertBefore( this[0] );\n      }\n\n      wrap.map(function() {\n        var elem = this;\n\n        while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n          elem = elem.firstChild;\n        }\n\n        return elem;\n      }).append( this );\n    }\n\n    return this;\n  },\n\n  wrapInner: function( html ) {\n    if ( jQuery.isFunction( html ) ) {\n      return this.each(function(i) {\n        jQuery(this).wrapInner( html.call(this, i) );\n      });\n    }\n\n    return this.each(function() {\n      var self = jQuery( this ),\n        contents = self.contents();\n\n      if ( contents.length ) {\n        contents.wrapAll( html );\n\n      } else {\n        self.append( html );\n      }\n    });\n  },\n\n  wrap: function( html ) {\n    var isFunction = jQuery.isFunction( html );\n\n    return this.each(function(i) {\n      jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n    });\n  },\n\n  unwrap: function() {\n    return this.parent().each(function() {\n      if ( !jQuery.nodeName( this, \"body\" ) ) {\n        jQuery( this ).replaceWith( this.childNodes );\n      }\n    }).end();\n  },\n\n  append: function() {\n    return this.domManip(arguments, true, function( elem ) {\n      if ( this.nodeType === 1 ) {\n        this.appendChild( elem );\n      }\n    });\n  },\n\n  prepend: function() {\n    return this.domManip(arguments, true, function( elem ) {\n      if ( this.nodeType === 1 ) {\n        this.insertBefore( elem, this.firstChild );\n      }\n    });\n  },\n\n  before: function() {\n    if ( this[0] && this[0].parentNode ) {\n      return this.domManip(arguments, false, function( elem ) {\n        this.parentNode.insertBefore( elem, this );\n      });\n    } else if ( arguments.length ) {\n      var set = jQuery.clean( arguments );\n      set.push.apply( set, this.toArray() );\n      return this.pushStack( set, \"before\", arguments );\n    }\n  },\n\n  after: function() {\n    if ( this[0] && this[0].parentNode ) {\n      return this.domManip(arguments, false, function( elem ) {\n        this.parentNode.insertBefore( elem, this.nextSibling );\n      });\n    } else if ( arguments.length ) {\n      var set = this.pushStack( this, \"after\", arguments );\n      set.push.apply( set, jQuery.clean(arguments) );\n      return set;\n    }\n  },\n\n  // keepData is for internal use only--do not document\n  remove: function( selector, keepData ) {\n    for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n      if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n        if ( !keepData && elem.nodeType === 1 ) {\n          jQuery.cleanData( elem.getElementsByTagName(\"*\") );\n          jQuery.cleanData( [ elem ] );\n        }\n\n        if ( elem.parentNode ) {\n          elem.parentNode.removeChild( elem );\n        }\n      }\n    }\n\n    return this;\n  },\n\n  empty: function() {\n    for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {\n      // Remove element nodes and prevent memory leaks\n      if ( elem.nodeType === 1 ) {\n        jQuery.cleanData( elem.getElementsByTagName(\"*\") );\n      }\n\n      // Remove any remaining nodes\n      while ( elem.firstChild ) {\n        elem.removeChild( elem.firstChild );\n      }\n    }\n\n    return this;\n  },\n\n  clone: function( dataAndEvents, deepDataAndEvents ) {\n    dataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n    deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n    return this.map( function () {\n      return jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n    });\n  },\n\n  html: function( value ) {\n    return jQuery.access( this, function( value ) {\n      var elem = this[0] || {},\n        i = 0,\n        l = this.length;\n\n      if ( value === undefined ) {\n        return elem.nodeType === 1 ?\n          elem.innerHTML.replace( rinlinejQuery, \"\" ) :\n          null;\n      }\n\n\n      if ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n        ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n        !wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n        value = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n        try {\n          for (; i < l; i++ ) {\n            // Remove element nodes and prevent memory leaks\n            elem = this[i] || {};\n            if ( elem.nodeType === 1 ) {\n              jQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n              elem.innerHTML = value;\n            }\n          }\n\n          elem = 0;\n\n        // If using innerHTML throws an exception, use the fallback method\n        } catch(e) {}\n      }\n\n      if ( elem ) {\n        this.empty().append( value );\n      }\n    }, null, value, arguments.length );\n  },\n\n  replaceWith: function( value ) {\n    if ( this[0] && this[0].parentNode ) {\n      // Make sure that the elements are removed from the DOM before they are inserted\n      // this can help fix replacing a parent with child elements\n      if ( jQuery.isFunction( value ) ) {\n        return this.each(function(i) {\n          var self = jQuery(this), old = self.html();\n          self.replaceWith( value.call( this, i, old ) );\n        });\n      }\n\n      if ( typeof value !== \"string\" ) {\n        value = jQuery( value ).detach();\n      }\n\n      return this.each(function() {\n        var next = this.nextSibling,\n          parent = this.parentNode;\n\n        jQuery( this ).remove();\n\n        if ( next ) {\n          jQuery(next).before( value );\n        } else {\n          jQuery(parent).append( value );\n        }\n      });\n    } else {\n      return this.length ?\n        this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n        this;\n    }\n  },\n\n  detach: function( selector ) {\n    return this.remove( selector, true );\n  },\n\n  domManip: function( args, table, callback ) {\n    var results, first, fragment, parent,\n      value = args[0],\n      scripts = [];\n\n    // We can't cloneNode fragments that contain checked, in WebKit\n    if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === \"string\" && rchecked.test( value ) ) {\n      return this.each(function() {\n        jQuery(this).domManip( args, table, callback, true );\n      });\n    }\n\n    if ( jQuery.isFunction(value) ) {\n      return this.each(function(i) {\n        var self = jQuery(this);\n        args[0] = value.call(this, i, table ? self.html() : undefined);\n        self.domManip( args, table, callback );\n      });\n    }\n\n    if ( this[0] ) {\n      parent = value && value.parentNode;\n\n      // If we're in a fragment, just use that instead of building a new one\n      if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {\n        results = { fragment: parent };\n\n      } else {\n        results = jQuery.buildFragment( args, this, scripts );\n      }\n\n      fragment = results.fragment;\n\n      if ( fragment.childNodes.length === 1 ) {\n        first = fragment = fragment.firstChild;\n      } else {\n        first = fragment.firstChild;\n      }\n\n      if ( first ) {\n        table = table && jQuery.nodeName( first, \"tr\" );\n\n        for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {\n          callback.call(\n            table ?\n              root(this[i], first) :\n              this[i],\n            // Make sure that we do not leak memory by inadvertently discarding\n            // the original fragment (which might have attached data) instead of\n            // using it; in addition, use the original fragment object for the last\n            // item instead of first because it can end up being emptied incorrectly\n            // in certain situations (Bug #8070).\n            // Fragments from the fragment cache must always be cloned and never used\n            // in place.\n            results.cacheable || ( l > 1 && i < lastIndex ) ?\n              jQuery.clone( fragment, true, true ) :\n              fragment\n          );\n        }\n      }\n\n      if ( scripts.length ) {\n        jQuery.each( scripts, function( i, elem ) {\n          if ( elem.src ) {\n            jQuery.ajax({\n              type: \"GET\",\n              global: false,\n              url: elem.src,\n              async: false,\n              dataType: \"script\"\n            });\n          } else {\n            jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"/*$0*/\" ) );\n          }\n\n          if ( elem.parentNode ) {\n            elem.parentNode.removeChild( elem );\n          }\n        });\n      }\n    }\n\n    return this;\n  }\n});\n\nfunction root( elem, cur ) {\n  return jQuery.nodeName(elem, \"table\") ?\n    (elem.getElementsByTagName(\"tbody\")[0] ||\n    elem.appendChild(elem.ownerDocument.createElement(\"tbody\"))) :\n    elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n  if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n    return;\n  }\n\n  var type, i, l,\n    oldData = jQuery._data( src ),\n    curData = jQuery._data( dest, oldData ),\n    events = oldData.events;\n\n  if ( events ) {\n    delete curData.handle;\n    curData.events = {};\n\n    for ( type in events ) {\n      for ( i = 0, l = events[ type ].length; i < l; i++ ) {\n        jQuery.event.add( dest, type, events[ type ][ i ] );\n      }\n    }\n  }\n\n  // make the cloned public data object a copy from the original\n  if ( curData.data ) {\n    curData.data = jQuery.extend( {}, curData.data );\n  }\n}\n\nfunction cloneFixAttributes( src, dest ) {\n  var nodeName;\n\n  // We do not need to do anything for non-Elements\n  if ( dest.nodeType !== 1 ) {\n    return;\n  }\n\n  // clearAttributes removes the attributes, which we don't want,\n  // but also removes the attachEvent events, which we *do* want\n  if ( dest.clearAttributes ) {\n    dest.clearAttributes();\n  }\n\n  // mergeAttributes, in contrast, only merges back on the\n  // original attributes, not the events\n  if ( dest.mergeAttributes ) {\n    dest.mergeAttributes( src );\n  }\n\n  nodeName = dest.nodeName.toLowerCase();\n\n  // IE6-8 fail to clone children inside object elements that use\n  // the proprietary classid attribute value (rather than the type\n  // attribute) to identify the type of content to display\n  if ( nodeName === \"object\" ) {\n    dest.outerHTML = src.outerHTML;\n\n  } else if ( nodeName === \"input\" && (src.type === \"checkbox\" || src.type === \"radio\") ) {\n    // IE6-8 fails to persist the checked state of a cloned checkbox\n    // or radio button. Worse, IE6-7 fail to give the cloned element\n    // a checked appearance if the defaultChecked value isn't also set\n    if ( src.checked ) {\n      dest.defaultChecked = dest.checked = src.checked;\n    }\n\n    // IE6-7 get confused and end up setting the value of a cloned\n    // checkbox/radio button to an empty string instead of \"on\"\n    if ( dest.value !== src.value ) {\n      dest.value = src.value;\n    }\n\n  // IE6-8 fails to return the selected option to the default selected\n  // state when cloning options\n  } else if ( nodeName === \"option\" ) {\n    dest.selected = src.defaultSelected;\n\n  // IE6-8 fails to set the defaultValue to the correct value when\n  // cloning other types of input fields\n  } else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n    dest.defaultValue = src.defaultValue;\n\n  // IE blanks contents when cloning scripts\n  } else if ( nodeName === \"script\" && dest.text !== src.text ) {\n    dest.text = src.text;\n  }\n\n  // Event data gets referenced instead of copied if the expando\n  // gets copied too\n  dest.removeAttribute( jQuery.expando );\n\n  // Clear flags for bubbling special change/submit events, they must\n  // be reattached when the newly cloned events are first activated\n  dest.removeAttribute( \"_submit_attached\" );\n  dest.removeAttribute( \"_change_attached\" );\n}\n\njQuery.buildFragment = function( args, nodes, scripts ) {\n  var fragment, cacheable, cacheresults, doc,\n  first = args[ 0 ];\n\n  // nodes may contain either an explicit document object,\n  // a jQuery collection or context object.\n  // If nodes[0] contains a valid object to assign to doc\n  if ( nodes && nodes[0] ) {\n    doc = nodes[0].ownerDocument || nodes[0];\n  }\n\n  // Ensure that an attr object doesn't incorrectly stand in as a document object\n  // Chrome and Firefox seem to allow this to occur and will throw exception\n  // Fixes #8950\n  if ( !doc.createDocumentFragment ) {\n    doc = document;\n  }\n\n  // Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n  // Cloning options loses the selected state, so don't cache them\n  // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n  // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n  // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n  if ( args.length === 1 && typeof first === \"string\" && first.length < 512 && doc === document &&\n    first.charAt(0) === \"<\" && !rnocache.test( first ) &&\n    (jQuery.support.checkClone || !rchecked.test( first )) &&\n    (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n    cacheable = true;\n\n    cacheresults = jQuery.fragments[ first ];\n    if ( cacheresults && cacheresults !== 1 ) {\n      fragment = cacheresults;\n    }\n  }\n\n  if ( !fragment ) {\n    fragment = doc.createDocumentFragment();\n    jQuery.clean( args, doc, fragment, scripts );\n  }\n\n  if ( cacheable ) {\n    jQuery.fragments[ first ] = cacheresults ? fragment : 1;\n  }\n\n  return { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n  appendTo: \"append\",\n  prependTo: \"prepend\",\n  insertBefore: \"before\",\n  insertAfter: \"after\",\n  replaceAll: \"replaceWith\"\n}, function( name, original ) {\n  jQuery.fn[ name ] = function( selector ) {\n    var ret = [],\n      insert = jQuery( selector ),\n      parent = this.length === 1 && this[0].parentNode;\n\n    if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {\n      insert[ original ]( this[0] );\n      return this;\n\n    } else {\n      for ( var i = 0, l = insert.length; i < l; i++ ) {\n        var elems = ( i > 0 ? this.clone(true) : this ).get();\n        jQuery( insert[i] )[ original ]( elems );\n        ret = ret.concat( elems );\n      }\n\n      return this.pushStack( ret, name, insert.selector );\n    }\n  };\n});\n\nfunction getAll( elem ) {\n  if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n    return elem.getElementsByTagName( \"*\" );\n\n  } else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n    return elem.querySelectorAll( \"*\" );\n\n  } else {\n    return [];\n  }\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n  if ( elem.type === \"checkbox\" || elem.type === \"radio\" ) {\n    elem.defaultChecked = elem.checked;\n  }\n}\n// Finds all inputs and passes them to fixDefaultChecked\nfunction findInputs( elem ) {\n  var nodeName = ( elem.nodeName || \"\" ).toLowerCase();\n  if ( nodeName === \"input\" ) {\n    fixDefaultChecked( elem );\n  // Skip scripts, get other children\n  } else if ( nodeName !== \"script\" && typeof elem.getElementsByTagName !== \"undefined\" ) {\n    jQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n  }\n}\n\n// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js\nfunction shimCloneNode( elem ) {\n  var div = document.createElement( \"div\" );\n  safeFragment.appendChild( div );\n\n  div.innerHTML = elem.outerHTML;\n  return div.firstChild;\n}\n\njQuery.extend({\n  clone: function( elem, dataAndEvents, deepDataAndEvents ) {\n    var srcElements,\n      destElements,\n      i,\n      // IE<=8 does not properly clone detached, unknown element nodes\n      clone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ?\n        elem.cloneNode( true ) :\n        shimCloneNode( elem );\n\n    if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n        (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n      // IE copies events bound via attachEvent when using cloneNode.\n      // Calling detachEvent on the clone will also remove the events\n      // from the original. In order to get around this, we use some\n      // proprietary methods to clear the events. Thanks to MooTools\n      // guys for this hotness.\n\n      cloneFixAttributes( elem, clone );\n\n      // Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n      srcElements = getAll( elem );\n      destElements = getAll( clone );\n\n      // Weird iteration because IE will replace the length property\n      // with an element if you are cloning the body and one of the\n      // elements on the page has a name or id of \"length\"\n      for ( i = 0; srcElements[i]; ++i ) {\n        // Ensure that the destination node is not null; Fixes #9587\n        if ( destElements[i] ) {\n          cloneFixAttributes( srcElements[i], destElements[i] );\n        }\n      }\n    }\n\n    // Copy the events from the original to the clone\n    if ( dataAndEvents ) {\n      cloneCopyEvent( elem, clone );\n\n      if ( deepDataAndEvents ) {\n        srcElements = getAll( elem );\n        destElements = getAll( clone );\n\n        for ( i = 0; srcElements[i]; ++i ) {\n          cloneCopyEvent( srcElements[i], destElements[i] );\n        }\n      }\n    }\n\n    srcElements = destElements = null;\n\n    // Return the cloned set\n    return clone;\n  },\n\n  clean: function( elems, context, fragment, scripts ) {\n    var checkScriptType, script, j,\n        ret = [];\n\n    context = context || document;\n\n    // !context.createElement fails in IE with an error but returns typeof 'object'\n    if ( typeof context.createElement === \"undefined\" ) {\n      context = context.ownerDocument || context[0] && context[0].ownerDocument || document;\n    }\n\n    for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n      if ( typeof elem === \"number\" ) {\n        elem += \"\";\n      }\n\n      if ( !elem ) {\n        continue;\n      }\n\n      // Convert html string into DOM nodes\n      if ( typeof elem === \"string\" ) {\n        if ( !rhtml.test( elem ) ) {\n          elem = context.createTextNode( elem );\n        } else {\n          // Fix \"XHTML\"-style tags in all browsers\n          elem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n          // Trim whitespace, otherwise indexOf won't work as expected\n          var tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase(),\n            wrap = wrapMap[ tag ] || wrapMap._default,\n            depth = wrap[0],\n            div = context.createElement(\"div\"),\n            safeChildNodes = safeFragment.childNodes,\n            remove;\n\n          // Append wrapper element to unknown element safe doc fragment\n          if ( context === document ) {\n            // Use the fragment we've already created for this document\n            safeFragment.appendChild( div );\n          } else {\n            // Use a fragment created with the owner document\n            createSafeFragment( context ).appendChild( div );\n          }\n\n          // Go to html and back, then peel off extra wrappers\n          div.innerHTML = wrap[1] + elem + wrap[2];\n\n          // Move to the right depth\n          while ( depth-- ) {\n            div = div.lastChild;\n          }\n\n          // Remove IE's autoinserted <tbody> from table fragments\n          if ( !jQuery.support.tbody ) {\n\n            // String was a <table>, *may* have spurious <tbody>\n            var hasBody = rtbody.test(elem),\n              tbody = tag === \"table\" && !hasBody ?\n                div.firstChild && div.firstChild.childNodes :\n\n                // String was a bare <thead> or <tfoot>\n                wrap[1] === \"<table>\" && !hasBody ?\n                  div.childNodes :\n                  [];\n\n            for ( j = tbody.length - 1; j >= 0 ; --j ) {\n              if ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n                tbody[ j ].parentNode.removeChild( tbody[ j ] );\n              }\n            }\n          }\n\n          // IE completely kills leading whitespace when innerHTML is used\n          if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n            div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n          }\n\n          elem = div.childNodes;\n\n          // Clear elements from DocumentFragment (safeFragment or otherwise)\n          // to avoid hoarding elements. Fixes #11356\n          if ( div ) {\n            div.parentNode.removeChild( div );\n\n            // Guard against -1 index exceptions in FF3.6\n            if ( safeChildNodes.length > 0 ) {\n              remove = safeChildNodes[ safeChildNodes.length - 1 ];\n\n              if ( remove && remove.parentNode ) {\n                remove.parentNode.removeChild( remove );\n              }\n            }\n          }\n        }\n      }\n\n      // Resets defaultChecked for any radios and checkboxes\n      // about to be appended to the DOM in IE 6/7 (#8060)\n      var len;\n      if ( !jQuery.support.appendChecked ) {\n        if ( elem[0] && typeof (len = elem.length) === \"number\" ) {\n          for ( j = 0; j < len; j++ ) {\n            findInputs( elem[j] );\n          }\n        } else {\n          findInputs( elem );\n        }\n      }\n\n      if ( elem.nodeType ) {\n        ret.push( elem );\n      } else {\n        ret = jQuery.merge( ret, elem );\n      }\n    }\n\n    if ( fragment ) {\n      checkScriptType = function( elem ) {\n        return !elem.type || rscriptType.test( elem.type );\n      };\n      for ( i = 0; ret[i]; i++ ) {\n        script = ret[i];\n        if ( scripts && jQuery.nodeName( script, \"script\" ) && (!script.type || rscriptType.test( script.type )) ) {\n          scripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script );\n\n        } else {\n          if ( script.nodeType === 1 ) {\n            var jsTags = jQuery.grep( script.getElementsByTagName( \"script\" ), checkScriptType );\n\n            ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n          }\n          fragment.appendChild( script );\n        }\n      }\n    }\n\n    return ret;\n  },\n\n  cleanData: function( elems ) {\n    var data, id,\n      cache = jQuery.cache,\n      special = jQuery.event.special,\n      deleteExpando = jQuery.support.deleteExpando;\n\n    for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n      if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {\n        continue;\n      }\n\n      id = elem[ jQuery.expando ];\n\n      if ( id ) {\n        data = cache[ id ];\n\n        if ( data && data.events ) {\n          for ( var type in data.events ) {\n            if ( special[ type ] ) {\n              jQuery.event.remove( elem, type );\n\n            // This is a shortcut to avoid jQuery.event.remove's overhead\n            } else {\n              jQuery.removeEvent( elem, type, data.handle );\n            }\n          }\n\n          // Null the DOM reference to avoid IE6/7/8 leak (#7054)\n          if ( data.handle ) {\n            data.handle.elem = null;\n          }\n        }\n\n        if ( deleteExpando ) {\n          delete elem[ jQuery.expando ];\n\n        } else if ( elem.removeAttribute ) {\n          elem.removeAttribute( jQuery.expando );\n        }\n\n        delete cache[ id ];\n      }\n    }\n  }\n});\n\n\n\n\nvar ralpha = /alpha\\([^)]*\\)/i,\n  ropacity = /opacity=([^)]*)/,\n  // fixed for IE9, see #8346\n  rupper = /([A-Z]|^ms)/g,\n  rnum = /^[\\-+]?(?:\\d*\\.)?\\d+$/i,\n  rnumnonpx = /^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,\n  rrelNum = /^([\\-+])=([\\-+.\\de]+)/,\n  rmargin = /^margin/,\n\n  cssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\n  // order is important!\n  cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\n  curCSS,\n\n  getComputedStyle,\n  currentStyle;\n\njQuery.fn.css = function( name, value ) {\n  return jQuery.access( this, function( elem, name, value ) {\n    return value !== undefined ?\n      jQuery.style( elem, name, value ) :\n      jQuery.css( elem, name );\n  }, name, value, arguments.length > 1 );\n};\n\njQuery.extend({\n  // Add in style property hooks for overriding the default\n  // behavior of getting and setting a style property\n  cssHooks: {\n    opacity: {\n      get: function( elem, computed ) {\n        if ( computed ) {\n          // We should always get a number back from opacity\n          var ret = curCSS( elem, \"opacity\" );\n          return ret === \"\" ? \"1\" : ret;\n\n        } else {\n          return elem.style.opacity;\n        }\n      }\n    }\n  },\n\n  // Exclude the following css properties to add px\n  cssNumber: {\n    \"fillOpacity\": true,\n    \"fontWeight\": true,\n    \"lineHeight\": true,\n    \"opacity\": true,\n    \"orphans\": true,\n    \"widows\": true,\n    \"zIndex\": true,\n    \"zoom\": true\n  },\n\n  // Add in properties whose names you wish to fix before\n  // setting or getting the value\n  cssProps: {\n    // normalize float css property\n    \"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n  },\n\n  // Get and set the style property on a DOM Node\n  style: function( elem, name, value, extra ) {\n    // Don't set styles on text and comment nodes\n    if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n      return;\n    }\n\n    // Make sure that we're working with the right name\n    var ret, type, origName = jQuery.camelCase( name ),\n      style = elem.style, hooks = jQuery.cssHooks[ origName ];\n\n    name = jQuery.cssProps[ origName ] || origName;\n\n    // Check if we're setting a value\n    if ( value !== undefined ) {\n      type = typeof value;\n\n      // convert relative number strings (+= or -=) to relative numbers. #7345\n      if ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n        value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );\n        // Fixes bug #9237\n        type = \"number\";\n      }\n\n      // Make sure that NaN and null values aren't set. See: #7116\n      if ( value == null || type === \"number\" && isNaN( value ) ) {\n        return;\n      }\n\n      // If a number was passed in, add 'px' to the (except for certain CSS properties)\n      if ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n        value += \"px\";\n      }\n\n      // If a hook was provided, use that value, otherwise just set the specified value\n      if ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {\n        // Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n        // Fixes bug #5509\n        try {\n          style[ name ] = value;\n        } catch(e) {}\n      }\n\n    } else {\n      // If a hook was provided get the non-computed value from there\n      if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n        return ret;\n      }\n\n      // Otherwise just get the value from the style object\n      return style[ name ];\n    }\n  },\n\n  css: function( elem, name, extra ) {\n    var ret, hooks;\n\n    // Make sure that we're working with the right name\n    name = jQuery.camelCase( name );\n    hooks = jQuery.cssHooks[ name ];\n    name = jQuery.cssProps[ name ] || name;\n\n    // cssFloat needs a special treatment\n    if ( name === \"cssFloat\" ) {\n      name = \"float\";\n    }\n\n    // If a hook was provided get the computed value from there\n    if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {\n      return ret;\n\n    // Otherwise, if a way to get the computed value exists, use that\n    } else if ( curCSS ) {\n      return curCSS( elem, name );\n    }\n  },\n\n  // A method for quickly swapping in/out CSS properties to get correct calculations\n  swap: function( elem, options, callback ) {\n    var old = {},\n      ret, name;\n\n    // Remember the old values, and insert the new ones\n    for ( name in options ) {\n      old[ name ] = elem.style[ name ];\n      elem.style[ name ] = options[ name ];\n    }\n\n    ret = callback.call( elem );\n\n    // Revert the old values\n    for ( name in options ) {\n      elem.style[ name ] = old[ name ];\n    }\n\n    return ret;\n  }\n});\n\n// DEPRECATED in 1.3, Use jQuery.css() instead\njQuery.curCSS = jQuery.css;\n\nif ( document.defaultView && document.defaultView.getComputedStyle ) {\n  getComputedStyle = function( elem, name ) {\n    var ret, defaultView, computedStyle, width,\n      style = elem.style;\n\n    name = name.replace( rupper, \"-$1\" ).toLowerCase();\n\n    if ( (defaultView = elem.ownerDocument.defaultView) &&\n        (computedStyle = defaultView.getComputedStyle( elem, null )) ) {\n\n      ret = computedStyle.getPropertyValue( name );\n      if ( ret === \"\" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n        ret = jQuery.style( elem, name );\n      }\n    }\n\n    // A tribute to the \"awesome hack by Dean Edwards\"\n    // WebKit uses \"computed value (percentage if specified)\" instead of \"used value\" for margins\n    // which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n    if ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) {\n      width = style.width;\n      style.width = ret;\n      ret = computedStyle.width;\n      style.width = width;\n    }\n\n    return ret;\n  };\n}\n\nif ( document.documentElement.currentStyle ) {\n  currentStyle = function( elem, name ) {\n    var left, rsLeft, uncomputed,\n      ret = elem.currentStyle && elem.currentStyle[ name ],\n      style = elem.style;\n\n    // Avoid setting ret to empty string here\n    // so we don't default to auto\n    if ( ret == null && style && (uncomputed = style[ name ]) ) {\n      ret = uncomputed;\n    }\n\n    // From the awesome hack by Dean Edwards\n    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n    // If we're not dealing with a regular pixel number\n    // but a number that has a weird ending, we need to convert it to pixels\n    if ( rnumnonpx.test( ret ) ) {\n\n      // Remember the original values\n      left = style.left;\n      rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n      // Put in the new values to get a computed value out\n      if ( rsLeft ) {\n        elem.runtimeStyle.left = elem.currentStyle.left;\n      }\n      style.left = name === \"fontSize\" ? \"1em\" : ret;\n      ret = style.pixelLeft + \"px\";\n\n      // Revert the changed values\n      style.left = left;\n      if ( rsLeft ) {\n        elem.runtimeStyle.left = rsLeft;\n      }\n    }\n\n    return ret === \"\" ? \"auto\" : ret;\n  };\n}\n\ncurCSS = getComputedStyle || currentStyle;\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n  // Start with offset property\n  var val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n    i = name === \"width\" ? 1 : 0,\n    len = 4;\n\n  if ( val > 0 ) {\n    if ( extra !== \"border\" ) {\n      for ( ; i < len; i += 2 ) {\n        if ( !extra ) {\n          val -= parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n        }\n        if ( extra === \"margin\" ) {\n          val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0;\n        } else {\n          val -= parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n        }\n      }\n    }\n\n    return val + \"px\";\n  }\n\n  // Fall back to computed then uncomputed css if necessary\n  val = curCSS( elem, name );\n  if ( val < 0 || val == null ) {\n    val = elem.style[ name ];\n  }\n\n  // Computed unit is not pixels. Stop here and return.\n  if ( rnumnonpx.test(val) ) {\n    return val;\n  }\n\n  // Normalize \"\", auto, and prepare for extra\n  val = parseFloat( val ) || 0;\n\n  // Add padding, border, margin\n  if ( extra ) {\n    for ( ; i < len; i += 2 ) {\n      val += parseFloat( jQuery.css( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n      if ( extra !== \"padding\" ) {\n        val += parseFloat( jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n      }\n      if ( extra === \"margin\" ) {\n        val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0;\n      }\n    }\n  }\n\n  return val + \"px\";\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n  jQuery.cssHooks[ name ] = {\n    get: function( elem, computed, extra ) {\n      if ( computed ) {\n        if ( elem.offsetWidth !== 0 ) {\n          return getWidthOrHeight( elem, name, extra );\n        } else {\n          return jQuery.swap( elem, cssShow, function() {\n            return getWidthOrHeight( elem, name, extra );\n          });\n        }\n      }\n    },\n\n    set: function( elem, value ) {\n      return rnum.test( value ) ?\n        value + \"px\" :\n        value;\n    }\n  };\n});\n\nif ( !jQuery.support.opacity ) {\n  jQuery.cssHooks.opacity = {\n    get: function( elem, computed ) {\n      // IE uses filters for opacity\n      return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n        ( parseFloat( RegExp.$1 ) / 100 ) + \"\" :\n        computed ? \"1\" : \"\";\n    },\n\n    set: function( elem, value ) {\n      var style = elem.style,\n        currentStyle = elem.currentStyle,\n        opacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n        filter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n      // IE has trouble with opacity if it does not have layout\n      // Force it by setting the zoom level\n      style.zoom = 1;\n\n      // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n      if ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" ) {\n\n        // Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n        // if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n        // style.removeAttribute is IE Only, but so apparently is this code path...\n        style.removeAttribute( \"filter\" );\n\n        // if there there is no filter style applied in a css rule, we are done\n        if ( currentStyle && !currentStyle.filter ) {\n          return;\n        }\n      }\n\n      // otherwise, set new filter values\n      style.filter = ralpha.test( filter ) ?\n        filter.replace( ralpha, opacity ) :\n        filter + \" \" + opacity;\n    }\n  };\n}\n\njQuery(function() {\n  // This hook cannot be added until DOM ready because the support test\n  // for it is not run until after DOM ready\n  if ( !jQuery.support.reliableMarginRight ) {\n    jQuery.cssHooks.marginRight = {\n      get: function( elem, computed ) {\n        // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n        // Work around by temporarily setting element display to inline-block\n        return jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n          if ( computed ) {\n            return curCSS( elem, \"margin-right\" );\n          } else {\n            return elem.style.marginRight;\n          }\n        });\n      }\n    };\n  }\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n  jQuery.expr.filters.hidden = function( elem ) {\n    var width = elem.offsetWidth,\n      height = elem.offsetHeight;\n\n    return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n  };\n\n  jQuery.expr.filters.visible = function( elem ) {\n    return !jQuery.expr.filters.hidden( elem );\n  };\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n  margin: \"\",\n  padding: \"\",\n  border: \"Width\"\n}, function( prefix, suffix ) {\n\n  jQuery.cssHooks[ prefix + suffix ] = {\n    expand: function( value ) {\n      var i,\n\n        // assumes a single number if not a string\n        parts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n        expanded = {};\n\n      for ( i = 0; i < 4; i++ ) {\n        expanded[ prefix + cssExpand[ i ] + suffix ] =\n          parts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n      }\n\n      return expanded;\n    }\n  };\n});\n\n\n\n\nvar r20 = /%20/g,\n  rbracket = /\\[\\]$/,\n  rCRLF = /\\r?\\n/g,\n  rhash = /#.*$/,\n  rheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n  rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n  // #7653, #8125, #8152: local protocol detection\n  rlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n  rnoContent = /^(?:GET|HEAD)$/,\n  rprotocol = /^\\/\\//,\n  rquery = /\\?/,\n  rscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n  rselectTextarea = /^(?:select|textarea)/i,\n  rspacesAjax = /\\s+/,\n  rts = /([?&])_=[^&]*/,\n  rurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,\n\n  // Keep a copy of the old load method\n  _load = jQuery.fn.load,\n\n  /* Prefilters\n   * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n   * 2) These are called:\n   *    - BEFORE asking for a transport\n   *    - AFTER param serialization (s.data is a string if s.processData is true)\n   * 3) key is the dataType\n   * 4) the catchall symbol \"*\" can be used\n   * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n   */\n  prefilters = {},\n\n  /* Transports bindings\n   * 1) key is the dataType\n   * 2) the catchall symbol \"*\" can be used\n   * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n   */\n  transports = {},\n\n  // Document location\n  ajaxLocation,\n\n  // Document location segments\n  ajaxLocParts,\n\n  // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n  allTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n  ajaxLocation = location.href;\n} catch( e ) {\n  // Use the href attribute of an A element\n  // since IE will modify it given document.location\n  ajaxLocation = document.createElement( \"a\" );\n  ajaxLocation.href = \"\";\n  ajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n  // dataTypeExpression is optional and defaults to \"*\"\n  return function( dataTypeExpression, func ) {\n\n    if ( typeof dataTypeExpression !== \"string\" ) {\n      func = dataTypeExpression;\n      dataTypeExpression = \"*\";\n    }\n\n    if ( jQuery.isFunction( func ) ) {\n      var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),\n        i = 0,\n        length = dataTypes.length,\n        dataType,\n        list,\n        placeBefore;\n\n      // For each dataType in the dataTypeExpression\n      for ( ; i < length; i++ ) {\n        dataType = dataTypes[ i ];\n        // We control if we're asked to add before\n        // any existing element\n        placeBefore = /^\\+/.test( dataType );\n        if ( placeBefore ) {\n          dataType = dataType.substr( 1 ) || \"*\";\n        }\n        list = structure[ dataType ] = structure[ dataType ] || [];\n        // then we add to the structure accordingly\n        list[ placeBefore ? \"unshift\" : \"push\" ]( func );\n      }\n    }\n  };\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n    dataType /* internal */, inspected /* internal */ ) {\n\n  dataType = dataType || options.dataTypes[ 0 ];\n  inspected = inspected || {};\n\n  inspected[ dataType ] = true;\n\n  var list = structure[ dataType ],\n    i = 0,\n    length = list ? list.length : 0,\n    executeOnly = ( structure === prefilters ),\n    selection;\n\n  for ( ; i < length && ( executeOnly || !selection ); i++ ) {\n    selection = list[ i ]( options, originalOptions, jqXHR );\n    // If we got redirected to another dataType\n    // we try there if executing only and not done already\n    if ( typeof selection === \"string\" ) {\n      if ( !executeOnly || inspected[ selection ] ) {\n        selection = undefined;\n      } else {\n        options.dataTypes.unshift( selection );\n        selection = inspectPrefiltersOrTransports(\n            structure, options, originalOptions, jqXHR, selection, inspected );\n      }\n    }\n  }\n  // If we're only executing or nothing was selected\n  // we try the catchall dataType if not done already\n  if ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n    selection = inspectPrefiltersOrTransports(\n        structure, options, originalOptions, jqXHR, \"*\", inspected );\n  }\n  // unnecessary when only executing (prefilters)\n  // but it'll be ignored by the caller in that case\n  return selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n  var key, deep,\n    flatOptions = jQuery.ajaxSettings.flatOptions || {};\n  for ( key in src ) {\n    if ( src[ key ] !== undefined ) {\n      ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n    }\n  }\n  if ( deep ) {\n    jQuery.extend( true, target, deep );\n  }\n}\n\njQuery.fn.extend({\n  load: function( url, params, callback ) {\n    if ( typeof url !== \"string\" && _load ) {\n      return _load.apply( this, arguments );\n\n    // Don't do a request if no elements are being requested\n    } else if ( !this.length ) {\n      return this;\n    }\n\n    var off = url.indexOf( \" \" );\n    if ( off >= 0 ) {\n      var selector = url.slice( off, url.length );\n      url = url.slice( 0, off );\n    }\n\n    // Default to a GET request\n    var type = \"GET\";\n\n    // If the second parameter was provided\n    if ( params ) {\n      // If it's a function\n      if ( jQuery.isFunction( params ) ) {\n        // We assume that it's the callback\n        callback = params;\n        params = undefined;\n\n      // Otherwise, build a param string\n      } else if ( typeof params === \"object\" ) {\n        params = jQuery.param( params, jQuery.ajaxSettings.traditional );\n        type = \"POST\";\n      }\n    }\n\n    var self = this;\n\n    // Request the remote document\n    jQuery.ajax({\n      url: url,\n      type: type,\n      dataType: \"html\",\n      data: params,\n      // Complete callback (responseText is used internally)\n      complete: function( jqXHR, status, responseText ) {\n        // Store the response as specified by the jqXHR object\n        responseText = jqXHR.responseText;\n        // If successful, inject the HTML into all the matched elements\n        if ( jqXHR.isResolved() ) {\n          // #4825: Get the actual response in case\n          // a dataFilter is present in ajaxSettings\n          jqXHR.done(function( r ) {\n            responseText = r;\n          });\n          // See if a selector was specified\n          self.html( selector ?\n            // Create a dummy div to hold the results\n            jQuery(\"<div>\")\n              // inject the contents of the document in, removing the scripts\n              // to avoid any 'Permission Denied' errors in IE\n              .append(responseText.replace(rscript, \"\"))\n\n              // Locate the specified elements\n              .find(selector) :\n\n            // If not, just inject the full result\n            responseText );\n        }\n\n        if ( callback ) {\n          self.each( callback, [ responseText, status, jqXHR ] );\n        }\n      }\n    });\n\n    return this;\n  },\n\n  serialize: function() {\n    return jQuery.param( this.serializeArray() );\n  },\n\n  serializeArray: function() {\n    return this.map(function(){\n      return this.elements ? jQuery.makeArray( this.elements ) : this;\n    })\n    .filter(function(){\n      return this.name && !this.disabled &&\n        ( this.checked || rselectTextarea.test( this.nodeName ) ||\n          rinput.test( this.type ) );\n    })\n    .map(function( i, elem ){\n      var val = jQuery( this ).val();\n\n      return val == null ?\n        null :\n        jQuery.isArray( val ) ?\n          jQuery.map( val, function( val, i ){\n            return { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n          }) :\n          { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n    }).get();\n  }\n});\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n  jQuery.fn[ o ] = function( f ){\n    return this.on( o, f );\n  };\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n  jQuery[ method ] = function( url, data, callback, type ) {\n    // shift arguments if data argument was omitted\n    if ( jQuery.isFunction( data ) ) {\n      type = type || callback;\n      callback = data;\n      data = undefined;\n    }\n\n    return jQuery.ajax({\n      type: method,\n      url: url,\n      data: data,\n      success: callback,\n      dataType: type\n    });\n  };\n});\n\njQuery.extend({\n\n  getScript: function( url, callback ) {\n    return jQuery.get( url, undefined, callback, \"script\" );\n  },\n\n  getJSON: function( url, data, callback ) {\n    return jQuery.get( url, data, callback, \"json\" );\n  },\n\n  // Creates a full fledged settings object into target\n  // with both ajaxSettings and settings fields.\n  // If target is omitted, writes into ajaxSettings.\n  ajaxSetup: function( target, settings ) {\n    if ( settings ) {\n      // Building a settings object\n      ajaxExtend( target, jQuery.ajaxSettings );\n    } else {\n      // Extending ajaxSettings\n      settings = target;\n      target = jQuery.ajaxSettings;\n    }\n    ajaxExtend( target, settings );\n    return target;\n  },\n\n  ajaxSettings: {\n    url: ajaxLocation,\n    isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n    global: true,\n    type: \"GET\",\n    contentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n    processData: true,\n    async: true,\n    /*\n    timeout: 0,\n    data: null,\n    dataType: null,\n    username: null,\n    password: null,\n    cache: null,\n    traditional: false,\n    headers: {},\n    */\n\n    accepts: {\n      xml: \"application/xml, text/xml\",\n      html: \"text/html\",\n      text: \"text/plain\",\n      json: \"application/json, text/javascript\",\n      \"*\": allTypes\n    },\n\n    contents: {\n      xml: /xml/,\n      html: /html/,\n      json: /json/\n    },\n\n    responseFields: {\n      xml: \"responseXML\",\n      text: \"responseText\"\n    },\n\n    // List of data converters\n    // 1) key format is \"source_type destination_type\" (a single space in-between)\n    // 2) the catchall symbol \"*\" can be used for source_type\n    converters: {\n\n      // Convert anything to text\n      \"* text\": window.String,\n\n      // Text to html (true = no transformation)\n      \"text html\": true,\n\n      // Evaluate text as a json expression\n      \"text json\": jQuery.parseJSON,\n\n      // Parse text as xml\n      \"text xml\": jQuery.parseXML\n    },\n\n    // For options that shouldn't be deep extended:\n    // you can add your own custom options here if\n    // and when you create one that shouldn't be\n    // deep extended (see ajaxExtend)\n    flatOptions: {\n      context: true,\n      url: true\n    }\n  },\n\n  ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n  ajaxTransport: addToPrefiltersOrTransports( transports ),\n\n  // Main method\n  ajax: function( url, options ) {\n\n    // If url is an object, simulate pre-1.5 signature\n    if ( typeof url === \"object\" ) {\n      options = url;\n      url = undefined;\n    }\n\n    // Force options to be an object\n    options = options || {};\n\n    var // Create the final options object\n      s = jQuery.ajaxSetup( {}, options ),\n      // Callbacks context\n      callbackContext = s.context || s,\n      // Context for global events\n      // It's the callbackContext if one was provided in the options\n      // and if it's a DOM node or a jQuery collection\n      globalEventContext = callbackContext !== s &&\n        ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n            jQuery( callbackContext ) : jQuery.event,\n      // Deferreds\n      deferred = jQuery.Deferred(),\n      completeDeferred = jQuery.Callbacks( \"once memory\" ),\n      // Status-dependent callbacks\n      statusCode = s.statusCode || {},\n      // ifModified key\n      ifModifiedKey,\n      // Headers (they are sent all at once)\n      requestHeaders = {},\n      requestHeadersNames = {},\n      // Response headers\n      responseHeadersString,\n      responseHeaders,\n      // transport\n      transport,\n      // timeout handle\n      timeoutTimer,\n      // Cross-domain detection vars\n      parts,\n      // The jqXHR state\n      state = 0,\n      // To know if global events are to be dispatched\n      fireGlobals,\n      // Loop variable\n      i,\n      // Fake xhr\n      jqXHR = {\n\n        readyState: 0,\n\n        // Caches the header\n        setRequestHeader: function( name, value ) {\n          if ( !state ) {\n            var lname = name.toLowerCase();\n            name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n            requestHeaders[ name ] = value;\n          }\n          return this;\n        },\n\n        // Raw string\n        getAllResponseHeaders: function() {\n          return state === 2 ? responseHeadersString : null;\n        },\n\n        // Builds headers hashtable if needed\n        getResponseHeader: function( key ) {\n          var match;\n          if ( state === 2 ) {\n            if ( !responseHeaders ) {\n              responseHeaders = {};\n              while( ( match = rheaders.exec( responseHeadersString ) ) ) {\n                responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n              }\n            }\n            match = responseHeaders[ key.toLowerCase() ];\n          }\n          return match === undefined ? null : match;\n        },\n\n        // Overrides response content-type header\n        overrideMimeType: function( type ) {\n          if ( !state ) {\n            s.mimeType = type;\n          }\n          return this;\n        },\n\n        // Cancel the request\n        abort: function( statusText ) {\n          statusText = statusText || \"abort\";\n          if ( transport ) {\n            transport.abort( statusText );\n          }\n          done( 0, statusText );\n          return this;\n        }\n      };\n\n    // Callback for when everything is done\n    // It is defined here because jslint complains if it is declared\n    // at the end of the function (which would be more logical and readable)\n    function done( status, nativeStatusText, responses, headers ) {\n\n      // Called once\n      if ( state === 2 ) {\n        return;\n      }\n\n      // State is \"done\" now\n      state = 2;\n\n      // Clear timeout if it exists\n      if ( timeoutTimer ) {\n        clearTimeout( timeoutTimer );\n      }\n\n      // Dereference transport for early garbage collection\n      // (no matter how long the jqXHR object will be used)\n      transport = undefined;\n\n      // Cache response headers\n      responseHeadersString = headers || \"\";\n\n      // Set readyState\n      jqXHR.readyState = status > 0 ? 4 : 0;\n\n      var isSuccess,\n        success,\n        error,\n        statusText = nativeStatusText,\n        response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,\n        lastModified,\n        etag;\n\n      // If successful, handle type chaining\n      if ( status >= 200 && status < 300 || status === 304 ) {\n\n        // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n        if ( s.ifModified ) {\n\n          if ( ( lastModified = jqXHR.getResponseHeader( \"Last-Modified\" ) ) ) {\n            jQuery.lastModified[ ifModifiedKey ] = lastModified;\n          }\n          if ( ( etag = jqXHR.getResponseHeader( \"Etag\" ) ) ) {\n            jQuery.etag[ ifModifiedKey ] = etag;\n          }\n        }\n\n        // If not modified\n        if ( status === 304 ) {\n\n          statusText = \"notmodified\";\n          isSuccess = true;\n\n        // If we have data\n        } else {\n\n          try {\n            success = ajaxConvert( s, response );\n            statusText = \"success\";\n            isSuccess = true;\n          } catch(e) {\n            // We have a parsererror\n            statusText = \"parsererror\";\n            error = e;\n          }\n        }\n      } else {\n        // We extract error from statusText\n        // then normalize statusText and status for non-aborts\n        error = statusText;\n        if ( !statusText || status ) {\n          statusText = \"error\";\n          if ( status < 0 ) {\n            status = 0;\n          }\n        }\n      }\n\n      // Set data for the fake xhr object\n      jqXHR.status = status;\n      jqXHR.statusText = \"\" + ( nativeStatusText || statusText );\n\n      // Success/Error\n      if ( isSuccess ) {\n        deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n      } else {\n        deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n      }\n\n      // Status-dependent callbacks\n      jqXHR.statusCode( statusCode );\n      statusCode = undefined;\n\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n            [ jqXHR, s, isSuccess ? success : error ] );\n      }\n\n      // Complete\n      completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n        // Handle the global AJAX counter\n        if ( !( --jQuery.active ) ) {\n          jQuery.event.trigger( \"ajaxStop\" );\n        }\n      }\n    }\n\n    // Attach deferreds\n    deferred.promise( jqXHR );\n    jqXHR.success = jqXHR.done;\n    jqXHR.error = jqXHR.fail;\n    jqXHR.complete = completeDeferred.add;\n\n    // Status-dependent callbacks\n    jqXHR.statusCode = function( map ) {\n      if ( map ) {\n        var tmp;\n        if ( state < 2 ) {\n          for ( tmp in map ) {\n            statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n          }\n        } else {\n          tmp = map[ jqXHR.status ];\n          jqXHR.then( tmp, tmp );\n        }\n      }\n      return this;\n    };\n\n    // Remove hash character (#7531: and string promotion)\n    // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n    // We also use the url parameter if available\n    s.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n    // Extract dataTypes list\n    s.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( rspacesAjax );\n\n    // Determine if a cross-domain request is in order\n    if ( s.crossDomain == null ) {\n      parts = rurl.exec( s.url.toLowerCase() );\n      s.crossDomain = !!( parts &&\n        ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||\n          ( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n            ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n      );\n    }\n\n    // Convert data if not already a string\n    if ( s.data && s.processData && typeof s.data !== \"string\" ) {\n      s.data = jQuery.param( s.data, s.traditional );\n    }\n\n    // Apply prefilters\n    inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n    // If request was aborted inside a prefilter, stop there\n    if ( state === 2 ) {\n      return false;\n    }\n\n    // We can fire global events as of now if asked to\n    fireGlobals = s.global;\n\n    // Uppercase the type\n    s.type = s.type.toUpperCase();\n\n    // Determine if request has content\n    s.hasContent = !rnoContent.test( s.type );\n\n    // Watch for a new set of requests\n    if ( fireGlobals && jQuery.active++ === 0 ) {\n      jQuery.event.trigger( \"ajaxStart\" );\n    }\n\n    // More options handling for requests with no content\n    if ( !s.hasContent ) {\n\n      // If data is available, append data to url\n      if ( s.data ) {\n        s.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n        // #9682: remove data so that it's not used in an eventual retry\n        delete s.data;\n      }\n\n      // Get ifModifiedKey before adding the anti-cache parameter\n      ifModifiedKey = s.url;\n\n      // Add anti-cache in url if needed\n      if ( s.cache === false ) {\n\n        var ts = jQuery.now(),\n          // try replacing _= if it is there\n          ret = s.url.replace( rts, \"$1_=\" + ts );\n\n        // if nothing was replaced, add timestamp to the end\n        s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n      }\n    }\n\n    // Set the correct header, if data is being sent\n    if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n      jqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n    }\n\n    // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n    if ( s.ifModified ) {\n      ifModifiedKey = ifModifiedKey || s.url;\n      if ( jQuery.lastModified[ ifModifiedKey ] ) {\n        jqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n      }\n      if ( jQuery.etag[ ifModifiedKey ] ) {\n        jqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n      }\n    }\n\n    // Set the Accepts header for the server, depending on the dataType\n    jqXHR.setRequestHeader(\n      \"Accept\",\n      s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n        s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n        s.accepts[ \"*\" ]\n    );\n\n    // Check for headers option\n    for ( i in s.headers ) {\n      jqXHR.setRequestHeader( i, s.headers[ i ] );\n    }\n\n    // Allow custom headers/mimetypes and early abort\n    if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n        // Abort if not done already\n        jqXHR.abort();\n        return false;\n\n    }\n\n    // Install callbacks on deferreds\n    for ( i in { success: 1, error: 1, complete: 1 } ) {\n      jqXHR[ i ]( s[ i ] );\n    }\n\n    // Get transport\n    transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n    // If no transport, we auto-abort\n    if ( !transport ) {\n      done( -1, \"No Transport\" );\n    } else {\n      jqXHR.readyState = 1;\n      // Send global event\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n      }\n      // Timeout\n      if ( s.async && s.timeout > 0 ) {\n        timeoutTimer = setTimeout( function(){\n          jqXHR.abort( \"timeout\" );\n        }, s.timeout );\n      }\n\n      try {\n        state = 1;\n        transport.send( requestHeaders, done );\n      } catch (e) {\n        // Propagate exception as error if not done\n        if ( state < 2 ) {\n          done( -1, e );\n        // Simply rethrow otherwise\n        } else {\n          throw e;\n        }\n      }\n    }\n\n    return jqXHR;\n  },\n\n  // Serialize an array of form elements or a set of\n  // key/values into a query string\n  param: function( a, traditional ) {\n    var s = [],\n      add = function( key, value ) {\n        // If value is a function, invoke it and return its value\n        value = jQuery.isFunction( value ) ? value() : value;\n        s[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n      };\n\n    // Set traditional to true for jQuery <= 1.3.2 behavior.\n    if ( traditional === undefined ) {\n      traditional = jQuery.ajaxSettings.traditional;\n    }\n\n    // If an array was passed in, assume that it is an array of form elements.\n    if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n      // Serialize the form elements\n      jQuery.each( a, function() {\n        add( this.name, this.value );\n      });\n\n    } else {\n      // If traditional, encode the \"old\" way (the way 1.3.2 or older\n      // did it), otherwise encode params recursively.\n      for ( var prefix in a ) {\n        buildParams( prefix, a[ prefix ], traditional, add );\n      }\n    }\n\n    // Return the resulting serialization\n    return s.join( \"&\" ).replace( r20, \"+\" );\n  }\n});\n\nfunction buildParams( prefix, obj, traditional, add ) {\n  if ( jQuery.isArray( obj ) ) {\n    // Serialize array item.\n    jQuery.each( obj, function( i, v ) {\n      if ( traditional || rbracket.test( prefix ) ) {\n        // Treat each array item as a scalar.\n        add( prefix, v );\n\n      } else {\n        // If array item is non-scalar (array or object), encode its\n        // numeric index to resolve deserialization ambiguity issues.\n        // Note that rack (as of 1.0.0) can't currently deserialize\n        // nested arrays properly, and attempting to do so may cause\n        // a server error. Possible fixes are to modify rack's\n        // deserialization algorithm or to provide an option or flag\n        // to force array serialization to be shallow.\n        buildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n      }\n    });\n\n  } else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n    // Serialize object item.\n    for ( var name in obj ) {\n      buildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n    }\n\n  } else {\n    // Serialize scalar item.\n    add( prefix, obj );\n  }\n}\n\n// This is still on the jQuery object... for now\n// Want to move this to jQuery.ajax some day\njQuery.extend({\n\n  // Counter for holding the number of active queries\n  active: 0,\n\n  // Last-Modified header cache for next request\n  lastModified: {},\n  etag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n  var contents = s.contents,\n    dataTypes = s.dataTypes,\n    responseFields = s.responseFields,\n    ct,\n    type,\n    finalDataType,\n    firstDataType;\n\n  // Fill responseXXX fields\n  for ( type in responseFields ) {\n    if ( type in responses ) {\n      jqXHR[ responseFields[type] ] = responses[ type ];\n    }\n  }\n\n  // Remove auto dataType and get content-type in the process\n  while( dataTypes[ 0 ] === \"*\" ) {\n    dataTypes.shift();\n    if ( ct === undefined ) {\n      ct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n    }\n  }\n\n  // Check if we're dealing with a known content-type\n  if ( ct ) {\n    for ( type in contents ) {\n      if ( contents[ type ] && contents[ type ].test( ct ) ) {\n        dataTypes.unshift( type );\n        break;\n      }\n    }\n  }\n\n  // Check to see if we have a response for the expected dataType\n  if ( dataTypes[ 0 ] in responses ) {\n    finalDataType = dataTypes[ 0 ];\n  } else {\n    // Try convertible dataTypes\n    for ( type in responses ) {\n      if ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n        finalDataType = type;\n        break;\n      }\n      if ( !firstDataType ) {\n        firstDataType = type;\n      }\n    }\n    // Or just use first one\n    finalDataType = finalDataType || firstDataType;\n  }\n\n  // If we found a dataType\n  // We add the dataType to the list if needed\n  // and return the corresponding response\n  if ( finalDataType ) {\n    if ( finalDataType !== dataTypes[ 0 ] ) {\n      dataTypes.unshift( finalDataType );\n    }\n    return responses[ finalDataType ];\n  }\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n  // Apply the dataFilter if provided\n  if ( s.dataFilter ) {\n    response = s.dataFilter( response, s.dataType );\n  }\n\n  var dataTypes = s.dataTypes,\n    converters = {},\n    i,\n    key,\n    length = dataTypes.length,\n    tmp,\n    // Current and previous dataTypes\n    current = dataTypes[ 0 ],\n    prev,\n    // Conversion expression\n    conversion,\n    // Conversion function\n    conv,\n    // Conversion functions (transitive conversion)\n    conv1,\n    conv2;\n\n  // For each dataType in the chain\n  for ( i = 1; i < length; i++ ) {\n\n    // Create converters map\n    // with lowercased keys\n    if ( i === 1 ) {\n      for ( key in s.converters ) {\n        if ( typeof key === \"string\" ) {\n          converters[ key.toLowerCase() ] = s.converters[ key ];\n        }\n      }\n    }\n\n    // Get the dataTypes\n    prev = current;\n    current = dataTypes[ i ];\n\n    // If current is auto dataType, update it to prev\n    if ( current === \"*\" ) {\n      current = prev;\n    // If no auto and dataTypes are actually different\n    } else if ( prev !== \"*\" && prev !== current ) {\n\n      // Get the converter\n      conversion = prev + \" \" + current;\n      conv = converters[ conversion ] || converters[ \"* \" + current ];\n\n      // If there is no direct converter, search transitively\n      if ( !conv ) {\n        conv2 = undefined;\n        for ( conv1 in converters ) {\n          tmp = conv1.split( \" \" );\n          if ( tmp[ 0 ] === prev || tmp[ 0 ] === \"*\" ) {\n            conv2 = converters[ tmp[1] + \" \" + current ];\n            if ( conv2 ) {\n              conv1 = converters[ conv1 ];\n              if ( conv1 === true ) {\n                conv = conv2;\n              } else if ( conv2 === true ) {\n                conv = conv1;\n              }\n              break;\n            }\n          }\n        }\n      }\n      // If we found no converter, dispatch an error\n      if ( !( conv || conv2 ) ) {\n        jQuery.error( \"No conversion from \" + conversion.replace(\" \",\" to \") );\n      }\n      // If found converter is not an equivalence\n      if ( conv !== true ) {\n        // Convert with 1 or 2 converters accordingly\n        response = conv ? conv( response ) : conv2( conv1(response) );\n      }\n    }\n  }\n  return response;\n}\n\n\n\n\nvar jsc = jQuery.now(),\n  jsre = /(\\=)\\?(&|$)|\\?\\?/i;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n  jsonp: \"callback\",\n  jsonpCallback: function() {\n    return jQuery.expando + \"_\" + ( jsc++ );\n  }\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n  var inspectData = ( typeof s.data === \"string\" ) && /^application\\/x\\-www\\-form\\-urlencoded/.test( s.contentType );\n\n  if ( s.dataTypes[ 0 ] === \"jsonp\" ||\n    s.jsonp !== false && ( jsre.test( s.url ) ||\n        inspectData && jsre.test( s.data ) ) ) {\n\n    var responseContainer,\n      jsonpCallback = s.jsonpCallback =\n        jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,\n      previous = window[ jsonpCallback ],\n      url = s.url,\n      data = s.data,\n      replace = \"$1\" + jsonpCallback + \"$2\";\n\n    if ( s.jsonp !== false ) {\n      url = url.replace( jsre, replace );\n      if ( s.url === url ) {\n        if ( inspectData ) {\n          data = data.replace( jsre, replace );\n        }\n        if ( s.data === data ) {\n          // Add callback manually\n          url += (/\\?/.test( url ) ? \"&\" : \"?\") + s.jsonp + \"=\" + jsonpCallback;\n        }\n      }\n    }\n\n    s.url = url;\n    s.data = data;\n\n    // Install callback\n    window[ jsonpCallback ] = function( response ) {\n      responseContainer = [ response ];\n    };\n\n    // Clean-up function\n    jqXHR.always(function() {\n      // Set callback back to previous value\n      window[ jsonpCallback ] = previous;\n      // Call if it was a function and we have a response\n      if ( responseContainer && jQuery.isFunction( previous ) ) {\n        window[ jsonpCallback ]( responseContainer[ 0 ] );\n      }\n    });\n\n    // Use data converter to retrieve json after script execution\n    s.converters[\"script json\"] = function() {\n      if ( !responseContainer ) {\n        jQuery.error( jsonpCallback + \" was not called\" );\n      }\n      return responseContainer[ 0 ];\n    };\n\n    // force json dataType\n    s.dataTypes[ 0 ] = \"json\";\n\n    // Delegate to script\n    return \"script\";\n  }\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n  accepts: {\n    script: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n  },\n  contents: {\n    script: /javascript|ecmascript/\n  },\n  converters: {\n    \"text script\": function( text ) {\n      jQuery.globalEval( text );\n      return text;\n    }\n  }\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n  if ( s.cache === undefined ) {\n    s.cache = false;\n  }\n  if ( s.crossDomain ) {\n    s.type = \"GET\";\n    s.global = false;\n  }\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n  // This transport only deals with cross domain requests\n  if ( s.crossDomain ) {\n\n    var script,\n      head = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n    return {\n\n      send: function( _, callback ) {\n\n        script = document.createElement( \"script\" );\n\n        script.async = \"async\";\n\n        if ( s.scriptCharset ) {\n          script.charset = s.scriptCharset;\n        }\n\n        script.src = s.url;\n\n        // Attach handlers for all browsers\n        script.onload = script.onreadystatechange = function( _, isAbort ) {\n\n          if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n            // Handle memory leak in IE\n            script.onload = script.onreadystatechange = null;\n\n            // Remove the script\n            if ( head && script.parentNode ) {\n              head.removeChild( script );\n            }\n\n            // Dereference the script\n            script = undefined;\n\n            // Callback if not abort\n            if ( !isAbort ) {\n              callback( 200, \"success\" );\n            }\n          }\n        };\n        // Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n        // This arises when a base node is used (#2709 and #4378).\n        head.insertBefore( script, head.firstChild );\n      },\n\n      abort: function() {\n        if ( script ) {\n          script.onload( 0, 1 );\n        }\n      }\n    };\n  }\n});\n\n\n\n\nvar // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n  xhrOnUnloadAbort = window.ActiveXObject ? function() {\n    // Abort all pending requests\n    for ( var key in xhrCallbacks ) {\n      xhrCallbacks[ key ]( 0, 1 );\n    }\n  } : false,\n  xhrId = 0,\n  xhrCallbacks;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n  try {\n    return new window.XMLHttpRequest();\n  } catch( e ) {}\n}\n\nfunction createActiveXHR() {\n  try {\n    return new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n  } catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n  /* Microsoft failed to properly\n   * implement the XMLHttpRequest in IE7 (can't request local files),\n   * so we use the ActiveXObject when it is available\n   * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n   * we need a fallback.\n   */\n  function() {\n    return !this.isLocal && createStandardXHR() || createActiveXHR();\n  } :\n  // For all other browsers, use the standard XMLHttpRequest object\n  createStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n  jQuery.extend( jQuery.support, {\n    ajax: !!xhr,\n    cors: !!xhr && ( \"withCredentials\" in xhr )\n  });\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n  jQuery.ajaxTransport(function( s ) {\n    // Cross domain only allowed if supported through XMLHttpRequest\n    if ( !s.crossDomain || jQuery.support.cors ) {\n\n      var callback;\n\n      return {\n        send: function( headers, complete ) {\n\n          // Get a new xhr\n          var xhr = s.xhr(),\n            handle,\n            i;\n\n          // Open the socket\n          // Passing null username, generates a login popup on Opera (#2865)\n          if ( s.username ) {\n            xhr.open( s.type, s.url, s.async, s.username, s.password );\n          } else {\n            xhr.open( s.type, s.url, s.async );\n          }\n\n          // Apply custom fields if provided\n          if ( s.xhrFields ) {\n            for ( i in s.xhrFields ) {\n              xhr[ i ] = s.xhrFields[ i ];\n            }\n          }\n\n          // Override mime type if needed\n          if ( s.mimeType && xhr.overrideMimeType ) {\n            xhr.overrideMimeType( s.mimeType );\n          }\n\n          // X-Requested-With header\n          // For cross-domain requests, seeing as conditions for a preflight are\n          // akin to a jigsaw puzzle, we simply never set it to be sure.\n          // (it can always be set on a per-request basis or even using ajaxSetup)\n          // For same-domain requests, won't change header if already provided.\n          if ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n            headers[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n          }\n\n          // Need an extra try/catch for cross domain requests in Firefox 3\n          try {\n            for ( i in headers ) {\n              xhr.setRequestHeader( i, headers[ i ] );\n            }\n          } catch( _ ) {}\n\n          // Do send the request\n          // This may raise an exception which is actually\n          // handled in jQuery.ajax (so no try/catch here)\n          xhr.send( ( s.hasContent && s.data ) || null );\n\n          // Listener\n          callback = function( _, isAbort ) {\n\n            var status,\n              statusText,\n              responseHeaders,\n              responses,\n              xml;\n\n            // Firefox throws exceptions when accessing properties\n            // of an xhr when a network error occured\n            // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n            try {\n\n              // Was never called and is aborted or complete\n              if ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n                // Only called once\n                callback = undefined;\n\n                // Do not keep as active anymore\n                if ( handle ) {\n                  xhr.onreadystatechange = jQuery.noop;\n                  if ( xhrOnUnloadAbort ) {\n                    delete xhrCallbacks[ handle ];\n                  }\n                }\n\n                // If it's an abort\n                if ( isAbort ) {\n                  // Abort it manually if needed\n                  if ( xhr.readyState !== 4 ) {\n                    xhr.abort();\n                  }\n                } else {\n                  status = xhr.status;\n                  responseHeaders = xhr.getAllResponseHeaders();\n                  responses = {};\n                  xml = xhr.responseXML;\n\n                  // Construct response list\n                  if ( xml && xml.documentElement /* #4958 */ ) {\n                    responses.xml = xml;\n                  }\n\n                  // When requesting binary data, IE6-9 will throw an exception\n                  // on any attempt to access responseText (#11426)\n                  try {\n                    responses.text = xhr.responseText;\n                  } catch( _ ) {\n                  }\n\n                  // Firefox throws an exception when accessing\n                  // statusText for faulty cross-domain requests\n                  try {\n                    statusText = xhr.statusText;\n                  } catch( e ) {\n                    // We normalize with Webkit giving an empty statusText\n                    statusText = \"\";\n                  }\n\n                  // Filter status for non standard behaviors\n\n                  // If the request is local and we have data: assume a success\n                  // (success with no data won't get notified, that's the best we\n                  // can do given current implementations)\n                  if ( !status && s.isLocal && !s.crossDomain ) {\n                    status = responses.text ? 200 : 404;\n                  // IE - #1450: sometimes returns 1223 when it should be 204\n                  } else if ( status === 1223 ) {\n                    status = 204;\n                  }\n                }\n              }\n            } catch( firefoxAccessException ) {\n              if ( !isAbort ) {\n                complete( -1, firefoxAccessException );\n              }\n            }\n\n            // Call complete if needed\n            if ( responses ) {\n              complete( status, statusText, responses, responseHeaders );\n            }\n          };\n\n          // if we're in sync mode or it's in cache\n          // and has been retrieved directly (IE6 & IE7)\n          // we need to manually fire the callback\n          if ( !s.async || xhr.readyState === 4 ) {\n            callback();\n          } else {\n            handle = ++xhrId;\n            if ( xhrOnUnloadAbort ) {\n              // Create the active xhrs callbacks list if needed\n              // and attach the unload handler\n              if ( !xhrCallbacks ) {\n                xhrCallbacks = {};\n                jQuery( window ).unload( xhrOnUnloadAbort );\n              }\n              // Add to list of active xhrs callbacks\n              xhrCallbacks[ handle ] = callback;\n            }\n            xhr.onreadystatechange = callback;\n          }\n        },\n\n        abort: function() {\n          if ( callback ) {\n            callback(0,1);\n          }\n        }\n      };\n    }\n  });\n}\n\n\n\n\nvar elemdisplay = {},\n  iframe, iframeDoc,\n  rfxtypes = /^(?:toggle|show|hide)$/,\n  rfxnum = /^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,\n  timerId,\n  fxAttrs = [\n    // height animations\n    [ \"height\", \"marginTop\", \"marginBottom\", \"paddingTop\", \"paddingBottom\" ],\n    // width animations\n    [ \"width\", \"marginLeft\", \"marginRight\", \"paddingLeft\", \"paddingRight\" ],\n    // opacity animations\n    [ \"opacity\" ]\n  ],\n  fxNow;\n\njQuery.fn.extend({\n  show: function( speed, easing, callback ) {\n    var elem, display;\n\n    if ( speed || speed === 0 ) {\n      return this.animate( genFx(\"show\", 3), speed, easing, callback );\n\n    } else {\n      for ( var i = 0, j = this.length; i < j; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.style ) {\n          display = elem.style.display;\n\n          // Reset the inline display of this element to learn if it is\n          // being hidden by cascaded rules or not\n          if ( !jQuery._data(elem, \"olddisplay\") && display === \"none\" ) {\n            display = elem.style.display = \"\";\n          }\n\n          // Set elements which have been overridden with display: none\n          // in a stylesheet to whatever the default browser style is\n          // for such an element\n          if ( (display === \"\" && jQuery.css(elem, \"display\") === \"none\") ||\n            !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {\n            jQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n          }\n        }\n      }\n\n      // Set the display of most of the elements in a second loop\n      // to avoid the constant reflow\n      for ( i = 0; i < j; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.style ) {\n          display = elem.style.display;\n\n          if ( display === \"\" || display === \"none\" ) {\n            elem.style.display = jQuery._data( elem, \"olddisplay\" ) || \"\";\n          }\n        }\n      }\n\n      return this;\n    }\n  },\n\n  hide: function( speed, easing, callback ) {\n    if ( speed || speed === 0 ) {\n      return this.animate( genFx(\"hide\", 3), speed, easing, callback);\n\n    } else {\n      var elem, display,\n        i = 0,\n        j = this.length;\n\n      for ( ; i < j; i++ ) {\n        elem = this[i];\n        if ( elem.style ) {\n          display = jQuery.css( elem, \"display\" );\n\n          if ( display !== \"none\" && !jQuery._data( elem, \"olddisplay\" ) ) {\n            jQuery._data( elem, \"olddisplay\", display );\n          }\n        }\n      }\n\n      // Set the display of the elements in a second loop\n      // to avoid the constant reflow\n      for ( i = 0; i < j; i++ ) {\n        if ( this[i].style ) {\n          this[i].style.display = \"none\";\n        }\n      }\n\n      return this;\n    }\n  },\n\n  // Save the old toggle function\n  _toggle: jQuery.fn.toggle,\n\n  toggle: function( fn, fn2, callback ) {\n    var bool = typeof fn === \"boolean\";\n\n    if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {\n      this._toggle.apply( this, arguments );\n\n    } else if ( fn == null || bool ) {\n      this.each(function() {\n        var state = bool ? fn : jQuery(this).is(\":hidden\");\n        jQuery(this)[ state ? \"show\" : \"hide\" ]();\n      });\n\n    } else {\n      this.animate(genFx(\"toggle\", 3), fn, fn2, callback);\n    }\n\n    return this;\n  },\n\n  fadeTo: function( speed, to, easing, callback ) {\n    return this.filter(\":hidden\").css(\"opacity\", 0).show().end()\n          .animate({opacity: to}, speed, easing, callback);\n  },\n\n  animate: function( prop, speed, easing, callback ) {\n    var optall = jQuery.speed( speed, easing, callback );\n\n    if ( jQuery.isEmptyObject( prop ) ) {\n      return this.each( optall.complete, [ false ] );\n    }\n\n    // Do not change referenced properties as per-property easing will be lost\n    prop = jQuery.extend( {}, prop );\n\n    function doAnimation() {\n      // XXX 'this' does not always have a nodeName when running the\n      // test suite\n\n      if ( optall.queue === false ) {\n        jQuery._mark( this );\n      }\n\n      var opt = jQuery.extend( {}, optall ),\n        isElement = this.nodeType === 1,\n        hidden = isElement && jQuery(this).is(\":hidden\"),\n        name, val, p, e, hooks, replace,\n        parts, start, end, unit,\n        method;\n\n      // will store per property easing and be used to determine when an animation is complete\n      opt.animatedProperties = {};\n\n      // first pass over propertys to expand / normalize\n      for ( p in prop ) {\n        name = jQuery.camelCase( p );\n        if ( p !== name ) {\n          prop[ name ] = prop[ p ];\n          delete prop[ p ];\n        }\n\n        if ( ( hooks = jQuery.cssHooks[ name ] ) && \"expand\" in hooks ) {\n          replace = hooks.expand( prop[ name ] );\n          delete prop[ name ];\n\n          // not quite $.extend, this wont overwrite keys already present.\n          // also - reusing 'p' from above because we have the correct \"name\"\n          for ( p in replace ) {\n            if ( ! ( p in prop ) ) {\n              prop[ p ] = replace[ p ];\n            }\n          }\n        }\n      }\n\n      for ( name in prop ) {\n        val = prop[ name ];\n        // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)\n        if ( jQuery.isArray( val ) ) {\n          opt.animatedProperties[ name ] = val[ 1 ];\n          val = prop[ name ] = val[ 0 ];\n        } else {\n          opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';\n        }\n\n        if ( val === \"hide\" && hidden || val === \"show\" && !hidden ) {\n          return opt.complete.call( this );\n        }\n\n        if ( isElement && ( name === \"height\" || name === \"width\" ) ) {\n          // Make sure that nothing sneaks out\n          // Record all 3 overflow attributes because IE does not\n          // change the overflow attribute when overflowX and\n          // overflowY are set to the same value\n          opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];\n\n          // Set display property to inline-block for height/width\n          // animations on inline elements that are having width/height animated\n          if ( jQuery.css( this, \"display\" ) === \"inline\" &&\n              jQuery.css( this, \"float\" ) === \"none\" ) {\n\n            // inline-level elements accept inline-block;\n            // block-level elements need to be inline with layout\n            if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === \"inline\" ) {\n              this.style.display = \"inline-block\";\n\n            } else {\n              this.style.zoom = 1;\n            }\n          }\n        }\n      }\n\n      if ( opt.overflow != null ) {\n        this.style.overflow = \"hidden\";\n      }\n\n      for ( p in prop ) {\n        e = new jQuery.fx( this, opt, p );\n        val = prop[ p ];\n\n        if ( rfxtypes.test( val ) ) {\n\n          // Tracks whether to show or hide based on private\n          // data attached to the element\n          method = jQuery._data( this, \"toggle\" + p ) || ( val === \"toggle\" ? hidden ? \"show\" : \"hide\" : 0 );\n          if ( method ) {\n            jQuery._data( this, \"toggle\" + p, method === \"show\" ? \"hide\" : \"show\" );\n            e[ method ]();\n          } else {\n            e[ val ]();\n          }\n\n        } else {\n          parts = rfxnum.exec( val );\n          start = e.cur();\n\n          if ( parts ) {\n            end = parseFloat( parts[2] );\n            unit = parts[3] || ( jQuery.cssNumber[ p ] ? \"\" : \"px\" );\n\n            // We need to compute starting value\n            if ( unit !== \"px\" ) {\n              jQuery.style( this, p, (end || 1) + unit);\n              start = ( (end || 1) / e.cur() ) * start;\n              jQuery.style( this, p, start + unit);\n            }\n\n            // If a +=/-= token was provided, we're doing a relative animation\n            if ( parts[1] ) {\n              end = ( (parts[ 1 ] === \"-=\" ? -1 : 1) * end ) + start;\n            }\n\n            e.custom( start, end, unit );\n\n          } else {\n            e.custom( start, val, \"\" );\n          }\n        }\n      }\n\n      // For JS strict compliance\n      return true;\n    }\n\n    return optall.queue === false ?\n      this.each( doAnimation ) :\n      this.queue( optall.queue, doAnimation );\n  },\n\n  stop: function( type, clearQueue, gotoEnd ) {\n    if ( typeof type !== \"string\" ) {\n      gotoEnd = clearQueue;\n      clearQueue = type;\n      type = undefined;\n    }\n    if ( clearQueue && type !== false ) {\n      this.queue( type || \"fx\", [] );\n    }\n\n    return this.each(function() {\n      var index,\n        hadTimers = false,\n        timers = jQuery.timers,\n        data = jQuery._data( this );\n\n      // clear marker counters if we know they won't be\n      if ( !gotoEnd ) {\n        jQuery._unmark( true, this );\n      }\n\n      function stopQueue( elem, data, index ) {\n        var hooks = data[ index ];\n        jQuery.removeData( elem, index, true );\n        hooks.stop( gotoEnd );\n      }\n\n      if ( type == null ) {\n        for ( index in data ) {\n          if ( data[ index ] && data[ index ].stop && index.indexOf(\".run\") === index.length - 4 ) {\n            stopQueue( this, data, index );\n          }\n        }\n      } else if ( data[ index = type + \".run\" ] && data[ index ].stop ){\n        stopQueue( this, data, index );\n      }\n\n      for ( index = timers.length; index--; ) {\n        if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n          if ( gotoEnd ) {\n\n            // force the next step to be the last\n            timers[ index ]( true );\n          } else {\n            timers[ index ].saveState();\n          }\n          hadTimers = true;\n          timers.splice( index, 1 );\n        }\n      }\n\n      // start the next in the queue if the last step wasn't forced\n      // timers currently will call their complete callbacks, which will dequeue\n      // but only if they were gotoEnd\n      if ( !( gotoEnd && hadTimers ) ) {\n        jQuery.dequeue( this, type );\n      }\n    });\n  }\n\n});\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n  setTimeout( clearFxNow, 0 );\n  return ( fxNow = jQuery.now() );\n}\n\nfunction clearFxNow() {\n  fxNow = undefined;\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, num ) {\n  var obj = {};\n\n  jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {\n    obj[ this ] = type;\n  });\n\n  return obj;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n  slideDown: genFx( \"show\", 1 ),\n  slideUp: genFx( \"hide\", 1 ),\n  slideToggle: genFx( \"toggle\", 1 ),\n  fadeIn: { opacity: \"show\" },\n  fadeOut: { opacity: \"hide\" },\n  fadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n  jQuery.fn[ name ] = function( speed, easing, callback ) {\n    return this.animate( props, speed, easing, callback );\n  };\n});\n\njQuery.extend({\n  speed: function( speed, easing, fn ) {\n    var opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n      complete: fn || !fn && easing ||\n        jQuery.isFunction( speed ) && speed,\n      duration: speed,\n      easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n    };\n\n    opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n      opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n    // normalize opt.queue - true/undefined/null -> \"fx\"\n    if ( opt.queue == null || opt.queue === true ) {\n      opt.queue = \"fx\";\n    }\n\n    // Queueing\n    opt.old = opt.complete;\n\n    opt.complete = function( noUnmark ) {\n      if ( jQuery.isFunction( opt.old ) ) {\n        opt.old.call( this );\n      }\n\n      if ( opt.queue ) {\n        jQuery.dequeue( this, opt.queue );\n      } else if ( noUnmark !== false ) {\n        jQuery._unmark( this );\n      }\n    };\n\n    return opt;\n  },\n\n  easing: {\n    linear: function( p ) {\n      return p;\n    },\n    swing: function( p ) {\n      return ( -Math.cos( p*Math.PI ) / 2 ) + 0.5;\n    }\n  },\n\n  timers: [],\n\n  fx: function( elem, options, prop ) {\n    this.options = options;\n    this.elem = elem;\n    this.prop = prop;\n\n    options.orig = options.orig || {};\n  }\n\n});\n\njQuery.fx.prototype = {\n  // Simple function for setting a style value\n  update: function() {\n    if ( this.options.step ) {\n      this.options.step.call( this.elem, this.now, this );\n    }\n\n    ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );\n  },\n\n  // Get the current size\n  cur: function() {\n    if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {\n      return this.elem[ this.prop ];\n    }\n\n    var parsed,\n      r = jQuery.css( this.elem, this.prop );\n    // Empty strings, null, undefined and \"auto\" are converted to 0,\n    // complex values such as \"rotate(1rad)\" are returned as is,\n    // simple values such as \"10px\" are parsed to Float.\n    return isNaN( parsed = parseFloat( r ) ) ? !r || r === \"auto\" ? 0 : r : parsed;\n  },\n\n  // Start an animation from one number to another\n  custom: function( from, to, unit ) {\n    var self = this,\n      fx = jQuery.fx;\n\n    this.startTime = fxNow || createFxNow();\n    this.end = to;\n    this.now = this.start = from;\n    this.pos = this.state = 0;\n    this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? \"\" : \"px\" );\n\n    function t( gotoEnd ) {\n      return self.step( gotoEnd );\n    }\n\n    t.queue = this.options.queue;\n    t.elem = this.elem;\n    t.saveState = function() {\n      if ( jQuery._data( self.elem, \"fxshow\" + self.prop ) === undefined ) {\n        if ( self.options.hide ) {\n          jQuery._data( self.elem, \"fxshow\" + self.prop, self.start );\n        } else if ( self.options.show ) {\n          jQuery._data( self.elem, \"fxshow\" + self.prop, self.end );\n        }\n      }\n    };\n\n    if ( t() && jQuery.timers.push(t) && !timerId ) {\n      timerId = setInterval( fx.tick, fx.interval );\n    }\n  },\n\n  // Simple 'show' function\n  show: function() {\n    var dataShow = jQuery._data( this.elem, \"fxshow\" + this.prop );\n\n    // Remember where we started, so that we can go back to it later\n    this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );\n    this.options.show = true;\n\n    // Begin the animation\n    // Make sure that we start at a small width/height to avoid any flash of content\n    if ( dataShow !== undefined ) {\n      // This show is picking up where a previous hide or show left off\n      this.custom( this.cur(), dataShow );\n    } else {\n      this.custom( this.prop === \"width\" || this.prop === \"height\" ? 1 : 0, this.cur() );\n    }\n\n    // Start by showing the element\n    jQuery( this.elem ).show();\n  },\n\n  // Simple 'hide' function\n  hide: function() {\n    // Remember where we started, so that we can go back to it later\n    this.options.orig[ this.prop ] = jQuery._data( this.elem, \"fxshow\" + this.prop ) || jQuery.style( this.elem, this.prop );\n    this.options.hide = true;\n\n    // Begin the animation\n    this.custom( this.cur(), 0 );\n  },\n\n  // Each step of an animation\n  step: function( gotoEnd ) {\n    var p, n, complete,\n      t = fxNow || createFxNow(),\n      done = true,\n      elem = this.elem,\n      options = this.options;\n\n    if ( gotoEnd || t >= options.duration + this.startTime ) {\n      this.now = this.end;\n      this.pos = this.state = 1;\n      this.update();\n\n      options.animatedProperties[ this.prop ] = true;\n\n      for ( p in options.animatedProperties ) {\n        if ( options.animatedProperties[ p ] !== true ) {\n          done = false;\n        }\n      }\n\n      if ( done ) {\n        // Reset the overflow\n        if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {\n\n          jQuery.each( [ \"\", \"X\", \"Y\" ], function( index, value ) {\n            elem.style[ \"overflow\" + value ] = options.overflow[ index ];\n          });\n        }\n\n        // Hide the element if the \"hide\" operation was done\n        if ( options.hide ) {\n          jQuery( elem ).hide();\n        }\n\n        // Reset the properties, if the item has been hidden or shown\n        if ( options.hide || options.show ) {\n          for ( p in options.animatedProperties ) {\n            jQuery.style( elem, p, options.orig[ p ] );\n            jQuery.removeData( elem, \"fxshow\" + p, true );\n            // Toggle data is no longer needed\n            jQuery.removeData( elem, \"toggle\" + p, true );\n          }\n        }\n\n        // Execute the complete function\n        // in the event that the complete function throws an exception\n        // we must ensure it won't be called twice. #5684\n\n        complete = options.complete;\n        if ( complete ) {\n\n          options.complete = false;\n          complete.call( elem );\n        }\n      }\n\n      return false;\n\n    } else {\n      // classical easing cannot be used with an Infinity duration\n      if ( options.duration == Infinity ) {\n        this.now = t;\n      } else {\n        n = t - this.startTime;\n        this.state = n / options.duration;\n\n        // Perform the easing function, defaults to swing\n        this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );\n        this.now = this.start + ( (this.end - this.start) * this.pos );\n      }\n      // Perform the next step of the animation\n      this.update();\n    }\n\n    return true;\n  }\n};\n\njQuery.extend( jQuery.fx, {\n  tick: function() {\n    var timer,\n      timers = jQuery.timers,\n      i = 0;\n\n    for ( ; i < timers.length; i++ ) {\n      timer = timers[ i ];\n      // Checks the timer has not already been removed\n      if ( !timer() && timers[ i ] === timer ) {\n        timers.splice( i--, 1 );\n      }\n    }\n\n    if ( !timers.length ) {\n      jQuery.fx.stop();\n    }\n  },\n\n  interval: 13,\n\n  stop: function() {\n    clearInterval( timerId );\n    timerId = null;\n  },\n\n  speeds: {\n    slow: 600,\n    fast: 200,\n    // Default speed\n    _default: 400\n  },\n\n  step: {\n    opacity: function( fx ) {\n      jQuery.style( fx.elem, \"opacity\", fx.now );\n    },\n\n    _default: function( fx ) {\n      if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {\n        fx.elem.style[ fx.prop ] = fx.now + fx.unit;\n      } else {\n        fx.elem[ fx.prop ] = fx.now;\n      }\n    }\n  }\n});\n\n// Ensure props that can't be negative don't go there on undershoot easing\njQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) {\n  // exclude marginTop, marginLeft, marginBottom and marginRight from this list\n  if ( prop.indexOf( \"margin\" ) ) {\n    jQuery.fx.step[ prop ] = function( fx ) {\n      jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );\n    };\n  }\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n  jQuery.expr.filters.animated = function( elem ) {\n    return jQuery.grep(jQuery.timers, function( fn ) {\n      return elem === fn.elem;\n    }).length;\n  };\n}\n\n// Try to restore the default display value of an element\nfunction defaultDisplay( nodeName ) {\n\n  if ( !elemdisplay[ nodeName ] ) {\n\n    var body = document.body,\n      elem = jQuery( \"<\" + nodeName + \">\" ).appendTo( body ),\n      display = elem.css( \"display\" );\n    elem.remove();\n\n    // If the simple way fails,\n    // get element's real default display by attaching it to a temp iframe\n    if ( display === \"none\" || display === \"\" ) {\n      // No iframe to use yet, so create it\n      if ( !iframe ) {\n        iframe = document.createElement( \"iframe\" );\n        iframe.frameBorder = iframe.width = iframe.height = 0;\n      }\n\n      body.appendChild( iframe );\n\n      // Create a cacheable copy of the iframe document on first call.\n      // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n      // document to it; WebKit & Firefox won't allow reusing the iframe document.\n      if ( !iframeDoc || !iframe.createElement ) {\n        iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n        iframeDoc.write( ( jQuery.support.boxModel ? \"<!doctype html>\" : \"\" ) + \"<html><body>\" );\n        iframeDoc.close();\n      }\n\n      elem = iframeDoc.createElement( nodeName );\n\n      iframeDoc.body.appendChild( elem );\n\n      display = jQuery.css( elem, \"display\" );\n      body.removeChild( iframe );\n    }\n\n    // Store the correct default display\n    elemdisplay[ nodeName ] = display;\n  }\n\n  return elemdisplay[ nodeName ];\n}\n\n\n\n\nvar getOffset,\n  rtable = /^t(?:able|d|h)$/i,\n  rroot = /^(?:body|html)$/i;\n\nif ( \"getBoundingClientRect\" in document.documentElement ) {\n  getOffset = function( elem, doc, docElem, box ) {\n    try {\n      box = elem.getBoundingClientRect();\n    } catch(e) {}\n\n    // Make sure we're not dealing with a disconnected DOM node\n    if ( !box || !jQuery.contains( docElem, elem ) ) {\n      return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };\n    }\n\n    var body = doc.body,\n      win = getWindow( doc ),\n      clientTop  = docElem.clientTop  || body.clientTop  || 0,\n      clientLeft = docElem.clientLeft || body.clientLeft || 0,\n      scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,\n      scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,\n      top  = box.top  + scrollTop  - clientTop,\n      left = box.left + scrollLeft - clientLeft;\n\n    return { top: top, left: left };\n  };\n\n} else {\n  getOffset = function( elem, doc, docElem ) {\n    var computedStyle,\n      offsetParent = elem.offsetParent,\n      prevOffsetParent = elem,\n      body = doc.body,\n      defaultView = doc.defaultView,\n      prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,\n      top = elem.offsetTop,\n      left = elem.offsetLeft;\n\n    while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {\n      if ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n        break;\n      }\n\n      computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;\n      top  -= elem.scrollTop;\n      left -= elem.scrollLeft;\n\n      if ( elem === offsetParent ) {\n        top  += elem.offsetTop;\n        left += elem.offsetLeft;\n\n        if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {\n          top  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n          left += parseFloat( computedStyle.borderLeftWidth ) || 0;\n        }\n\n        prevOffsetParent = offsetParent;\n        offsetParent = elem.offsetParent;\n      }\n\n      if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== \"visible\" ) {\n        top  += parseFloat( computedStyle.borderTopWidth  ) || 0;\n        left += parseFloat( computedStyle.borderLeftWidth ) || 0;\n      }\n\n      prevComputedStyle = computedStyle;\n    }\n\n    if ( prevComputedStyle.position === \"relative\" || prevComputedStyle.position === \"static\" ) {\n      top  += body.offsetTop;\n      left += body.offsetLeft;\n    }\n\n    if ( jQuery.support.fixedPosition && prevComputedStyle.position === \"fixed\" ) {\n      top  += Math.max( docElem.scrollTop, body.scrollTop );\n      left += Math.max( docElem.scrollLeft, body.scrollLeft );\n    }\n\n    return { top: top, left: left };\n  };\n}\n\njQuery.fn.offset = function( options ) {\n  if ( arguments.length ) {\n    return options === undefined ?\n      this :\n      this.each(function( i ) {\n        jQuery.offset.setOffset( this, options, i );\n      });\n  }\n\n  var elem = this[0],\n    doc = elem && elem.ownerDocument;\n\n  if ( !doc ) {\n    return null;\n  }\n\n  if ( elem === doc.body ) {\n    return jQuery.offset.bodyOffset( elem );\n  }\n\n  return getOffset( elem, doc, doc.documentElement );\n};\n\njQuery.offset = {\n\n  bodyOffset: function( body ) {\n    var top = body.offsetTop,\n      left = body.offsetLeft;\n\n    if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n      top  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n      left += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n    }\n\n    return { top: top, left: left };\n  },\n\n  setOffset: function( elem, options, i ) {\n    var position = jQuery.css( elem, \"position\" );\n\n    // set position first, in-case top/left are set even on static elem\n    if ( position === \"static\" ) {\n      elem.style.position = \"relative\";\n    }\n\n    var curElem = jQuery( elem ),\n      curOffset = curElem.offset(),\n      curCSSTop = jQuery.css( elem, \"top\" ),\n      curCSSLeft = jQuery.css( elem, \"left\" ),\n      calculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n      props = {}, curPosition = {}, curTop, curLeft;\n\n    // need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n    if ( calculatePosition ) {\n      curPosition = curElem.position();\n      curTop = curPosition.top;\n      curLeft = curPosition.left;\n    } else {\n      curTop = parseFloat( curCSSTop ) || 0;\n      curLeft = parseFloat( curCSSLeft ) || 0;\n    }\n\n    if ( jQuery.isFunction( options ) ) {\n      options = options.call( elem, i, curOffset );\n    }\n\n    if ( options.top != null ) {\n      props.top = ( options.top - curOffset.top ) + curTop;\n    }\n    if ( options.left != null ) {\n      props.left = ( options.left - curOffset.left ) + curLeft;\n    }\n\n    if ( \"using\" in options ) {\n      options.using.call( elem, props );\n    } else {\n      curElem.css( props );\n    }\n  }\n};\n\n\njQuery.fn.extend({\n\n  position: function() {\n    if ( !this[0] ) {\n      return null;\n    }\n\n    var elem = this[0],\n\n    // Get *real* offsetParent\n    offsetParent = this.offsetParent(),\n\n    // Get correct offsets\n    offset       = this.offset(),\n    parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n    // Subtract element margins\n    // note: when an element has margin: auto the offsetLeft and marginLeft\n    // are the same in Safari causing offset.left to incorrectly be 0\n    offset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n    offset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n    // Add offsetParent borders\n    parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n    parentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n    // Subtract the two offsets\n    return {\n      top:  offset.top  - parentOffset.top,\n      left: offset.left - parentOffset.left\n    };\n  },\n\n  offsetParent: function() {\n    return this.map(function() {\n      var offsetParent = this.offsetParent || document.body;\n      while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent;\n    });\n  }\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n  var top = /Y/.test( prop );\n\n  jQuery.fn[ method ] = function( val ) {\n    return jQuery.access( this, function( elem, method, val ) {\n      var win = getWindow( elem );\n\n      if ( val === undefined ) {\n        return win ? (prop in win) ? win[ prop ] :\n          jQuery.support.boxModel && win.document.documentElement[ method ] ||\n            win.document.body[ method ] :\n          elem[ method ];\n      }\n\n      if ( win ) {\n        win.scrollTo(\n          !top ? val : jQuery( win ).scrollLeft(),\n           top ? val : jQuery( win ).scrollTop()\n        );\n\n      } else {\n        elem[ method ] = val;\n      }\n    }, method, val, arguments.length, null );\n  };\n});\n\nfunction getWindow( elem ) {\n  return jQuery.isWindow( elem ) ?\n    elem :\n    elem.nodeType === 9 ?\n      elem.defaultView || elem.parentWindow :\n      false;\n}\n\n\n\n\n// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n  var clientProp = \"client\" + name,\n    scrollProp = \"scroll\" + name,\n    offsetProp = \"offset\" + name;\n\n  // innerHeight and innerWidth\n  jQuery.fn[ \"inner\" + name ] = function() {\n    var elem = this[0];\n    return elem ?\n      elem.style ?\n      parseFloat( jQuery.css( elem, type, \"padding\" ) ) :\n      this[ type ]() :\n      null;\n  };\n\n  // outerHeight and outerWidth\n  jQuery.fn[ \"outer\" + name ] = function( margin ) {\n    var elem = this[0];\n    return elem ?\n      elem.style ?\n      parseFloat( jQuery.css( elem, type, margin ? \"margin\" : \"border\" ) ) :\n      this[ type ]() :\n      null;\n  };\n\n  jQuery.fn[ type ] = function( value ) {\n    return jQuery.access( this, function( elem, type, value ) {\n      var doc, docElemProp, orig, ret;\n\n      if ( jQuery.isWindow( elem ) ) {\n        // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat\n        doc = elem.document;\n        docElemProp = doc.documentElement[ clientProp ];\n        return jQuery.support.boxModel && docElemProp ||\n          doc.body && doc.body[ clientProp ] || docElemProp;\n      }\n\n      // Get document width or height\n      if ( elem.nodeType === 9 ) {\n        // Either scroll[Width/Height] or offset[Width/Height], whichever is greater\n        doc = elem.documentElement;\n\n        // when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height]\n        // so we can't use max, as it'll choose the incorrect offset[Width/Height]\n        // instead we use the correct client[Width/Height]\n        // support:IE6\n        if ( doc[ clientProp ] >= doc[ scrollProp ] ) {\n          return doc[ clientProp ];\n        }\n\n        return Math.max(\n          elem.body[ scrollProp ], doc[ scrollProp ],\n          elem.body[ offsetProp ], doc[ offsetProp ]\n        );\n      }\n\n      // Get width or height on the element\n      if ( value === undefined ) {\n        orig = jQuery.css( elem, type );\n        ret = parseFloat( orig );\n        return jQuery.isNumeric( ret ) ? ret : orig;\n      }\n\n      // Set the width or height on the element\n      jQuery( elem ).css( type, value );\n    }, type, value, arguments.length, null );\n  };\n});\n\n\n\n\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n  define( \"jquery\", [], function () { return jQuery; } );\n}\n\n\n\n})( window );"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/resources/static/js/jquery.validate.js",
    "content": "/**\n * jQuery Validation Plugin @VERSION\n *\n * http://bassistance.de/jquery-plugins/jquery-plugin-validation/\n * http://docs.jquery.com/Plugins/Validation\n *\n * Copyright (c) 2012 JÃ¶rn Zaefferer\n *\n * Dual licensed under the MIT and GPL licenses:\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n */\n\n(function($) {\n\n$.extend($.fn, {\n  // http://docs.jquery.com/Plugins/Validation/validate\n  validate: function( options ) {\n\n    // if nothing is selected, return nothing; can't chain anyway\n    if (!this.length) {\n      if (options && options.debug && window.console) {\n        console.warn( \"nothing selected, can't validate, returning nothing\" );\n      }\n      return;\n    }\n\n    // check if a validator for this form was already created\n    var validator = $.data(this[0], 'validator');\n    if ( validator ) {\n      return validator;\n    }\n\n    // Add novalidate tag if HTML5.\n    this.attr('novalidate', 'novalidate');\n\n    validator = new $.validator( options, this[0] );\n    $.data(this[0], 'validator', validator);\n\n    if ( validator.settings.onsubmit ) {\n\n      this.validateDelegate( \":submit\", \"click\", function(ev) {\n        if ( validator.settings.submitHandler ) {\n          validator.submitButton = ev.target;\n        }\n        // allow suppressing validation by adding a cancel class to the submit button\n        if ( $(ev.target).hasClass('cancel') ) {\n          validator.cancelSubmit = true;\n        }\n      });\n\n      // validate the form on submit\n      this.submit( function( event ) {\n        if ( validator.settings.debug ) {\n          // prevent form submit to be able to see console output\n          event.preventDefault();\n        }\n        function handle() {\n          var hidden;\n          if ( validator.settings.submitHandler ) {\n            if (validator.submitButton) {\n              // insert a hidden input as a replacement for the missing submit button\n              hidden = $(\"<input type='hidden'/>\").attr(\"name\", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);\n            }\n            validator.settings.submitHandler.call( validator, validator.currentForm, event );\n            if (validator.submitButton) {\n              // and clean up afterwards; thanks to no-block-scope, hidden can be referenced\n              hidden.remove();\n            }\n            return false;\n          }\n          return true;\n        }\n\n        // prevent submit for invalid forms or custom submit handlers\n        if ( validator.cancelSubmit ) {\n          validator.cancelSubmit = false;\n          return handle();\n        }\n        if ( validator.form() ) {\n          if ( validator.pendingRequest ) {\n            validator.formSubmitted = true;\n            return false;\n          }\n          return handle();\n        } else {\n          validator.focusInvalid();\n          return false;\n        }\n      });\n    }\n\n    return validator;\n  },\n  // http://docs.jquery.com/Plugins/Validation/valid\n  valid: function() {\n    if ( $(this[0]).is('form')) {\n      return this.validate().form();\n    } else {\n      var valid = true;\n      var validator = $(this[0].form).validate();\n      this.each(function() {\n        valid &= validator.element(this);\n      });\n      return valid;\n    }\n  },\n  // attributes: space seperated list of attributes to retrieve and remove\n  removeAttrs: function(attributes) {\n    var result = {},\n      $element = this;\n    $.each(attributes.split(/\\s/), function(index, value) {\n      result[value] = $element.attr(value);\n      $element.removeAttr(value);\n    });\n    return result;\n  },\n  // http://docs.jquery.com/Plugins/Validation/rules\n  rules: function(command, argument) {\n    var element = this[0];\n\n    if (command) {\n      var settings = $.data(element.form, 'validator').settings;\n      var staticRules = settings.rules;\n      var existingRules = $.validator.staticRules(element);\n      switch(command) {\n      case \"add\":\n        $.extend(existingRules, $.validator.normalizeRule(argument));\n        staticRules[element.name] = existingRules;\n        if (argument.messages) {\n          settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );\n        }\n        break;\n      case \"remove\":\n        if (!argument) {\n          delete staticRules[element.name];\n          return existingRules;\n        }\n        var filtered = {};\n        $.each(argument.split(/\\s/), function(index, method) {\n          filtered[method] = existingRules[method];\n          delete existingRules[method];\n        });\n        return filtered;\n      }\n    }\n\n    var data = $.validator.normalizeRules(\n    $.extend(\n      {},\n      $.validator.metadataRules(element),\n      $.validator.classRules(element),\n      $.validator.attributeRules(element),\n      $.validator.staticRules(element)\n    ), element);\n\n    // make sure required is at front\n    if (data.required) {\n      var param = data.required;\n      delete data.required;\n      data = $.extend({required: param}, data);\n    }\n\n    return data;\n  }\n});\n\n// Custom selectors\n$.extend($.expr[\":\"], {\n  // http://docs.jquery.com/Plugins/Validation/blank\n  blank: function(a) {return !$.trim(\"\" + a.value);},\n  // http://docs.jquery.com/Plugins/Validation/filled\n  filled: function(a) {return !!$.trim(\"\" + a.value);},\n  // http://docs.jquery.com/Plugins/Validation/unchecked\n  unchecked: function(a) {return !a.checked;}\n});\n\n// constructor for validator\n$.validator = function( options, form ) {\n  this.settings = $.extend( true, {}, $.validator.defaults, options );\n  this.currentForm = form;\n  this.init();\n};\n\n$.validator.format = function(source, params) {\n  if ( arguments.length === 1 ) {\n    return function() {\n      var args = $.makeArray(arguments);\n      args.unshift(source);\n      return $.validator.format.apply( this, args );\n    };\n  }\n  if ( arguments.length > 2 && params.constructor !== Array  ) {\n    params = $.makeArray(arguments).slice(1);\n  }\n  if ( params.constructor !== Array ) {\n    params = [ params ];\n  }\n  $.each(params, function(i, n) {\n    source = source.replace(new RegExp(\"\\\\{\" + i + \"\\\\}\", \"g\"), n);\n  });\n  return source;\n};\n\n$.extend($.validator, {\n\n  defaults: {\n    messages: {},\n    groups: {},\n    rules: {},\n    errorClass: \"error\",\n    validClass: \"valid\",\n    errorElement: \"label\",\n    focusInvalid: true,\n    errorContainer: $( [] ),\n    errorLabelContainer: $( [] ),\n    onsubmit: true,\n    ignore: \":hidden\",\n    ignoreTitle: false,\n    onfocusin: function(element, event) {\n      this.lastActive = element;\n\n      // hide error label and remove error class on focus if enabled\n      if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {\n        if ( this.settings.unhighlight ) {\n          this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );\n        }\n        this.addWrapper(this.errorsFor(element)).hide();\n      }\n    },\n    onfocusout: function(element, event) {\n      if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {\n        this.element(element);\n      }\n    },\n    onkeyup: function(element, event) {\n      if ( element.name in this.submitted || element === this.lastElement ) {\n        this.element(element);\n      }\n    },\n    onclick: function(element, event) {\n      // click on selects, radiobuttons and checkboxes\n      if ( element.name in this.submitted ) {\n        this.element(element);\n      }\n      // or option elements, check parent select in that case\n      else if (element.parentNode.name in this.submitted) {\n        this.element(element.parentNode);\n      }\n    },\n    highlight: function(element, errorClass, validClass) {\n      if (element.type === 'radio') {\n        this.findByName(element.name).addClass(errorClass).removeClass(validClass);\n      } else {\n        $(element).addClass(errorClass).removeClass(validClass);\n      }\n    },\n    unhighlight: function(element, errorClass, validClass) {\n      if (element.type === 'radio') {\n        this.findByName(element.name).removeClass(errorClass).addClass(validClass);\n      } else {\n        $(element).removeClass(errorClass).addClass(validClass);\n      }\n    }\n  },\n\n  // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults\n  setDefaults: function(settings) {\n    $.extend( $.validator.defaults, settings );\n  },\n\n  messages: {\n    required: \"This field is required.\",\n    remote: \"Please fix this field.\",\n    email: \"Please enter a valid email address.\",\n    url: \"Please enter a valid URL.\",\n    date: \"Please enter a valid date.\",\n    dateISO: \"Please enter a valid date (ISO).\",\n    number: \"Please enter a valid number.\",\n    digits: \"Please enter only digits.\",\n    creditcard: \"Please enter a valid credit card number.\",\n    equalTo: \"Please enter the same value again.\",\n    accept: \"Please enter a value with a valid extension.\",\n    maxlength: $.validator.format(\"Please enter no more than {0} characters.\"),\n    minlength: $.validator.format(\"Please enter at least {0} characters.\"),\n    rangelength: $.validator.format(\"Please enter a value between {0} and {1} characters long.\"),\n    range: $.validator.format(\"Please enter a value between {0} and {1}.\"),\n    max: $.validator.format(\"Please enter a value less than or equal to {0}.\"),\n    min: $.validator.format(\"Please enter a value greater than or equal to {0}.\")\n  },\n\n  autoCreateRanges: false,\n\n  prototype: {\n\n    init: function() {\n      this.labelContainer = $(this.settings.errorLabelContainer);\n      this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);\n      this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );\n      this.submitted = {};\n      this.valueCache = {};\n      this.pendingRequest = 0;\n      this.pending = {};\n      this.invalid = {};\n      this.reset();\n\n      var groups = (this.groups = {});\n      $.each(this.settings.groups, function(key, value) {\n        $.each(value.split(/\\s/), function(index, name) {\n          groups[name] = key;\n        });\n      });\n      var rules = this.settings.rules;\n      $.each(rules, function(key, value) {\n        rules[key] = $.validator.normalizeRule(value);\n      });\n\n      function delegate(event) {\n        var validator = $.data(this[0].form, \"validator\"),\n          eventType = \"on\" + event.type.replace(/^validate/, \"\");\n        if (validator.settings[eventType]) {\n          validator.settings[eventType].call(validator, this[0], event);\n        }\n      }\n      $(this.currentForm)\n        .validateDelegate(\"[type='text'], [type='password'], [type='file'], select, textarea, \" +\n          \"[type='number'], [type='search'] ,[type='tel'], [type='url'], \" +\n          \"[type='email'], [type='datetime'], [type='date'], [type='month'], \" +\n          \"[type='week'], [type='time'], [type='datetime-local'], \" +\n          \"[type='range'], [type='color'] \",\n          \"focusin focusout keyup\", delegate)\n        .validateDelegate(\"[type='radio'], [type='checkbox'], select, option\", \"click\", delegate);\n\n      if (this.settings.invalidHandler) {\n        $(this.currentForm).bind(\"invalid-form.validate\", this.settings.invalidHandler);\n      }\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Validator/form\n    form: function() {\n      this.checkForm();\n      $.extend(this.submitted, this.errorMap);\n      this.invalid = $.extend({}, this.errorMap);\n      if (!this.valid()) {\n        $(this.currentForm).triggerHandler(\"invalid-form\", [this]);\n      }\n      this.showErrors();\n      return this.valid();\n    },\n\n    checkForm: function() {\n      this.prepareForm();\n      for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {\n        this.check( elements[i] );\n      }\n      return this.valid();\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Validator/element\n    element: function( element ) {\n      element = this.validationTargetFor( this.clean( element ) );\n      this.lastElement = element;\n      this.prepareElement( element );\n      this.currentElements = $(element);\n      var result = this.check( element ) !== false;\n      if (result) {\n        delete this.invalid[element.name];\n      } else {\n        this.invalid[element.name] = true;\n      }\n      if ( !this.numberOfInvalids() ) {\n        // Hide error containers on last error\n        this.toHide = this.toHide.add( this.containers );\n      }\n      this.showErrors();\n      return result;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Validator/showErrors\n    showErrors: function(errors) {\n      if(errors) {\n        // add items to error list and map\n        $.extend( this.errorMap, errors );\n        this.errorList = [];\n        for ( var name in errors ) {\n          this.errorList.push({\n            message: errors[name],\n            element: this.findByName(name)[0]\n          });\n        }\n        // remove items from success list\n        this.successList = $.grep( this.successList, function(element) {\n          return !(element.name in errors);\n        });\n      }\n      if (this.settings.showErrors) {\n        this.settings.showErrors.call( this, this.errorMap, this.errorList );\n      } else {\n        this.defaultShowErrors();\n      }\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Validator/resetForm\n    resetForm: function() {\n      if ( $.fn.resetForm ) {\n        $( this.currentForm ).resetForm();\n      }\n      this.submitted = {};\n      this.lastElement = null;\n      this.prepareForm();\n      this.hideErrors();\n      this.elements().removeClass( this.settings.errorClass );\n    },\n\n    numberOfInvalids: function() {\n      return this.objectLength(this.invalid);\n    },\n\n    objectLength: function( obj ) {\n      var count = 0;\n      for ( var i in obj ) {\n        count++;\n      }\n      return count;\n    },\n\n    hideErrors: function() {\n      this.addWrapper( this.toHide ).hide();\n    },\n\n    valid: function() {\n      return this.size() === 0;\n    },\n\n    size: function() {\n      return this.errorList.length;\n    },\n\n    focusInvalid: function() {\n      if( this.settings.focusInvalid ) {\n        try {\n          $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])\n          .filter(\":visible\")\n          .focus()\n          // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find\n          .trigger(\"focusin\");\n        } catch(e) {\n          // ignore IE throwing errors when focusing hidden elements\n        }\n      }\n    },\n\n    findLastActive: function() {\n      var lastActive = this.lastActive;\n      return lastActive && $.grep(this.errorList, function(n) {\n        return n.element.name === lastActive.name;\n      }).length === 1 && lastActive;\n    },\n\n    elements: function() {\n      var validator = this,\n        rulesCache = {};\n\n      // select all valid inputs inside the form (no submit or reset buttons)\n      return $(this.currentForm)\n      .find(\"input, select, textarea\")\n      .not(\":submit, :reset, :image, [disabled]\")\n      .not( this.settings.ignore )\n      .filter(function() {\n        if ( !this.name && validator.settings.debug && window.console ) {\n          console.error( \"%o has no name assigned\", this);\n        }\n\n        // select only the first element for each name, and only those with rules specified\n        if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) {\n          return false;\n        }\n\n        rulesCache[this.name] = true;\n        return true;\n      });\n    },\n\n    clean: function( selector ) {\n      return $( selector )[0];\n    },\n\n    errors: function() {\n      var errorClass = this.settings.errorClass.replace(' ', '.');\n      return $( this.settings.errorElement + \".\" + errorClass, this.errorContext );\n    },\n\n    reset: function() {\n      this.successList = [];\n      this.errorList = [];\n      this.errorMap = {};\n      this.toShow = $([]);\n      this.toHide = $([]);\n      this.currentElements = $([]);\n    },\n\n    prepareForm: function() {\n      this.reset();\n      this.toHide = this.errors().add( this.containers );\n    },\n\n    prepareElement: function( element ) {\n      this.reset();\n      this.toHide = this.errorsFor(element);\n    },\n\n    elementValue: function( element ) {\n      var val = $(element).val();\n      if( typeof val === 'string' ) {\n        return val.replace(/\\r/g, \"\");\n      }\n      return val;\n    },\n\n    check: function( element ) {\n      element = this.validationTargetFor( this.clean( element ) );\n\n      var rules = $(element).rules();\n      var dependencyMismatch = false;\n      var val = this.elementValue(element);\n      var result;\n\n      for (var method in rules ) {\n        var rule = { method: method, parameters: rules[method] };\n        try {\n\n          result = $.validator.methods[method].call( this, val, element, rule.parameters );\n\n          // if a method indicates that the field is optional and therefore valid,\n          // don't mark it as valid when there are no other rules\n          if ( result === \"dependency-mismatch\" ) {\n            dependencyMismatch = true;\n            continue;\n          }\n          dependencyMismatch = false;\n\n          if ( result === \"pending\" ) {\n            this.toHide = this.toHide.not( this.errorsFor(element) );\n            return;\n          }\n\n          if( !result ) {\n            this.formatAndAdd( element, rule );\n            return false;\n          }\n        } catch(e) {\n          if ( this.settings.debug && window.console ) {\n            console.log(\"exception occured when checking element \" + element.id + \", check the '\" + rule.method + \"' method\", e);\n          }\n          throw e;\n        }\n      }\n      if (dependencyMismatch) {\n        return;\n      }\n      if ( this.objectLength(rules) ) {\n        this.successList.push(element);\n      }\n      return true;\n    },\n\n    // return the custom message for the given element and validation method\n    // specified in the element's \"messages\" metadata\n    customMetaMessage: function(element, method) {\n      if (!$.metadata) {\n        return;\n      }\n      var meta = this.settings.meta ? $(element).metadata()[this.settings.meta] : $(element).metadata();\n      return meta && meta.messages && meta.messages[method];\n    },\n\n    // return the custom message for the given element name and validation method\n    customMessage: function( name, method ) {\n      var m = this.settings.messages[name];\n      return m && (m.constructor === String ? m : m[method]);\n    },\n\n    // return the first defined argument, allowing empty strings\n    findDefined: function() {\n      for(var i = 0; i < arguments.length; i++) {\n        if (arguments[i] !== undefined) {\n          return arguments[i];\n        }\n      }\n      return undefined;\n    },\n\n    defaultMessage: function( element, method) {\n      return this.findDefined(\n        this.customMessage( element.name, method ),\n        this.customMetaMessage( element, method ),\n        // title is never undefined, so handle empty string as undefined\n        !this.settings.ignoreTitle && element.title || undefined,\n        $.validator.messages[method],\n        \"<strong>Warning: No message defined for \" + element.name + \"</strong>\"\n      );\n    },\n\n    formatAndAdd: function( element, rule ) {\n      var message = this.defaultMessage( element, rule.method ),\n        theregex = /\\$?\\{(\\d+)\\}/g;\n      if ( typeof message === \"function\" ) {\n        message = message.call(this, rule.parameters, element);\n      } else if (theregex.test(message)) {\n        message = $.validator.format(message.replace(theregex, '{$1}'), rule.parameters);\n      }\n      this.errorList.push({\n        message: message,\n        element: element\n      });\n\n      this.errorMap[element.name] = message;\n      this.submitted[element.name] = message;\n    },\n\n    addWrapper: function(toToggle) {\n      if ( this.settings.wrapper ) {\n        toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );\n      }\n      return toToggle;\n    },\n\n    defaultShowErrors: function() {\n      var i, elements;\n      for ( i = 0; this.errorList[i]; i++ ) {\n        var error = this.errorList[i];\n        if ( this.settings.highlight ) {\n          this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );\n        }\n        this.showLabel( error.element, error.message );\n      }\n      if( this.errorList.length ) {\n        this.toShow = this.toShow.add( this.containers );\n      }\n      if (this.settings.success) {\n        for ( i = 0; this.successList[i]; i++ ) {\n          this.showLabel( this.successList[i] );\n        }\n      }\n      if (this.settings.unhighlight) {\n        for ( i = 0, elements = this.validElements(); elements[i]; i++ ) {\n          this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );\n        }\n      }\n      this.toHide = this.toHide.not( this.toShow );\n      this.hideErrors();\n      this.addWrapper( this.toShow ).show();\n    },\n\n    validElements: function() {\n      return this.currentElements.not(this.invalidElements());\n    },\n\n    invalidElements: function() {\n      return $(this.errorList).map(function() {\n        return this.element;\n      });\n    },\n\n    showLabel: function(element, message) {\n      var label = this.errorsFor( element );\n      if ( label.length ) {\n        // refresh error/success class\n        label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );\n\n        // check if we have a generated label, replace the message then\n        if ( label.attr(\"generated\") ) {\n          label.html(message);\n        }\n      } else {\n        // create label\n        label = $(\"<\" + this.settings.errorElement + \"/>\")\n          .attr({\"for\":  this.idOrName(element), generated: true})\n          .addClass(this.settings.errorClass)\n          .html(message || \"\");\n        if ( this.settings.wrapper ) {\n          // make sure the element is visible, even in IE\n          // actually showing the wrapped element is handled elsewhere\n          label = label.hide().show().wrap(\"<\" + this.settings.wrapper + \"/>\").parent();\n        }\n        if ( !this.labelContainer.append(label).length ) {\n          if ( this.settings.errorPlacement ) {\n            this.settings.errorPlacement(label, $(element) );\n          } else {\n          label.insertAfter(element);\n          }\n        }\n      }\n      if ( !message && this.settings.success ) {\n        label.text(\"\");\n        if ( typeof this.settings.success === \"string\" ) {\n          label.addClass( this.settings.success );\n        } else {\n          this.settings.success( label );\n        }\n      }\n      this.toShow = this.toShow.add(label);\n    },\n\n    errorsFor: function(element) {\n      var name = this.idOrName(element);\n      return this.errors().filter(function() {\n        return $(this).attr('for') === name;\n      });\n    },\n\n    idOrName: function(element) {\n      return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);\n    },\n\n    validationTargetFor: function(element) {\n      // if radio/checkbox, validate first element in group instead\n      if (this.checkable(element)) {\n        element = this.findByName( element.name ).not(this.settings.ignore)[0];\n      }\n      return element;\n    },\n\n    checkable: function( element ) {\n      return (/radio|checkbox/i).test(element.type);\n    },\n\n    findByName: function( name ) {\n      // select by name and filter by form for performance over form.find(\"[name=...]\")\n      var form = this.currentForm;\n      return $(document.getElementsByName(name)).map(function(index, element) {\n        return element.form === form && element.name === name && element  || null;\n      });\n    },\n\n    getLength: function(value, element) {\n      switch( element.nodeName.toLowerCase() ) {\n      case 'select':\n        return $(\"option:selected\", element).length;\n      case 'input':\n        if( this.checkable( element) ) {\n          return this.findByName(element.name).filter(':checked').length;\n        }\n      }\n      return value.length;\n    },\n\n    depend: function(param, element) {\n      return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true;\n    },\n\n    dependTypes: {\n      \"boolean\": function(param, element) {\n        return param;\n      },\n      \"string\": function(param, element) {\n        return !!$(param, element.form).length;\n      },\n      \"function\": function(param, element) {\n        return param(element);\n      }\n    },\n\n    optional: function(element) {\n      var val = this.elementValue(element);\n      return !$.validator.methods.required.call(this, val, element) && \"dependency-mismatch\";\n    },\n\n    startRequest: function(element) {\n      if (!this.pending[element.name]) {\n        this.pendingRequest++;\n        this.pending[element.name] = true;\n      }\n    },\n\n    stopRequest: function(element, valid) {\n      this.pendingRequest--;\n      // sometimes synchronization fails, make sure pendingRequest is never < 0\n      if (this.pendingRequest < 0) {\n        this.pendingRequest = 0;\n      }\n      delete this.pending[element.name];\n      if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {\n        $(this.currentForm).submit();\n        this.formSubmitted = false;\n      } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) {\n        $(this.currentForm).triggerHandler(\"invalid-form\", [this]);\n        this.formSubmitted = false;\n      }\n    },\n\n    previousValue: function(element) {\n      return $.data(element, \"previousValue\") || $.data(element, \"previousValue\", {\n        old: null,\n        valid: true,\n        message: this.defaultMessage( element, \"remote\" )\n      });\n    }\n\n  },\n\n  classRuleSettings: {\n    required: {required: true},\n    email: {email: true},\n    url: {url: true},\n    date: {date: true},\n    dateISO: {dateISO: true},\n    number: {number: true},\n    digits: {digits: true},\n    creditcard: {creditcard: true}\n  },\n\n  addClassRules: function(className, rules) {\n    if ( className.constructor === String ) {\n      this.classRuleSettings[className] = rules;\n    } else {\n      $.extend(this.classRuleSettings, className);\n    }\n  },\n\n  classRules: function(element) {\n    var rules = {};\n    var classes = $(element).attr('class');\n    if ( classes ) {\n      $.each(classes.split(' '), function() {\n        if (this in $.validator.classRuleSettings) {\n          $.extend(rules, $.validator.classRuleSettings[this]);\n        }\n      });\n    }\n    return rules;\n  },\n\n  attributeRules: function(element) {\n    var rules = {};\n    var $element = $(element);\n\n    for (var method in $.validator.methods) {\n      var value;\n\n      // support for <input required> in both html5 and older browsers\n      if (method === 'required') {\n        value = $element.get(0).getAttribute(method);\n        // Some browsers return an empty string for the required attribute\n        // and non-HTML5 browsers might have required=\"\" markup\n        if (value === \"\") {\n          value = true;\n        } else if (value === \"false\") {\n          value = false;\n        }\n        // force non-HTML5 browsers to return bool\n        value = !!value;\n      } else {\n        value = $element.attr(method);\n      }\n\n      if (value) {\n        rules[method] = value;\n      } else if ($element[0].getAttribute(\"type\") === method) {\n        rules[method] = true;\n      }\n    }\n\n    // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs\n    if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {\n      delete rules.maxlength;\n    }\n\n    return rules;\n  },\n\n  metadataRules: function(element) {\n    if (!$.metadata) {\n      return {};\n    }\n\n    var meta = $.data(element.form, 'validator').settings.meta;\n    return meta ?\n      $(element).metadata()[meta] :\n      $(element).metadata();\n  },\n\n  staticRules: function(element) {\n    var rules = {};\n    var validator = $.data(element.form, 'validator');\n    if (validator.settings.rules) {\n      rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};\n    }\n    return rules;\n  },\n\n  normalizeRules: function(rules, element) {\n    // handle dependency check\n    $.each(rules, function(prop, val) {\n      // ignore rule when param is explicitly false, eg. required:false\n      if (val === false) {\n        delete rules[prop];\n        return;\n      }\n      if (val.param || val.depends) {\n        var keepRule = true;\n        switch (typeof val.depends) {\n          case \"string\":\n            keepRule = !!$(val.depends, element.form).length;\n            break;\n          case \"function\":\n            keepRule = val.depends.call(element, element);\n            break;\n        }\n        if (keepRule) {\n          rules[prop] = val.param !== undefined ? val.param : true;\n        } else {\n          delete rules[prop];\n        }\n      }\n    });\n\n    // evaluate parameters\n    $.each(rules, function(rule, parameter) {\n      rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;\n    });\n\n    // clean number parameters\n    $.each(['minlength', 'maxlength', 'min', 'max'], function() {\n      if (rules[this]) {\n        rules[this] = Number(rules[this]);\n      }\n    });\n    $.each(['rangelength', 'range'], function() {\n      if (rules[this]) {\n        rules[this] = [Number(rules[this][0]), Number(rules[this][1])];\n      }\n    });\n\n    if ($.validator.autoCreateRanges) {\n      // auto-create ranges\n      if (rules.min && rules.max) {\n        rules.range = [rules.min, rules.max];\n        delete rules.min;\n        delete rules.max;\n      }\n      if (rules.minlength && rules.maxlength) {\n        rules.rangelength = [rules.minlength, rules.maxlength];\n        delete rules.minlength;\n        delete rules.maxlength;\n      }\n    }\n\n    // To support custom messages in metadata ignore rule methods titled \"messages\"\n    if (rules.messages) {\n      delete rules.messages;\n    }\n\n    return rules;\n  },\n\n  // Converts a simple string to a {string: true} rule, e.g., \"required\" to {required:true}\n  normalizeRule: function(data) {\n    if( typeof data === \"string\" ) {\n      var transformed = {};\n      $.each(data.split(/\\s/), function() {\n        transformed[this] = true;\n      });\n      data = transformed;\n    }\n    return data;\n  },\n\n  // http://docs.jquery.com/Plugins/Validation/Validator/addMethod\n  addMethod: function(name, method, message) {\n    $.validator.methods[name] = method;\n    $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];\n    if (method.length < 3) {\n      $.validator.addClassRules(name, $.validator.normalizeRule(name));\n    }\n  },\n\n  methods: {\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/required\n    required: function(value, element, param) {\n      // check if dependency is met\n      if ( !this.depend(param, element) ) {\n        return \"dependency-mismatch\";\n      }\n      if ( element.nodeName.toLowerCase() === \"select\" ) {\n        // could be an array for select-multiple or a string, both are fine this way\n        var val = $(element).val();\n        return val && val.length > 0;\n      }\n      if ( this.checkable(element) ) {\n        return this.getLength(value, element) > 0;\n      }\n      return $.trim(value).length > 0;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/remote\n    remote: function(value, element, param) {\n      if ( this.optional(element) ) {\n        return \"dependency-mismatch\";\n      }\n\n      var previous = this.previousValue(element);\n      if (!this.settings.messages[element.name] ) {\n        this.settings.messages[element.name] = {};\n      }\n      previous.originalMessage = this.settings.messages[element.name].remote;\n      this.settings.messages[element.name].remote = previous.message;\n\n      param = typeof param === \"string\" && {url:param} || param;\n\n      if ( this.pending[element.name] ) {\n        return \"pending\";\n      }\n      if ( previous.old === value ) {\n        return previous.valid;\n      }\n\n      previous.old = value;\n      var validator = this;\n      this.startRequest(element);\n      var data = {};\n      data[element.name] = value;\n      $.ajax($.extend(true, {\n        url: param,\n        mode: \"abort\",\n        port: \"validate\" + element.name,\n        dataType: \"json\",\n        data: data,\n        success: function(response) {\n          validator.settings.messages[element.name].remote = previous.originalMessage;\n          var valid = response === true;\n          if ( valid ) {\n            var submitted = validator.formSubmitted;\n            validator.prepareElement(element);\n            validator.formSubmitted = submitted;\n            validator.successList.push(element);\n            validator.showErrors();\n          } else {\n            var errors = {};\n            var message = response || validator.defaultMessage( element, \"remote\" );\n            errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;\n            validator.showErrors(errors);\n          }\n          previous.valid = valid;\n          validator.stopRequest(element, valid);\n        }\n      }, param));\n      return \"pending\";\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/minlength\n    minlength: function(value, element, param) {\n      var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);\n      return this.optional(element) || length >= param;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/maxlength\n    maxlength: function(value, element, param) {\n      var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);\n      return this.optional(element) || length <= param;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/rangelength\n    rangelength: function(value, element, param) {\n      var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);\n      return this.optional(element) || ( length >= param[0] && length <= param[1] );\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/min\n    min: function( value, element, param ) {\n      return this.optional(element) || value >= param;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/max\n    max: function( value, element, param ) {\n      return this.optional(element) || value <= param;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/range\n    range: function( value, element, param ) {\n      return this.optional(element) || ( value >= param[0] && value <= param[1] );\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/email\n    email: function(value, element) {\n      // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/\n      return this.optional(element) || /^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$/i.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/url\n    url: function(value, element) {\n      // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/\n      return this.optional(element) || /^(https?|ftp):\\/\\/(((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/date\n    date: function(value, element) {\n      return this.optional(element) || !/Invalid|NaN/.test(new Date(value));\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/dateISO\n    dateISO: function(value, element) {\n      return this.optional(element) || /^\\d{4}[\\/\\-]\\d{1,2}[\\/\\-]\\d{1,2}$/.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/number\n    number: function(value, element) {\n      return this.optional(element) || /^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$/.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/digits\n    digits: function(value, element) {\n      return this.optional(element) || /^\\d+$/.test(value);\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/creditcard\n    // based on http://en.wikipedia.org/wiki/Luhn\n    creditcard: function(value, element) {\n      if ( this.optional(element) ) {\n        return \"dependency-mismatch\";\n      }\n      // accept only spaces, digits and dashes\n      if (/[^0-9 \\-]+/.test(value)) {\n        return false;\n      }\n      var nCheck = 0,\n        nDigit = 0,\n        bEven = false;\n\n      value = value.replace(/\\D/g, \"\");\n\n      for (var n = value.length - 1; n >= 0; n--) {\n        var cDigit = value.charAt(n);\n        nDigit = parseInt(cDigit, 10);\n        if (bEven) {\n          if ((nDigit *= 2) > 9) {\n            nDigit -= 9;\n          }\n        }\n        nCheck += nDigit;\n        bEven = !bEven;\n      }\n\n      return (nCheck % 10) === 0;\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/accept\n    accept: function(value, element, param) {\n      param = typeof param === \"string\" ? param.replace(/,/g, '|') : \"png|jpe?g|gif\";\n      return this.optional(element) || value.match(new RegExp(\".(\" + param + \")$\", \"i\"));\n    },\n\n    // http://docs.jquery.com/Plugins/Validation/Methods/equalTo\n    equalTo: function(value, element, param) {\n      // bind to the blur event of the target in order to revalidate whenever the target field is updated\n      // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead\n      var target = $(param).unbind(\".validate-equalTo\").bind(\"blur.validate-equalTo\", function() {\n        $(element).valid();\n      });\n      return value === target.val();\n    }\n\n  }\n\n});\n\n// deprecated, use $.validator.format instead\n$.format = $.validator.format;\n\n}(jQuery));\n\n// ajax mode: abort\n// usage: $.ajax({ mode: \"abort\"[, port: \"uniqueport\"]});\n// if mode:\"abort\" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()\n(function($) {\n  var pendingRequests = {};\n  // Use a prefilter if available (1.5+)\n  if ( $.ajaxPrefilter ) {\n    $.ajaxPrefilter(function(settings, _, xhr) {\n      var port = settings.port;\n      if (settings.mode === \"abort\") {\n        if ( pendingRequests[port] ) {\n          pendingRequests[port].abort();\n        }\n        pendingRequests[port] = xhr;\n      }\n    });\n  } else {\n    // Proxy ajax\n    var ajax = $.ajax;\n    $.ajax = function(settings) {\n      var mode = ( \"mode\" in settings ? settings : $.ajaxSettings ).mode,\n        port = ( \"port\" in settings ? settings : $.ajaxSettings ).port;\n      if (mode === \"abort\") {\n        if ( pendingRequests[port] ) {\n          pendingRequests[port].abort();\n        }\n        return (pendingRequests[port] = ajax.apply(this, arguments));\n      }\n      return ajax.apply(this, arguments);\n    };\n  }\n}(jQuery));\n\n// provides cross-browser focusin and focusout events\n// IE has native support, in other browsers, use event caputuring (neither bubbles)\n\n// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation\n// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target\n(function($) {\n  // only implement if not provided by jQuery core (since 1.4)\n  // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs\n  if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {\n    $.each({\n      focus: 'focusin',\n      blur: 'focusout'\n    }, function( original, fix ){\n      $.event.special[fix] = {\n        setup:function() {\n          this.addEventListener( original, handler, true );\n        },\n        teardown:function() {\n          this.removeEventListener( original, handler, true );\n        },\n        handler: function(e) {\n          var args = arguments;\n          args[0] = $.event.fix(e);\n          args[0].type = fix;\n          return $.event.handle.apply(this, args);\n        }\n      };\n      function handler(e) {\n        e = $.event.fix(e);\n        e.type = fix;\n        return $.event.handle.call(this, e);\n      }\n    });\n  }\n  $.extend($.fn, {\n    validateDelegate: function(delegate, type, handler) {\n      return this.bind(type, function(event) {\n        var target = $(event.target);\n        if (target.is(delegate)) {\n          return handler.apply(target, arguments);\n        }\n      });\n    }\n  });\n}(jQuery));"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/resources/templates/layout.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\" xmlns:layout=\"http://www.ultraq.net.nz/web/thymeleaf/layout\">\n  <head>\n    <title>Layout</title>\n    <link rel=\"stylesheet\"\n      th:href=\"@{/css/bootstrap.min.css}\"\n      href=\"../../css/bootstrap.min.css\"/>\n  </head>\n  <body>\n    <div class=\"container\">\n      <div class=\"navbar\">\n        <div class=\"navbar-inner\">\n          <a class=\"brand\"\n              href=\"https://github.com/ultraq/thymeleaf-layout-dialect\">\n              Thymeleaf - Layout\n          </a>\n          <ul class=\"nav\">\n            <li>\n              <a th:href=\"@{/}\" href=\"messages.html\">\n                Messages\n              </a>\n            </li>\n          </ul>\n        </div>\n      </div>\n      <h1 layout:fragment=\"header\">Layout</h1>\n      <div layout:fragment=\"content\">\n        Fake content\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/resources/templates/messages/form.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\"\n  xmlns:layout=\"http://www.ultraq.net.nz/web/thymeleaf/layout\"\n  layout:decorator=\"layout\">\n  <head>\n    <title>Messages : Create</title>\n  </head>\n  <body>\n    <h1 layout:fragment=\"header\">Messages : Create</h1>\n    <div layout:fragment=\"content\"\n        class=\"container\">\n      <form id=\"messageForm\"\n          th:action=\"@{/(form)}\"\n          th:object=\"${message}\"\n          action=\"#\"\n          method=\"post\">\n        <div th:if=\"${#fields.hasErrors('*')}\"\n            class=\"alert alert-error\">\n          <p th:each=\"error : ${#fields.errors('*')}\"\n              th:text=\"${error}\">\n            Validation error\n          </p>\n        </div>\n        <div class=\"pull-right\">\n          <a th:href=\"@{/}\" href=\"messages.html\">\n            Messages\n          </a>\n        </div>\n        <label for=\"summary\">Summary</label>\n        <input type=\"text\"\n            th:field=\"*{summary}\"\n            th:class=\"${#fields.hasErrors('summary')} ? 'field-error'\"/>\n        <label for=\"text\">Message</label>\n        <textarea\n            th:field=\"*{text}\"\n            th:class=\"${#fields.hasErrors('text')} ? 'field-error'\"></textarea>\n        <div class=\"form-actions\">\n          <input type=\"submit\" value=\"Create\"/>\n        </div>\n      </form>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/resources/templates/messages/list.html",
    "content": "<!DOCTYPE html>\n<html xmlns:th=\"http://www.thymeleaf.org\"\n  xmlns:layout=\"http://www.ultraq.net.nz/web/thymeleaf/layout\"\n  layout:decorator=\"layout\">\n  <head>\n    <title>Messages : View all</title>\n  </head>\n  <body>\n    <h1 layout:fragment=\"header\">Messages : View all</h1>\n    <div layout:fragment=\"content\" class=\"container\">\n      <div class=\"pull-right\">\n        <a href=\"form.html\" th:href=\"@{/(form)}\">Create Message</a>\n       </div>\n      <table class=\"table table-bordered table-striped\">\n        <thead>\n          <tr>\n            <td>ID</td>\n            <td>Created</td>\n            <td>Summary</td>\n          </tr>\n        </thead>\n        <tbody>\n          <tr th:if=\"${messages.empty}\">\n            <td colspan=\"3\">\n              No messages\n            </td>\n          </tr>\n          <tr th:each=\"message : ${messages}\">\n            <td th:text=\"${message.id}\">1</td>\n            <td th:text=\"${#calendars.format(message.created)}\">\n              July 11, 2012 2:17:16 PM CDT\n            </td>\n            <td>\n              <a href=\"view.html\"\n                  th:href=\"@{'/' + ${message.id}}\"\n                  th:text=\"${message.summary}\">\n                The summary\n              </a>\n            </td>\n          </tr>\n        </tbody>\n      </table>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/main/resources/templates/messages/view.html",
    "content": "<html xmlns:th=\"http://www.thymeleaf.org\"\n  xmlns:layout=\"http://www.ultraq.net.nz/web/thymeleaf/layout\"\n  layout:decorator=\"layout\">\n  <head>\n    <title>Messages : View</title>\n  </head>\n  <body>\n    <h1 layout:fragment=\"header\">Messages : Create</h1>\n    <div layout:fragment=\"content\"\n        class=\"container\">\n      <div class=\"alert alert-success\"\n          th:if=\"${globalMessage}\"\n          th:text=\"${globalMessage}\">\n        Some Success message\n      </div>\n      <div class=\"pull-right\">\n        <a th:href=\"@{/}\" href=\"list.html\">\n          Messages\n        </a>\n      </div>\n      <dl>\n        <dt>ID</dt>\n        <dd id=\"id\" th:text=\"${message.id}\">123</dd>\n        <dt>Date</dt>\n        <dd id=\"created\"\n            th:text=\"${#calendars.format(message.created)}\">\n          July 11, 2012 2:17:16 PM CDT\n        </dd>\n        <dt>Summary</dt>\n        <dd id=\"summary\"\n            th:text=\"${message.summary}\">\n          A short summary...\n        </dd>\n        <dt>Message</dt>\n        <dd id=\"text\"\n            th:text=\"${message.text}\">\n          A detailed message that is longer than the summary.\n        </dd>\n      </dl>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-ui/src/test/java/comsat/sample/ui/SampleWebUiApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original authors Biju Kunjummen and Doo-Hwan, Kwak.\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.ui;\n\nimport java.net.URI;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.util.LinkedMultiValueMap;\nimport org.springframework.util.MultiValueMap;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for demo application.\n *\n * @author Dave Syer\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebUiApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port:0\")\n@DirtiesContext\npublic class SampleWebUiApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testHome() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body (title doesn't match):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"<title>Messages\"));\n        assertFalse(\"Wrong body (found layout:fragment):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"layout:fragment\"));\n    }\n\n    @Test\n    public void testCreate() throws Exception {\n        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();\n        map.set(\"text\", \"FOO text\");\n        map.set(\"summary\", \"FOO\");\n        URI location = new TestRestTemplate().postForLocation(\"http://localhost:\"\n                + this.port, map);\n        assertTrue(\"Wrong location:\\n\" + location,\n                location.toString().contains(\"localhost:\" + this.port));\n    }\n\n    @Test\n    public void testCreateValidation() throws Exception {\n        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();\n        map.set(\"text\", \"\");\n        map.set(\"summary\", \"\");\n        ResponseEntity<String> entity = new TestRestTemplate().postForEntity(\"http://localhost:\"\n                + this.port, map, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body ('required' validation error doesn't match):\\n\" + entity.getBody(), entity\n                .getBody().contains(\"is required\"));\n    }\n\n    @Test\n    public void testCss() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port + \"/css/bootstrap.min.css\", String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(), entity.getBody().contains(\"body\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-velocity/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.boot:spring-boot-starter-velocity:$springBootVer\"\n    compile project(\":comsat-spring:comsat-spring-boot\")\n\n    runtime \"org.springframework.boot:spring-boot-starter-tomcat:$springBootVer\"\n\n    testCompile \"org.springframework.boot:spring-boot-starter-test:$springBootVer\"\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-velocity/src/main/java/comsat/sample/velocity/SampleWebVelocityApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.velocity;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport org.springframework.boot.SpringApplication;\n\n@FiberSpringBootApplication // This will enable fiber-blocking\npublic class SampleWebVelocityApplication {\n    public static void main(String[] args) throws Exception {\n        SpringApplication.run(SampleWebVelocityApplication.class, args);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-velocity/src/main/java/comsat/sample/velocity/WelcomeController.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.velocity;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport java.util.Date;\nimport java.util.Map;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.RequestMapping;\n\n@Controller\npublic class WelcomeController {\n\n    @Value(\"${application.message:Hello World}\")\n    private String message = \"Hello World\";\n\n    @RequestMapping(\"/\")\n    public String welcome(Map<String, Object> model) throws InterruptedException, SuspendExecution {\n        Fiber.sleep(10);\n        model.put(\"time\", new Date());\n        model.put(\"message\", this.message);\n        return \"welcome\";\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-velocity/src/main/resources/application.properties",
    "content": "application.message: Hello, Andy\nspring.velocity.dateToolAttribute: dateTool"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-velocity/src/main/resources/templates/error.vm",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<body>\n\tSomething went wrong: ${status} ${error}\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-velocity/src/main/resources/templates/welcome.vm",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<body>\n\t<span>Time:</span>\n\t<ul>\n\t\t<li>From controller: $time</li>\n\t\t<li>From velocity: $dateTool</li>\n\t</ul>\n\t<span>Message: $message</span>\n</body>\n\n</html>\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-velocity/src/test/java/comsat/sample/velocity/SampleWebVelocityApplicationTests.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on the corresponding class in Spring Boot Samples.\n * Copyright the original author(s).\n * Released under the ASF 2.0 license.\n */\npackage comsat.sample.velocity;\n\nimport java.util.Arrays;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.boot.test.IntegrationTest;\nimport org.springframework.boot.test.SpringApplicationConfiguration;\nimport org.springframework.boot.test.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.annotation.DirtiesContext;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * Basic integration tests for Velocity application.\n *\n * @author Phillip Webb\n * @author Andy Wilkinson\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringApplicationConfiguration(classes = SampleWebVelocityApplication.class)\n@WebAppConfiguration\n@IntegrationTest(\"server.port=0\")\n@DirtiesContext\npublic class SampleWebVelocityApplicationTests {\n\n    @Value(\"${local.server.port}\")\n    private int port;\n\n    @Test\n    public void testVelocityTemplate() throws Exception {\n        ResponseEntity<String> entity = new TestRestTemplate().getForEntity(\n                \"http://localhost:\" + this.port, String.class);\n        assertEquals(HttpStatus.OK, entity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + entity.getBody(),\n                entity.getBody().contains(\"Hello, Andy\"));\n    }\n\n    @Test\n    public void testVelocityErrorTemplate() throws Exception {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));\n        HttpEntity<String> requestEntity = new HttpEntity<String>(headers);\n\n        ResponseEntity<String> responseEntity = new TestRestTemplate().exchange(\n                \"http://localhost:\" + this.port + \"/does-not-exist\", HttpMethod.GET,\n                requestEntity, String.class);\n\n        assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode());\n        assertTrue(\"Wrong body:\\n\" + responseEntity.getBody(), responseEntity.getBody()\n                .contains(\"Something went wrong: 404 Not Found\"));\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/src/main/java/co/paralleluniverse/springframework/boot/autoconfigure/web/FiberSpringBootApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.springframework.boot.autoconfigure.web;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Import;\n\n/**\n * Convenience annotation for fiber-enabled Spring Boot applications\n * \n * @author circlespainter\n */\n@Target(value = {ElementType.TYPE})\n@Retention(value = RetentionPolicy.RUNTIME)\n@Documented\n@Inherited\n@Configuration\n@SpringBootApplication\n// The following will enable fiber-blocking while still preserving autoconfiguration\n@Import(FiberWebMvcAutoConfiguration.class)\npublic @interface FiberSpringBootApplication {\n    public Class<?>[] exclude() default {};\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot/src/main/java/co/paralleluniverse/springframework/boot/autoconfigure/web/FiberWebMvcAutoConfiguration.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.springframework.boot.autoconfigure.web;\n\nimport co.paralleluniverse.springframework.web.servlet.config.annotation.FiberWebMvcConfigurationSupport;\nimport javax.servlet.Servlet;\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;\nimport org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;\nimport org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Import;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.web.servlet.DispatcherServlet;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\n\n/**\n * Supports fiber-blocking without disabling Spring Boot Web Autoconfiguration.\n *\n * @author circlespainter\n */\n@Configuration\n@ConditionalOnWebApplication\n@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class })\n// @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) // Luckily not inherited\n@Import(FiberWebMvcConfigurationSupport.class)\n@Order(Ordered.HIGHEST_PRECEDENCE + 20)\n@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)\npublic class FiberWebMvcAutoConfiguration extends WebMvcAutoConfiguration {}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot-security/build.gradle",
    "content": "dependencies {\n    compile project(\":comsat-spring:comsat-spring-boot\")\n    compile project(\":comsat-spring:comsat-spring-security\")\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-boot-security/src/main/java/co/paralleluniverse/springframework/boot/security/autoconfigure/web/FiberSecureSpringBootApplication.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.springframework.boot.security.autoconfigure.web;\n\nimport co.paralleluniverse.springframework.boot.autoconfigure.web.FiberSpringBootApplication;\nimport co.paralleluniverse.springframework.security.config.FiberSecurityContextHolderConfig;\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Import;\n\n/**\n * Convenience annotation for fiber-enabled Spring Boot applications\n * \n * @author circlespainter\n */\n@Target(value = {ElementType.TYPE})\n@Retention(value = RetentionPolicy.RUNTIME)\n@Documented\n@Inherited\n@Configuration\n@FiberSpringBootApplication\n// The following will enable security context inheritance for fibers\n@Import(FiberSecurityContextHolderConfig.class)\npublic @interface FiberSecureSpringBootApplication {\n    public Class<?>[] exclude() default {};\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-security/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework.security:spring-security-core:$springSecurityVer\"\n    compile \"org.springframework.security:spring-security-config:$springSecurityVer\"\n    compile \"org.springframework.security:spring-security-web:$springSecurityVer\"\n}"
  },
  {
    "path": "comsat-spring/comsat-spring-security/src/main/java/co/paralleluniverse/springframework/security/config/FiberSecurityContextHolderConfig.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.springframework.security.config;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.core.context.SecurityContextHolder;\n\n@Configuration\npublic class FiberSecurityContextHolderConfig {\n    public FiberSecurityContextHolderConfig() {\n        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-webmvc/build.gradle",
    "content": "dependencies {\n    compile \"org.springframework:spring-webmvc:$springVer\"\n}"
  },
  {
    "path": "comsat-spring/comsat-spring-webmvc/src/main/java/co/paralleluniverse/springframework/web/method/support/FiberInvocableHandlerMethod.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on org.springframework.web.method.support.InvocableHandlerMethod in\n * Spring Framework Web MVC.\n * Copyright the original author Rossen Stoyanchev.\n * Released under the ASF 2.0 license.\n */\npackage co.paralleluniverse.springframework.web.method.support;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\nimport org.springframework.util.ReflectionUtils;\nimport org.springframework.web.context.request.async.DeferredResult;\nimport org.springframework.web.method.HandlerMethod;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.fibers.instrument.SuspendableHelper;\nimport co.paralleluniverse.strands.SuspendableRunnable;\nimport java.util.Arrays;\nimport java.util.concurrent.Callable;\nimport org.springframework.web.method.support.InvocableHandlerMethod;\n\n/**\n * A fiber-blocking {@link InvocableHandlerMethod}\n *\n * @author circlespainter\n */\npublic class FiberInvocableHandlerMethod extends InvocableHandlerMethod {\n    // TODO need avoiding async error handling due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=454022, remove as sson as it's fixed\n    private static final String SPRING_BOOT_ERROR_CONTROLLER_CLASS_NAME = \"org.springframework.boot.autoconfigure.web.ErrorController\";\n    private static Class springBootErrorControllerClass;\n    static {\n        try {\n            springBootErrorControllerClass = Class.forName(SPRING_BOOT_ERROR_CONTROLLER_CLASS_NAME);\n        } catch( ClassNotFoundException e ) {}\n    }    \n\n    public FiberInvocableHandlerMethod(Object bean, Method method) {\n        super(bean, method);\n    }\n\n    public FiberInvocableHandlerMethod(HandlerMethod handlerMethod) {\n        super(handlerMethod);\n    }\n\n    public FiberInvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {\n        super(bean, methodName, parameterTypes);\n    }\n\n    /**\n     * @return `true` if the controller is a Spring Boot error controller\n     */\n    private boolean isBootErrorController() {\n        return springBootErrorControllerClass != null && springBootErrorControllerClass.isAssignableFrom(getBean().getClass());\n    }\n\n    /**\n     * @return `true` if the method is not annotated with `@Suspendable` and it doesn't throw `SuspendExecution` nor it is instrumented in any other way.\n     */\n    private boolean isSpringTraditionalThreadBlockingControllerMethod() {\n        final Method m = getMethod();\n        return\n            m.getAnnotation(Suspendable.class) == null &&\n            !Arrays.asList(m.getExceptionTypes()).contains(SuspendExecution.class) &&\n            !SuspendableHelper.isInstrumented(m);\n    }\n    \n    /**\n     * Invoke the handler method with the given argument values, either traditional thread-blocking or in a new fiber.\n     */\n    @Override\n    protected Object doInvoke(final Object... args) throws Exception {\n        if (isBootErrorController() // TODO need avoiding async error handling due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=454022, remove as sson as it's fixed\n            || isSpringTraditionalThreadBlockingControllerMethod())\n            return threadBlockingInvoke(args);\n        else\n            return fiberDispatchInvoke(args);\n    }\n\n    protected Object threadBlockingInvoke(Object... args) throws IllegalAccessException, Exception {\n        return super.doInvoke(args);\n    }\n\n    protected Object fiberDispatchInvoke(final Object... args) {\n        final Object b = getBean();\n        final Method m = getBridgedMethod();\n        ReflectionUtils.makeAccessible(m);\n        \n        // Returning deferred even for normal return values, Spring return handlers will take care dynamically based on the actual returned value\n        final DeferredResult ret = new DeferredResult();\n        \n        // The actual method execution and deferred completion is dispatched to a new fiber\n        new Fiber(new SuspendableRunnable() {\n            private Object deAsync(final Object o) throws SuspendExecution, Exception {\n                if (o instanceof Callable)\n                    return deAsync(((Callable) o).call());\n                else\n                    return o;\n            }\n    \n            @Override\n            public void run() throws SuspendExecution, InterruptedException {\n                try {\n                    Object originalRet = m.invoke(b, args);\n                    ret.setResult(deAsync(originalRet));\n                } catch (IllegalArgumentException ex) {\n                    assertTargetBean(m, b, args);\n                    ret.setErrorResult(new IllegalStateException(getInvocationErrorMessage(ex.getMessage(), args), ex));\n                } catch (InvocationTargetException ex) {\n                    // Unwrap for HandlerExceptionResolvers ...\n                    Throwable targetException = ex.getTargetException();\n                    if (targetException instanceof RuntimeException || targetException instanceof Error || targetException instanceof Exception) {\n                        ret.setErrorResult(targetException);\n                    } else {\n                        String msg = getInvocationErrorMessage(\"Failed to invoke controller method\", args);\n                        ret.setErrorResult(new IllegalStateException(msg, targetException));\n                    }\n                } catch (Exception ex) {\n                    ret.setErrorResult(ex);\n                }\n            }\n        }).start();\n\n        return ret;\n    }\n\n    /**\n     * Assert that the target bean class is an instance of the class where the given\n     * method is declared. In some cases the actual controller instance at request-\n     * processing time may be a JDK dynamic proxy (lazy initialization, prototype\n     * beans, and others). {@code @Controller}'s that require proxying should prefer\n     * class-based proxy mechanisms.\n     */\n    private void assertTargetBean(Method method, Object targetBean, Object[] args) {\n        Class<?> methodDeclaringClass = method.getDeclaringClass();\n        Class<?> targetBeanClass = targetBean.getClass();\n        if (!methodDeclaringClass.isAssignableFrom(targetBeanClass)) {\n            String msg = \"The mapped controller method class '\" + methodDeclaringClass.getName() +\n                         \"' is not an instance of the actual controller bean instance '\" +\n                         targetBeanClass.getName() + \"'. If the controller requires proxying \" +\n                         \"(e.g. due to @Transactional), please use class-based proxying.\";\n            throw new IllegalStateException(getInvocationErrorMessage(msg, args));\n        }\n    }\n\n    private String getInvocationErrorMessage(String message, Object[] resolvedArgs) {\n        StringBuilder sb = new StringBuilder(getDetailedErrorMessage(message));\n        sb.append(\"Resolved arguments: \\n\");\n        for (int i=0; i < resolvedArgs.length; i++) {\n            sb.append(\"[\").append(i).append(\"] \");\n            if (resolvedArgs[i] == null) {\n                sb.append(\"[null] \\n\");\n            }\n            else {\n                sb.append(\"[type=\").append(resolvedArgs[i].getClass().getName()).append(\"] \");\n                sb.append(\"[value=\").append(resolvedArgs[i]).append(\"]\\n\");\n            }\n        }\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-webmvc/src/main/java/co/paralleluniverse/springframework/web/servlet/config/annotation/FiberWebMvcConfigurationSupport.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on org.springframework.web.servlet.config.annotation.FiberWebMvcConfigurationSupport\n * in Spring Framework Web MVC.\n * Copyright the original authors Rossen Stoyanchev, Brian Clozel and Sebastien Deleuze.\n * Released under the ASF 2.0 license.\n */\npackage co.paralleluniverse.springframework.web.servlet.config.annotation;\n\nimport co.paralleluniverse.springframework.web.servlet.mvc.method.annotation.FiberRequestMappingHandlerAdapter;\nimport java.util.ArrayList;\nimport java.util.List;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.method.support.HandlerMethodArgumentResolver;\nimport org.springframework.web.method.support.HandlerMethodReturnValueHandler;\nimport org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;\nimport org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;\nimport org.springframework.web.servlet.config.annotation.ServletConfigAnnotationProtectedProxy;\n\n/**\n * Provides a fiber-dispatching controller method invoker\n * \n * @author circlespainter\n * \n * @see EnableWebMvc\n * @see WebMvcConfigurer\n * @see WebMvcConfigurerAdapter\n */\n@Configuration\npublic class FiberWebMvcConfigurationSupport extends DelegatingWebMvcConfiguration {    \n    @Bean\n    public FiberRequestMappingHandlerAdapter fiberRequestMappingHandlerAdapter() {\n        List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>();\n        addArgumentResolvers(argumentResolvers);\n\n        List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<>();\n        addReturnValueHandlers(returnValueHandlers);\n\n        FiberRequestMappingHandlerAdapter adapter = new FiberRequestMappingHandlerAdapter();\n        adapter.setContentNegotiationManager(mvcContentNegotiationManager());\n        adapter.setMessageConverters(getMessageConverters());\n        adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer());\n        adapter.setCustomArgumentResolvers(argumentResolvers);\n        adapter.setCustomReturnValueHandlers(returnValueHandlers);\n\n        AsyncSupportConfigurer configurer = new AsyncSupportConfigurer();\n        configureAsyncSupport(configurer);\n\n        if (ServletConfigAnnotationProtectedProxy.getTaskExecutor(configurer) != null) {\n            adapter.setTaskExecutor(ServletConfigAnnotationProtectedProxy.getTaskExecutor(configurer));\n        }\n        if (ServletConfigAnnotationProtectedProxy.getTimeout(configurer) != null) {\n            adapter.setAsyncRequestTimeout(ServletConfigAnnotationProtectedProxy.getTimeout(configurer));\n        }\n        adapter.setCallableInterceptors(ServletConfigAnnotationProtectedProxy.getCallableInterceptors(configurer));\n        adapter.setDeferredResultInterceptors(ServletConfigAnnotationProtectedProxy.getDeferredResultInterceptors(configurer));\n\n        return adapter;\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-webmvc/src/main/java/co/paralleluniverse/springframework/web/servlet/mvc/method/annotation/FiberRequestMappingHandlerAdapter.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter\n * in Spring Framework Web MVC.\n * Copyright the original author Rossen Stoyanchev.\n * Released under the ASF 2.0 license.\n */\npackage co.paralleluniverse.springframework.web.servlet.mvc.method.annotation;\n\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ConcurrentHashMap;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.servlet.http.HttpSession;\nimport org.springframework.beans.factory.BeanFactory;\nimport org.springframework.beans.factory.BeanFactoryAware;\nimport org.springframework.beans.factory.InitializingBean;\nimport org.springframework.beans.factory.config.ConfigurableBeanFactory;\nimport org.springframework.core.DefaultParameterNameDiscoverer;\nimport org.springframework.core.OrderComparator;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.ParameterNameDiscoverer;\nimport org.springframework.core.annotation.AnnotationUtils;\nimport org.springframework.core.task.AsyncTaskExecutor;\nimport org.springframework.core.task.SimpleAsyncTaskExecutor;\nimport org.springframework.http.converter.ByteArrayHttpMessageConverter;\nimport org.springframework.http.converter.HttpMessageConverter;\nimport org.springframework.http.converter.StringHttpMessageConverter;\nimport org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;\nimport org.springframework.http.converter.xml.SourceHttpMessageConverter;\nimport org.springframework.ui.ModelMap;\nimport org.springframework.util.Assert;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.util.ReflectionUtils.MethodFilter;\nimport org.springframework.web.accept.ContentNegotiationManager;\nimport org.springframework.web.bind.annotation.InitBinder;\nimport org.springframework.web.bind.annotation.ModelAttribute;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.support.DefaultDataBinderFactory;\nimport org.springframework.web.bind.support.DefaultSessionAttributeStore;\nimport org.springframework.web.bind.support.SessionAttributeStore;\nimport org.springframework.web.bind.support.WebBindingInitializer;\nimport org.springframework.web.bind.support.WebDataBinderFactory;\nimport org.springframework.web.context.request.NativeWebRequest;\nimport org.springframework.web.context.request.ServletWebRequest;\nimport org.springframework.web.context.request.WebRequest;\nimport org.springframework.web.context.request.async.AsyncWebRequest;\nimport org.springframework.web.context.request.async.CallableProcessingInterceptor;\nimport org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;\nimport org.springframework.web.context.request.async.WebAsyncManager;\nimport org.springframework.web.context.request.async.WebAsyncTask;\nimport org.springframework.web.context.request.async.WebAsyncUtils;\nimport org.springframework.web.method.ControllerAdviceBean;\nimport org.springframework.web.method.HandlerMethod;\nimport org.springframework.web.method.HandlerMethodSelector;\nimport org.springframework.web.method.annotation.ErrorsMethodArgumentResolver;\nimport org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver;\nimport org.springframework.web.method.annotation.InitBinderDataBinderFactory;\nimport org.springframework.web.method.annotation.MapMethodProcessor;\nimport org.springframework.web.method.annotation.ModelAttributeMethodProcessor;\nimport org.springframework.web.method.annotation.ModelFactory;\nimport org.springframework.web.method.annotation.ModelMethodProcessor;\nimport org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver;\nimport org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver;\nimport org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver;\nimport org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;\nimport org.springframework.web.method.annotation.SessionAttributesHandler;\nimport org.springframework.web.method.annotation.SessionStatusMethodArgumentResolver;\nimport org.springframework.web.method.support.HandlerMethodArgumentResolver;\nimport org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;\nimport org.springframework.web.method.support.HandlerMethodReturnValueHandler;\nimport org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;\nimport org.springframework.web.method.support.InvocableHandlerMethod;\nimport org.springframework.web.method.support.ModelAndViewContainer;\nimport org.springframework.web.servlet.ModelAndView;\nimport org.springframework.web.servlet.View;\nimport org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;\nimport org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter;\nimport org.springframework.web.servlet.mvc.method.annotation.AsyncTaskMethodReturnValueHandler;\nimport org.springframework.web.servlet.mvc.method.annotation.CallableMethodReturnValueHandler;\nimport org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler;\nimport org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor;\nimport org.springframework.web.servlet.mvc.method.annotation.HttpHeadersReturnValueHandler;\nimport org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler;\nimport org.springframework.web.servlet.mvc.method.annotation.ModelAndViewResolverMethodReturnValueHandler;\nimport org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.RedirectAttributesMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;\nimport org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor;\nimport org.springframework.web.servlet.mvc.method.annotation.ServletRequestDataBinderFactory;\nimport org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.UriComponentsBuilderMethodArgumentResolver;\nimport org.springframework.web.servlet.mvc.method.annotation.ViewMethodReturnValueHandler;\nimport org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler;\nimport org.springframework.web.servlet.mvc.support.RedirectAttributes;\nimport org.springframework.web.servlet.support.RequestContextUtils;\nimport org.springframework.web.util.WebUtils;\n\n// TODO subclass instead of this copy&paste horror when https://jira.spring.io/browse/SPR-12460 is released\n\n/**\n * An {@link AbstractHandlerMethodAdapter} that supports {@link HandlerMethod}s\n * with the signature -- method argument and return types, defined in\n * {@code @RequestMapping}.\n *\n * <p>\n * Support for custom argument and return value types can be added via\n * {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}.\n * Or alternatively to re-configure all argument and return value types use\n * {@link #setArgumentResolvers} and {@link #setReturnValueHandlers(List)}.\n *\n * @author Rossen Stoyanchev\n * @since 3.1\n * @see HandlerMethodArgumentResolver\n * @see HandlerMethodReturnValueHandler\n */\npublic class FiberRequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter\n        implements BeanFactoryAware, InitializingBean, Ordered /* This will give it priority */  {\n\n    private List<HandlerMethodArgumentResolver> customArgumentResolvers;\n\n    private HandlerMethodArgumentResolverComposite argumentResolvers;\n\n    private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;\n\n    private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;\n\n    private HandlerMethodReturnValueHandlerComposite returnValueHandlers;\n\n    private List<ModelAndViewResolver> modelAndViewResolvers;\n\n    private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();\n\n    private List<HttpMessageConverter<?>> messageConverters;\n\n    private WebBindingInitializer webBindingInitializer;\n\n    private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(\"MvcAsync\");\n\n    private Long asyncRequestTimeout;\n\n    private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[]{};\n\n    private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[]{};\n\n    private boolean ignoreDefaultModelOnRedirect = false;\n\n    private int cacheSecondsForSessionAttributeHandlers = 0;\n\n    private boolean synchronizeOnSession = false;\n\n    private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();\n\n    private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();\n\n    private ConfigurableBeanFactory beanFactory;\n\n    private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache\n        = new ConcurrentHashMap<>(64);\n\n    private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);\n\n    private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache\n        = new LinkedHashMap<>();\n\n    private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);\n\n    private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache\n        = new LinkedHashMap<>();\n\n    /**\n     * Default constructor.\n     */\n    public FiberRequestMappingHandlerAdapter() {\n\n        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();\n        stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316\n\n        this.messageConverters = new ArrayList<>();\n        this.messageConverters.add(new ByteArrayHttpMessageConverter());\n        this.messageConverters.add(stringHttpMessageConverter);\n        this.messageConverters.add(new SourceHttpMessageConverter<>());\n        this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());\n    }\n\n    /**\n     * Provide resolvers for custom argument types. Custom resolvers are ordered\n     * after built-in ones. To override the built-in support for argument\n     * resolution use {@link #setArgumentResolvers} instead.\n     */\n    public void setCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {\n        this.customArgumentResolvers = argumentResolvers;\n    }\n\n    /**\n     * Return the custom argument resolvers, or {@code null}.\n     */\n    public List<HandlerMethodArgumentResolver> getCustomArgumentResolvers() {\n        return this.customArgumentResolvers;\n    }\n\n    /**\n     * Configure the complete list of supported argument types thus overriding\n     * the resolvers that would otherwise be configured by default.\n     */\n    public void setArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {\n        if (argumentResolvers == null) {\n            this.argumentResolvers = null;\n        } else {\n            this.argumentResolvers = new HandlerMethodArgumentResolverComposite();\n            this.argumentResolvers.addResolvers(argumentResolvers);\n        }\n    }\n\n    /**\n     * Return the configured argument resolvers, or possibly {@code null} if\n     * not initialized yet via {@link #afterPropertiesSet()}.\n     */\n    public List<HandlerMethodArgumentResolver> getArgumentResolvers() {\n        return (this.argumentResolvers != null) ? this.argumentResolvers.getResolvers() : null;\n    }\n\n    /**\n     * Configure the supported argument types in {@code @InitBinder} methods.\n     */\n    public void setInitBinderArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {\n        if (argumentResolvers == null) {\n            this.initBinderArgumentResolvers = null;\n        } else {\n            this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite();\n            this.initBinderArgumentResolvers.addResolvers(argumentResolvers);\n        }\n    }\n\n    /**\n     * Return the argument resolvers for {@code @InitBinder} methods, or possibly\n     * {@code null} if not initialized yet via {@link #afterPropertiesSet()}.\n     */\n    public List<HandlerMethodArgumentResolver> getInitBinderArgumentResolvers() {\n        return (this.initBinderArgumentResolvers != null) ? this.initBinderArgumentResolvers.getResolvers() : null;\n    }\n\n    /**\n     * Provide handlers for custom return value types. Custom handlers are\n     * ordered after built-in ones. To override the built-in support for\n     * return value handling use {@link #setReturnValueHandlers}.\n     */\n    public void setCustomReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {\n        this.customReturnValueHandlers = returnValueHandlers;\n    }\n\n    /**\n     * Return the custom return value handlers, or {@code null}.\n     */\n    public List<HandlerMethodReturnValueHandler> getCustomReturnValueHandlers() {\n        return this.customReturnValueHandlers;\n    }\n\n    /**\n     * Configure the complete list of supported return value types thus\n     * overriding handlers that would otherwise be configured by default.\n     */\n    public void setReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {\n        if (returnValueHandlers == null) {\n            this.returnValueHandlers = null;\n        } else {\n            this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite();\n            this.returnValueHandlers.addHandlers(returnValueHandlers);\n        }\n    }\n\n    /**\n     * Return the configured handlers, or possibly {@code null} if not\n     * initialized yet via {@link #afterPropertiesSet()}.\n     */\n    public List<HandlerMethodReturnValueHandler> getReturnValueHandlers() {\n        return this.returnValueHandlers.getHandlers();\n    }\n\n    /**\n     * Provide custom {@link ModelAndViewResolver}s.\n     * <p>\n     * <strong>Note:</strong> This method is available for backwards\n     * compatibility only. However, it is recommended to re-write a\n     * {@code ModelAndViewResolver} as {@link HandlerMethodReturnValueHandler}.\n     * An adapter between the two interfaces is not possible since the\n     * {@link HandlerMethodReturnValueHandler#supportsReturnType} method\n     * cannot be implemented. Hence {@code ModelAndViewResolver}s are limited\n     * to always being invoked at the end after all other return value\n     * handlers have been given a chance.\n     * <p>\n     * A {@code HandlerMethodReturnValueHandler} provides better access to\n     * the return type and controller method information and can be ordered\n     * freely relative to other return value handlers.\n     */\n    public void setModelAndViewResolvers(List<ModelAndViewResolver> modelAndViewResolvers) {\n        this.modelAndViewResolvers = modelAndViewResolvers;\n    }\n\n    /**\n     * Return the configured {@link ModelAndViewResolver}s, or {@code null}.\n     */\n    public List<ModelAndViewResolver> getModelAndViewResolvers() {\n        return modelAndViewResolvers;\n    }\n\n    /**\n     * Provide the converters to use in argument resolvers and return value\n     * handlers that support reading and/or writing to the body of the\n     * request and response.\n     */\n    public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {\n        this.messageConverters = messageConverters;\n    }\n\n    /**\n     * Set the {@link ContentNegotiationManager} to use to determine requested media types.\n     * If not set, the default constructor is used.\n     */\n    public void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) {\n        this.contentNegotiationManager = contentNegotiationManager;\n    }\n\n    /**\n     * Return the configured message body converters.\n     */\n    public List<HttpMessageConverter<?>> getMessageConverters() {\n        return messageConverters;\n    }\n\n    /**\n     * Provide a WebBindingInitializer with \"global\" initialization to apply\n     * to every DataBinder instance.\n     */\n    public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) {\n        this.webBindingInitializer = webBindingInitializer;\n    }\n\n    /**\n     * Return the configured WebBindingInitializer, or {@code null}.\n     */\n    public WebBindingInitializer getWebBindingInitializer() {\n        return webBindingInitializer;\n    }\n\n    /**\n     * Set the default {@link AsyncTaskExecutor} to use when a controller method\n     * return a {@link Callable}. Controller methods can override this default on\n     * a per-request basis by returning an {@link WebAsyncTask}.\n     * <p>\n     * By default a {@link SimpleAsyncTaskExecutor} instance is used.\n     * It's recommended to change that default in production as the simple executor\n     * does not re-use threads.\n     */\n    public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {\n        this.taskExecutor = taskExecutor;\n    }\n\n    /**\n     * Specify the amount of time, in milliseconds, before concurrent handling\n     * should time out. In Servlet 3, the timeout begins after the main request\n     * processing thread has exited and ends when the request is dispatched again\n     * for further processing of the concurrently produced result.\n     * <p>\n     * If this value is not set, the default timeout of the underlying\n     * implementation is used, e.g. 10 seconds on Tomcat with Servlet 3.\n     *\n     * @param timeout the timeout value in milliseconds\n     */\n    public void setAsyncRequestTimeout(long timeout) {\n        this.asyncRequestTimeout = timeout;\n    }\n\n    /**\n     * Configure {@code CallableProcessingInterceptor}'s to register on async requests.\n     *\n     * @param interceptors the interceptors to register\n     */\n    public void setCallableInterceptors(List<CallableProcessingInterceptor> interceptors) {\n        Assert.notNull(interceptors);\n        this.callableInterceptors = interceptors.toArray(new CallableProcessingInterceptor[interceptors.size()]);\n    }\n\n    /**\n     * Configure {@code DeferredResultProcessingInterceptor}'s to register on async requests.\n     *\n     * @param interceptors the interceptors to register\n     */\n    public void setDeferredResultInterceptors(List<DeferredResultProcessingInterceptor> interceptors) {\n        Assert.notNull(interceptors);\n        this.deferredResultInterceptors = interceptors.toArray(new DeferredResultProcessingInterceptor[interceptors.size()]);\n    }\n\n    /**\n     * By default the content of the \"default\" model is used both during\n     * rendering and redirect scenarios. Alternatively a controller method\n     * can declare a {@link RedirectAttributes} argument and use it to provide\n     * attributes for a redirect.\n     * <p>\n     * Setting this flag to {@code true} guarantees the \"default\" model is\n     * never used in a redirect scenario even if a RedirectAttributes argument\n     * is not declared. Setting it to {@code false} means the \"default\" model\n     * may be used in a redirect if the controller method doesn't declare a\n     * RedirectAttributes argument.\n     * <p>\n     * The default setting is {@code false} but new applications should\n     * consider setting it to {@code true}.\n     *\n     * @see RedirectAttributes\n     */\n    public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) {\n        this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect;\n    }\n\n    /**\n     * Specify the strategy to store session attributes with. The default is\n     * {@link org.springframework.web.bind.support.DefaultSessionAttributeStore},\n     * storing session attributes in the HttpSession with the same attribute\n     * name as in the model.\n     */\n    public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) {\n        this.sessionAttributeStore = sessionAttributeStore;\n    }\n\n    /**\n     * Cache content produced by {@code @SessionAttributes} annotated handlers\n     * for the given number of seconds. Default is 0, preventing caching completely.\n     * <p>\n     * In contrast to the \"cacheSeconds\" property which will apply to all general\n     * handlers (but not to {@code @SessionAttributes} annotated handlers),\n     * this setting will apply to {@code @SessionAttributes} handlers only.\n     *\n     * @see #setCacheSeconds\n     * @see org.springframework.web.bind.annotation.SessionAttributes\n     */\n    public void setCacheSecondsForSessionAttributeHandlers(int cacheSecondsForSessionAttributeHandlers) {\n        this.cacheSecondsForSessionAttributeHandlers = cacheSecondsForSessionAttributeHandlers;\n    }\n\n    /**\n     * Set if controller execution should be synchronized on the session,\n     * to serialize parallel invocations from the same client.\n     * <p>\n     * More specifically, the execution of the {@code handleRequestInternal}\n     * method will get synchronized if this flag is \"true\". The best available\n     * session mutex will be used for the synchronization; ideally, this will\n     * be a mutex exposed by HttpSessionMutexListener.\n     * <p>\n     * The session mutex is guaranteed to be the same object during\n     * the entire lifetime of the session, available under the key defined\n     * by the {@code SESSION_MUTEX_ATTRIBUTE} constant. It serves as a\n     * safe reference to synchronize on for locking on the current session.\n     * <p>\n     * In many cases, the HttpSession reference itself is a safe mutex\n     * as well, since it will always be the same object reference for the\n     * same active logical session. However, this is not guaranteed across\n     * different servlet containers; the only 100% safe way is a session mutex.\n     *\n     * @see org.springframework.web.util.HttpSessionMutexListener\n     * @see org.springframework.web.util.WebUtils#getSessionMutex(javax.servlet.http.HttpSession)\n     */\n    public void setSynchronizeOnSession(boolean synchronizeOnSession) {\n        this.synchronizeOnSession = synchronizeOnSession;\n    }\n\n    /**\n     * Set the ParameterNameDiscoverer to use for resolving method parameter names if needed\n     * (e.g. for default attribute names).\n     * <p>\n     * Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.\n     */\n    public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {\n        this.parameterNameDiscoverer = parameterNameDiscoverer;\n    }\n\n    /**\n     * {@inheritDoc}\n     * <p>\n     * A {@link ConfigurableBeanFactory} is expected for resolving\n     * expressions in method argument default values.\n     */\n    @Override\n    public void setBeanFactory(BeanFactory beanFactory) {\n        if (beanFactory instanceof ConfigurableBeanFactory) {\n            this.beanFactory = (ConfigurableBeanFactory) beanFactory;\n        }\n    }\n\n    /**\n     * Return the owning factory of this bean instance, or {@code null}.\n     */\n    protected ConfigurableBeanFactory getBeanFactory() {\n        return this.beanFactory;\n    }\n\n    @Override\n    public void afterPropertiesSet() {\n        if (this.argumentResolvers == null) {\n            List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();\n            this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);\n        }\n        if (this.initBinderArgumentResolvers == null) {\n            List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();\n            this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);\n        }\n        if (this.returnValueHandlers == null) {\n            List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();\n            this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);\n        }\n        initControllerAdviceCache();\n    }\n\n    /**\n     * Return the list of argument resolvers to use including built-in resolvers\n     * and custom resolvers provided via {@link #setCustomArgumentResolvers}.\n     */\n    private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {\n        List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();\n\n        // Annotation-based argument resolution\n        resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));\n        resolvers.add(new RequestParamMapMethodArgumentResolver());\n        resolvers.add(new PathVariableMethodArgumentResolver());\n        resolvers.add(new PathVariableMapMethodArgumentResolver());\n        resolvers.add(new MatrixVariableMethodArgumentResolver());\n        resolvers.add(new MatrixVariableMapMethodArgumentResolver());\n        resolvers.add(new ServletModelAttributeMethodProcessor(false));\n        resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));\n        resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));\n        resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));\n        resolvers.add(new RequestHeaderMapMethodArgumentResolver());\n        resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));\n        resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));\n\n        // Type-based argument resolution\n        resolvers.add(new ServletRequestMethodArgumentResolver());\n        resolvers.add(new ServletResponseMethodArgumentResolver());\n        resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));\n        resolvers.add(new RedirectAttributesMethodArgumentResolver());\n        resolvers.add(new ModelMethodProcessor());\n        resolvers.add(new MapMethodProcessor());\n        resolvers.add(new ErrorsMethodArgumentResolver());\n        resolvers.add(new SessionStatusMethodArgumentResolver());\n        resolvers.add(new UriComponentsBuilderMethodArgumentResolver());\n\n        // Custom arguments\n        if (getCustomArgumentResolvers() != null) {\n            resolvers.addAll(getCustomArgumentResolvers());\n        }\n\n        // Catch-all\n        resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));\n        resolvers.add(new ServletModelAttributeMethodProcessor(true));\n\n        return resolvers;\n    }\n\n    /**\n     * Return the list of argument resolvers to use for {@code @InitBinder}\n     * methods including built-in and custom resolvers.\n     */\n    private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {\n        List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();\n\n        // Annotation-based argument resolution\n        resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));\n        resolvers.add(new RequestParamMapMethodArgumentResolver());\n        resolvers.add(new PathVariableMethodArgumentResolver());\n        resolvers.add(new PathVariableMapMethodArgumentResolver());\n        resolvers.add(new MatrixVariableMethodArgumentResolver());\n        resolvers.add(new MatrixVariableMapMethodArgumentResolver());\n        resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));\n\n        // Type-based argument resolution\n        resolvers.add(new ServletRequestMethodArgumentResolver());\n        resolvers.add(new ServletResponseMethodArgumentResolver());\n\n        // Custom arguments\n        if (getCustomArgumentResolvers() != null) {\n            resolvers.addAll(getCustomArgumentResolvers());\n        }\n\n        // Catch-all\n        resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));\n\n        return resolvers;\n    }\n\n    /**\n     * Return the list of return value handlers to use including built-in and\n     * custom handlers provided via {@link #setReturnValueHandlers}.\n     */\n    private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {\n        List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>();\n\n        // Single-purpose return value types\n        handlers.add(new ModelAndViewMethodReturnValueHandler());\n        handlers.add(new ModelMethodProcessor());\n        handlers.add(new ViewMethodReturnValueHandler());\n        handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));\n        handlers.add(new HttpHeadersReturnValueHandler());\n        handlers.add(new CallableMethodReturnValueHandler());\n        handlers.add(new DeferredResultMethodReturnValueHandler());\n        handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));\n\n        // Annotation-based return value types\n        handlers.add(new ModelAttributeMethodProcessor(false));\n        handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));\n\n        // Multi-purpose return value types\n        handlers.add(new ViewNameMethodReturnValueHandler());\n        handlers.add(new MapMethodProcessor());\n\n        // Custom return value types\n        if (getCustomReturnValueHandlers() != null) {\n            handlers.addAll(getCustomReturnValueHandlers());\n        }\n\n        // Catch-all\n        if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {\n            handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));\n        } else {\n            handlers.add(new ModelAttributeMethodProcessor(true));\n        }\n\n        return handlers;\n    }\n\n    private void initControllerAdviceCache() {\n        if (getApplicationContext() == null) {\n            return;\n        }\n        if (logger.isDebugEnabled()) {\n            logger.debug(\"Looking for controller advice: \" + getApplicationContext());\n        }\n\n        List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());\n        Collections.sort(beans, new OrderComparator());\n\n        for (ControllerAdviceBean bean : beans) {\n            Set<Method> attrMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);\n            if (!attrMethods.isEmpty()) {\n                this.modelAttributeAdviceCache.put(bean, attrMethods);\n                logger.info(\"Detected @ModelAttribute methods in \" + bean);\n            }\n            Set<Method> binderMethods = HandlerMethodSelector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);\n            if (!binderMethods.isEmpty()) {\n                this.initBinderAdviceCache.put(bean, binderMethods);\n                logger.info(\"Detected @InitBinder methods in \" + bean);\n            }\n        }\n    }\n\n    /**\n     * Always return {@code true} since any method argument and return value\n     * type will be processed in some way. A method argument not recognized\n     * by any HandlerMethodArgumentResolver is interpreted as a request parameter\n     * if it is a simple type, or as a model attribute otherwise. A return value\n     * not recognized by any HandlerMethodReturnValueHandler will be interpreted\n     * as a model attribute.\n     */\n    @Override\n    protected boolean supportsInternal(HandlerMethod handlerMethod) {\n        return true;\n    }\n\n    /**\n     * This implementation always returns -1. An {@code @RequestMapping}\n     * method can calculate the lastModified value, call\n     * {@link WebRequest#checkNotModified(long)}, and return {@code null}\n     * if the result of that call is {@code true}.\n     */\n    @Override\n    protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {\n        return -1;\n    }\n\n    @Override\n    protected final ModelAndView handleInternal(HttpServletRequest request,\n            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {\n\n        if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {\n            // Always prevent caching in case of session attribute management.\n            checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);\n        } else {\n            // Uses configured default cacheSeconds setting.\n            checkAndPrepare(request, response, true);\n        }\n\n        // Execute invokeHandlerMethod in synchronized block if required.\n        if (this.synchronizeOnSession) {\n            HttpSession session = request.getSession(false);\n            if (session != null) {\n                Object mutex = WebUtils.getSessionMutex(session);\n                synchronized (mutex) {\n                    return invokeHandleMethod(request, response, handlerMethod);\n                }\n            }\n        }\n\n        return invokeHandleMethod(request, response, handlerMethod);\n    }\n\n    /**\n     * Return the {@link SessionAttributesHandler} instance for the given\n     * handler type, never {@code null}.\n     */\n    private SessionAttributesHandler getSessionAttributesHandler(HandlerMethod handlerMethod) {\n        Class<?> handlerType = handlerMethod.getBeanType();\n        SessionAttributesHandler sessionAttrHandler = null;\n        synchronized (this.sessionAttributesHandlerCache) {\n            sessionAttrHandler = this.sessionAttributesHandlerCache.get(handlerType);\n            if (sessionAttrHandler == null) {\n                sessionAttrHandler = new SessionAttributesHandler(handlerType, sessionAttributeStore);\n                this.sessionAttributesHandlerCache.put(handlerType, sessionAttrHandler);\n            }\n        }\n        return sessionAttrHandler;\n    }\n\n    /**\n     * Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}\n     * if view resolution is required.\n     */\n    private ModelAndView invokeHandleMethod(HttpServletRequest request,\n            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {\n        ServletWebRequest webRequest = new ServletWebRequest(request, response);\n\n        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);\n        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);\n        FiberServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);\n\n        ModelAndViewContainer mavContainer = new ModelAndViewContainer();\n        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));\n        modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);\n        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);\n\n        AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);\n        asyncWebRequest.setTimeout(this.asyncRequestTimeout);\n\n        final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);\n        asyncManager.setTaskExecutor(this.taskExecutor);\n        asyncManager.setAsyncWebRequest(asyncWebRequest);\n        asyncManager.registerCallableInterceptors(this.callableInterceptors);\n        asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);\n\n        if (asyncManager.hasConcurrentResult()) {\n            Object result = asyncManager.getConcurrentResult();\n            mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];\n            asyncManager.clearConcurrentResult();\n\n            if (logger.isDebugEnabled()) {\n                logger.debug(\"Found concurrent result value [\" + result + \"]\");\n            }\n            requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);\n        }\n\n        requestMappingMethod.invokeAndHandle(webRequest, mavContainer);\n\n        if (asyncManager.isConcurrentHandlingStarted()) {\n            return null;\n        }\n\n        return getModelAndView(mavContainer, modelFactory, webRequest);\n    }\n\n    private FiberServletInvocableHandlerMethod createRequestMappingMethod(\n            HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {\n\n        FiberServletInvocableHandlerMethod requestMethod;\n        requestMethod = new FiberServletInvocableHandlerMethod(handlerMethod);\n        requestMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);\n        requestMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);\n        requestMethod.setDataBinderFactory(binderFactory);\n        requestMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);\n        return requestMethod;\n    }\n\n    private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {\n        SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);\n        Class<?> handlerType = handlerMethod.getBeanType();\n        Set<Method> methods = this.modelAttributeCache.get(handlerType);\n        if (methods == null) {\n            methods = HandlerMethodSelector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);\n            this.modelAttributeCache.put(handlerType, methods);\n        }\n        List<InvocableHandlerMethod> attrMethods = new ArrayList<>();\n        // Global methods first\n        for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {\n            if (entry.getKey().isApplicableToBeanType(handlerType)) {\n                Object bean = entry.getKey().resolveBean();\n                for (Method method : entry.getValue()) {\n                    attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));\n                }\n            }\n        }\n        for (Method method : methods) {\n            Object bean = handlerMethod.getBean();\n            attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));\n        }\n        return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);\n    }\n\n    private InvocableHandlerMethod createModelAttributeMethod(WebDataBinderFactory factory, Object bean, Method method) {\n        InvocableHandlerMethod attrMethod = new InvocableHandlerMethod(bean, method);\n        attrMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);\n        attrMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);\n        attrMethod.setDataBinderFactory(factory);\n        return attrMethod;\n    }\n\n    private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {\n        Class<?> handlerType = handlerMethod.getBeanType();\n        Set<Method> methods = this.initBinderCache.get(handlerType);\n        if (methods == null) {\n            methods = HandlerMethodSelector.selectMethods(handlerType, INIT_BINDER_METHODS);\n            this.initBinderCache.put(handlerType, methods);\n        }\n        List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();\n        // Global methods first\n        for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache.entrySet()) {\n            if (entry.getKey().isApplicableToBeanType(handlerType)) {\n                Object bean = entry.getKey().resolveBean();\n                for (Method method : entry.getValue()) {\n                    initBinderMethods.add(createInitBinderMethod(bean, method));\n                }\n            }\n        }\n        for (Method method : methods) {\n            Object bean = handlerMethod.getBean();\n            initBinderMethods.add(createInitBinderMethod(bean, method));\n        }\n        return createDataBinderFactory(initBinderMethods);\n    }\n\n    private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {\n        InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);\n        binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);\n        binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));\n        binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);\n        return binderMethod;\n    }\n\n    /**\n     * Template method to create a new InitBinderDataBinderFactory instance.\n     * <p>\n     * The default implementation creates a ServletRequestDataBinderFactory.\n     * This can be overridden for custom ServletRequestDataBinder subclasses.\n     *\n     * @param binderMethods {@code @InitBinder} methods\n     * @return the InitBinderDataBinderFactory instance to use\n     * @throws Exception in case of invalid state or arguments\n     */\n    protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods)\n            throws Exception {\n        return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());\n    }\n\n    private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,\n            ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {\n        modelFactory.updateModel(webRequest, mavContainer);\n        if (mavContainer.isRequestHandled()) {\n            return null;\n        }\n        ModelMap model = mavContainer.getModel();\n        ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);\n        if (!mavContainer.isViewReference()) {\n            mav.setView((View) mavContainer.getView());\n        }\n        if (model instanceof RedirectAttributes) {\n            Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();\n            HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);\n            RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);\n        }\n        return mav;\n    }\n\n    /**\n     * MethodFilter that matches {@link InitBinder @InitBinder} methods.\n     */\n    public static final MethodFilter INIT_BINDER_METHODS = new MethodFilter() {\n        @Override\n        public boolean matches(Method method) {\n            return AnnotationUtils.findAnnotation(method, InitBinder.class) != null;\n        }\n    };\n\n    /**\n     * MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods.\n     */\n    public static final MethodFilter MODEL_ATTRIBUTE_METHODS = new MethodFilter() {\n        @Override\n        public boolean matches(Method method) {\n            return ((AnnotationUtils.findAnnotation(method, RequestMapping.class) == null)\n                    && (AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null));\n        }\n    };\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-webmvc/src/main/java/co/paralleluniverse/springframework/web/servlet/mvc/method/annotation/FiberServletInvocableHandlerMethod.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\n/*\n * Based on org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod\n * in Spring Framework Web MVC.\n * Copyright the original author Rossen Stoyanchev.\n * Released under the ASF 2.0 license.\n */\npackage co.paralleluniverse.springframework.web.servlet.mvc.method.annotation;\n\nimport java.io.IOException;\nimport java.lang.annotation.Annotation;\nimport java.lang.reflect.Method;\nimport java.util.concurrent.Callable;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.util.ClassUtils;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.bind.annotation.ResponseStatus;\nimport org.springframework.web.context.request.ServletWebRequest;\nimport org.springframework.web.method.HandlerMethod;\nimport org.springframework.web.method.support.HandlerMethodReturnValueHandler;\nimport org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;\nimport org.springframework.web.method.support.InvocableHandlerMethod;\nimport org.springframework.web.method.support.ModelAndViewContainer;\nimport org.springframework.web.servlet.View;\nimport org.springframework.web.util.NestedServletException;\n\nimport co.paralleluniverse.springframework.web.method.support.FiberInvocableHandlerMethod;\n\n// TODO subclass instead of this copy&paste horror when https://jira.spring.io/browse/SPR-12484 is released\n\n/**\n * Extends {@link InvocableHandlerMethod} with the ability to handle return\n * values through a registered {@link HandlerMethodReturnValueHandler} and\n * also supports setting the response status based on a method-level\n * {@code @ResponseStatus} annotation.\n *\n * <p>A {@code null} return value (including void) may be interpreted as the\n * end of request processing in combination with a {@code @ResponseStatus}\n * annotation, a not-modified check condition\n * (see {@link ServletWebRequest#checkNotModified(long)}), or\n * a method argument that provides access to the response stream.\n *\n * @author Rossen Stoyanchev\n * @since 3.1\n */\npublic class FiberServletInvocableHandlerMethod extends FiberInvocableHandlerMethod {\n\n    private HttpStatus responseStatus;\n\n    private String responseReason;\n\n    private HandlerMethodReturnValueHandlerComposite returnValueHandlers;\n\n    /**\n     * Creates an instance from the given handler and method.\n     */\n    public FiberServletInvocableHandlerMethod(Object handler, Method method) {\n        super(handler, method);\n        initResponseStatus();\n    }\n\n    /**\n     * Create an instance from a {@code HandlerMethod}.\n     */\n    public FiberServletInvocableHandlerMethod(HandlerMethod handlerMethod) {\n        super(handlerMethod);\n        initResponseStatus();\n    }\n\n    private void initResponseStatus() {\n        ResponseStatus annot = getMethodAnnotation(ResponseStatus.class);\n        if (annot != null) {\n            this.responseStatus = annot.value();\n            this.responseReason = annot.reason();\n        }\n    }\n\n    /**\n     * Register {@link HandlerMethodReturnValueHandler} instances to use to\n     * handle return values.\n     */\n    public void setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite returnValueHandlers) {\n        this.returnValueHandlers = returnValueHandlers;\n    }\n\n    /**\n     * Invokes the method and handles the return value through a registered\n     * {@link HandlerMethodReturnValueHandler}.\n     *\n     * @param webRequest the current request\n     * @param mavContainer the ModelAndViewContainer for this request\n     * @param providedArgs \"given\" arguments matched by type, not resolved\n     */\n    public final void invokeAndHandle(ServletWebRequest webRequest,\n        ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {\n\n        Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);\n\n        setResponseStatus(webRequest);\n\n        if (returnValue == null) {\n            if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {\n                mavContainer.setRequestHandled(true);\n                return;\n            }\n        } else if (StringUtils.hasText(this.responseReason)) {\n            mavContainer.setRequestHandled(true);\n            return;\n        }\n\n        mavContainer.setRequestHandled(false);\n\n        try {\n            this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);\n        } catch (Exception ex) {\n            if (logger.isTraceEnabled()) {\n                logger.trace(getReturnValueHandlingErrorMessage(\"Error handling return value\", returnValue), ex);\n            }\n            throw ex;\n        }\n    }\n\n    /**\n     * Set the response status according to the {@link ResponseStatus} annotation.\n     */\n    private void setResponseStatus(ServletWebRequest webRequest) throws IOException {\n        if (this.responseStatus == null) {\n            return;\n        }\n\n        if (StringUtils.hasText(this.responseReason)) {\n            webRequest.getResponse().sendError(this.responseStatus.value(), this.responseReason);\n        }\n        else {\n            webRequest.getResponse().setStatus(this.responseStatus.value());\n        }\n\n        // to be picked up by the RedirectView\n        webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, this.responseStatus);\n    }\n\n    /**\n     * Does the given request qualify as \"not modified\"?\n     * @see ServletWebRequest#checkNotModified(long)\n     * @see ServletWebRequest#checkNotModified(String)\n     */\n    private boolean isRequestNotModified(ServletWebRequest webRequest) {\n        return webRequest.isNotModified();\n    }\n\n    /**\n     * Does this method have the response status instruction?\n     */\n    private boolean hasResponseStatus() {\n        return responseStatus != null;\n    }\n\n    private String getReturnValueHandlingErrorMessage(String message, Object returnValue) {\n        StringBuilder sb = new StringBuilder(message);\n        if (returnValue != null) {\n            sb.append(\" [type=\").append(returnValue.getClass().getName()).append(\"] \");\n        }\n        sb.append(\"[value=\").append(returnValue).append(\"]\");\n        return getDetailedErrorMessage(sb.toString());\n    }\n\n    /**\n     * Create a ServletInvocableHandlerMethod that will return the given value from an\n     * async operation instead of invoking the controller method again. The async result\n     * value is then either processed as if the controller method returned it or an\n     * exception is raised if the async result value itself is an Exception.\n     */\n    FiberServletInvocableHandlerMethod wrapConcurrentResult(final Object result) {\n        return new CallableHandlerMethod(new Callable<Object>() {\n            @Override\n            public Object call() throws Exception {\n                if (result instanceof Exception) {\n                        throw (Exception) result;\n                }\n                else if (result instanceof Throwable) {\n                        throw new NestedServletException(\"Async processing failed\", (Throwable) result);\n                }\n                return result;\n            }\n        });\n    }\n\n\n    /**\n     * A sub-class of {@link HandlerMethod} that invokes the given {@link Callable}\n     * instead of the target controller method. This is useful for resuming processing\n     * with the result of an async operation. The goal is to process the value returned\n     * from the Callable as if it was returned by the target controller method, i.e.\n     * taking into consideration both method and type-level controller annotations (e.g.\n     * {@code @ResponseBody}, {@code @ResponseStatus}, etc).\n     */\n    private class CallableHandlerMethod extends FiberServletInvocableHandlerMethod {\n        public CallableHandlerMethod(Callable<?> callable) {\n            super(callable, ClassUtils.getMethod(callable.getClass(), \"call\"));\n            this.setHandlerMethodReturnValueHandlers(FiberServletInvocableHandlerMethod.this.returnValueHandlers);\n        }\n\n        // Don't spawn fibers when the same URL is dispatchde (and so the same method is called)\n        // after completing the (async on fibers) main invocation\n        @Override\n        protected Object doInvoke(Object... args) throws Exception {\n            return threadBlockingInvoke(args);\n        }\n\n        /**\n         * Bridge to type-level annotations of the target controller method.\n         */\n        @Override\n        public Class<?> getBeanType() {\n            return FiberServletInvocableHandlerMethod.this.getBeanType();\n        }\n\n        /**\n         * Bridge to method-level annotations of the target controller method.\n         */\n        @Override\n        public <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {\n            return FiberServletInvocableHandlerMethod.this.getMethodAnnotation(annotationType);\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-spring/comsat-spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ServletConfigAnnotationProtectedProxy.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage org.springframework.web.servlet.config.annotation;\n\nimport java.util.List;\nimport org.springframework.core.task.AsyncTaskExecutor;\nimport org.springframework.web.accept.ContentNegotiationManager;\nimport org.springframework.web.context.request.async.CallableProcessingInterceptor;\nimport org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;\nimport org.springframework.web.servlet.handler.AbstractHandlerMapping;\n\n// TODO generate dynamically\n\n/**\n * Same-package proxy for several functions used in comsat-spring-web.\n *\n * @author circlespainter\n */\npublic class ServletConfigAnnotationProtectedProxy {\n    /**\n     * @see InterceptorRegistry#getInterceptors()\n     */\n    public static List<Object> getInterceptors(InterceptorRegistry ir) {\n        return ir.getInterceptors();\n    }\n\n    /**\n     * @see ContentNegotiationConfigurer#getContentNegotiationManager()\n     */\n    public static ContentNegotiationManager getContentNegotiationManager(ContentNegotiationConfigurer configurer) throws Exception {\n        return configurer.getContentNegotiationManager();\n    }\n\n    /**\n     * @see ViewControllerRegistry#getHandlerMapping()\n     */\n    public static AbstractHandlerMapping getHandlerMapping(ViewControllerRegistry registry) {\n        return registry.getHandlerMapping();\n    }\n\n    /**\n     * @see ResourceHandlerRegistry#getHandlerMapping()\n     */\n    public static AbstractHandlerMapping getHandlerMappingResource(ResourceHandlerRegistry registry) {\n        return registry.getHandlerMapping();\n    }\n\n    /**\n     * @see DefaultServletHandlerConfigurer#getHandlerMapping()\n     */\n    public static AbstractHandlerMapping getHandlerMappingDefaultServlet(DefaultServletHandlerConfigurer configurer) {\n        return configurer.getHandlerMapping();\n    }\n\n    /**\n     * @see AsyncSupportConfigurer#getTaskExecutor()\n     */\n    public static AsyncTaskExecutor getTaskExecutor(AsyncSupportConfigurer configurer) {\n        return configurer.getTaskExecutor();\n    }\n\n    /**\n     * @see AsyncSupportConfigurer#getTaskExecutor()\n     */\n    public static Long getTimeout(AsyncSupportConfigurer configurer) {\n        return configurer.getTimeout();\n    }\n\n    /**\n     * @see AsyncSupportConfigurer#getDeferredResultInterceptors()\n     */\n    public static List<DeferredResultProcessingInterceptor> getDeferredResultInterceptors(AsyncSupportConfigurer configurer) {\n        return configurer.getDeferredResultInterceptors();\n    }\n\n    /**\n     * @see AsyncSupportConfigurer#getCallableInterceptors()\n     */\n    public static List<CallableProcessingInterceptor> getCallableInterceptors(AsyncSupportConfigurer configurer) {\n        return configurer.getCallableInterceptors();\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/comsat/webactors/AbstractWebActorTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2015-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.strands.SettableFuture;\nimport org.apache.http.client.CookieStore;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.CloseableHttpResponse;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.impl.client.BasicCookieStore;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.util.EntityUtils;\nimport org.glassfish.jersey.client.ClientProperties;\nimport org.glassfish.jersey.media.sse.EventInput;\nimport org.glassfish.jersey.media.sse.InboundEvent;\nimport org.glassfish.jersey.media.sse.SseFeature;\nimport org.junit.Test;\n\nimport javax.websocket.*;\nimport javax.ws.rs.client.Client;\nimport javax.ws.rs.client.ClientBuilder;\nimport javax.ws.rs.client.Entity;\nimport javax.ws.rs.core.NewCookie;\nimport javax.ws.rs.core.Response;\nimport java.io.IOException;\nimport java.net.URI;\nimport java.util.concurrent.ExecutionException;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * @author circlespainter\n */\npublic abstract class AbstractWebActorTest {\n    private static final int DEFAULT_TIMEOUT = 60_000;\n\n    private final RequestConfig requestConfig;\n\n    protected int timeout = DEFAULT_TIMEOUT;\n\n    protected AbstractWebActorTest() {\n        requestConfig = RequestConfig.custom()\n            .setConnectTimeout(timeout)\n            .setConnectionRequestTimeout(timeout)\n            .setSocketTimeout(timeout)\n            .build();\n    }\n\n    @Test\n    public final void testHttpMsg() throws IOException, InterruptedException, ExecutionException {\n        final HttpGet httpGet = new HttpGet(\"http://localhost:8080\");\n        try (final CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(requestConfig).build()) {\n            final CloseableHttpResponse res = client.execute(httpGet);\n            assertEquals(200, res.getStatusLine().getStatusCode());\n            assertEquals(\"text/html\", res.getFirstHeader(\"Content-Type\").getValue());\n            assertEquals(\"12\", res.getFirstHeader(\"Content-Length\").getValue());\n            assertEquals(\"httpResponse\", EntityUtils.toString(res.getEntity()));\n        }\n    }\n\n    @Test\n    public final void testHttpNotFound() throws IOException, InterruptedException, ExecutionException {\n        final HttpGet httpGet = new HttpGet(\"http://localhost:8080/notfound\");\n        try (final CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(requestConfig).build()) {\n            final CloseableHttpResponse res = client.execute(httpGet);\n            assertEquals(404, res.getStatusLine().getStatusCode());\n        }\n    }\n\n    @Test\n    public void testDie() throws IOException, InterruptedException, ExecutionException {\n        final HttpGet httpGet = new HttpGet(\"http://localhost:8080/die\");\n        try (final CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(requestConfig).build()) {\n            final CloseableHttpResponse res = client.execute(httpGet);\n            assertEquals(500, res.getStatusLine().getStatusCode());\n            assertTrue(EntityUtils.toString(res.getEntity()).contains(\"die\"));\n        }\n    }\n\n    @Test\n    public final void testHttpRedirect() throws IOException, InterruptedException, ExecutionException {\n        final HttpGet httpGet = new HttpGet(\"http://localhost:8080/redirect\");\n        try (final CloseableHttpClient client = HttpClients.custom().disableRedirectHandling().setDefaultRequestConfig(requestConfig).build()) {\n            final CloseableHttpResponse res = client.execute(httpGet);\n            final String s = EntityUtils.toString(res.getEntity());\n            System.out.println(s);\n            assertEquals(302, res.getStatusLine().getStatusCode());\n            assertTrue(res.getFirstHeader(\"Location\").getValue().endsWith(\"/foo\"));\n        }\n    }\n\n    @Test\n    public final void testWebSocketMsg() throws IOException, InterruptedException, ExecutionException, DeploymentException {\n        BasicCookieStore cookieStore = new BasicCookieStore();\n        final HttpGet httpGet = new HttpGet(\"http://localhost:8080\");\n        HttpClients.custom().setDefaultRequestConfig(requestConfig).setDefaultCookieStore(cookieStore).build().execute(httpGet, new BasicResponseHandler());\n\n        final SettableFuture<String> res = new SettableFuture<>();\n        final WebSocketContainer wsContainer = ContainerProvider.getWebSocketContainer();\n        wsContainer.setAsyncSendTimeout(timeout);\n        wsContainer.setDefaultMaxSessionIdleTimeout(timeout);\n        try (final Session ignored = wsContainer.connectToServer(sendAndGetTextEndPoint(\"test it\", res), getClientEndPointConfig(cookieStore), URI.create(\"ws://localhost:8080/ws\"))) {\n            final String s = res.get();\n            assertEquals(\"test it\", s);\n        }\n    }\n\n    @Test\n    public final void testSSE() throws IOException, InterruptedException, DeploymentException, ExecutionException {\n        Client client = null;\n        try {\n            client = ClientBuilder.newBuilder().register(SseFeature.class).build();\n            client.property(ClientProperties.CONNECT_TIMEOUT, timeout);\n            client.property(ClientProperties.READ_TIMEOUT, timeout);\n            final Response resp = client.target(\"http://localhost:8080/ssechannel\").request().get();\n            final NewCookie session = resp.getCookies().get(getSessionIdCookieName());\n            final EventInput eventInput = resp.readEntity(EventInput.class);\n            final SettableFuture<String> res = new SettableFuture<>();\n            new Thread(new Runnable() {\n                @Override\n                public final void run() {\n                    try {\n                        while (!eventInput.isClosed() && !res.isDone()) {\n                            final InboundEvent inboundEvent = eventInput.read();\n                            if (inboundEvent == null)\n                                break;\n                            res.set(inboundEvent.readData(String.class));\n                        }\n                    } catch (Throwable t) {\n                        t.printStackTrace();\n                        res.setException(t);\n                    }\n                }\n            }).start();\n            client.target(\"http://localhost:8080/ssepublish\").request().cookie(session).post(Entity.text(\"test it\"));\n            final String s = res.get();\n            assertEquals(\"test it\", s);\n        } finally {\n            if (client != null)\n                client.close();\n        }\n    }\n\n    protected abstract String getSessionIdCookieName();\n\n    protected ClientEndpointConfig getClientEndPointConfig(CookieStore cs) {\n        return ClientEndpointConfig.Builder.create().build();\n    }\n\n    private static Endpoint sendAndGetTextEndPoint(final String sendText, final SettableFuture<String> res) {\n        return new Endpoint() {\n            @Override\n            public void onOpen(final Session session, EndpointConfig config) {\n                session.addMessageHandler(new MessageHandler.Whole<String>() {\n                    @Override\n                    public final void onMessage(String text) {\n                        res.set(text);\n                    }\n                });\n                try {\n                    session.getBasicRemote().sendText(sendText);\n                } catch (final IOException ignored) {\n                }\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/comsat/webactors/MyWebActor.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.webactors;\n\nimport co.paralleluniverse.actors.*;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.strands.channels.Channels;\nimport co.paralleluniverse.strands.channels.SendPort;\nimport com.google.common.base.Function;\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\npublic class MyWebActor extends BasicActor<WebMessage, Void> {\n    // There is one actor for each client\n    private static final Set<ActorRef<WebMessage>> actors =\n        Collections.newSetFromMap(new ConcurrentHashMap<ActorRef<WebMessage>, Boolean>());\n\n    // The client representation of this actor\n    private SendPort<WebDataMessage> peer;\n\n    @Override\n    protected final Void doRun() throws InterruptedException, SuspendExecution {\n        actors.add(self());\n        try {\n            //noinspection InfiniteLoopStatement\n            for (;;) {\n                final Object message = receive();\n                if (message instanceof HttpRequest) {\n                    final HttpRequest msg = (HttpRequest) message;\n                    switch (msg.getRequestURI()) {\n                        case \"/\":\n                            msg.getFrom().send(HttpResponse.ok(self(), msg, \"httpResponse\").setContentType(\"text/html\").build());\n                            break;\n                        case \"/notfound\":\n                            msg.getFrom().send(HttpResponse.error(self(), msg, 404, \"Not found\").setContentType(\"text/plain\").build());\n                            break;\n                        case \"/die\":\n                            throw new RuntimeException(\"die\");\n                        case \"/redirect\":\n                            msg.getFrom().send(HttpResponse.redirect(msg, \"/foo\").build());\n                            break;\n                        case \"/ssepublish\":\n                            postMessage(new WebDataMessage(self(), msg.getStringBody()));\n                            msg.getFrom().send(HttpResponse.ok(self(), msg, \"\").build());\n                            break;\n                        case \"/ssechannel\":\n                            msg.getFrom().send(SSE.startSSE(self(), msg).build());\n                            break;\n                    }\n                } // -------- WebSocket/SSE opened --------\n                else if (message instanceof WebStreamOpened) {\n                    final WebStreamOpened msg = (WebStreamOpened) message;\n                    watch(msg.getFrom()); // will call handleLifecycleMessage with ExitMessage when the session ends\n\n                    SendPort<WebDataMessage> p = msg.getFrom();\n                    if (msg instanceof HttpStreamOpened)\n                        p = wrapAsSSE(p);\n                    this.peer = p;\n\n//                    p.send(new WebDataMessage(self(), \"Welcome. \" + actors.size() + \" listeners\"));\n                } // -------- WebSocket message received --------\n                else if (message instanceof WebDataMessage) {\n                    postMessage((WebDataMessage) message);\n                }\n            }\n        } finally {\n            actors.remove(self());\n        }\n    }\n\n    private SendPort<WebDataMessage> wrapAsSSE(SendPort<WebDataMessage> actor) {\n        return Channels.mapSend(actor, new Function<WebDataMessage, WebDataMessage>() {\n            @Override\n            public final WebDataMessage apply(WebDataMessage f) {\n                return new WebDataMessage(f.getFrom(), SSE.event(f.getStringBody()));\n            }\n        });\n    }\n\n    private void postMessage(final WebDataMessage webDataMessage) throws InterruptedException, SuspendExecution {\n        if (peer != null)\n            peer.send(webDataMessage);\n        if (webDataMessage.getFrom().equals(peer))\n            for (final SendPort actor : actors)\n                if (actor != self())\n                    //noinspection unchecked\n                    actor.send(webDataMessage);\n    }\n\n    @Override\n    protected final WebMessage handleLifecycleMessage(LifecycleMessage m) {\n        // while listeners might contain an SSE actor wrapped with Channels.map, the wrapped SendPort maintains the original actors hashCode and equals behavior\n        if (m instanceof ExitMessage)\n            actors.remove(((ExitMessage) m).getActor());\n        return super.handleLifecycleMessage(m);\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/embedded/containers/AbstractEmbeddedServer.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.containers;\n\nimport java.io.IOException;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.conn.HttpHostConnectException;\nimport org.apache.http.impl.client.HttpClients;\n\npublic abstract class AbstractEmbeddedServer implements EmbeddedServer {\n    protected int port = 8080;\n    protected int nThreads = 100;\n    protected int maxConn = 1000;\n\n    @Override\n    public final EmbeddedServer setPort(int port) {\n        this.port = port;\n        return this;\n    }\n\n    @Override\n    public final EmbeddedServer setNumThreads(int nThreads) {\n        this.nThreads = nThreads;\n        return this;\n    }\n\n    @Override\n    public final EmbeddedServer setMaxConnections(int maxConn) {\n        this.maxConn = maxConn;\n        return this;\n    }\n\n    public static void waitUrlAvailable(final String url) throws InterruptedException, IOException {\n        for (;;) {\n            Thread.sleep(10);\n            try {\n                if (HttpClients.createDefault().execute(new HttpGet(url)).getStatusLine().getStatusCode() > -100)\n                    break;\n            } catch (HttpHostConnectException ex) {\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/embedded/containers/EmbeddedServer.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2015, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.containers;\n\nimport javax.servlet.Servlet;\nimport javax.servlet.ServletContextListener;\n\npublic interface EmbeddedServer {\n    EmbeddedServer setPort(int port);\n    EmbeddedServer setNumThreads(int nThreads);\n    EmbeddedServer setMaxConnections(int maxConn);\n    ServletDesc addServlet(String name, Class<? extends Servlet> servletClass, String mapping);\n    void addServletContextListener(Class <? extends ServletContextListener> scl);\n    void setResourceBase(String resourceBaseUrl);\n    \n    void enableWebsockets() throws Exception;\n    void start() throws Exception;\n    void stop() throws Exception;\n    \n    interface ServletDesc {\n        ServletDesc setInitParameter(String name, String value);\n        ServletDesc setLoadOnStartup(int load);\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/embedded/containers/JettyServer.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.containers;\n\nimport javax.servlet.Servlet;\nimport javax.servlet.ServletContextListener;\nimport org.eclipse.jetty.server.Server;\nimport org.eclipse.jetty.server.ServerConnector;\nimport org.eclipse.jetty.servlet.ServletContextHandler;\nimport org.eclipse.jetty.servlet.ServletHolder;\nimport org.eclipse.jetty.util.thread.QueuedThreadPool;\nimport org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;\n\npublic final class JettyServer extends AbstractEmbeddedServer {\n    private Server server;\n    private ServletContextHandler context;\n    private boolean wsEnabled;\n\n    private void build() {\n        if (server != null)\n            return;\n        this.server = new Server(new QueuedThreadPool(nThreads, nThreads));\n        final ServerConnector http = new ServerConnector(server);\n        http.setPort(port);\n        http.setAcceptQueueSize(maxConn);\n        server.addConnector(http);\n        this.context = new ServletContextHandler(ServletContextHandler.SESSIONS);\n    }\n\n    @Override\n    public final ServletDesc addServlet(String name, Class<? extends Servlet> servletClass, String mapping) {\n        if (context == null)\n            build();\n        ServletHolder sh = new ServletHolder(servletClass);\n        context.addServlet(sh, mapping);\n        return new JettyServletDesc(sh);\n    }\n\n    @Override\n    public final void addServletContextListener(Class<? extends ServletContextListener> scl) {\n        if (context == null)\n            build();\n        try {\n            context.addEventListener(scl.newInstance());\n        } catch (InstantiationException | IllegalAccessException ex) {\n            throw new RuntimeException(ex);\n        }\n    }\n\n    @Override\n    public final void start() throws Exception {\n        if (context==null)\n            build();\n        server.setHandler(context);\n        if (wsEnabled)\n            WebSocketServerContainerInitializer.configureContext(context);\n        server.start();\n    }\n\n    @Override\n    public final void stop() throws Exception {\n        server.stop();\n    }\n\n    @Override\n    public final void enableWebsockets() throws Exception {\n        this.wsEnabled = true;\n    }\n\n    @Override\n    public final void setResourceBase(final String resourceBaseUrl) {\n        if (context==null)\n            build();\n        context.setResourceBase(resourceBaseUrl);\n    }\n\n    private static final class JettyServletDesc implements ServletDesc {\n        private final ServletHolder impl;\n\n        public JettyServletDesc(ServletHolder sh) {\n            this.impl = sh;\n        }\n\n        @Override\n        public final ServletDesc setInitParameter(String name, String value) {\n            impl.setInitParameter(name, value);\n            return this;\n        }\n\n        @Override\n        public final ServletDesc setLoadOnStartup(int load) {\n            impl.setInitOrder(load);\n            return this;\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/embedded/containers/TomcatServer.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.containers;\n\nimport java.io.File;\nimport javax.servlet.Servlet;\nimport javax.servlet.ServletContextListener;\n\nimport org.apache.catalina.Context;\nimport org.apache.catalina.LifecycleException;\nimport org.apache.catalina.Wrapper;\nimport org.apache.catalina.core.StandardContext;\nimport org.apache.catalina.startup.Tomcat;\nimport org.apache.tomcat.websocket.server.WsSci;\n\npublic final class TomcatServer extends AbstractEmbeddedServer {\n    private static final String defaultResDir = System.getProperty(TomcatServer.class.getName() + \".defaultResDir\", \"./build\");\n\n    protected final Tomcat tomcat;\n    protected final Context context;\n\n    public TomcatServer() {\n        this(defaultResDir);\n    }\n\n    public TomcatServer(String resDir) {\n        tomcat = new Tomcat();\n        context = tomcat.addContext(\"/\", new File(resDir).getAbsolutePath());\n    }\n\n    @Override\n    public final ServletDesc addServlet(String name, Class<? extends Servlet> servletClass, String mapping) {\n        final Wrapper w = Tomcat.addServlet(context, name, servletClass.getName());\n        w.addMapping(mapping);\n        return new TomcatServletDesc(w);\n    }\n\n    @Override\n    public final void start() throws Exception {\n        tomcat.setPort(port);\n\n        tomcat.getConnector().setAttribute(\"maxThreads\", nThreads);\n        tomcat.getConnector().setAttribute(\"acceptCount\", maxConn);\n\n        Runtime.getRuntime().addShutdownHook(new Thread() {\n            @Override\n            public final void run() {\n                try {\n                    tomcat.stop();\n                } catch (LifecycleException ignored) {}\n            }\n        });\n\n        tomcat.start();\n\n        new Thread() {\n            @Override\n            public final void run() {\n                tomcat.getServer().await();\n            }\n        }.start();\n    }\n\n    @Override\n    public final void stop() throws Exception {\n        tomcat.stop();\n        tomcat.getConnector().destroy();\n        tomcat.destroy();\n    }\n\n    @Override\n    public final void enableWebsockets() throws Exception {\n        context.addServletContainerInitializer(new WsSci(), null);\n    }\n\n    @Override\n    public final void addServletContextListener(Class<? extends ServletContextListener> scl) {\n        StandardContext tomcatCtx = (StandardContext) this.context;\n        tomcatCtx.addApplicationListener(scl.getName());\n    }\n\n    @Override\n    public final void setResourceBase(String resourceBaseUrl) {\n        // TODO\n        throw new UnsupportedOperationException(\"Not supported yet.\");\n    }\n\n    private static final class TomcatServletDesc implements ServletDesc {\n        private final Wrapper impl;\n\n        public TomcatServletDesc(Wrapper w) {\n            this.impl = w;\n        }\n\n        @Override\n        public final ServletDesc setInitParameter(String name, String value) {\n            impl.addInitParameter(name, value);\n            return this;\n        }\n\n        @Override\n        public final ServletDesc setLoadOnStartup(int load) {\n            impl.setLoadOnStartup(load);\n            return this;\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/embedded/containers/UndertowServer.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.containers;\n\nimport io.undertow.Handlers;\nimport io.undertow.Undertow;\nimport io.undertow.server.DefaultByteBufferPool;\nimport io.undertow.server.HttpHandler;\nimport io.undertow.server.handlers.RequestLimit;\nimport io.undertow.servlet.Servlets;\nimport io.undertow.servlet.api.*;\nimport io.undertow.servlet.core.CompositeThreadSetupAction;\nimport io.undertow.servlet.util.ConstructorInstanceFactory;\nimport io.undertow.websockets.jsr.JsrWebSocketFilter;\nimport io.undertow.websockets.jsr.ServerWebSocketContainer;\nimport java.util.Collections;\nimport javax.servlet.DispatcherType;\nimport javax.servlet.Servlet;\nimport javax.servlet.ServletContextListener;\nimport org.xnio.OptionMap;\nimport org.xnio.Options;\nimport org.xnio.Xnio;\nimport org.xnio.XnioWorker;\n\npublic final class UndertowServer extends AbstractEmbeddedServer {\n    private static final String ANY_LOCAL_ADDRESS = \"0.0.0.0\"; // not \"localhost\"!\n\n    private DeploymentInfo deployment;\n    private Undertow server;\n\n    private void build() {\n        if (deployment != null)\n            return;\n\n        this.deployment =\n            Servlets.deployment().setDeploymentName(\"\")\n                .setClassLoader(ClassLoader.getSystemClassLoader())\n                .setContextPath(\"/\");\n    }\n\n    @Override\n    public final ServletDesc addServlet(String name, Class<? extends Servlet> servletClass, String mapping) {\n        build();\n        final ServletInfo info = Servlets.servlet(name, servletClass).addMapping(mapping).setAsyncSupported(true);\n        deployment.addServlet(info);\n        return new UndertowServletDesc(info);\n    }\n\n    @Override\n    public final void start() throws Exception {\n        final DeploymentManager servletsContainer = Servlets.defaultContainer().addDeployment(deployment);\n        servletsContainer.deploy();\n        HttpHandler handler = servletsContainer.start();\n        handler = Handlers.requestLimitingHandler(new RequestLimit(maxConn), handler);\n        this.server = Undertow.builder()\n                .setHandler(handler)\n                .setIoThreads(nThreads)\n                .addHttpListener(port, ANY_LOCAL_ADDRESS)\n                .build();\n        new Thread(new Runnable() {\n            @Override\n            public final void run() {\n                server.start();\n            }\n        }).start();\n        waitUrlAvailable(\"http://localhost:\" + port);\n    }\n\n    @Override\n    public final void stop() throws Exception {\n        if (server != null)\n            server.stop();\n    }\n\n    @Override\n    public final void addServletContextListener(Class<? extends ServletContextListener> scl) {\n        build();\n        final ListenerInfo li = Servlets.listener(scl);\n        deployment.addListener(li);\n    }\n\n    @Override\n    public final void enableWebsockets() throws Exception {\n        final Xnio xnio = Xnio.getInstance(\"nio\", this.getClass().getClassLoader());\n        final XnioWorker worker = xnio.createWorker(OptionMap.builder()\n                        .set(Options.WORKER_IO_THREADS, 8)\n                        .set(Options.CONNECTION_HIGH_WATER, 1000000)\n                        .set(Options.CONNECTION_LOW_WATER, 1000000)\n                        .set(Options.WORKER_TASK_CORE_THREADS, 30)\n                        .set(Options.WORKER_TASK_MAX_THREADS, 30)\n                        .set(Options.TCP_NODELAY, true)\n                        .set(Options.CORK, true)\n                        .getMap());\n        final ClassIntrospecter ci = new ClassIntrospecter() {\n            @Override\n            public final <T> InstanceFactory<T> createInstanceFactory(final Class<T> clazz) {\n                try {\n                    return new ConstructorInstanceFactory<>(clazz.getDeclaredConstructor());\n                } catch (NoSuchMethodException e) {\n                    throw new RuntimeException(e);\n                }\n            }\n        };\n        //noinspection unchecked\n        final ServerWebSocketContainer wsc =\n            new ServerWebSocketContainer (\n                ci, worker, new DefaultByteBufferPool(true, 100),\n                new CompositeThreadSetupAction(Collections.EMPTY_LIST), false, false\n            );\n        final FilterInfo fi = new FilterInfo(\"filter\", JsrWebSocketFilter.class);\n        fi.setAsyncSupported(true);\n        deployment\n            .addFilter(fi)\n            .addFilterUrlMapping(\"filter\", \"/*\", DispatcherType.REQUEST)\n            .addServletContextAttribute(javax.websocket.server.ServerContainer.class.getName(), wsc);\n    }\n\n    @Override\n    public final void setResourceBase(String resourceBaseUrl) {\n        // TODO\n        throw new UnsupportedOperationException(\"Not supported yet.\");\n    }\n\n    private static final class UndertowServletDesc implements ServletDesc {\n        private final ServletInfo impl;\n\n        public UndertowServletDesc(ServletInfo info) {\n            this.impl = info;\n        }\n\n        @Override\n        public final ServletDesc setInitParameter(String name, String value) {\n            impl.addInitParam(name, value);\n            return this;\n        }\n\n        @Override\n        public final ServletDesc setLoadOnStartup(int load) {\n            impl.setLoadOnStartup(load);\n            return this;\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/embedded/db/H2JdbcDatasource.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.db;\n\nimport org.h2.jdbcx.JdbcDataSource;\n\npublic class H2JdbcDatasource extends JdbcDataSource {\n    public H2JdbcDatasource() {\n        this(\"jdbc:h2:./build/h2default\");\n    }\n\n    public H2JdbcDatasource(String url) {\n        setURL(url);\n    }\n}\n"
  },
  {
    "path": "comsat-test-utils/src/main/java/co/paralleluniverse/test/categories/CI.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.test.categories;\n\n/**\n * Tests that should be run by Continuous Integration\n * \n * @author fabio\n */\npublic interface CI {}"
  },
  {
    "path": "comsat-test-utils/src/test/java/co/paralleluniverse/embedded/containers/EmbeddedServerTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.containers;\n\nimport co.paralleluniverse.common.util.Debug;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.junit.After;\nimport static org.junit.Assert.assertEquals;\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.TestName;\nimport org.junit.rules.TestRule;\nimport org.junit.rules.TestWatcher;\nimport org.junit.runner.Description;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.Parameterized;\n\n@RunWith(Parameterized.class)\npublic class EmbeddedServerTest {\n\n    @Parameterized.Parameters(name=\"{0}\")\n    public static Collection<Object[]> data() {\n        return Arrays.asList(new Object[][]{\n            {JettyServer.class},\n            {TomcatServer.class},\n            {UndertowServer.class},});\n    }\n    private final Class<? extends EmbeddedServer> cls;\n    private EmbeddedServer instance;\n    private CloseableHttpClient client;\n\n    public EmbeddedServerTest(Class<? extends EmbeddedServer> cls) {\n        this.cls = cls;\n    }\n\n    @Before\n    public void setUp() throws Exception {\n        this.instance = cls.newInstance();\n        instance.addServlet(\"test\", TestServlet.class, \"/\");\n        instance.start();\n        this.client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()\n                .setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000)\n                .build()).build();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        instance.stop();\n        client.close();\n    }\n\n    @Test\n    public void testGet() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testGet\", client.execute(new HttpGet(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER));\n    }\n\n    @Test\n    public void testPost() throws IOException, InterruptedException, Exception {\n        for (int i = 0; i < 10; i++)\n            assertEquals(\"testPost\", client.execute(new HttpPost(\"http://localhost:8080\"), BASIC_RESPONSE_HANDLER));\n    }\n\n    public static class TestServlet extends HttpServlet {\n        @Override\n        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                out.print(\"testPost\");\n            }\n        }\n\n        @Override\n        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n            try (PrintWriter out = resp.getWriter()) {\n                out.print(\"testGet\");\n            }\n        }\n    }\n\n    @Rule\n    public TestName name = new TestName();\n    @Rule\n    public TestRule watchman = new TestWatcher() {\n        @Override\n        protected void starting(Description desc) {\n            if (Debug.isDebug()) {\n                System.out.println(\"STARTING TEST \" + desc.getMethodName());\n                Debug.record(0, \"STARTING TEST \" + desc.getMethodName());\n            }\n        }\n\n        @Override\n        public void failed(Throwable e, Description desc) {\n            System.out.println(\"FAILED TEST \" + desc.getMethodName() + \": \" + e.getMessage());\n            e.printStackTrace(System.err);\n            if (Debug.isDebug() && !(e instanceof OutOfMemoryError)) {\n                Debug.record(0, \"EXCEPTION IN THREAD \" + Thread.currentThread().getName() + \": \" + e + \" - \" + Arrays.toString(e.getStackTrace()));\n                Debug.dumpRecorder(\"~/quasar.dump\");\n            }\n        }\n\n        @Override\n        protected void succeeded(Description desc) {\n            Debug.record(0, \"DONE TEST \" + desc.getMethodName());\n        }\n    };\n    private static final BasicResponseHandler BASIC_RESPONSE_HANDLER = new BasicResponseHandler();\n\n}\n"
  },
  {
    "path": "comsat-test-war/TestServlet.java",
    "content": "package co.paralleluniverse.examples.test;\n\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport javax.servlet.ServletException;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * This servlet is used by the RS-client tests\n */\n@WebServlet(urlPatterns = \"/test\")\npublic class TestServlet extends HttpServlet {\n    @Override\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n        try (PrintWriter out = resp.getWriter()) {\n            out.print(\"testGet\");\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-test-war/build.gradle",
    "content": "apply plugin: 'war' \n\ninstall.enabled = false\nuploadArchives.enabled = false\n\ndependencies {    \n    compile project(':comsat-servlet')\n}\n"
  },
  {
    "path": "comsat-test-war/src/main/java/co/paralleluniverse/examples/test/MyFiberServlet.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.examples.test;\n\nimport co.paralleluniverse.fibers.Fiber;\nimport co.paralleluniverse.fibers.SuspendExecution;\nimport co.paralleluniverse.fibers.Suspendable;\nimport co.paralleluniverse.fibers.servlet.FiberHttpServlet;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.sql.Connection;\nimport java.sql.SQLException;\nimport javax.naming.Context;\nimport javax.naming.InitialContext;\nimport javax.naming.NamingException;\nimport javax.servlet.ServletException;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport javax.sql.DataSource;\n\n@WebServlet(urlPatterns = \"/\", asyncSupported = true)\npublic class MyFiberServlet extends FiberHttpServlet {\n    final static DataSource ds = lookupDataSourceJDBC(\"jdbc/fiberds\");\n\n    @Suspendable\n    @Override\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n        try (PrintWriter out = resp.getWriter(); Connection connection = ds.getConnection()) {\n            Fiber.sleep(10);\n            out.print(connection);\n        } catch (InterruptedException | SuspendExecution | SQLException ex) {\n            throw new RuntimeException(ex);\n        }\n    }\n\n    public static DataSource lookupDataSourceJDBC(final String name) {\n        try {\n            Context envCtx = (Context) new InitialContext().lookup(\"java:comp/env\");\n            return (DataSource) envCtx.lookup(name);\n        } catch (NamingException ex) {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "comsat-test-war/src/main/webapp/META-INF/context.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<Context path=\"/\">\n    <!--load the webApp with quasar class loader for insturmentation purposes-->\n    <!-- snippet loader -->\n    <Loader loaderClass=\"co.paralleluniverse.comsat.tomcat.QuasarWebAppClassLoader\" />\n    <!-- end of snippet -->\n    <Manager pathname=\"\"/>\n\n    <!-- snippet fiber ds -->\n    <!--link to the global db resource-->\n    <ResourceLink name=\"jdbc/linkds\"\n                  global=\"jdbc/globalds\"\n                  type=\"javax.sql.DataSource\" />\n    <!--wrap the linked global db resource by fiber wrapper-->\n    <Resource name=\"jdbc/fiberds\" auth=\"Container\" \n              type=\"javax.sql.DataSource\"\n              rawDataSource=\"jdbc/linkds\"\n              threadsCount=\"10\"\n              url=\"fiber\"\n              factory=\"co.paralleluniverse.fibers.jdbc.FiberDataSourceFactory\"\n    />    \n    <!-- end of snippet -->\n</Context>"
  },
  {
    "path": "comsat-test-war/src/main/webapp/WEB-INF/jetty-env.xml",
    "content": "<!-- snippet fiber ds -->\n<Configure id='wac' class=\"org.eclipse.jetty.webapp.WebAppContext\">\n    <!--jdbc linkds - create link to the global ds-->\n    <Call class=\"org.eclipse.jetty.plus.jndi.NamingEntryUtil\" name=\"bindToENC\">\n        <Arg></Arg> \n        <Arg>jdbc/linkds</Arg>\n        <Arg>jdbc/globalds</Arg>\n    </Call>\n\n    <!--jdbc/fiberds - create fiber wrap for the deplyed datasource-->\n    <New class=\"org.eclipse.jetty.plus.jndi.Resource\">\n        <Arg>\n            <Ref id='wac'/>\n        </Arg>\n        <Arg>jdbc/webxmlds</Arg>\n        <Arg>\n            <Call class=\"co.paralleluniverse.fibers.jdbc.FiberDataSourceFactory\" name=\"create\">\n                <!-- jndi name of the native dataSource -->\n                <Arg>jdbc/linkds</Arg> \n                <!-- number of threads in the pool -->\n                <Arg type=\"Integer\">10</Arg>\n            </Call>\n        </Arg>\n        <Call name=\"bindToENC\"> <!-- spare web.xml definitions -->\n            <Arg>jdbc/fiberds</Arg> \n        </Call>\n    </New>\n</Configure>\n<!-- end of snippet -->\n"
  },
  {
    "path": "comsat-test-war/src/main/webapp/WEB-INF/web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"\r\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n         xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee\r\n                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd\"\r\n         version=\"3.1\"\r\n         metadata-complete=\"false\">\r\n\r\n    <display-name>Test Servlet</display-name>\r\n    <description>\r\n        A test servlet used to test the COMSAT HTTP client.\r\n    </description>\r\n\r\n    <!-- Define example application events listeners -->\r\n    <!--    \r\n    <listener>\r\n        <listener-class>listeners.ContextListener</listener-class>\r\n    </listener>\r\n    <listener>\r\n        <listener-class>listeners.SessionListener</listener-class>\r\n    </listener>\r\n    -->\r\n\r\n    <!-- Define servlets that are included in the example application -->\r\n    <!--    \r\n    <servlet>\r\n        <servlet-name>rest</servlet-name>\r\n        <servlet-class> co.paralleluniverse.fibers.jersey.ServletContainer</servlet-class>        \r\n        <init-param>\r\n            <param-name>jersey.config.server.provider.packages</param-name> \r\n            <param-value>example.tomcat</param-value> \r\n        </init-param>      \r\n    </servlet>\r\n    <servlet-mapping>\r\n        <servlet-name>rest</servlet-name>\r\n        <url-pattern>/rest/*</url-pattern>\r\n    </servlet-mapping>\r\n    -->\r\n</web-app>\r\n"
  },
  {
    "path": "comsat-tomcat-loader/build.gradle",
    "content": "// TODO Add full integration tests based on Cargo\nsourceSets {\n    jdk7 {\n        java {\n            srcDir 'src/main/java'\n        }\n            \n        compileClasspath += main.compileClasspath\n        runtimeClasspath += main.runtimeClasspath\n    }\n    jdk8 {\n        java {\n            srcDir 'src/main/java'\n        }\n            \n        compileClasspath += main.compileClasspath\n        runtimeClasspath += main.runtimeClasspath\n    }\n}\n\ncompileJdk7Java {\n    sourceCompatibility = '1.7'\n    targetCompatibility = '1.7'\n}\n\ncompileJdk8Java {\n    sourceCompatibility = '1.8'\n    targetCompatibility = '1.8'\n}\n\ndependencies {\n    jdk7Compile \"co.paralleluniverse:quasar-core:$quasarVer\"\n    jdk8Compile \"co.paralleluniverse:quasar-core:$quasarVer:jdk8\"\n\n    provided \"org.apache.tomcat:tomcat-juli:$tomcatVer\"\n    provided \"org.apache.tomcat.embed:tomcat-embed-core:$tomcatVer\"\n\n    testCompile (project(':comsat-test-utils')) {\n        exclude group: 'org.eclipse.jetty.websocket', module: '*'         \n    }\n\n    testRuntime project(':comsat-jdbc')\n}\n\ndef ssets = [sourceSets.jdk7]\nif(ext.java8) {\n    ssets += sourceSets.jdk8\n}\nssets.each { set ->\n    def jarTask = task(\"${set.name}Jar\", type: Jar) {\n        from set.output\n        from { project.configurations[\"${set.name}Runtime\"].collect { it.isDirectory() ? it : zipTree(it) } }\n    } \n\n    artifacts {\n        archives jarTask\n    }\n\n    assemble.dependsOn jarTask\n}\n\nif (ext.java8) {\n    jdk8Jar {\n        classifier = 'jdk8'\n    }\n}\n\nartifacts {\n    archives sourcesJar\n    archives javadocJar\n}\n\ntask deployWar(type: Copy) {\n    evaluationDependsOn \":comsat-test-war\"\n    into \"build/wars\"\n    from project(\":comsat-test-war\").war\n}\n\ntasks.withType(Test) {\n    dependsOn deployWar\n}\n"
  },
  {
    "path": "comsat-tomcat-loader/src/main/java/co/paralleluniverse/comsat/tomcat/QuasarWebAppClassLoader.java",
    "content": "/*\n * COMSAT\n * Copyright (c) 2013-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.comsat.tomcat;\n\nimport co.paralleluniverse.fibers.instrument.Log;\nimport co.paralleluniverse.fibers.instrument.LogLevel;\nimport co.paralleluniverse.fibers.instrument.MethodDatabase;\nimport co.paralleluniverse.fibers.instrument.QuasarInstrumentor;\nimport java.util.Arrays;\nimport org.apache.catalina.loader.ResourceEntry;\nimport org.apache.catalina.loader.WebappClassLoader;\n\n/**\n * See:\n * http://tomcat.apache.org/tomcat-7.0-doc/config/loader.html\n * http://tomcat.apache.org/tomcat-8.0-doc/config/loader.html\n *\n * @author pron\n */\npublic final class QuasarWebAppClassLoader extends WebappClassLoader {\n    @Override\n    protected final synchronized boolean filter(String name, boolean isClassName) {\n        // Don't re-load the instrumentation logic, including the `SuspendableClassifier` interface,\n        // else implementations in the webapp classloader will have trouble loading when running in\n        // a standalone servlet container\n        return\n            isClassName &&\n            name.startsWith(\"co.paralleluniverse.common.\") ||\n            name.startsWith(\"co.paralleluniverse.fibers.instrument.\") ||\n            name.startsWith(\"jsr166e\") ||\n            name.startsWith(\"co.paralleluniverse.asm.\");\n    }\n\n    private QuasarInstrumentor instrumentor;\n\n    public QuasarWebAppClassLoader() {}\n\n    public QuasarWebAppClassLoader(ClassLoader parent) {\n        super(parent);\n    }\n\n    private QuasarInstrumentor newInstrumentor() {\n        final QuasarInstrumentor inst = new QuasarInstrumentor(); // must be called *after* construction has completed\n        inst.setLog(new Log() {\n            @Override\n            public final void log(LogLevel level, String msg, Object... args) {\n                System.err.println(\"[quasar] \" + level + \": \" + String.format(msg, args));\n            }\n\n            @Override\n            public final void error(String msg, Throwable exc) {\n                System.err.println(\"[quasar] ERROR: \" + msg);\n                exc.printStackTrace(System.err);\n            }\n        });\n        inst.setVerbose(false);\n        inst.setDebug(false);\n        return inst;\n    }\n\n    private synchronized void initInstrumentor() {\n        if (instrumentor == null)\n            instrumentor = newInstrumentor();\n    }\n\n    @Override\n    protected final ResourceEntry findResourceInternal(String name, String path) {\n        initInstrumentor();\n        final ResourceEntry entry = super.findResourceInternal(name, path);\n        if (name != null && path != null && path.endsWith(CLASS_SUFFIX) && entry != null && entry.binaryContent != null) {\n            final int nameLen = name.length();\n            final String className = name.substring(0, name.endsWith(CLASS_SUFFIX) ? nameLen - CLASS_SUFFIX_LENGTH : nameLen);\n            try {\n                final byte[] res = instrumentor.instrumentClass(this, className, entry.binaryContent);\n                if (res != null)\n                    entry.binaryContent = res;\n            } catch (final Exception ex) {\n                if (MethodDatabase.isProblematicClass(className))\n                    instrumentor.log(LogLevel.INFO, \"Skipping problematic class instrumentation %s - %s %s\", className, ex, Arrays.toString(ex.getStackTrace()));\n                else\n                    instrumentor.error(\"Unable to instrument \" + className, ex);\n            }\n        }\n        return entry;\n    }\n\n    private static final String CLASS_SUFFIX = \".class\";\n    private static final int CLASS_SUFFIX_LENGTH = CLASS_SUFFIX.length();\n}\n"
  },
  {
    "path": "comsat-tomcat-loader/src/test/java/co/paralleluniverse/embedded/containers/TomcatLoaderTest.java",
    "content": "/*\n * COMSAT\n * Copyright (C) 2014-2016, Parallel Universe Software Co. All rights reserved.\n *\n * This program and the accompanying materials are dual-licensed under\n * either the terms of the Eclipse Public License v1.0 as published by\n * the Eclipse Foundation\n *\n *   or (per the licensee's choosing)\n *\n * under the terms of the GNU Lesser General Public License version 3.0\n * as published by the Free Software Foundation.\n */\npackage co.paralleluniverse.embedded.containers;\n\nimport io.undertow.util.FileUtils;\nimport java.io.File;\nimport java.io.IOException;\nimport javax.servlet.ServletException;\nimport org.apache.catalina.startup.Tomcat;\nimport org.apache.http.client.config.RequestConfig;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.impl.client.BasicResponseHandler;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.tomcat.util.descriptor.web.ContextResource;\nimport org.junit.After;\nimport static org.junit.Assert.assertTrue;\nimport org.junit.Before;\nimport org.junit.Test;\n\npublic class TomcatLoaderTest {\n\n//    private EmbeddedServer instance;\n    private CloseableHttpClient client;\n    private Tomcat tomcat;\n\n    @Before\n    public void setUp() throws Exception {\n        this.tomcat = new Tomcat();\n        loadWars(tomcat, \"build\", \"build/wars\", \"/\");\n        registerDB(tomcat, \"jdbc/globalds\", \"org.h2.Driver\", \"jdbc:h2:./build/h2testdb\");\n        tomcat.start();\n        this.client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()\n                .setSocketTimeout(10000).setConnectTimeout(10000).setConnectionRequestTimeout(10000)\n                .build()).build();\n    }\n\n    @After\n    public void tearDown() throws Exception {\n        tomcat.stop();\n        client.close();\n    }\n\n    @Test\n    public void testGetDeployedWar() throws Exception {\n        for (int i = 0; i < 10; i++) {\n            final String result = client.execute(new HttpGet(\"http://localhost:8080/\"), BASIC_RESPONSE_HANDLER);\n            assertTrue(result.contains(\"h2testdb\"));\n        }\n    }\n\n    private static final BasicResponseHandler BASIC_RESPONSE_HANDLER = new BasicResponseHandler();\n    public static void registerDB(final Tomcat tomcat, final String name, final String driver, final String url) {\n        final ContextResource dbDsRes = new ContextResource();\n        dbDsRes.setName(name);\n        dbDsRes.setAuth(\"Container\");\n        dbDsRes.setType(\"javax.sql.DataSource\");\n        dbDsRes.setProperty(\"maxActive\", \"100\");\n        dbDsRes.setProperty(\"maxIdle\", \"30\");\n        dbDsRes.setProperty(\"maxWait\", \"10000\");\n        dbDsRes.setScope(\"Sharable\");\n        dbDsRes.setProperty(\"driverClassName\", driver);\n        dbDsRes.setProperty(\"url\", url);\n        dbDsRes.setProperty(\"username\", \"\");\n        dbDsRes.setProperty(\"password\", \"\");\n        tomcat.enableNaming();\n        tomcat.getServer().getGlobalNamingResources().addResource(dbDsRes);\n    }\n\n    public static void loadWars(final Tomcat tomcat, String baseDir, String warDir, String path) throws ServletException, IOException {\n        final File webapps = new File(baseDir + \"/webapps\");\n        FileUtils.deleteRecursive(webapps.toPath());\n        //noinspection ResultOfMethodCallIgnored\n        webapps.mkdirs();\n        tomcat.setBaseDir(baseDir);\n\n        // scan for the first war\n        //noinspection ConstantConditions\n        for (final File fileEntry : new File(warDir).listFiles()) {\n            System.out.println(\"Found: \" + fileEntry.getName());\n            if (fileEntry.getName().endsWith(\".war\")) {\n                final String war = fileEntry.getName().substring(0, fileEntry.getName().length() - \".war\".length());\n                System.out.println(\"Loading WAR: \" + war + \" to: http://localhost:8080\" + path);\n                tomcat.addWebapp(path, fileEntry.getAbsolutePath());\n                break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "docs/_config.yml",
    "content": "markdown: enhanced_kramdown\nhighlighter: pygments\nlsi: false\nsafe: false\nbaseurl: /comsat\n\n# Site globals used throughout docs.\nproject: Comsat\nversion: 0.7.0\ngithub: puniverse/comsat\ngoogle_group: \"https://groups.google.com/forum/#!forum/comsat-user\"\ntagline: \"Scalable web application libraries\"\nga_tracking_id: UA-25007319-2\ncode_dir: \"../\"\n"
  },
  {
    "path": "docs/_includes/footer.html",
    "content": "<footer>\r\n        <div class=\"container\">\r\n            <div id=\"logo-footer\"></div>\r\n            <ul>\r\n                <li><a href=\"http://paralleluniverse.co/support/\">Support</a></li>\r\n                <li><a href=\"http://docs.paralleluniverse.co\">Documentation</a></li>\r\n                <li><a href=\"http://paralleluniverse.co/about/\">Company</a></li>\r\n                <li><a href=\"http://blog.paralleluniverse.co\">Blog</a></li>\r\n            </ul>\r\n            <a href=\"https://www.facebook.com/puniverseco\" class=\"social social1\">social</a>\r\n            <a href=\"https://twitter.com/puniverseco\" class=\"social social2\">social</a>\r\n            <a href=\"http://www.linkedin.com/company/parallel-universe?trk=company_name\" class=\"social social3\">social</a>\r\n        </div><!--container-->\r\n</footer>\r\n"
  },
  {
    "path": "docs/_includes/head.html",
    "content": "<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n<head>\n        <meta charset=\"utf-8\">\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n        <title>Parallel Universe</title>\n        <meta name=\"description\" content=\"\">\n        <meta name=\"format-detection\" content=\"telephone=no\">\n        <meta name=\"viewport\" content=\"width=1100\">\n        <script type=\"text/javascript\" src=\"//use.typekit.net/pfn0abv.js\"></script>\n        <script type=\"text/javascript\">try{Typekit.load();}catch(e){}</script>\n        <link href='http://fonts.googleapis.com/css?family=Arimo:400,700,400italic,700italic' rel='stylesheet' type='text/css'>\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"{{site.baseurl}}/css/screen.css\">\n        <script src=\"{{site.baseurl}}/js/vendor/modernizr-2.6.2.min.js\"></script>\n\n        <script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js\"></script>\n        <script>window.jQuery || document.write('<script src=\"/js/vendor/jquery-1.9.1.min.js\"><\\/script>')</script>\n        <script src=\"{{site.baseurl}}/js/plugins.js\"></script>\n        <script src=\"{{site.baseurl}}/js/main.js\"></script>\n\n        <script>\n            var _gaq=[['_setAccount','UA-25007319-2'],['_trackPageview']];\n            (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];\n            g.src='//www.google-analytics.com/ga.js';\n            s.parentNode.insertBefore(g,s)}(document,'script'));\n        </script>\n\n        {% include meta.html %}\n    <!--[if lt IE 9]>\n        <script src=\"js/vendor/html5shiv.js\"></script>\n    <![endif]-->\n     <!--[if lt IE 8]>\n            <p class=\"chromeframe\">You are using an <strong>outdated</strong> browser. Please <a href=\"http://browsehappy.com/\">upgrade your browser</a> or <a href=\"http://www.google.com/chromeframe/?redirect=true\">activate Google Chrome Frame</a> to improve your experience.</p>\n        <![endif]-->\n</head>"
  },
  {
    "path": "docs/_includes/header.html",
    "content": "\r\n<header>\r\n    <div class=\"container\">\r\n        <a href=\"http://paralleluniverse.co\" id=\"logo\">Parallel Universe</a>\r\n        <ul id=\"nav\">\r\n            <li class=\"sub\">\r\n                <a>Products</a>\r\n                <ul>\r\n                    <li class=\"li1\"><a href=\"http://paralleluniverse.co/comsat/\">Comsat</a></li>\r\n                    <li class=\"li2\"><a href=\"http://paralleluniverse.co/quasar/\">Quasar</a></li>\r\n                    <li class=\"li3\"><a href=\"http://paralleluniverse.co/spacebase/\">Spacebase</a></li>\r\n                    <li class=\"li4\"><a href=\"http://paralleluniverse.co/galaxy/\">Galaxy</a></li>\r\n                </ul>\r\n            </li>\r\n            <li><a href=\"http://paralleluniverse.co/support/\">Support</a></li>\r\n            <li><a href=\"http://docs.paralleluniverse.co\">Documentation</a></li>\r\n            <li><a href=\"http://paralleluniverse.co/about/\">Company</a></li>\r\n            <li><a href=\"http://blog.paralleluniverse.co\">Blog</a></li>\r\n        </ul>\r\n    </div>\r\n</header>\r\n"
  },
  {
    "path": "docs/_includes/meta.html",
    "content": "<meta name=\"twitter:site\" content=\"@puniverseco\"> \n{% if page.title and page.description %}\n\t<!-- Twitter -->\n\t<meta name=\"twitter:card\" content=\"summary\"> \n\t<meta name=\"twitter:title\" content=\"{{ page.title }}\"> \n\t<meta name=\"twitter:description\" content=\"{{ page.description }}\"> \n\n\t<!-- OpenGraph -->\n\t<meta property=\"og:site_name\" content=\"Parallel Universe\">\n\t<meta property=\"og:type\" content=\"website\">\n\t<meta property=\"og:title\" content=\"{{ page.title }}\">\n\t<meta property=\"og:description\" content=\"{{ page.description }}\">\n\t<meta property=\"og:url\" content=\"{{site.url}}{{site.baseurl}}{{ page.url | replace:'/index.html','/' }}\">\n\t<meta property=\"og:image\" content=\"http://www.gravatar.com/avatar/d942a0d3bac0a907acfb7d78c8846d1a?s=200\">\n{% endif %}"
  },
  {
    "path": "docs/_includes/top-nav.html",
    "content": "<!-- <top-nav> -->\r\n<div id=\"doumentation-bottom-bar\">\r\n\t<div class=\"container\">\r\n\t\t<div class=\"side-title\"><h2>documentation</h2></div>\r\n\t\t<h3>{{site.project}}</h3>\r\n\t\t<a href=\"https://github.com/{{site.github}}\" class=\"btn-1\"><span>View on Github</span></a>\r\n\t\t<a href=\"{{site.baseurl}}/javadoc/index.html\" class=\"btn-2\"><span>API</span></a>\r\n\t\t<a href=\"https://github.com/{{site.github}}/issues/new\" class=\"btn-3\"><span>File a bug</span></a>\r\n\t\t<a href=\"{{site.google_group}}\" class=\"btn-4\"><span>Discuss</span></a>\r\n\t</div>\r\n</div>\r\n<!-- </top-nav> -->\r\n"
  },
  {
    "path": "docs/_layouts/default.html",
    "content": "<!DOCTYPE html>\n<html itemscope itemtype=\"http://schema.org/Organization\">\n<head>\n\t{% include head.html %}\n</head>\n<body class=\"fixed-documentation\">\n\tֿ{% include header.html %} \n\n\t<section id=\"main\">\n\t\t<div class=\"container\">\n\t\t\t<div id=\"docs-cont\" class=\"clearfix\">\n\t\t\t\t<div class=\"sidebar\">\n\t\t\t\t\t{{content | toc}}\n\t\t\t\t</div>\n\n\t\t\t\t<div class=\"main\">\n\t\t\t\t\t<div class=\"doc-text\">\n\t\t\t\t\t\t{{content}}\n\t\t\t\t\t</div>\n\t\t\t\t</div><!--main-->\n\t\t\t</div><!--docs-cont-->\n\t\t</div> <!--container-->\n\t</section><!--main-->\n\n\t{% include top-nav.html %}\n\n\t{% include footer.html %}\n</body>\n</html>\n"
  },
  {
    "path": "docs/_plugins/domain_name.filter.rb",
    "content": "# Strips https?:// from a URL.\n# Usage: {{ page.url | domain_name }}\n# https://github.com/LawrenceWoodman/domain_name-liquid_filter\n\nrequire 'liquid'\n\nmodule DomainNameFilter\n\n  # Return the url's domain name\n  def domain_name(url)\n    return url.sub(%r{(https?://){0,1}([^/]*)(/.*$){0,1}}i, '\\\\2\\\\3')\n  end\n\nend\n\nLiquid::Template.register_filter(DomainNameFilter)\n"
  },
  {
    "path": "docs/_plugins/enhanced_kramdown.rb",
    "content": "require 'kramdown'\nrequire 'pygments'\nrequire 'typogruby'\n\nmodule Kramdown\n  module Converter\n    class Pygs < Html\n      def convert_codeblock(el, indent)\n        attr = el.attr.dup\n        lang = extract_code_language!(attr)\n        if lang\n          add_code_tags(\n            Pygments.highlight(el.value,\n             :lexer => lang,\n             :options => { :encoding => 'utf-8', :linespans => 'line' }) \n            )\n        else\n          \"<pre><code>#{el.value}</code></pre>\"\n        end\n      end\n\n      def add_code_tags(code)\n        code = code.sub(/<pre>/,'<pre><code>')\n        code = code.sub(/<\\/pre>/,\"</code></pre>\")\n      end\n    end\n  end\nend\n\nclass Hash\n  def symbolize_keys!\n    keys.each do |key|\n      self[(key.to_sym rescue key) || key] = delete(key)\n    end\n    self\n  end\n\n  def symbolize_keys\n    dup.symbolize_keys!\n  end\nend\n\nmodule Jekyll\n  module Converters\n    class Markdown\n      class EnhancedKramdownParser\n        def initialize(config)\n          @config = config\n        end\n\n        def convert(content)\n          html = Kramdown::Document.new(content, @config[\"kramdown\"].symbolize_keys).to_pygs\n          return Typogruby.improve(html)\n        end\n      end\n    end\n  end\nend"
  },
  {
    "path": "docs/_plugins/exclude_toc.filter.rb",
    "content": "require 'nokogiri'\n\nmodule ExcludeTocFilter\n  def exclude_toc(html)\n    doc = Nokogiri::HTML(html)\n    doc.css('#markdown-toc').remove\n    doc.to_html\n  end\nend\nLiquid::Template.register_filter(ExcludeTocFilter)"
  },
  {
    "path": "docs/_plugins/include_external.rb",
    "content": "module Jekyll\n  class IncludeExternal < Liquid::Tag\n\n    def initialize(tag_name, text, tokens)\n      @text = text\n\n      begin\n        f = File.new(@text.strip, \"r\")\n        @output = f.read()\n      rescue => e\n        @output = \"<div class=\\\"error\\\">IncludeExternal error: #{e}</div>\"\n      ensure\n        f.close unless f.nil?\n      end\n\n      super\n    end\n\n    def render(context)\n      @output\n    end\n  end\nend\n\nLiquid::Template.register_tag('include_external', Jekyll::IncludeExternal)\n"
  },
  {
    "path": "docs/_plugins/include_snippet.rb",
    "content": "# Title: Include Snippet Tag for Jekyll\n# Author: Eitan Yarden https://github.com/eitan101\n# Description: Import your code snippets into any blog post.\n# Configuration: You can set default import path in _config.yml (defaults to code_dir: downloads/code)\n#\n# Syntax {% include_snippet snippet_name path/to/file %}\n#\n# Example 1:\n# ~~~ java\n# {% include_code hello world javascripts/test.java %}\n# ~~~\n#\n# This will import test.js starting from the line which contains \"snippet hello world\" till\n# the line which contains \"end of snippet\". You can use the \"snippet_exclude_begin\" and \"snippet_exclude_end // ...\" for\n# block exclusion. For code higlight wrap the tag with the appropritate md tag.\n#\n#\n\nrequire 'pathname'\n\nmodule Jekyll\n\n  class IncludeCodeTag < Liquid::Tag\n    # include HighlightCode\n    # include TemplateWrapper\n    def initialize(tag_name, markup, tokens)\n      @title = nil\n      if markup.strip =~ /(.*)?(\\s+|^)(\\/*\\S+)/i\n        @title = $1 || nil\n        @file = $3\n      else\n        fail \"no title in '#{markup.strip}'\"\n      end\n      super\n    end\n\n    def render(context)\n      code_dir = (context.registers[:site].config['code_dir'].sub(/^\\//,'') || 'downloads/code')\n      code_path = (Pathname.new(context.registers[:site].source) + code_dir).expand_path\n      file = code_path + @file\n\n      if File.symlink?(code_path)\n        return \"Code directory '#{code_path}' cannot be a symlink\"\n      end\n\n      unless file.file?\n        fail \"File #{file} could not be found\"\n      end\n\n      Dir.chdir(code_path) do\n        code = file.read\n        source = \"\"\n        inblock = false\n        exclude = false\n        spaces = -1;\n        snippet_found = false\n        code.lines.each_with_index do |line,index|\n          if line =~ /end of snippet/\n            inblock = false\n          end\n          if (line =~ /snippet_exclude_begin/)\n            exclude = true\n          end\n          if inblock && !exclude\n              if spaces==-1\n                spaces = line.index(/[^ ]/)\n              end\n              if spaces>-1 && spaces <= line.index(/[^ ]/)\n                line = line[spaces..line.length]\n              end\n              source  += \"#{line}\"\n          end\n          if (line =~ /snippet_exclude_end/)\n            # add what comes after \"snippet_exclude_end\" as a block replacement\n            # for example \"// ...\"\n            # update: disabled. causes problems in cases like <!--snippet_exclude_end-->\n            # index = line.index(/snippet_exclude_end/)\n            # if (index) + 20 +1 < line.length\n            #   source += line[index+20..line.length]\n            # end\n            exclude = false\n          end\n          if line =~ /snippet #{@title}/\n            inblock = true\n            snippet_found = true\n          end\n        end\n        if not snippet_found\n          fail \"snippet #{@title} not found in #{file}\"\n        end\n        ouput = source\n      end\n    end\n  end\n\nend\n\nLiquid::Template.register_tag('include_snippet', Jekyll::IncludeCodeTag)\n"
  },
  {
    "path": "docs/_plugins/markdown_converter.rb",
    "content": "module Jekyll\n  module Converters\n    class Markdown < Converter\n      safe true\n\n      # pygments_prefix \"\\n\"\n      # pygments_suffix \"\\n\"\n      # for jekyll 2.0.3\n      highlighter_prefix \"\\n\"\n      highlighter_suffix \"\\n\"\n\n      def setup\n        return if @setup\n        @parser = case @config['markdown']\n          when 'redcarpet'\n            RedcarpetParser.new @config\n          when 'kramdown'\n            KramdownParser.new @config\n          when 'rdiscount'\n            RDiscountParser.new @config\n          when 'maruku'\n            MarukuParser.new @config\n          when 'enhanced_kramdown'\n            EnhancedKramdownParser.new @config\n          else\n            STDERR.puts \"Invalid Markdown processor: #{@config['markdown']}\"\n            STDERR.puts \" Valid options are [ maruku | rdiscount | kramdown | enhanced_kramdown ]\"\n            raise FatalException.new(\"Invalid Markdown process: #{@config['markdown']}\")\n        end\n        @setup = true\n      end\n\n      def matches(ext)\n        rgx = '(' + @config['markdown_ext'].gsub(',','|') +')'\n        ext =~ Regexp.new(rgx, Regexp::IGNORECASE)\n      end\n\n      def output_ext(ext)\n        \".html\"\n      end\n\n      def convert(content)\n        setup\n        @parser.convert(content)\n      end\n    end\n  end\nend"
  },
  {
    "path": "docs/_plugins/sorted_for.rb",
    "content": "module Jekyll\n  class SortedForTag < Liquid::For\n    def render(context)\n      sorted_collection = context[@collection_name].dup\n      sorted_collection.reject! { |i| i.to_liquid[@attributes['sort_by']].nil? }\n      sorted_collection.sort_by! { |i| i.to_liquid[@attributes['sort_by']] }\n\n      sorted_collection_name = \"#{@collection_name}_sorted\".sub('.', '_')\n      context[sorted_collection_name] = sorted_collection\n      @collection_name = sorted_collection_name\n\n      super\n    end\n\n    def end_tag\n      'endsorted_for'\n    end\n  end\nend\n\nLiquid::Template.register_tag('sorted_for', Jekyll::SortedForTag)"
  },
  {
    "path": "docs/_plugins/svg_support.rb",
    "content": "require 'webrick'\ninclude WEBrick\n\nWEBrick::HTTPUtils::DefaultMimeTypes.store 'svg', 'image/svg+xml'\n"
  },
  {
    "path": "docs/_plugins/toc.filter.rb",
    "content": "require 'nokogiri'\n\n# Tutorials:\n# http://ruby.bastardsbook.com/chapters/html-parsing/\n# http://nokogiri.org/tutorials\n\nmodule TocFilter\n  def toc(html)\n    doc = Nokogiri::HTML(html)\n    tocul = Nokogiri::XML::Node.new \"ul\", doc\n    tocul['id'] = 'docs-sidemenu'\n    ul = tocul\n    li = nil\n    prev_level = nil\n    doc.xpath('//h1 | //h2 | //h3').each do |h| # xpath(\"//*[@id='markdown-toc']\")\n      level = h.name[1].to_i\n      if prev_level.nil?\n        prev_level = level\n      end\n      if level > prev_level\n        ul = Nokogiri::XML::Node.new \"ul\", doc\n        li.add_child ul\n\n        pl = prev_level + 1\n        while pl < level do\n          li = Nokogiri::XML::Node.new \"li\", doc\n          ul.add_child li\n          ul = Nokogiri::XML::Node.new \"ul\", doc\n          li.add_child ul\n          pl = pl + 1\n        end\n      elsif level < prev_level\n        pl = prev_level\n        while pl > level do\n          ul = (ul == tocul ? ul : ul.parent.parent)\n          pl = pl - 1\n        end\n      end\n      prev_level = level\n\n      # puts \"#{h.name}: #{h.text}\" + '#' + h['id'].to_s\n      li = Nokogiri::XML::Node.new \"li\", doc\n      ul.add_child li\n\n      a = Nokogiri::XML::Node.new \"a\", doc\n      li.add_child a\n      a['href'] = ('#' + h['id'])\n      a.content = h.text\n      if level == 1\n        li['class'] = 'li1'\n      elsif level == 2\n        a['class'] = 'cat-link'\n      end\n    end\n    tocul.to_html\n  end\nend\n\nLiquid::Template.register_filter(TocFilter)\n\n# module TocFilter\n#   def toc(html)\n#     output = \"\"\n#     ul = Nokogiri::HTML(html).css('#markdown-toc')\n#     ul.each do |elem| # xpath(\"//*[@id='markdown-toc']\")\n#       # elem is main toc ul\n#       elem['id'] = 'docs-sidemenu'\n#       elem.children.each do |li1|\n#         # li1 is li level 1\n#         li1['class'] = 'li1'\n#         li1.children.select{ |x| x.name == 'ul'}.each do |c|\n#           # c is ul under li1\n#           c.children.each do |li2|\n#             # li2 is li under c\n#             li2.children.select{ |x| x.name == 'a'}.each do |a|\n#               # a is \"a href\" under li level 2\n#               a['class'] = 'cat-link'\n#             end\n#           end\n#         end\n#       end\n#     end\n#     ul.to_html\n#   end\n# end\n"
  },
  {
    "path": "docs/css/PIE.htc",
    "content": "<!--\nPIE: CSS3 rendering for IE\nVersion 1.0.0\nhttp://css3pie.com\nDual-licensed for use under the Apache License Version 2.0 or the General Public License (GPL) Version 2.\n-->\n<PUBLIC:COMPONENT lightWeight=\"true\">\n<!-- saved from url=(0014)about:internet -->\n<PUBLIC:ATTACH EVENT=\"oncontentready\" FOR=\"element\" ONEVENT=\"init()\" />\n<PUBLIC:ATTACH EVENT=\"ondocumentready\" FOR=\"element\" ONEVENT=\"init()\" />\n<PUBLIC:ATTACH EVENT=\"ondetach\" FOR=\"element\" ONEVENT=\"cleanup()\" />\n\n<script type=\"text/javascript\">\nvar doc = element.document;var f=window.PIE;\nif(!f){f=window.PIE={F:\"-pie-\",nb:\"Pie\",La:\"pie_\",Ac:{TD:1,TH:1},cc:{TABLE:1,THEAD:1,TBODY:1,TFOOT:1,TR:1,INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,IMG:1,HR:1},fc:{A:1,INPUT:1,TEXTAREA:1,SELECT:1,BUTTON:1},Gd:{submit:1,button:1,reset:1},aa:function(){}};try{doc.execCommand(\"BackgroundImageCache\",false,true)}catch(aa){}for(var ba=4,Z=doc.createElement(\"div\"),ca=Z.getElementsByTagName(\"i\"),ga;Z.innerHTML=\"<!--[if gt IE \"+ ++ba+\"]><i></i><![endif]--\\>\",ca[0];);f.O=ba;if(ba===6)f.F=f.F.replace(/^-/,\"\");f.ja=\ndoc.documentMode||f.O;Z.innerHTML='<v:shape adj=\"1\"/>';ga=Z.firstChild;ga.style.behavior=\"url(#default#VML)\";f.zc=typeof ga.adj===\"object\";(function(){var a,b=0,c={};f.p={Za:function(d){if(!a){a=doc.createDocumentFragment();a.namespaces.add(\"css3vml\",\"urn:schemas-microsoft-com:vml\")}return a.createElement(\"css3vml:\"+d)},Ba:function(d){return d&&d._pieId||(d._pieId=\"_\"+ ++b)},Eb:function(d){var e,g,j,i,h=arguments;e=1;for(g=h.length;e<g;e++){i=h[e];for(j in i)if(i.hasOwnProperty(j))d[j]=i[j]}return d},\nRb:function(d,e,g){var j=c[d],i,h;if(j)Object.prototype.toString.call(j)===\"[object Array]\"?j.push([e,g]):e.call(g,j);else{h=c[d]=[[e,g]];i=new Image;i.onload=function(){j=c[d]={h:i.width,f:i.height};for(var k=0,n=h.length;k<n;k++)h[k][0].call(h[k][1],j);i.onload=null};i.src=d}}}})();f.Na={gc:function(a,b,c,d){function e(){k=j>=90&&j<270?b:0;n=j<180?c:0;m=b-k;p=c-n}function g(){for(;j<0;)j+=360;j%=360}var j=d.sa;d=d.zb;var i,h,k,n,m,p,r,t;if(d){d=d.coords(a,b,c);i=d.x;h=d.y}if(j){j=j.jd();g();e();\nif(!d){i=k;h=n}d=f.Na.tc(i,h,j,m,p);a=d[0];d=d[1]}else if(d){a=b-i;d=c-h}else{i=h=a=0;d=c}r=a-i;t=d-h;if(j===void 0){j=!r?t<0?90:270:!t?r<0?180:0:-Math.atan2(t,r)/Math.PI*180;g();e()}return{sa:j,xc:i,yc:h,td:a,ud:d,Wd:k,Xd:n,rd:m,sd:p,kd:r,ld:t,rc:f.Na.dc(i,h,a,d)}},tc:function(a,b,c,d,e){if(c===0||c===180)return[d,b];else if(c===90||c===270)return[a,e];else{c=Math.tan(-c*Math.PI/180);a=c*a-b;b=-1/c;d=b*d-e;e=b-c;return[(d-a)/e,(c*d-b*a)/e]}},dc:function(a,b,c,d){a=c-a;b=d-b;return Math.abs(a===0?\nb:b===0?a:Math.sqrt(a*a+b*b))}};f.ea=function(){this.Gb=[];this.oc={}};f.ea.prototype={ba:function(a){var b=f.p.Ba(a),c=this.oc,d=this.Gb;if(!(b in c)){c[b]=d.length;d.push(a)}},Ha:function(a){a=f.p.Ba(a);var b=this.oc;if(a&&a in b){delete this.Gb[b[a]];delete b[a]}},xa:function(){for(var a=this.Gb,b=a.length;b--;)a[b]&&a[b]()}};f.Oa=new f.ea;f.Oa.Rd=function(){var a=this,b;if(!a.Sd){b=doc.documentElement.currentStyle.getAttribute(f.F+\"poll-interval\")||250;(function c(){a.xa();setTimeout(c,b)})();\na.Sd=1}};(function(){function a(){f.L.xa();window.detachEvent(\"onunload\",a);window.PIE=null}f.L=new f.ea;window.attachEvent(\"onunload\",a);f.L.ta=function(b,c,d){b.attachEvent(c,d);this.ba(function(){b.detachEvent(c,d)})}})();f.Qa=new f.ea;f.L.ta(window,\"onresize\",function(){f.Qa.xa()});(function(){function a(){f.mb.xa()}f.mb=new f.ea;f.L.ta(window,\"onscroll\",a);f.Qa.ba(a)})();(function(){function a(){c=f.kb.md()}function b(){if(c){for(var d=0,e=c.length;d<e;d++)f.attach(c[d]);c=0}}var c;if(f.ja<9){f.L.ta(window,\n\"onbeforeprint\",a);f.L.ta(window,\"onafterprint\",b)}})();f.lb=new f.ea;f.L.ta(doc,\"onmouseup\",function(){f.lb.xa()});f.he=function(){function a(h){this.Y=h}var b=doc.createElement(\"length-calc\"),c=doc.body||doc.documentElement,d=b.style,e={},g=[\"mm\",\"cm\",\"in\",\"pt\",\"pc\"],j=g.length,i={};d.position=\"absolute\";d.top=d.left=\"-9999px\";for(c.appendChild(b);j--;){d.width=\"100\"+g[j];e[g[j]]=b.offsetWidth/100}c.removeChild(b);d.width=\"1em\";a.prototype={Kb:/(px|em|ex|mm|cm|in|pt|pc|%)$/,ic:function(){var h=\nthis.Jd;if(h===void 0)h=this.Jd=parseFloat(this.Y);return h},yb:function(){var h=this.ae;if(!h)h=this.ae=(h=this.Y.match(this.Kb))&&h[0]||\"px\";return h},a:function(h,k){var n=this.ic(),m=this.yb();switch(m){case \"px\":return n;case \"%\":return n*(typeof k===\"function\"?k():k)/100;case \"em\":return n*this.xb(h);case \"ex\":return n*this.xb(h)/2;default:return n*e[m]}},xb:function(h){var k=h.currentStyle.fontSize,n,m;if(k.indexOf(\"px\")>0)return parseFloat(k);else if(h.tagName in f.cc){m=this;n=h.parentNode;\nreturn f.n(k).a(n,function(){return m.xb(n)})}else{h.appendChild(b);k=b.offsetWidth;b.parentNode===h&&h.removeChild(b);return k}}};f.n=function(h){return i[h]||(i[h]=new a(h))};return a}();f.Ja=function(){function a(e){this.X=e}var b=f.n(\"50%\"),c={top:1,center:1,bottom:1},d={left:1,center:1,right:1};a.prototype={zd:function(){if(!this.ac){var e=this.X,g=e.length,j=f.v,i=j.qa,h=f.n(\"0\");i=i.na;h=[\"left\",h,\"top\",h];if(g===1){e.push(new j.ob(i,\"center\"));g++}if(g===2){i&(e[0].k|e[1].k)&&e[0].d in c&&\ne[1].d in d&&e.push(e.shift());if(e[0].k&i)if(e[0].d===\"center\")h[1]=b;else h[0]=e[0].d;else if(e[0].W())h[1]=f.n(e[0].d);if(e[1].k&i)if(e[1].d===\"center\")h[3]=b;else h[2]=e[1].d;else if(e[1].W())h[3]=f.n(e[1].d)}this.ac=h}return this.ac},coords:function(e,g,j){var i=this.zd(),h=i[1].a(e,g);e=i[3].a(e,j);return{x:i[0]===\"right\"?g-h:h,y:i[2]===\"bottom\"?j-e:e}}};return a}();f.Ka=function(){function a(b,c){this.h=b;this.f=c}a.prototype={a:function(b,c,d,e,g){var j=this.h,i=this.f,h=c/d;e=e/g;if(j===\n\"contain\"){j=e>h?c:d*e;i=e>h?c/e:d}else if(j===\"cover\"){j=e<h?c:d*e;i=e<h?c/e:d}else if(j===\"auto\"){i=i===\"auto\"?g:i.a(b,d);j=i*e}else{j=j.a(b,c);i=i===\"auto\"?j/e:i.a(b,d)}return{h:j,f:i}}};a.Kc=new a(\"auto\",\"auto\");return a}();f.Ec=function(){function a(b){this.Y=b}a.prototype={Kb:/[a-z]+$/i,yb:function(){return this.ad||(this.ad=this.Y.match(this.Kb)[0].toLowerCase())},jd:function(){var b=this.Vc,c;if(b===undefined){b=this.yb();c=parseFloat(this.Y,10);b=this.Vc=b===\"deg\"?c:b===\"rad\"?c/Math.PI*180:\nb===\"grad\"?c/400*360:b===\"turn\"?c*360:0}return b}};return a}();f.Jc=function(){function a(c){this.Y=c}var b={};a.Qd=/\\s*rgba\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d+|\\d*\\.\\d+)\\s*\\)\\s*/;a.Fb={aliceblue:\"F0F8FF\",antiquewhite:\"FAEBD7\",aqua:\"0FF\",aquamarine:\"7FFFD4\",azure:\"F0FFFF\",beige:\"F5F5DC\",bisque:\"FFE4C4\",black:\"000\",blanchedalmond:\"FFEBCD\",blue:\"00F\",blueviolet:\"8A2BE2\",brown:\"A52A2A\",burlywood:\"DEB887\",cadetblue:\"5F9EA0\",chartreuse:\"7FFF00\",chocolate:\"D2691E\",coral:\"FF7F50\",cornflowerblue:\"6495ED\",\ncornsilk:\"FFF8DC\",crimson:\"DC143C\",cyan:\"0FF\",darkblue:\"00008B\",darkcyan:\"008B8B\",darkgoldenrod:\"B8860B\",darkgray:\"A9A9A9\",darkgreen:\"006400\",darkkhaki:\"BDB76B\",darkmagenta:\"8B008B\",darkolivegreen:\"556B2F\",darkorange:\"FF8C00\",darkorchid:\"9932CC\",darkred:\"8B0000\",darksalmon:\"E9967A\",darkseagreen:\"8FBC8F\",darkslateblue:\"483D8B\",darkslategray:\"2F4F4F\",darkturquoise:\"00CED1\",darkviolet:\"9400D3\",deeppink:\"FF1493\",deepskyblue:\"00BFFF\",dimgray:\"696969\",dodgerblue:\"1E90FF\",firebrick:\"B22222\",floralwhite:\"FFFAF0\",\nforestgreen:\"228B22\",fuchsia:\"F0F\",gainsboro:\"DCDCDC\",ghostwhite:\"F8F8FF\",gold:\"FFD700\",goldenrod:\"DAA520\",gray:\"808080\",green:\"008000\",greenyellow:\"ADFF2F\",honeydew:\"F0FFF0\",hotpink:\"FF69B4\",indianred:\"CD5C5C\",indigo:\"4B0082\",ivory:\"FFFFF0\",khaki:\"F0E68C\",lavender:\"E6E6FA\",lavenderblush:\"FFF0F5\",lawngreen:\"7CFC00\",lemonchiffon:\"FFFACD\",lightblue:\"ADD8E6\",lightcoral:\"F08080\",lightcyan:\"E0FFFF\",lightgoldenrodyellow:\"FAFAD2\",lightgreen:\"90EE90\",lightgrey:\"D3D3D3\",lightpink:\"FFB6C1\",lightsalmon:\"FFA07A\",\nlightseagreen:\"20B2AA\",lightskyblue:\"87CEFA\",lightslategray:\"789\",lightsteelblue:\"B0C4DE\",lightyellow:\"FFFFE0\",lime:\"0F0\",limegreen:\"32CD32\",linen:\"FAF0E6\",magenta:\"F0F\",maroon:\"800000\",mediumauqamarine:\"66CDAA\",mediumblue:\"0000CD\",mediumorchid:\"BA55D3\",mediumpurple:\"9370D8\",mediumseagreen:\"3CB371\",mediumslateblue:\"7B68EE\",mediumspringgreen:\"00FA9A\",mediumturquoise:\"48D1CC\",mediumvioletred:\"C71585\",midnightblue:\"191970\",mintcream:\"F5FFFA\",mistyrose:\"FFE4E1\",moccasin:\"FFE4B5\",navajowhite:\"FFDEAD\",\nnavy:\"000080\",oldlace:\"FDF5E6\",olive:\"808000\",olivedrab:\"688E23\",orange:\"FFA500\",orangered:\"FF4500\",orchid:\"DA70D6\",palegoldenrod:\"EEE8AA\",palegreen:\"98FB98\",paleturquoise:\"AFEEEE\",palevioletred:\"D87093\",papayawhip:\"FFEFD5\",peachpuff:\"FFDAB9\",peru:\"CD853F\",pink:\"FFC0CB\",plum:\"DDA0DD\",powderblue:\"B0E0E6\",purple:\"800080\",red:\"F00\",rosybrown:\"BC8F8F\",royalblue:\"4169E1\",saddlebrown:\"8B4513\",salmon:\"FA8072\",sandybrown:\"F4A460\",seagreen:\"2E8B57\",seashell:\"FFF5EE\",sienna:\"A0522D\",silver:\"C0C0C0\",skyblue:\"87CEEB\",\nslateblue:\"6A5ACD\",slategray:\"708090\",snow:\"FFFAFA\",springgreen:\"00FF7F\",steelblue:\"4682B4\",tan:\"D2B48C\",teal:\"008080\",thistle:\"D8BFD8\",tomato:\"FF6347\",turquoise:\"40E0D0\",violet:\"EE82EE\",wheat:\"F5DEB3\",white:\"FFF\",whitesmoke:\"F5F5F5\",yellow:\"FF0\",yellowgreen:\"9ACD32\"};a.prototype={parse:function(){if(!this.Ua){var c=this.Y,d;if(d=c.match(a.Qd)){this.Ua=\"rgb(\"+d[1]+\",\"+d[2]+\",\"+d[3]+\")\";this.Yb=parseFloat(d[4])}else{if((d=c.toLowerCase())in a.Fb)c=\"#\"+a.Fb[d];this.Ua=c;this.Yb=c===\"transparent\"?0:\n1}}},U:function(c){this.parse();return this.Ua===\"currentColor\"?c.currentStyle.color:this.Ua},fa:function(){this.parse();return this.Yb}};f.ha=function(c){return b[c]||(b[c]=new a(c))};return a}();f.v=function(){function a(c){this.$a=c;this.ch=0;this.X=[];this.Ga=0}var b=a.qa={Ia:1,Wb:2,z:4,Lc:8,Xb:16,na:32,K:64,oa:128,pa:256,Ra:512,Tc:1024,URL:2048};a.ob=function(c,d){this.k=c;this.d=d};a.ob.prototype={Ca:function(){return this.k&b.K||this.k&b.oa&&this.d===\"0\"},W:function(){return this.Ca()||this.k&\nb.Ra}};a.prototype={de:/\\s/,Kd:/^[\\+\\-]?(\\d*\\.)?\\d+/,url:/^url\\(\\s*(\"([^\"]*)\"|'([^']*)'|([!#$%&*-~]*))\\s*\\)/i,nc:/^\\-?[_a-z][\\w-]*/i,Yd:/^(\"([^\"]*)\"|'([^']*)')/,Bd:/^#([\\da-f]{6}|[\\da-f]{3})/i,be:{px:b.K,em:b.K,ex:b.K,mm:b.K,cm:b.K,\"in\":b.K,pt:b.K,pc:b.K,deg:b.Ia,rad:b.Ia,grad:b.Ia},fd:{rgb:1,rgba:1,hsl:1,hsla:1},next:function(c){function d(p,r){p=new a.ob(p,r);if(!c){k.X.push(p);k.Ga++}return p}function e(){k.Ga++;return null}var g,j,i,h,k=this;if(this.Ga<this.X.length)return this.X[this.Ga++];for(;this.de.test(this.$a.charAt(this.ch));)this.ch++;\nif(this.ch>=this.$a.length)return e();j=this.ch;g=this.$a.substring(this.ch);i=g.charAt(0);switch(i){case \"#\":if(h=g.match(this.Bd)){this.ch+=h[0].length;return d(b.z,h[0])}break;case '\"':case \"'\":if(h=g.match(this.Yd)){this.ch+=h[0].length;return d(b.Tc,h[2]||h[3]||\"\")}break;case \"/\":case \",\":this.ch++;return d(b.pa,i);case \"u\":if(h=g.match(this.url)){this.ch+=h[0].length;return d(b.URL,h[2]||h[3]||h[4]||\"\")}}if(h=g.match(this.Kd)){i=h[0];this.ch+=i.length;if(g.charAt(i.length)===\"%\"){this.ch++;\nreturn d(b.Ra,i+\"%\")}if(h=g.substring(i.length).match(this.nc)){i+=h[0];this.ch+=h[0].length;return d(this.be[h[0].toLowerCase()]||b.Lc,i)}return d(b.oa,i)}if(h=g.match(this.nc)){i=h[0];this.ch+=i.length;if(i.toLowerCase()in f.Jc.Fb||i===\"currentColor\"||i===\"transparent\")return d(b.z,i);if(g.charAt(i.length)===\"(\"){this.ch++;if(i.toLowerCase()in this.fd){g=function(p){return p&&p.k&b.oa};h=function(p){return p&&p.k&(b.oa|b.Ra)};var n=function(p,r){return p&&p.d===r},m=function(){return k.next(1)};\nif((i.charAt(0)===\"r\"?h(m()):g(m()))&&n(m(),\",\")&&h(m())&&n(m(),\",\")&&h(m())&&(i===\"rgb\"||i===\"hsa\"||n(m(),\",\")&&g(m()))&&n(m(),\")\"))return d(b.z,this.$a.substring(j,this.ch));return e()}return d(b.Xb,i)}return d(b.na,i)}this.ch++;return d(b.Wb,i)},D:function(){return this.X[this.Ga-- -2]},all:function(){for(;this.next(););return this.X},ma:function(c,d){for(var e=[],g,j;g=this.next();){if(c(g)){j=true;this.D();break}e.push(g)}return d&&!j?null:e}};return a}();var ha=function(a){this.e=a};ha.prototype=\n{Z:0,Od:function(){var a=this.qb,b;return!a||(b=this.o())&&(a.x!==b.x||a.y!==b.y)},Td:function(){var a=this.qb,b;return!a||(b=this.o())&&(a.h!==b.h||a.f!==b.f)},hc:function(){var a=this.e,b=a.getBoundingClientRect(),c=f.ja===9,d=f.O===7,e=b.right-b.left;return{x:b.left,y:b.top,h:c||d?a.offsetWidth:e,f:c||d?a.offsetHeight:b.bottom-b.top,Hd:d&&e?a.offsetWidth/e:1}},o:function(){return this.Z?this.Va||(this.Va=this.hc()):this.hc()},Ad:function(){return!!this.qb},cb:function(){++this.Z},hb:function(){if(!--this.Z){if(this.Va)this.qb=\nthis.Va;this.Va=null}}};(function(){function a(b){var c=f.p.Ba(b);return function(){if(this.Z){var d=this.$b||(this.$b={});return c in d?d[c]:(d[c]=b.call(this))}else return b.call(this)}}f.B={Z:0,ka:function(b){function c(d){this.e=d;this.Zb=this.ia()}f.p.Eb(c.prototype,f.B,b);c.$c={};return c},j:function(){var b=this.ia(),c=this.constructor.$c;return b?b in c?c[b]:(c[b]=this.la(b)):null},ia:a(function(){var b=this.e,c=this.constructor,d=b.style;b=b.currentStyle;var e=this.wa,g=this.Fa,j=c.Yc||(c.Yc=\nf.F+e);c=c.Zc||(c.Zc=f.nb+g.charAt(0).toUpperCase()+g.substring(1));return d[c]||b.getAttribute(j)||d[g]||b.getAttribute(e)}),i:a(function(){return!!this.j()}),H:a(function(){var b=this.ia(),c=b!==this.Zb;this.Zb=b;return c}),va:a,cb:function(){++this.Z},hb:function(){--this.Z||delete this.$b}}})();f.Sb=f.B.ka({wa:f.F+\"background\",Fa:f.nb+\"Background\",cd:{scroll:1,fixed:1,local:1},fb:{\"repeat-x\":1,\"repeat-y\":1,repeat:1,\"no-repeat\":1},sc:{\"padding-box\":1,\"border-box\":1,\"content-box\":1},Pd:{top:1,right:1,\nbottom:1,left:1,center:1},Ud:{contain:1,cover:1},eb:{Ma:\"backgroundClip\",z:\"backgroundColor\",da:\"backgroundImage\",Pa:\"backgroundOrigin\",S:\"backgroundPosition\",T:\"backgroundRepeat\",Sa:\"backgroundSize\"},la:function(a){function b(s){return s&&s.W()||s.k&k&&s.d in t}function c(s){return s&&(s.W()&&f.n(s.d)||s.d===\"auto\"&&\"auto\")}var d=this.e.currentStyle,e,g,j,i=f.v.qa,h=i.pa,k=i.na,n=i.z,m,p,r=0,t=this.Pd,v,l,q={M:[]};if(this.wb()){e=new f.v(a);for(j={};g=e.next();){m=g.k;p=g.d;if(!j.P&&m&i.Xb&&p===\n\"linear-gradient\"){v={ca:[],P:p};for(l={};g=e.next();){m=g.k;p=g.d;if(m&i.Wb&&p===\")\"){l.color&&v.ca.push(l);v.ca.length>1&&f.p.Eb(j,v);break}if(m&n){if(v.sa||v.zb){g=e.D();if(g.k!==h)break;e.next()}l={color:f.ha(p)};g=e.next();if(g.W())l.db=f.n(g.d);else e.D()}else if(m&i.Ia&&!v.sa&&!l.color&&!v.ca.length)v.sa=new f.Ec(g.d);else if(b(g)&&!v.zb&&!l.color&&!v.ca.length){e.D();v.zb=new f.Ja(e.ma(function(s){return!b(s)},false))}else if(m&h&&p===\",\"){if(l.color){v.ca.push(l);l={}}}else break}}else if(!j.P&&\nm&i.URL){j.Ab=p;j.P=\"image\"}else if(b(g)&&!j.$){e.D();j.$=new f.Ja(e.ma(function(s){return!b(s)},false))}else if(m&k)if(p in this.fb&&!j.bb)j.bb=p;else if(p in this.sc&&!j.Wa){j.Wa=p;if((g=e.next())&&g.k&k&&g.d in this.sc)j.ub=g.d;else{j.ub=p;e.D()}}else if(p in this.cd&&!j.bc)j.bc=p;else return null;else if(m&n&&!q.color)q.color=f.ha(p);else if(m&h&&p===\"/\"&&!j.Xa&&j.$){g=e.next();if(g.k&k&&g.d in this.Ud)j.Xa=new f.Ka(g.d);else if(g=c(g)){m=c(e.next());if(!m){m=g;e.D()}j.Xa=new f.Ka(g,m)}else return null}else if(m&\nh&&p===\",\"&&j.P){j.Hb=a.substring(r,e.ch-1);r=e.ch;q.M.push(j);j={}}else return null}if(j.P){j.Hb=a.substring(r);q.M.push(j)}}else this.Bc(f.ja<9?function(){var s=this.eb,o=d[s.S+\"X\"],u=d[s.S+\"Y\"],x=d[s.da],y=d[s.z];if(y!==\"transparent\")q.color=f.ha(y);if(x!==\"none\")q.M=[{P:\"image\",Ab:(new f.v(x)).next().d,bb:d[s.T],$:new f.Ja((new f.v(o+\" \"+u)).all())}]}:function(){var s=this.eb,o=/\\s*,\\s*/,u=d[s.da].split(o),x=d[s.z],y,z,B,E,D,C;if(x!==\"transparent\")q.color=f.ha(x);if((E=u.length)&&u[0]!==\"none\"){x=\nd[s.T].split(o);y=d[s.S].split(o);z=d[s.Pa].split(o);B=d[s.Ma].split(o);s=d[s.Sa].split(o);q.M=[];for(o=0;o<E;o++)if((D=u[o])&&D!==\"none\"){C=s[o].split(\" \");q.M.push({Hb:D+\" \"+x[o]+\" \"+y[o]+\" / \"+s[o]+\" \"+z[o]+\" \"+B[o],P:\"image\",Ab:(new f.v(D)).next().d,bb:x[o],$:new f.Ja((new f.v(y[o])).all()),Wa:z[o],ub:B[o],Xa:new f.Ka(C[0],C[1])})}}});return q.color||q.M[0]?q:null},Bc:function(a){var b=f.ja>8,c=this.eb,d=this.e.runtimeStyle,e=d[c.da],g=d[c.z],j=d[c.T],i,h,k,n;if(e)d[c.da]=\"\";if(g)d[c.z]=\"\";if(j)d[c.T]=\n\"\";if(b){i=d[c.Ma];h=d[c.Pa];n=d[c.S];k=d[c.Sa];if(i)d[c.Ma]=\"\";if(h)d[c.Pa]=\"\";if(n)d[c.S]=\"\";if(k)d[c.Sa]=\"\"}a=a.call(this);if(e)d[c.da]=e;if(g)d[c.z]=g;if(j)d[c.T]=j;if(b){if(i)d[c.Ma]=i;if(h)d[c.Pa]=h;if(n)d[c.S]=n;if(k)d[c.Sa]=k}return a},ia:f.B.va(function(){return this.wb()||this.Bc(function(){var a=this.e.currentStyle,b=this.eb;return a[b.z]+\" \"+a[b.da]+\" \"+a[b.T]+\" \"+a[b.S+\"X\"]+\" \"+a[b.S+\"Y\"]})}),wb:f.B.va(function(){var a=this.e;return a.style[this.Fa]||a.currentStyle.getAttribute(this.wa)}),\nqc:function(){var a=0;if(f.O<7){a=this.e;a=\"\"+(a.style[f.nb+\"PngFix\"]||a.currentStyle.getAttribute(f.F+\"png-fix\"))===\"true\"}return a},i:f.B.va(function(){return(this.wb()||this.qc())&&!!this.j()})});f.Vb=f.B.ka({wc:[\"Top\",\"Right\",\"Bottom\",\"Left\"],Id:{thin:\"1px\",medium:\"3px\",thick:\"5px\"},la:function(){var a={},b={},c={},d=false,e=true,g=true,j=true;this.Cc(function(){for(var i=this.e.currentStyle,h=0,k,n,m,p,r,t,v;h<4;h++){m=this.wc[h];v=m.charAt(0).toLowerCase();k=b[v]=i[\"border\"+m+\"Style\"];n=i[\"border\"+\nm+\"Color\"];m=i[\"border\"+m+\"Width\"];if(h>0){if(k!==p)g=false;if(n!==r)e=false;if(m!==t)j=false}p=k;r=n;t=m;c[v]=f.ha(n);m=a[v]=f.n(b[v]===\"none\"?\"0\":this.Id[m]||m);if(m.a(this.e)>0)d=true}});return d?{J:a,Zd:b,gd:c,ee:j,hd:e,$d:g}:null},ia:f.B.va(function(){var a=this.e,b=a.currentStyle,c;a.tagName in f.Ac&&a.offsetParent.currentStyle.borderCollapse===\"collapse\"||this.Cc(function(){c=b.borderWidth+\"|\"+b.borderStyle+\"|\"+b.borderColor});return c}),Cc:function(a){var b=this.e.runtimeStyle,c=b.borderWidth,\nd=b.borderColor;if(c)b.borderWidth=\"\";if(d)b.borderColor=\"\";a=a.call(this);if(c)b.borderWidth=c;if(d)b.borderColor=d;return a}});(function(){f.jb=f.B.ka({wa:\"border-radius\",Fa:\"borderRadius\",la:function(b){var c=null,d,e,g,j,i=false;if(b){e=new f.v(b);var h=function(){for(var k=[],n;(g=e.next())&&g.W();){j=f.n(g.d);n=j.ic();if(n<0)return null;if(n>0)i=true;k.push(j)}return k.length>0&&k.length<5?{tl:k[0],tr:k[1]||k[0],br:k[2]||k[0],bl:k[3]||k[1]||k[0]}:null};if(b=h()){if(g){if(g.k&f.v.qa.pa&&g.d===\n\"/\")d=h()}else d=b;if(i&&b&&d)c={x:b,y:d}}}return c}});var a=f.n(\"0\");a={tl:a,tr:a,br:a,bl:a};f.jb.Dc={x:a,y:a}})();f.Ub=f.B.ka({wa:\"border-image\",Fa:\"borderImage\",fb:{stretch:1,round:1,repeat:1,space:1},la:function(a){var b=null,c,d,e,g,j,i,h=0,k=f.v.qa,n=k.na,m=k.oa,p=k.Ra;if(a){c=new f.v(a);b={};for(var r=function(l){return l&&l.k&k.pa&&l.d===\"/\"},t=function(l){return l&&l.k&n&&l.d===\"fill\"},v=function(){g=c.ma(function(l){return!(l.k&(m|p))});if(t(c.next())&&!b.fill)b.fill=true;else c.D();if(r(c.next())){h++;\nj=c.ma(function(l){return!l.W()&&!(l.k&n&&l.d===\"auto\")});if(r(c.next())){h++;i=c.ma(function(l){return!l.Ca()})}}else c.D()};a=c.next();){d=a.k;e=a.d;if(d&(m|p)&&!g){c.D();v()}else if(t(a)&&!b.fill){b.fill=true;v()}else if(d&n&&this.fb[e]&&!b.repeat){b.repeat={f:e};if(a=c.next())if(a.k&n&&this.fb[a.d])b.repeat.Ob=a.d;else c.D()}else if(d&k.URL&&!b.src)b.src=e;else return null}if(!b.src||!g||g.length<1||g.length>4||j&&j.length>4||h===1&&j.length<1||i&&i.length>4||h===2&&i.length<1)return null;if(!b.repeat)b.repeat=\n{f:\"stretch\"};if(!b.repeat.Ob)b.repeat.Ob=b.repeat.f;a=function(l,q){return{t:q(l[0]),r:q(l[1]||l[0]),b:q(l[2]||l[0]),l:q(l[3]||l[1]||l[0])}};b.slice=a(g,function(l){return f.n(l.k&m?l.d+\"px\":l.d)});if(j&&j[0])b.J=a(j,function(l){return l.W()?f.n(l.d):l.d});if(i&&i[0])b.Da=a(i,function(l){return l.Ca()?f.n(l.d):l.d})}return b}});f.Ic=f.B.ka({wa:\"box-shadow\",Fa:\"boxShadow\",la:function(a){var b,c=f.n,d=f.v.qa,e;if(a){e=new f.v(a);b={Da:[],Bb:[]};for(a=function(){for(var g,j,i,h,k,n;g=e.next();){i=g.d;\nj=g.k;if(j&d.pa&&i===\",\")break;else if(g.Ca()&&!k){e.D();k=e.ma(function(m){return!m.Ca()})}else if(j&d.z&&!h)h=i;else if(j&d.na&&i===\"inset\"&&!n)n=true;else return false}g=k&&k.length;if(g>1&&g<5){(n?b.Bb:b.Da).push({fe:c(k[0].d),ge:c(k[1].d),blur:c(k[2]?k[2].d:\"0\"),Vd:c(k[3]?k[3].d:\"0\"),color:f.ha(h||\"currentColor\")});return true}return false};a(););}return b&&(b.Bb.length||b.Da.length)?b:null}});f.Uc=f.B.ka({ia:f.B.va(function(){var a=this.e.currentStyle;return a.visibility+\"|\"+a.display}),la:function(){var a=\nthis.e,b=a.runtimeStyle;a=a.currentStyle;var c=b.visibility,d;b.visibility=\"\";d=a.visibility;b.visibility=c;return{ce:d!==\"hidden\",nd:a.display!==\"none\"}},i:function(){return false}});f.u={R:function(a){function b(c,d,e,g){this.e=c;this.s=d;this.g=e;this.parent=g}f.p.Eb(b.prototype,f.u,a);return b},Cb:false,Q:function(){return false},Ea:f.aa,Lb:function(){this.m();this.i()&&this.V()},ib:function(){this.Cb=true},Mb:function(){this.i()?this.V():this.m()},sb:function(a,b){this.vc(a);for(var c=this.ra||\n(this.ra=[]),d=a+1,e=c.length,g;d<e;d++)if(g=c[d])break;c[a]=b;this.I().insertBefore(b,g||null)},za:function(a){var b=this.ra;return b&&b[a]||null},vc:function(a){var b=this.za(a),c=this.Ta;if(b&&c){c.removeChild(b);this.ra[a]=null}},Aa:function(a,b,c,d){var e=this.rb||(this.rb={}),g=e[a];if(!g){g=e[a]=f.p.Za(\"shape\");if(b)g.appendChild(g[b]=f.p.Za(b));if(d){c=this.za(d);if(!c){this.sb(d,doc.createElement(\"group\"+d));c=this.za(d)}}c.appendChild(g);a=g.style;a.position=\"absolute\";a.left=a.top=0;a.behavior=\n\"url(#default#VML)\"}return g},vb:function(a){var b=this.rb,c=b&&b[a];if(c){c.parentNode.removeChild(c);delete b[a]}return!!c},kc:function(a){var b=this.e,c=this.s.o(),d=c.h,e=c.f,g,j,i,h,k,n;c=a.x.tl.a(b,d);g=a.y.tl.a(b,e);j=a.x.tr.a(b,d);i=a.y.tr.a(b,e);h=a.x.br.a(b,d);k=a.y.br.a(b,e);n=a.x.bl.a(b,d);a=a.y.bl.a(b,e);d=Math.min(d/(c+j),e/(i+k),d/(n+h),e/(g+a));if(d<1){c*=d;g*=d;j*=d;i*=d;h*=d;k*=d;n*=d;a*=d}return{x:{tl:c,tr:j,br:h,bl:n},y:{tl:g,tr:i,br:k,bl:a}}},ya:function(a,b,c){b=b||1;var d,e,\ng=this.s.o();e=g.h*b;g=g.f*b;var j=this.g.G,i=Math.floor,h=Math.ceil,k=a?a.Jb*b:0,n=a?a.Ib*b:0,m=a?a.tb*b:0;a=a?a.Db*b:0;var p,r,t,v,l;if(c||j.i()){d=this.kc(c||j.j());c=d.x.tl*b;j=d.y.tl*b;p=d.x.tr*b;r=d.y.tr*b;t=d.x.br*b;v=d.y.br*b;l=d.x.bl*b;b=d.y.bl*b;e=\"m\"+i(a)+\",\"+i(j)+\"qy\"+i(c)+\",\"+i(k)+\"l\"+h(e-p)+\",\"+i(k)+\"qx\"+h(e-n)+\",\"+i(r)+\"l\"+h(e-n)+\",\"+h(g-v)+\"qy\"+h(e-t)+\",\"+h(g-m)+\"l\"+i(l)+\",\"+h(g-m)+\"qx\"+i(a)+\",\"+h(g-b)+\" x e\"}else e=\"m\"+i(a)+\",\"+i(k)+\"l\"+h(e-n)+\",\"+i(k)+\"l\"+h(e-n)+\",\"+h(g-m)+\"l\"+i(a)+\n\",\"+h(g-m)+\"xe\";return e},I:function(){var a=this.parent.za(this.N),b;if(!a){a=doc.createElement(this.Ya);b=a.style;b.position=\"absolute\";b.top=b.left=0;this.parent.sb(this.N,a)}return a},mc:function(){var a=this.e,b=a.currentStyle,c=a.runtimeStyle,d=a.tagName,e=f.O===6,g;if(e&&(d in f.cc||d===\"FIELDSET\")||d===\"BUTTON\"||d===\"INPUT\"&&a.type in f.Gd){c.borderWidth=\"\";d=this.g.w.wc;for(g=d.length;g--;){e=d[g];c[\"padding\"+e]=\"\";c[\"padding\"+e]=f.n(b[\"padding\"+e]).a(a)+f.n(b[\"border\"+e+\"Width\"]).a(a)+(f.O!==\n8&&g%2?1:0)}c.borderWidth=0}else if(e){if(a.childNodes.length!==1||a.firstChild.tagName!==\"ie6-mask\"){b=doc.createElement(\"ie6-mask\");d=b.style;d.visibility=\"visible\";for(d.zoom=1;d=a.firstChild;)b.appendChild(d);a.appendChild(b);c.visibility=\"hidden\"}}else c.borderColor=\"transparent\"},ie:function(){},m:function(){this.parent.vc(this.N);delete this.rb;delete this.ra}};f.Rc=f.u.R({i:function(){var a=this.ed;for(var b in a)if(a.hasOwnProperty(b)&&a[b].i())return true;return false},Q:function(){return this.g.Pb.H()},\nib:function(){if(this.i()){var a=this.jc(),b=a,c;a=a.currentStyle;var d=a.position,e=this.I().style,g=0,j=0;j=this.s.o();var i=j.Hd;if(d===\"fixed\"&&f.O>6){g=j.x*i;j=j.y*i;b=d}else{do b=b.offsetParent;while(b&&b.currentStyle.position===\"static\");if(b){c=b.getBoundingClientRect();b=b.currentStyle;g=(j.x-c.left)*i-(parseFloat(b.borderLeftWidth)||0);j=(j.y-c.top)*i-(parseFloat(b.borderTopWidth)||0)}else{b=doc.documentElement;g=(j.x+b.scrollLeft-b.clientLeft)*i;j=(j.y+b.scrollTop-b.clientTop)*i}b=\"absolute\"}e.position=\nb;e.left=g;e.top=j;e.zIndex=d===\"static\"?-1:a.zIndex;this.Cb=true}},Mb:f.aa,Nb:function(){var a=this.g.Pb.j();this.I().style.display=a.ce&&a.nd?\"\":\"none\"},Lb:function(){this.i()?this.Nb():this.m()},jc:function(){var a=this.e;return a.tagName in f.Ac?a.offsetParent:a},I:function(){var a=this.Ta,b;if(!a){b=this.jc();a=this.Ta=doc.createElement(\"css3-container\");a.style.direction=\"ltr\";this.Nb();b.parentNode.insertBefore(a,b)}return a},ab:f.aa,m:function(){var a=this.Ta,b;if(a&&(b=a.parentNode))b.removeChild(a);\ndelete this.Ta;delete this.ra}});f.Fc=f.u.R({N:2,Ya:\"background\",Q:function(){var a=this.g;return a.C.H()||a.G.H()},i:function(){var a=this.g;return a.q.i()||a.G.i()||a.C.i()||a.ga.i()&&a.ga.j().Bb},V:function(){var a=this.s.o();if(a.h&&a.f){this.od();this.pd()}},od:function(){var a=this.g.C.j(),b=this.s.o(),c=this.e,d=a&&a.color,e,g;if(d&&d.fa()>0){this.lc();a=this.Aa(\"bgColor\",\"fill\",this.I(),1);e=b.h;b=b.f;a.stroked=false;a.coordsize=e*2+\",\"+b*2;a.coordorigin=\"1,1\";a.path=this.ya(null,2);g=a.style;\ng.width=e;g.height=b;a.fill.color=d.U(c);c=d.fa();if(c<1)a.fill.opacity=c}else this.vb(\"bgColor\")},pd:function(){var a=this.g.C.j(),b=this.s.o();a=a&&a.M;var c,d,e,g,j;if(a){this.lc();d=b.h;e=b.f;for(j=a.length;j--;){b=a[j];c=this.Aa(\"bgImage\"+j,\"fill\",this.I(),2);c.stroked=false;c.fill.type=\"tile\";c.fillcolor=\"none\";c.coordsize=d*2+\",\"+e*2;c.coordorigin=\"1,1\";c.path=this.ya(0,2);g=c.style;g.width=d;g.height=e;if(b.P===\"linear-gradient\")this.bd(c,b);else{c.fill.src=b.Ab;this.Nd(c,j)}}}for(j=a?a.length:\n0;this.vb(\"bgImage\"+j++););},Nd:function(a,b){var c=this;f.p.Rb(a.fill.src,function(d){var e=c.e,g=c.s.o(),j=g.h;g=g.f;if(j&&g){var i=a.fill,h=c.g,k=h.w.j(),n=k&&k.J;k=n?n.t.a(e):0;var m=n?n.r.a(e):0,p=n?n.b.a(e):0;n=n?n.l.a(e):0;h=h.C.j().M[b];e=h.$?h.$.coords(e,j-d.h-n-m,g-d.f-k-p):{x:0,y:0};h=h.bb;p=m=0;var r=j+1,t=g+1,v=f.O===8?0:1;n=Math.round(e.x)+n+0.5;k=Math.round(e.y)+k+0.5;i.position=n/j+\",\"+k/g;i.size.x=1;i.size=d.h+\"px,\"+d.f+\"px\";if(h&&h!==\"repeat\"){if(h===\"repeat-x\"||h===\"no-repeat\"){m=\nk+1;t=k+d.f+v}if(h===\"repeat-y\"||h===\"no-repeat\"){p=n+1;r=n+d.h+v}a.style.clip=\"rect(\"+m+\"px,\"+r+\"px,\"+t+\"px,\"+p+\"px)\"}}})},bd:function(a,b){var c=this.e,d=this.s.o(),e=d.h,g=d.f;a=a.fill;d=b.ca;var j=d.length,i=Math.PI,h=f.Na,k=h.tc,n=h.dc;b=h.gc(c,e,g,b);h=b.sa;var m=b.xc,p=b.yc,r=b.Wd,t=b.Xd,v=b.rd,l=b.sd,q=b.kd,s=b.ld;b=b.rc;e=h%90?Math.atan2(q*e/g,s)/i*180:h+90;e+=180;e%=360;v=k(r,t,h,v,l);g=n(r,t,v[0],v[1]);i=[];v=k(m,p,h,r,t);n=n(m,p,v[0],v[1])/g*100;k=[];for(h=0;h<j;h++)k.push(d[h].db?d[h].db.a(c,\nb):h===0?0:h===j-1?b:null);for(h=1;h<j;h++){if(k[h]===null){m=k[h-1];b=h;do p=k[++b];while(p===null);k[h]=m+(p-m)/(b-h+1)}k[h]=Math.max(k[h],k[h-1])}for(h=0;h<j;h++)i.push(n+k[h]/g*100+\"% \"+d[h].color.U(c));a.angle=e;a.type=\"gradient\";a.method=\"sigma\";a.color=d[0].color.U(c);a.color2=d[j-1].color.U(c);if(a.colors)a.colors.value=i.join(\",\");else a.colors=i.join(\",\")},lc:function(){var a=this.e.runtimeStyle;a.backgroundImage=\"url(about:blank)\";a.backgroundColor=\"transparent\"},m:function(){f.u.m.call(this);\nvar a=this.e.runtimeStyle;a.backgroundImage=a.backgroundColor=\"\"}});f.Gc=f.u.R({N:4,Ya:\"border\",Q:function(){var a=this.g;return a.w.H()||a.G.H()},i:function(){var a=this.g;return a.G.i()&&!a.q.i()&&a.w.i()},V:function(){var a=this.e,b=this.g.w.j(),c=this.s.o(),d=c.h;c=c.f;var e,g,j,i,h;if(b){this.mc();b=this.wd(2);i=0;for(h=b.length;i<h;i++){j=b[i];e=this.Aa(\"borderPiece\"+i,j.stroke?\"stroke\":\"fill\",this.I());e.coordsize=d*2+\",\"+c*2;e.coordorigin=\"1,1\";e.path=j.path;g=e.style;g.width=d;g.height=c;\ne.filled=!!j.fill;e.stroked=!!j.stroke;if(j.stroke){e=e.stroke;e.weight=j.Qb+\"px\";e.color=j.color.U(a);e.dashstyle=j.stroke===\"dashed\"?\"2 2\":j.stroke===\"dotted\"?\"1 1\":\"solid\";e.linestyle=j.stroke===\"double\"&&j.Qb>2?\"ThinThin\":\"Single\"}else e.fill.color=j.fill.U(a)}for(;this.vb(\"borderPiece\"+i++););}},wd:function(a){var b=this.e,c,d,e,g=this.g.w,j=[],i,h,k,n,m=Math.round,p,r,t;if(g.i()){c=g.j();g=c.J;r=c.Zd;t=c.gd;if(c.ee&&c.$d&&c.hd){if(t.t.fa()>0){c=g.t.a(b);k=c/2;j.push({path:this.ya({Jb:k,Ib:k,\ntb:k,Db:k},a),stroke:r.t,color:t.t,Qb:c})}}else{a=a||1;c=this.s.o();d=c.h;e=c.f;c=m(g.t.a(b));k=m(g.r.a(b));n=m(g.b.a(b));b=m(g.l.a(b));var v={t:c,r:k,b:n,l:b};b=this.g.G;if(b.i())p=this.kc(b.j());i=Math.floor;h=Math.ceil;var l=function(o,u){return p?p[o][u]:0},q=function(o,u,x,y,z,B){var E=l(\"x\",o),D=l(\"y\",o),C=o.charAt(1)===\"r\";o=o.charAt(0)===\"b\";return E>0&&D>0?(B?\"al\":\"ae\")+(C?h(d-E):i(E))*a+\",\"+(o?h(e-D):i(D))*a+\",\"+(i(E)-u)*a+\",\"+(i(D)-x)*a+\",\"+y*65535+\",\"+2949075*(z?1:-1):(B?\"m\":\"l\")+(C?d-\nu:u)*a+\",\"+(o?e-x:x)*a},s=function(o,u,x,y){var z=o===\"t\"?i(l(\"x\",\"tl\"))*a+\",\"+h(u)*a:o===\"r\"?h(d-u)*a+\",\"+i(l(\"y\",\"tr\"))*a:o===\"b\"?h(d-l(\"x\",\"br\"))*a+\",\"+i(e-u)*a:i(u)*a+\",\"+h(e-l(\"y\",\"bl\"))*a;o=o===\"t\"?h(d-l(\"x\",\"tr\"))*a+\",\"+h(u)*a:o===\"r\"?h(d-u)*a+\",\"+h(e-l(\"y\",\"br\"))*a:o===\"b\"?i(l(\"x\",\"bl\"))*a+\",\"+i(e-u)*a:i(u)*a+\",\"+i(l(\"y\",\"tl\"))*a;return x?(y?\"m\"+o:\"\")+\"l\"+z:(y?\"m\"+z:\"\")+\"l\"+o};b=function(o,u,x,y,z,B){var E=o===\"l\"||o===\"r\",D=v[o],C,F;if(D>0&&r[o]!==\"none\"&&t[o].fa()>0){C=v[E?o:u];u=v[E?u:\no];F=v[E?o:x];x=v[E?x:o];if(r[o]===\"dashed\"||r[o]===\"dotted\"){j.push({path:q(y,C,u,B+45,0,1)+q(y,0,0,B,1,0),fill:t[o]});j.push({path:s(o,D/2,0,1),stroke:r[o],Qb:D,color:t[o]});j.push({path:q(z,F,x,B,0,1)+q(z,0,0,B-45,1,0),fill:t[o]})}else j.push({path:q(y,C,u,B+45,0,1)+s(o,D,0,0)+q(z,F,x,B,0,0)+(r[o]===\"double\"&&D>2?q(z,F-i(F/3),x-i(x/3),B-45,1,0)+s(o,h(D/3*2),1,0)+q(y,C-i(C/3),u-i(u/3),B,1,0)+\"x \"+q(y,i(C/3),i(u/3),B+45,0,1)+s(o,i(D/3),1,0)+q(z,i(F/3),i(x/3),B,0,0):\"\")+q(z,0,0,B-45,1,0)+s(o,0,1,\n0)+q(y,0,0,B,1,0),fill:t[o]})}};b(\"t\",\"l\",\"r\",\"tl\",\"tr\",90);b(\"r\",\"t\",\"b\",\"tr\",\"br\",0);b(\"b\",\"r\",\"l\",\"br\",\"bl\",-90);b(\"l\",\"b\",\"t\",\"bl\",\"tl\",-180)}}return j},m:function(){if(this.ec||!this.g.q.i())this.e.runtimeStyle.borderColor=\"\";f.u.m.call(this)}});f.Tb=f.u.R({N:5,Md:[\"t\",\"tr\",\"r\",\"br\",\"b\",\"bl\",\"l\",\"tl\",\"c\"],Q:function(){return this.g.q.H()},i:function(){return this.g.q.i()},V:function(){this.I();var a=this.g.q.j(),b=this.g.w.j(),c=this.s.o(),d=this.e,e=this.uc;f.p.Rb(a.src,function(g){function j(s,\no,u,x,y){s=e[s].style;var z=Math.max;s.width=z(o,0);s.height=z(u,0);s.left=x;s.top=y}function i(s,o,u){for(var x=0,y=s.length;x<y;x++)e[s[x]].imagedata[o]=u}var h=c.h,k=c.f,n=f.n(\"0\"),m=a.J||(b?b.J:{t:n,r:n,b:n,l:n});n=m.t.a(d);var p=m.r.a(d),r=m.b.a(d);m=m.l.a(d);var t=a.slice,v=t.t.a(d),l=t.r.a(d),q=t.b.a(d);t=t.l.a(d);j(\"tl\",m,n,0,0);j(\"t\",h-m-p,n,m,0);j(\"tr\",p,n,h-p,0);j(\"r\",p,k-n-r,h-p,n);j(\"br\",p,r,h-p,k-r);j(\"b\",h-m-p,r,m,k-r);j(\"bl\",m,r,0,k-r);j(\"l\",m,k-n-r,0,n);j(\"c\",h-m-p,k-n-r,m,n);i([\"tl\",\n\"t\",\"tr\"],\"cropBottom\",(g.f-v)/g.f);i([\"tl\",\"l\",\"bl\"],\"cropRight\",(g.h-t)/g.h);i([\"bl\",\"b\",\"br\"],\"cropTop\",(g.f-q)/g.f);i([\"tr\",\"r\",\"br\"],\"cropLeft\",(g.h-l)/g.h);i([\"l\",\"r\",\"c\"],\"cropTop\",v/g.f);i([\"l\",\"r\",\"c\"],\"cropBottom\",q/g.f);i([\"t\",\"b\",\"c\"],\"cropLeft\",t/g.h);i([\"t\",\"b\",\"c\"],\"cropRight\",l/g.h);e.c.style.display=a.fill?\"\":\"none\"},this)},I:function(){var a=this.parent.za(this.N),b,c,d,e=this.Md,g=e.length;if(!a){a=doc.createElement(\"border-image\");b=a.style;b.position=\"absolute\";this.uc={};for(d=\n0;d<g;d++){c=this.uc[e[d]]=f.p.Za(\"rect\");c.appendChild(f.p.Za(\"imagedata\"));b=c.style;b.behavior=\"url(#default#VML)\";b.position=\"absolute\";b.top=b.left=0;c.imagedata.src=this.g.q.j().src;c.stroked=false;c.filled=false;a.appendChild(c)}this.parent.sb(this.N,a)}return a},Ea:function(){if(this.i()){var a=this.e,b=a.runtimeStyle,c=this.g.q.j().J;b.borderStyle=\"solid\";if(c){b.borderTopWidth=c.t.a(a)+\"px\";b.borderRightWidth=c.r.a(a)+\"px\";b.borderBottomWidth=c.b.a(a)+\"px\";b.borderLeftWidth=c.l.a(a)+\"px\"}this.mc()}},\nm:function(){var a=this.e.runtimeStyle;a.borderStyle=\"\";if(this.ec||!this.g.w.i())a.borderColor=a.borderWidth=\"\";f.u.m.call(this)}});f.Hc=f.u.R({N:1,Ya:\"outset-box-shadow\",Q:function(){var a=this.g;return a.ga.H()||a.G.H()},i:function(){var a=this.g.ga;return a.i()&&a.j().Da[0]},V:function(){function a(C,F,O,H,M,P,I){C=b.Aa(\"shadow\"+C+F,\"fill\",d,j-C);F=C.fill;C.coordsize=n*2+\",\"+m*2;C.coordorigin=\"1,1\";C.stroked=false;C.filled=true;F.color=M.U(c);if(P){F.type=\"gradienttitle\";F.color2=F.color;F.opacity=\n0}C.path=I;l=C.style;l.left=O;l.top=H;l.width=n;l.height=m;return C}var b=this,c=this.e,d=this.I(),e=this.g,g=e.ga.j().Da;e=e.G.j();var j=g.length,i=j,h,k=this.s.o(),n=k.h,m=k.f;k=f.O===8?1:0;for(var p=[\"tl\",\"tr\",\"br\",\"bl\"],r,t,v,l,q,s,o,u,x,y,z,B,E,D;i--;){t=g[i];q=t.fe.a(c);s=t.ge.a(c);h=t.Vd.a(c);o=t.blur.a(c);t=t.color;u=-h-o;if(!e&&o)e=f.jb.Dc;u=this.ya({Jb:u,Ib:u,tb:u,Db:u},2,e);if(o){x=(h+o)*2+n;y=(h+o)*2+m;z=x?o*2/x:0;B=y?o*2/y:0;if(o-h>n/2||o-h>m/2)for(h=4;h--;){r=p[h];E=r.charAt(0)===\"b\";\nD=r.charAt(1)===\"r\";r=a(i,r,q,s,t,o,u);v=r.fill;v.focusposition=(D?1-z:z)+\",\"+(E?1-B:B);v.focussize=\"0,0\";r.style.clip=\"rect(\"+((E?y/2:0)+k)+\"px,\"+(D?x:x/2)+\"px,\"+(E?y:y/2)+\"px,\"+((D?x/2:0)+k)+\"px)\"}else{r=a(i,\"\",q,s,t,o,u);v=r.fill;v.focusposition=z+\",\"+B;v.focussize=1-z*2+\",\"+(1-B*2)}}else{r=a(i,\"\",q,s,t,o,u);q=t.fa();if(q<1)r.fill.opacity=q}}}});f.Pc=f.u.R({N:6,Ya:\"imgEl\",Q:function(){var a=this.g;return this.e.src!==this.Xc||a.G.H()},i:function(){var a=this.g;return a.G.i()||a.C.qc()},V:function(){this.Xc=\nj;this.Cd();var a=this.Aa(\"img\",\"fill\",this.I()),b=a.fill,c=this.s.o(),d=c.h;c=c.f;var e=this.g.w.j(),g=e&&e.J;e=this.e;var j=e.src,i=Math.round,h=e.currentStyle,k=f.n;if(!g||f.O<7){g=f.n(\"0\");g={t:g,r:g,b:g,l:g}}a.stroked=false;b.type=\"frame\";b.src=j;b.position=(d?0.5/d:0)+\",\"+(c?0.5/c:0);a.coordsize=d*2+\",\"+c*2;a.coordorigin=\"1,1\";a.path=this.ya({Jb:i(g.t.a(e)+k(h.paddingTop).a(e)),Ib:i(g.r.a(e)+k(h.paddingRight).a(e)),tb:i(g.b.a(e)+k(h.paddingBottom).a(e)),Db:i(g.l.a(e)+k(h.paddingLeft).a(e))},\n2);a=a.style;a.width=d;a.height=c},Cd:function(){this.e.runtimeStyle.filter=\"alpha(opacity=0)\"},m:function(){f.u.m.call(this);this.e.runtimeStyle.filter=\"\"}});f.Oc=f.u.R({ib:f.aa,Mb:f.aa,Nb:f.aa,Lb:f.aa,Ld:/^,+|,+$/g,Fd:/,+/g,gb:function(a,b){(this.pb||(this.pb=[]))[a]=b||void 0},ab:function(){var a=this.pb,b;if(a&&(b=a.join(\",\").replace(this.Ld,\"\").replace(this.Fd,\",\"))!==this.Wc)this.Wc=this.e.runtimeStyle.background=b},m:function(){this.e.runtimeStyle.background=\"\";delete this.pb}});f.Mc=f.u.R({ua:1,\nQ:function(){return this.g.C.H()},i:function(){var a=this.g;return a.C.i()||a.q.i()},V:function(){var a=this.g.C.j(),b,c,d=0,e,g;if(a){b=[];if(c=a.M)for(;e=c[d++];)if(e.P===\"linear-gradient\"){g=this.vd(e.Wa);g=(e.Xa||f.Ka.Kc).a(this.e,g.h,g.f,g.h,g.f);b.push(\"url(data:image/svg+xml,\"+escape(this.xd(e,g.h,g.f))+\") \"+this.dd(e.$)+\" / \"+g.h+\"px \"+g.f+\"px \"+(e.bc||\"\")+\" \"+(e.Wa||\"\")+\" \"+(e.ub||\"\"))}else b.push(e.Hb);a.color&&b.push(a.color.Y);this.parent.gb(this.ua,b.join(\",\"))}},dd:function(a){return a?\na.X.map(function(b){return b.d}).join(\" \"):\"0 0\"},vd:function(a){var b=this.e,c=this.s.o(),d=c.h;c=c.f;var e;if(a!==\"border-box\")if((e=this.g.w.j())&&(e=e.J)){d-=e.l.a(b)+e.l.a(b);c-=e.t.a(b)+e.b.a(b)}if(a===\"content-box\"){a=f.n;e=b.currentStyle;d-=a(e.paddingLeft).a(b)+a(e.paddingRight).a(b);c-=a(e.paddingTop).a(b)+a(e.paddingBottom).a(b)}return{h:d,f:c}},xd:function(a,b,c){var d=this.e,e=a.ca,g=e.length,j=f.Na.gc(d,b,c,a);a=j.xc;var i=j.yc,h=j.td,k=j.ud;j=j.rc;var n,m,p,r,t;n=[];for(m=0;m<g;m++)n.push(e[m].db?\ne[m].db.a(d,j):m===0?0:m===g-1?j:null);for(m=1;m<g;m++)if(n[m]===null){r=n[m-1];p=m;do t=n[++p];while(t===null);n[m]=r+(t-r)/(p-m+1)}b=['<svg width=\"'+b+'\" height=\"'+c+'\" xmlns=\"http://www.w3.org/2000/svg\"><defs><linearGradient id=\"g\" gradientUnits=\"userSpaceOnUse\" x1=\"'+a/b*100+'%\" y1=\"'+i/c*100+'%\" x2=\"'+h/b*100+'%\" y2=\"'+k/c*100+'%\">'];for(m=0;m<g;m++)b.push('<stop offset=\"'+n[m]/j+'\" stop-color=\"'+e[m].color.U(d)+'\" stop-opacity=\"'+e[m].color.fa()+'\"/>');b.push('</linearGradient></defs><rect width=\"100%\" height=\"100%\" fill=\"url(#g)\"/></svg>');\nreturn b.join(\"\")},m:function(){this.parent.gb(this.ua)}});f.Nc=f.u.R({T:\"repeat\",Sc:\"stretch\",Qc:\"round\",ua:0,Q:function(){return this.g.q.H()},i:function(){return this.g.q.i()},V:function(){var a=this,b=a.g.q.j(),c=a.g.w.j(),d=a.s.o(),e=b.repeat,g=e.f,j=e.Ob,i=a.e,h=0;f.p.Rb(b.src,function(k){function n(Q,R,U,V,W,Y,X,S,w,A){K.push('<pattern patternUnits=\"userSpaceOnUse\" id=\"pattern'+G+'\" x=\"'+(g===l?Q+U/2-w/2:Q)+'\" y=\"'+(j===l?R+V/2-A/2:R)+'\" width=\"'+w+'\" height=\"'+A+'\"><svg width=\"'+w+'\" height=\"'+\nA+'\" viewBox=\"'+W+\" \"+Y+\" \"+X+\" \"+S+'\" preserveAspectRatio=\"none\"><image xlink:href=\"'+v+'\" x=\"0\" y=\"0\" width=\"'+r+'\" height=\"'+t+'\" /></svg></pattern>');J.push('<rect x=\"'+Q+'\" y=\"'+R+'\" width=\"'+U+'\" height=\"'+V+'\" fill=\"url(#pattern'+G+')\" />');G++}var m=d.h,p=d.f,r=k.h,t=k.f,v=a.Dd(b.src,r,t),l=a.T,q=a.Sc;k=a.Qc;var s=Math.ceil,o=f.n(\"0\"),u=b.J||(c?c.J:{t:o,r:o,b:o,l:o});o=u.t.a(i);var x=u.r.a(i),y=u.b.a(i);u=u.l.a(i);var z=b.slice,B=z.t.a(i),E=z.r.a(i),D=z.b.a(i);z=z.l.a(i);var C=m-u-x,F=p-o-\ny,O=r-z-E,H=t-B-D,M=g===q?C:O*o/B,P=j===q?F:H*x/E,I=g===q?C:O*y/D;q=j===q?F:H*u/z;var K=[],J=[],G=0;if(g===k){M-=(M-(C%M||M))/s(C/M);I-=(I-(C%I||I))/s(C/I)}if(j===k){P-=(P-(F%P||P))/s(F/P);q-=(q-(F%q||q))/s(F/q)}k=['<svg width=\"'+m+'\" height=\"'+p+'\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">'];n(0,0,u,o,0,0,z,B,u,o);n(u,0,C,o,z,0,O,B,M,o);n(m-x,0,x,o,r-E,0,E,B,x,o);n(0,o,u,F,0,B,z,H,u,q);if(b.fill)n(u,o,C,F,z,B,O,H,M||I||O,q||P||H);n(m-x,o,x,F,r-E,B,E,H,x,P);n(0,\np-y,u,y,0,t-D,z,D,u,y);n(u,p-y,C,y,z,t-D,O,D,I,y);n(m-x,p-y,x,y,r-E,t-D,E,D,x,y);k.push(\"<defs>\"+K.join(\"\\n\")+\"</defs>\"+J.join(\"\\n\")+\"</svg>\");a.parent.gb(a.ua,\"url(data:image/svg+xml,\"+escape(k.join(\"\"))+\") no-repeat border-box border-box\");h&&a.parent.ab()},a);h=1},Dd:function(){var a={};return function(b,c,d){var e=a[b],g;if(!e){e=new Image;g=doc.createElement(\"canvas\");e.src=b;g.width=c;g.height=d;g.getContext(\"2d\").drawImage(e,0,0);e=a[b]=g.toDataURL()}return e}}(),Ea:f.Tb.prototype.Ea,m:function(){var a=\nthis.e.runtimeStyle;this.parent.gb(this.ua);a.borderColor=a.borderStyle=a.borderWidth=\"\"}});f.kb=function(){function a(l,q){l.className+=\" \"+q}function b(l){var q=v.slice.call(arguments,1),s=q.length;setTimeout(function(){if(l)for(;s--;)a(l,q[s])},0)}function c(l){var q=v.slice.call(arguments,1),s=q.length;setTimeout(function(){if(l)for(;s--;){var o=q[s];o=t[o]||(t[o]=new RegExp(\"\\\\b\"+o+\"\\\\b\",\"g\"));l.className=l.className.replace(o,\"\")}},0)}function d(l){function q(){if(!U){var w,A,L=f.ja,T=l.currentStyle,\nN=T.getAttribute(g)===\"true\",da=T.getAttribute(i)!==\"false\",ea=T.getAttribute(h)!==\"false\";S=T.getAttribute(j);S=L>7?S!==\"false\":S===\"true\";if(!R){R=1;l.runtimeStyle.zoom=1;T=l;for(var fa=1;T=T.previousSibling;)if(T.nodeType===1){fa=0;break}fa&&a(l,p)}J.cb();if(N&&(A=J.o())&&(w=doc.documentElement||doc.body)&&(A.y>w.clientHeight||A.x>w.clientWidth||A.y+A.f<0||A.x+A.h<0)){if(!Y){Y=1;f.mb.ba(q)}}else{U=1;Y=R=0;f.mb.Ha(q);if(L===9){G={C:new f.Sb(l),q:new f.Ub(l),w:new f.Vb(l)};Q=[G.C,G.q];K=new f.Oc(l,\nJ,G);w=[new f.Mc(l,J,G,K),new f.Nc(l,J,G,K)]}else{G={C:new f.Sb(l),w:new f.Vb(l),q:new f.Ub(l),G:new f.jb(l),ga:new f.Ic(l),Pb:new f.Uc(l)};Q=[G.C,G.w,G.q,G.G,G.ga,G.Pb];K=new f.Rc(l,J,G);w=[new f.Hc(l,J,G,K),new f.Fc(l,J,G,K),new f.Gc(l,J,G,K),new f.Tb(l,J,G,K)];l.tagName===\"IMG\"&&w.push(new f.Pc(l,J,G,K));K.ed=w}I=[K].concat(w);if(w=l.currentStyle.getAttribute(f.F+\"watch-ancestors\")){w=parseInt(w,10);A=0;for(N=l.parentNode;N&&(w===\"NaN\"||A++<w);){H(N,\"onpropertychange\",C);H(N,\"onmouseenter\",x);\nH(N,\"onmouseleave\",y);H(N,\"onmousedown\",z);if(N.tagName in f.fc){H(N,\"onfocus\",E);H(N,\"onblur\",D)}N=N.parentNode}}if(S){f.Oa.ba(o);f.Oa.Rd()}o(1)}if(!V){V=1;L<9&&H(l,\"onmove\",s);H(l,\"onresize\",s);H(l,\"onpropertychange\",u);ea&&H(l,\"onmouseenter\",x);if(ea||da)H(l,\"onmouseleave\",y);da&&H(l,\"onmousedown\",z);if(l.tagName in f.fc){H(l,\"onfocus\",E);H(l,\"onblur\",D)}f.Qa.ba(s);f.L.ba(M)}J.hb()}}function s(){J&&J.Ad()&&o()}function o(w){if(!X)if(U){var A,L=I.length;F();for(A=0;A<L;A++)I[A].Ea();if(w||J.Od())for(A=\n0;A<L;A++)I[A].ib();if(w||J.Td())for(A=0;A<L;A++)I[A].Mb();K.ab();O()}else R||q()}function u(){var w,A=I.length,L;w=event;if(!X&&!(w&&w.propertyName in r))if(U){F();for(w=0;w<A;w++)I[w].Ea();for(w=0;w<A;w++){L=I[w];L.Cb||L.ib();L.Q()&&L.Lb()}K.ab();O()}else R||q()}function x(){b(l,k)}function y(){c(l,k,n)}function z(){b(l,n);f.lb.ba(B)}function B(){c(l,n);f.lb.Ha(B)}function E(){b(l,m)}function D(){c(l,m)}function C(){var w=event.propertyName;if(w===\"className\"||w===\"id\")u()}function F(){J.cb();for(var w=\nQ.length;w--;)Q[w].cb()}function O(){for(var w=Q.length;w--;)Q[w].hb();J.hb()}function H(w,A,L){w.attachEvent(A,L);W.push([w,A,L])}function M(){if(V){for(var w=W.length,A;w--;){A=W[w];A[0].detachEvent(A[1],A[2])}f.L.Ha(M);V=0;W=[]}}function P(){if(!X){var w,A;M();X=1;if(I){w=0;for(A=I.length;w<A;w++){I[w].ec=1;I[w].m()}}S&&f.Oa.Ha(o);f.Qa.Ha(o);I=J=G=Q=l=null}}var I,K,J=new ha(l),G,Q,R,U,V,W=[],Y,X,S;this.Ed=q;this.update=o;this.m=P;this.qd=l}var e={},g=f.F+\"lazy-init\",j=f.F+\"poll\",i=f.F+\"track-active\",\nh=f.F+\"track-hover\",k=f.La+\"hover\",n=f.La+\"active\",m=f.La+\"focus\",p=f.La+\"first-child\",r={background:1,bgColor:1,display:1},t={},v=[];d.yd=function(l){var q=f.p.Ba(l);return e[q]||(e[q]=new d(l))};d.m=function(l){l=f.p.Ba(l);var q=e[l];if(q){q.m();delete e[l]}};d.md=function(){var l=[],q;if(e){for(var s in e)if(e.hasOwnProperty(s)){q=e[s];l.push(q.qd);q.m()}e={}}return l};return d}();f.supportsVML=f.zc;f.attach=function(a){f.ja<10&&f.zc&&f.kb.yd(a).Ed()};f.detach=function(a){f.kb.m(a)}};\nvar $=element;function init(){if(doc.media!==\"print\"){var a=window.PIE;a&&a.attach($)}}function cleanup(){if(doc.media!==\"print\"){var a=window.PIE;if(a){a.detach($);$=0}}}$.readyState===\"complete\"&&init();\n</script>\n</PUBLIC:COMPONENT>\n"
  },
  {
    "path": "docs/css/pygments/default.css",
    "content": ".hll { background-color: #ffffcc }\n.c { color: #408080; font-style: italic } /* Comment */\n/* .err { border: 1px solid #FF0000 } Error */\n.err { color: #008000; font-weight: bold } /* Error hack */\n.k { color: #008000; font-weight: bold } /* Keyword */\n.o { color: #666666 } /* Operator */\n.cm { color: #408080; font-style: italic } /* Comment.Multiline */\n.cp { color: #BC7A00 } /* Comment.Preproc */\n.c1 { color: #408080; font-style: italic } /* Comment.Single */\n.cs { color: #408080; font-style: italic } /* Comment.Special */\n.gd { color: #A00000 } /* Generic.Deleted */\n.ge { font-style: italic } /* Generic.Emph */\n.gr { color: #FF0000 } /* Generic.Error */\n.gh { color: #000080; font-weight: bold } /* Generic.Heading */\n.gi { color: #00A000 } /* Generic.Inserted */\n.go { color: #808080 } /* Generic.Output */\n.gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n.gs { font-weight: bold } /* Generic.Strong */\n.gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n.gt { color: #0040D0 } /* Generic.Traceback */\n.kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n.kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n.kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n.kp { color: #008000 } /* Keyword.Pseudo */\n.kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n.kt { color: #B00040 } /* Keyword.Type */\n.m { color: #666666 } /* Literal.Number */\n.s { color: #BA2121 } /* Literal.String */\n.na { color: #7D9029 } /* Name.Attribute */\n.nb { color: #008000 } /* Name.Builtin */\n.nc { color: #0000FF; font-weight: bold } /* Name.Class */\n.no { color: #880000 } /* Name.Constant */\n.nd { color: #AA22FF } /* Name.Decorator */\n.ni { color: #999999; font-weight: bold } /* Name.Entity */\n.ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n.nf { color: #0000FF } /* Name.Function */\n.nl { color: #A0A000 } /* Name.Label */\n.nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n.nt { color: #008000; font-weight: bold } /* Name.Tag */\n.nv { color: #19177C } /* Name.Variable */\n.ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n.w { color: #bbbbbb } /* Text.Whitespace */\n.mf { color: #666666 } /* Literal.Number.Float */\n.mh { color: #666666 } /* Literal.Number.Hex */\n.mi { color: #666666 } /* Literal.Number.Integer */\n.mo { color: #666666 } /* Literal.Number.Oct */\n.sb { color: #BA2121 } /* Literal.String.Backtick */\n.sc { color: #BA2121 } /* Literal.String.Char */\n.sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n.s2 { color: #BA2121 } /* Literal.String.Double */\n.se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n.sh { color: #BA2121 } /* Literal.String.Heredoc */\n.si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n.sx { color: #008000 } /* Literal.String.Other */\n.sr { color: #BB6688 } /* Literal.String.Regex */\n.s1 { color: #BA2121 } /* Literal.String.Single */\n.ss { color: #19177C } /* Literal.String.Symbol */\n.bp { color: #008000 } /* Name.Builtin.Pseudo */\n.vc { color: #19177C } /* Name.Variable.Class */\n.vg { color: #19177C } /* Name.Variable.Global */\n.vi { color: #19177C } /* Name.Variable.Instance */\n.il { color: #666666 } /* Literal.Number.Integer.Long */\n"
  },
  {
    "path": "docs/css/pygments/github.css",
    "content": "/*\n * GitHub style for Pygments\n * Courtesy of GitHub.com\n */\n\n.hll { background-color: #f3f3f3; border: 1px solid #ccc; padding: 6px 10px; border-radius: 3px; }\n.c { color: #999988; font-style: italic; }\n.err { color: #a61717; background-color: #e3d2d2; }\n.k { font-weight: bold; }\n.o { font-weight: bold; }\n.cm { color: #999988; font-style: italic; }\n.cp { color: #999999; font-weight: bold; }\n.c1 { color: #999988; font-style: italic; }\n.cs { color: #999999; font-weight: bold; font-style: italic; }\n.gd { color: #000000; background-color: #ffdddd; }\n.gd .x { color: #000000; background-color: #ffaaaa; }\n.ge { font-style: italic; }\n.gr { color: #aa0000; }\n.gh { color: #999999; }\n.gi { color: #000000; background-color: #ddffdd; }\n.gi .x { color: #000000; background-color: #aaffaa; }\n.go { color: #888888; }\n.gp { color: #555555; }\n.gs { font-weight: bold; }\n.gu { color: #800080; font-weight: bold; }\n.gt { color: #aa0000; }\n.kc { font-weight: bold; }\n.kd { font-weight: bold; }\n.kn { font-weight: bold; }\n.kp { font-weight: bold; }\n.kr { font-weight: bold; }\n.kt { color: #445588; font-weight: bold; }\n.m { color: #009999; }\n.s { color: #dd1144; }\n.n { color: #333333; }\n.na { color: teal; }\n.nb { color: #0086b3; }\n.nc { color: #445588; font-weight: bold; }\n.no { color: teal; }\n.ni { color: purple; }\n.ne { color: #990000; font-weight: bold; }\n.nf { color: #990000; font-weight: bold; }\n.nn { color: #555555; }\n.nt { color: navy; }\n.nv { color: teal; }\n.ow { font-weight: bold; }\n.w { color: #bbbbbb; }\n.mf { color: #009999; }\n.mh { color: #009999; }\n.mi { color: #009999; }\n.mo { color: #009999; }\n.sb { color: #dd1144; }\n.sc { color: #dd1144; }\n.sd { color: #dd1144; }\n.s2 { color: #dd1144; }\n.se { color: #dd1144; }\n.sh { color: #dd1144; }\n.si { color: #dd1144; }\n.sx { color: #dd1144; }\n.sr { color: #009926; }\n.s1 { color: #dd1144; }\n.ss { color: #990073; }\n.bp { color: #999999; }\n.vc { color: teal; }\n.vg { color: teal; }\n.vi { color: teal; }\n.il { color: #009999; }\n.gc { color: #999; background-color: #EAF2F5; }\n"
  },
  {
    "path": "docs/css/pygments/jekyll-github.css",
    "content": "/*\n * GitHub style for Pygments syntax highlighter, for use with Jekyll\n * Courtesy of GitHub.com\n */\n\n\n.highlight pre, pre, .highlight .hll { \n\tbackground-color: #f3f3f3; \n\tborder: 1px solid #ccc; \n\tpadding: 6px 10px; \n\tborder-radius: 3px; \n}\n\n.highlight .c { color: #999988; font-style: italic; }\n.highlight .err { color: #a61717; background-color: #e3d2d2; }\n.highlight .k { font-weight: bold; }\n.highlight .o { font-weight: bold; }\n.highlight .cm { color: #999988; font-style: italic; }\n.highlight .cp { color: #999999; font-weight: bold; }\n.highlight .c1 { color: #999988; font-style: italic; }\n.highlight .cs { color: #999999; font-weight: bold; font-style: italic; }\n.highlight .gd { color: #000000; background-color: #ffdddd; }\n.highlight .gd .x { color: #000000; background-color: #ffaaaa; }\n.highlight .ge { font-style: italic; }\n.highlight .gr { color: #aa0000; }\n.highlight .gh { color: #999999; }\n.highlight .gi { color: #000000; background-color: #ddffdd; }\n.highlight .gi .x { color: #000000; background-color: #aaffaa; }\n.highlight .go { color: #888888; }\n.highlight .gp { color: #555555; }\n.highlight .gs { font-weight: bold; }\n.highlight .gu { color: #800080; font-weight: bold; }\n.highlight .gt { color: #aa0000; }\n.highlight .kc { font-weight: bold; }\n.highlight .kd { font-weight: bold; }\n.highlight .kn { font-weight: bold; }\n.highlight .kp { font-weight: bold; }\n.highlight .kr { font-weight: bold; }\n.highlight .kt { color: #445588; font-weight: bold; }\n.highlight .m { color: #009999; }\n.highlight .s { color: #dd1144; }\n.highlight .n { color: #333333; }\n.highlight .na { color: teal; }\n.highlight .nb { color: #0086b3; }\n.highlight .nc { color: #445588; font-weight: bold; }\n.highlight .no { color: teal; }\n.highlight .ni { color: purple; }\n.highlight .ne { color: #990000; font-weight: bold; }\n.highlight .nf { color: #990000; font-weight: bold; }\n.highlight .nn { color: #555555; }\n.highlight .nt { color: navy; }\n.highlight .nv { color: teal; }\n.highlight .ow { font-weight: bold; }\n.highlight .w { color: #bbbbbb; }\n.highlight .mf { color: #009999; }\n.highlight .mh { color: #009999; }\n.highlight .mi { color: #009999; }\n.highlight .mo { color: #009999; }\n.highlight .sb { color: #dd1144; }\n.highlight .sc { color: #dd1144; }\n.highlight .sd { color: #dd1144; }\n.highlight .s2 { color: #dd1144; }\n.highlight .se { color: #dd1144; }\n.highlight .sh { color: #dd1144; }\n.highlight .si { color: #dd1144; }\n.highlight .sx { color: #dd1144; }\n.highlight .sr { color: #009926; }\n.highlight .s1 { color: #dd1144; }\n.highlight .ss { color: #990073; }\n.highlight .bp { color: #999999; }\n.highlight .vc { color: teal; }\n.highlight .vg { color: teal; }\n.highlight .vi { color: teal; }\n.highlight .il { color: #009999; }\n.highlight .gc { color: #999; background-color: #EAF2F5; }\n"
  },
  {
    "path": "docs/css/pygments/linenos.css",
    "content": ".highlight pre {\n  font-family: \"Inconsolata\", Monaco, Courier, monospace;\n  font-size: .65em;\n  border: 1px solid #efefef;\n  border-left: 2em solid #efefef;\n  position: relative;\n  margin: 1em 0;\n}\n.highlight pre code {\n  counter-reset: linenumbers;\n  position: relative;\n  overflow: auto;\n}\n\n.highlight pre code > span:before {\n  font-size: .9em;\n  color: #aaa;\n  content: counter(linenumbers);\n  counter-increment: linenumbers;\n  left: -5.5ex;\n  position: absolute;\n  text-align: right;\n  width: 3.5ex;\n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -khtml-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n"
  },
  {
    "path": "docs/css/screen.css",
    "content": "/*\r\n * Parallel Universe Styles\r\n * \r\n */\r\n\r\n/* ==========================================================================\r\n   Base styles and resets\r\n   ========================================================================== */\r\n\r\nhtml{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,strong,th,var{font-style:normal;font-weight:normal;}em{font-style:italic;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}\r\nhtml{-webkit-text-size-adjust: none;}\r\nstrong{ font-weight:bold;}\r\nimg{ vertical-align:top;}\r\n.cl{ clear:both; font-size:0;}\r\n\r\narticle, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; }\r\naudio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }\r\naudio:not([controls]) { display: none; }\r\n[hidden] { display: none; }\r\n\r\nhtml { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }\r\nhtml, button, input, select, textarea { font-family: sans-serif; color: #222; }\r\nbody { margin: 0; font-size: 1em; line-height: 1.4; }\r\n\r\na { color: #00e; }\r\na:hover { color: #06e; }\r\na:focus { outline: thin dotted; }\r\na:hover, a:active { outline: 0; }\r\nabbr[title] { border-bottom: 1px dotted; }\r\nb, strong { font-weight: bold; }\r\nblockquote { margin: 1em 40px; }\r\ndfn { font-style: italic; }\r\nhr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }\r\nins { background: #ff9; color: #000; text-decoration: none; }\r\nmark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }\r\n\r\nq { quotes: none; }\r\nq:before, q:after { content: \"\"; content: none; }\r\nsmall { font-size: 85%; }\r\nsub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }\r\nsup { top: -0.5em; }\r\nsub { bottom: -0.25em; }\r\n\r\nul, ol { margin: 0; padding: 0; }\r\nli { list-style:none; margin:0; padding:0; }\r\ndd { margin: 0 0 0 40px; }\r\nnav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }\r\n\r\nimg { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }\r\nsvg:not(:root) { overflow: hidden; }\r\nfigure { margin: 0; }\r\n\r\nform { margin: 0; }\r\nfieldset { border: 0; margin: 0; padding: 0; }\r\n\r\nlabel { cursor: pointer; }\r\nlegend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; }\r\nbutton, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }\r\nbutton, input { line-height: normal; }\r\nbutton, input[type=\"button\"], input[type=\"reset\"], input[type=\"submit\"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; }\r\nbutton[disabled], input[disabled] { cursor: default; }\r\ninput[type=\"checkbox\"], input[type=\"radio\"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; }\r\ninput[type=\"search\"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }\r\ninput[type=\"search\"]::-webkit-search-decoration, input[type=\"search\"]::-webkit-search-cancel-button { -webkit-appearance: none; }\r\nbutton::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }\r\ntextarea { overflow: auto; vertical-align: top; resize: vertical; }\r\ninput:valid, textarea:valid {  }\r\ninput:invalid, textarea:invalid { background-color: #f0dddd; }\r\n\r\ntable { border-collapse: collapse; border-spacing: 0; }\r\ntd { vertical-align: top; }\r\n\r\n.chromeframe { margin: 0.2em 0; background: #ccc; color: black; padding: 0.2em 0; }\r\n\r\n.clearfix:before, .clearfix:after { content: \"\"; display: table; }\r\n.clearfix:after { clear: both; }\r\n.clearfix { *zoom: 1; }\r\n\r\ncode, pre {\r\n  font-family: \"Source Code Pro\",Monaco,Menlo,Consolas,\"Courier New\",monospace;\r\n}\r\n\r\n.highlight pre {\r\n  font-family: \"Inconsolata\", Monaco, Courier, monospace;\r\n  font-size: .65em;\r\n  border: 1px solid #efefef;\r\n  border-left: 2em solid #efefef;\r\n  position: relative;\r\n  margin: 1em 0;\r\n}\r\n.highlight pre code {\r\n  counter-reset: linenumbers;\r\n  position: relative;\r\n  overflow: auto;\r\n}\r\n\r\n.highlight pre code > span:before {\r\n  font-size: .9em;\r\n  color: #aaa;\r\n  content: counter(linenumbers);\r\n  counter-increment: linenumbers;\r\n  left: -5.5ex;\r\n  position: absolute;\r\n  text-align: right;\r\n  width: 3.5ex;\r\n  -webkit-touch-callout: none;\r\n  -webkit-user-select: none;\r\n  -khtml-user-select: none;\r\n  -moz-user-select: none;\r\n  -ms-user-select: none;\r\n  user-select: none;\r\n}\r\n\r\n/*\r\n * GitHub style for Pygments syntax highlighter, for use with Jekyll\r\n * Courtesy of GitHub.com\r\n */\r\n\r\n\r\n.highlight pre, pre, .highlight .hll { \r\n\tbackground-color: #f3f3f3; \r\n\tborder: 1px solid #ccc; \r\n\tpadding: 6px 10px; \r\n\tborder-radius: 3px; \r\n}\r\n\r\n.highlight .c { color: #999988; font-style: italic; }\r\n.highlight .err { color: #a61717; background-color: #e3d2d2; }\r\n.highlight .k { font-weight: bold; }\r\n.highlight .o { font-weight: bold; }\r\n.highlight .cm { color: #999988; font-style: italic; }\r\n.highlight .cp { color: #999999; font-weight: bold; }\r\n.highlight .c1 { color: #999988; font-style: italic; }\r\n.highlight .cs { color: #999999; font-weight: bold; font-style: italic; }\r\n.highlight .gd { color: #000000; background-color: #ffdddd; }\r\n.highlight .gd .x { color: #000000; background-color: #ffaaaa; }\r\n.highlight .ge { font-style: italic; }\r\n.highlight .gr { color: #aa0000; }\r\n.highlight .gh { color: #999999; }\r\n.highlight .gi { color: #000000; background-color: #ddffdd; }\r\n.highlight .gi .x { color: #000000; background-color: #aaffaa; }\r\n.highlight .go { color: #888888; }\r\n.highlight .gp { color: #555555; }\r\n.highlight .gs { font-weight: bold; }\r\n.highlight .gu { color: #800080; font-weight: bold; }\r\n.highlight .gt { color: #aa0000; }\r\n.highlight .kc { font-weight: bold; }\r\n.highlight .kd { font-weight: bold; }\r\n.highlight .kn { font-weight: bold; }\r\n.highlight .kp { font-weight: bold; }\r\n.highlight .kr { font-weight: bold; }\r\n.highlight .kt { color: #445588; font-weight: bold; }\r\n.highlight .m { color: #009999; }\r\n.highlight .s { color: #dd1144; }\r\n.highlight .n { color: #333333; }\r\n.highlight .na { color: teal; }\r\n.highlight .nb { color: #0086b3; }\r\n.highlight .nc { color: #445588; font-weight: bold; }\r\n.highlight .no { color: teal; }\r\n.highlight .ni { color: purple; }\r\n.highlight .ne { color: #990000; font-weight: bold; }\r\n.highlight .nf { color: #990000; font-weight: bold; }\r\n.highlight .nn { color: #555555; }\r\n.highlight .nt { color: navy; }\r\n.highlight .nv { color: teal; }\r\n.highlight .ow { font-weight: bold; }\r\n.highlight .w { color: #bbbbbb; }\r\n.highlight .mf { color: #009999; }\r\n.highlight .mh { color: #009999; }\r\n.highlight .mi { color: #009999; }\r\n.highlight .mo { color: #009999; }\r\n.highlight .sb { color: #dd1144; }\r\n.highlight .sc { color: #dd1144; }\r\n.highlight .sd { color: #dd1144; }\r\n.highlight .s2 { color: #dd1144; }\r\n.highlight .se { color: #dd1144; }\r\n.highlight .sh { color: #dd1144; }\r\n.highlight .si { color: #dd1144; }\r\n.highlight .sx { color: #dd1144; }\r\n.highlight .sr { color: #009926; }\r\n.highlight .s1 { color: #dd1144; }\r\n.highlight .ss { color: #990073; }\r\n.highlight .bp { color: #999999; }\r\n.highlight .vc { color: teal; }\r\n.highlight .vg { color: teal; }\r\n.highlight .vi { color: teal; }\r\n.highlight .il { color: #009999; }\r\n.highlight .gc { color: #999; background-color: #EAF2F5; }\r\n\r\ncode,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,\"Courier New\",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}\r\ncode{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;white-space:nowrap;}\r\npre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}pre.prettyprint{margin-bottom:20px;}\r\npre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0;}\r\n.pre-scrollable{max-height:340px;overflow-y:scroll;}\r\n.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#ffffff;vertical-align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#999999;}\r\n.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}\r\n.badge{padding-left:9px;padding-right:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px;}\r\n.label:empty,.badge:empty{display:none;}\r\na.label:hover,a.badge:hover{color:#ffffff;text-decoration:none;cursor:pointer;}\r\n.label-important,.badge-important{background-color:#b94a48;}\r\n.label-important[href],.badge-important[href]{background-color:#953b39;}\r\n.label-warning,.badge-warning{background-color:#f89406;}\r\n.label-warning[href],.badge-warning[href]{background-color:#c67605;}\r\n.label-success,.badge-success{background-color:#468847;}\r\n.label-success[href],.badge-success[href]{background-color:#356635;}\r\n.label-info,.badge-info{background-color:#3a87ad;}\r\n.label-info[href],.badge-info[href]{background-color:#2d6987;}\r\n.label-inverse,.badge-inverse{background-color:#333333;}\r\n.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a;}\r\n.btn .label,.btn .badge{position:relative;top:-1px;}\r\n.btn-mini .label,.btn-mini .badge{top:0;}\r\n\r\n/* ==========================================================================\r\n   General styles\r\n   ========================================================================== */\r\nhtml { background:#fff; }\r\nbody { font-family:Arimo, Arial, Helvetica, sans-serif; color:#fff; font-weight:400; font-size:14px; padding-top:90px; }\r\n\r\n.container { width:1000px; margin:0 auto; position:relative; }\r\n.container:before, .container:after { content: \"\"; display: table; }\r\n.container:after { clear: both; }\r\n.container { *zoom: 1; }\r\n\r\na { text-decoration:none; outline:none!important; }\r\n\ta:hover { color:#4b4b4c; }\r\n\r\n* {\r\n  -webkit-box-sizing: border-box;\r\n     -moz-box-sizing: border-box;\r\n          box-sizing: border-box;\r\n}\r\n\r\n@font-face {\r\n\tfont-family: 'FairpNarMedIta';\r\n\tsrc: url('fonts/FairpNarMedIta.eot');\r\n\tsrc: local('☺'), url('fonts/FairpNarMedIta.woff') format('woff'), url('fonts/FairpNarMedIta.ttf') format('truetype'), url('fonts/FairpNarMedIta.svg') format('svg');\r\n\tfont-weight: normal;\r\n\tfont-style: normal;\r\n}\r\n\r\n/* ==========================================================================\r\n   Header\r\n   ========================================================================== */\r\nheader { background:#f1eff2; width:100%; height:90px; position:fixed; top:0; left:0; z-index:100; -webkit-transition: height 200ms ease; \r\n\t-moz-transition: height 200ms ease;-ms-transition: height 200ms ease;-o-transition: height 200ms ease;transition: height 200ms ease; }\r\n\t.fixed-head header { height:55px; }\r\n\t#logo { display:block; overflow:hidden; text-indent:-99999px; width:265px; height:54px; background:url(../images/logo.png); float:left; margin-top:21px; background-size:cover;\r\n\t -webkit-transition: all 300ms ease; -moz-transition: all 300ms ease;-ms-transition: all 300ms ease;-o-transition: all 300ms ease;transition: all 300ms ease; }\r\n\t\t.fixed-head #logo { width:197px; height:40px; margin-top:8px; background-repeat:no-repeat; }\r\n\theader ul { float:right; margin-top:44px; }\r\n\t\t.fixed-head header ul { margin-top:17px; }\r\n\t\theader li { display:block; margin-left:20px; position:relative; float:left; }\r\n\t\t\t/*header li.sub:after { position:absolute; width:100%; height:5px; content:\".\"; overflow:hidden; text-indent:-999999px;\r\n\t\t\tbackground:url(../images/arrow.png) center center no-repeat; bottom:-6px; left:0; }\r\n\t\t\t\theader li.sub:hover :after{ opacity:1; }*/\r\n\t\t\theader li a { font-size:14px; color:#4b4b4c; }\r\n\t\t\t\theader li a:hover { color:#5e5e5e; }\r\n\t\t\t#nav ul { position:absolute; top:2px; left:-1px; width:160px; background:#f0f0f0; border:1px solid #1e5b7d; z-index:1000; }\r\n\t\t\t\t.fixed-head #nav ul { top:21px; }\r\n\t\t\t\t#nav ul:before { position:absolute; width:8px; height:5px; content:\".\"; overflow:hidden; text-indent:-999999px;\r\n\t\t\t\tbackground:url(../images/arrow.png) center center no-repeat; top:-17px; left:26px; }\r\n\t\t\t\t.fixed-head #nav ul:before { top:-12px; }\r\n\t\t\t\t#nav ul li { border-bottom:1px solid #d5d5d5; line-height:36px; display:block; margin:0; float:none; }\r\n\t\t\t\t\t#nav ul li a { display:block; padding-left:9px; border-bottom:1px solid #f0f0f0; font-size:14px; color:#393939;\r\n\t\t\t\t\t -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease; -o-transition: all 400ms ease;\r\n\t\t\t\t\t transition: all 400ms ease; }\r\n\t\t\t\t\t#nav ul li.li1 a:hover { background:#805875; color:#fff; border-bottom:1px solid #1e5b7d; }\r\n\t\t\t\t\t#nav ul li.li2 a:hover { background:#49beb0; color:#fff; border-bottom:1px solid #1e5b7d; }\r\n\t\t\t\t\t#nav ul li.li3 a:hover { background:#393939; color:#fff; border-bottom:1px solid #1e5b7d; }\r\n\t\t\t\t\t#nav ul li.li4 a:hover { background:#f4f4f4; color:#393939; border-bottom:1px solid #f0f0f0; }\r\n\r\n\r\n/* ==========================================================================\r\n   Homepage\r\n   ========================================================================== */\r\n#section1 { height:4300px; background:url(../images/bg-orange.png) top left repeat; overflow:hidden; }   \r\n\t.mobile #section1, .mobile #section1 .container { height:730px; }\r\n\t#section1 .container { height:4300px; }\r\n\t.wrapit { height:670px; width:1000px; position:absolute; bottom:45px; left:0; }\r\n\t.fixed .wrapit { position:fixed; top:90px; left:50%; margin-left:-500px; }\r\n\t.noscroll.fixed .wrapit { position:absolute; bottom:45px; left:0; margin-left:0; top:auto; }\r\n\t\r\n\t#intro-wrapper { width:100%; height:100%; position:relative; overflow:hidden; }\r\n\t\t.reverse-scroll #intro-wrapper { display:none; }\r\n\t#intro { width:100%; height:320px; position:absolute; top:255px; text-align:center; z-index:2; }\r\n\t\t#intro h1 { display:inline-block; border-bottom:1px solid rgba(255,255,255,0.2); line-height:1em; padding-bottom:10px;\r\n\t\tfont-size:60px; color:#fff; margin-bottom:15px; font-family: \"mic-32-new-web-n5\",\"mic-32-new-web\",sans-serif;\r\n\t\tfont-style: normal; font-weight: 500; }\r\n\t\t#intro p { font-weight:bold; font-size:18px; line-height:1em; margin-bottom:75px; }\r\n\t\t#intro div { display:inline-block; font-size:18px; color:#ec9057; padding-bottom:110px;\r\n\t\tbackground:url(../images/indicator.png) bottom center no-repeat; }\r\n\t\t\t#intro div.arrows { width:25px; height:25px; position:absolute; bottom:0; left:50%; margin-left:-12px; background:none; padding:0; }\r\n\t\t\t\t#intro div.arrows span { display:block; width:25px; height:15px; overflow:hidden; text-indent:-999999px; background:url(../images/arrow5.png);\r\n\t\t\t\tposition:absolute; top:0; left:0;  }\r\n\t\t\t\t\t#intro div.arrows span.arrow1 { -webkit-animation: arrowanim 1.9s ease; -webkit-animation-iteration-count: infinite;\r\n\t\t\t\t\t-moz-animation: arrowanim 1.9s ease; -moz-animation-iteration-count: infinite; }\r\n\t\t\t\t\t#intro div.arrows span.arrow2 { top:11px; -webkit-animation: arrowanim 1.9s .3s ease; -webkit-animation-iteration-count: infinite;\r\n\t\t\t\t\t-moz-animation: arrowanim 1.9s .3s ease; -moz-animation-iteration-count: infinite; }\r\n\t\t\t\t\t\r\n\t\t\t\t\t@-webkit-keyframes arrowanim {\r\n\t\t\t\t\t  0% { margin-top:0; }\r\n\t\t\t\t\t  25% { opacity:1; }\r\n\t\t\t\t\t  50% { opacity:0; margin-top:3px; }\r\n\t\t\t\t\t  100% { opacity:1; margin:0; }\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t@-moz-keyframes arrowanim {\r\n\t\t\t\t\t  0% { margin-top:0; }\r\n\t\t\t\t\t  25% { opacity:1; }\r\n\t\t\t\t\t  50% { opacity:0; margin-top:3px; }\r\n\t\t\t\t\t  100% { opacity:1; margin:0; }\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t@-o-keyframes arrowanim {\r\n\t\t\t\t\t  0% { margin-top:0; }\r\n\t\t\t\t\t  25% { opacity:1; }\r\n\t\t\t\t\t  50% { opacity:0; margin-top:3px; }\r\n\t\t\t\t\t  100% { opacity:1; margin:0; }\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t@keyframes arrowanim {\r\n\t\t\t\t\t  0% { margin-top:0; }\r\n\t\t\t\t\t  25% { opacity:1; }\r\n\t\t\t\t\t  50% { opacity:0; margin-top:3px; }\r\n\t\t\t\t\t  100% { opacity:1; margin:0; }\r\n\t\t\t\t\t}\r\n\t\r\n\t#engine { width:595px; height:588px; position:absolute; right:0; top:35px; z-index:1; }\r\n\t\t.part { position:absolute; top:0; right:0; }\r\n\t\t\t#part1 { background:url(../images/part1.png) no-repeat; width:581px; height:618px; top:-680px; /*right:5px;*/ right:-680px; padding-bottom:34px; }\r\n\t\t\t\t.reverse-scroll #part1 { top:0; right:5px; }\r\n\t\t\t\t#part1 .shadow-bottom { width:374px; height:29px; background:url(../images/shadow.png); position:absolute; bottom:0; left:50%;\r\n\t\t\t\tmargin-left:-187px; z-index:5; }\r\n\t\t\t\t#part11 { width:509px; height:572px; position:absolute; top:12px; left:0; z-index:10; background:url(../images/part11.png); }\r\n\t\t\t\t\t#part11 .shadow { width:323px; height:292px; background:url(../images/shadow1.png); position:absolute; top:104px; left:184px; }\r\n\t\t\t\t\t\r\n\t\t\t#part2 { background:url(../images/part2.png); width:594px; height:575px; /*top:17px;*/ right:8px; top:-680px; }\r\n\t\t\t\t.reverse-scroll #part2 { top:17px; }\r\n\t\t\t\t#part21 { width:515px; height:517px; position:absolute; top:6px; left:67px; z-index:5; background:url(../images/part21.png); }\r\n\t\t\t\t\r\n\t\t\t#part3 { background:url(../images/part3.png); width:370px; height:362px; /*top:23px;*/ right:8px; top:-600px; }\r\n\t\t\t\t.reverse-scroll #part3 { top:23px; }\r\n\t\t\t\t#part31 { width:368px; height:362px; position:absolute; top:0; left:0; z-index:4; background:url(../images/part31.png); }\r\n\t\t\t\t\t#part3 .shadow { width:175px; height:166px; background:url(../images/shadow3.png); position:absolute; top:36px; right:19px; z-index:3; }\r\n\t\t\t\t\r\n\t\t\t#part4 { background:url(../images/part4.png); z-index:2; width:271px; height:265px; /*top:20px;*/ right:0; top:-600px; }\r\n\t\t\t\t.reverse-scroll #part4 { top:20px; }\r\n\t\t\t\t\r\n\t#bg-help { width:284px; height:292px; position:absolute; bottom:-4px; left:-20px; background:url(../images/bg-orange.png) top left repeat; z-index:4;\r\n\t-webkit-border-radius: 18px; border-radius: 18px;  }\r\n\t\t.reverse-scroll #bg-help { bottom:-4px; left:-20px; }\r\n \t#banner-title { width:630px; position:absolute; bottom:125px; left:0; z-index:10; display:none; }\r\n\t\t.noscroll #banner-title { display:block; }\r\n\t\t#banner-title h1 { width:100%; line-height:1em; color:#fff; font-size:60px; padding-bottom:10px; margin-bottom:15px;\r\n\t\tborder-bottom:1px solid rgba(255,255,255,0.2); font-family: \"mic-32-new-web-n5\",\"mic-32-new-web\",sans-serif;\r\n\t\tfont-style: normal; font-weight: 500; }\r\n\t\t#banner-title p { font-weight:bold; text-align:right; font-size:18px; }\r\n\t\r\n\t.intro-title { top:275px; left:160px; position:absolute; z-index:3; width:369px; opacity:0; }\r\n\t.intro-title p { font-size:17px; color:#fff; line-height:1em; padding-top:2px; }\r\n\t.intro-title img { display:block; }\r\n\t#title2 { width:579px; top:340px; }\r\n\t#title3 { width:819px; left:0; top:220px; }\t\r\n\t#title4 { width:381px; left:auto; right:0; top:120px; }\t\r\n\t\t#title4 p { text-align:right; }\r\n\t\r\n\t#section1 .scroll-to-arrow { position:absolute; bottom:0; left:50%; margin-left:-13px; opacity:0; }\r\n\t\t.reverse-scroll #section1 .scroll-to-arrow { opacity:1; }\r\n\t\t\r\n \r\n/* Section2 */   \r\n#section2 { background:url(../images/bg.png); padding-top:50px; }\r\n\t.scroll-to-arrow { width:27px; height:17px; background:url(../images/arrow2.png); display:block; margin:0 auto; position:relative; }\r\n\t\t.scroll-to-arrow span { width:100%; height:100%; position:absolute; top:0; left:0; background:url(../images/arrow2.png) 0 -18px; display:block; overflow:hidden; text-indent:-99999px;\r\n\t\topacity:0; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease; -o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t.scroll-to-arrow:hover span { opacity:1; }\r\n\t.big-icon { width:131px; height:131px; background:url(../images/icon.png); margin:15px auto 50px; position:relative; }\r\n\t\t.big-icon span { width:100%; height:100%; position:absolute; top:0; left:0; background:url(../images/icon_hover.png); display:block; overflow:hidden; text-indent:-99999px;\r\n\t\topacity:0; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease; -o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t.big-icon:hover span { opacity:1; }\r\n\t#intro-text { text-align:center; width:750px; margin:0 auto; }\r\n\t\t#intro-text p { font-size:15px; color:#707070; line-height:1.6em; }\r\n\t\t#intro-text h2 { font-size:40px; color:#4b4b4c; line-height:1.1em; margin:50px 0 45px; font-family: \"mic-32-new-web-n5\",\"mic-32-new-web\",sans-serif;\r\n\t\tfont-style: normal; font-weight: 500;}\r\n\t#tabs-btns { width:485px; margin:50px auto 0; position:relative; z-index:2; }\r\n\t\t#tabs-btns li { display:block; float:left; border-top:1px solid #b0b0b0; border-bottom:1px solid #434343; }\r\n\t\t\t#tabs-btns li.li1 a { border-left:1px solid #b0b0b0; }\r\n\t\t\t#tabs-btns a { display:block; line-height:39px; width:120px; text-align:center; font-size:16px; font-weight:bold; color:#434343;\r\n\t\t\tborder-right:1px solid #b0b0b0; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t\t\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t#tabs-btns li.li1 a:hover { background:#6e5971; color:#fff; }\r\n\t\t\t#tabs-btns li.li2 a:hover { background:#66a682; color:#fff; }\r\n\t\t\t#tabs-btns li.li3 a:hover { background:#3e3e3e; color:#fff; }\r\n\t\t\t#tabs-btns li.li4 a:hover { background:#e7e7e7; color:#434343; }\r\n\t\t\t#tabs-btns li.li1.active { border-bottom:1px solid #6e5971; }\r\n\t\t\t\t#tabs-btns li.li1.active a { background:#6e5971; color:#fff; }\r\n\t\t\t#tabs-btns li.li2.active { border-bottom:1px solid #66a682; }\r\n\t\t\t\t#tabs-btns li.li2.active a { background:#66a682; color:#fff; }\r\n\t\t\t#tabs-btns li.li3.active { border-bottom:1px solid #3e3e3e; }\r\n\t\t\t\t#tabs-btns li.li3.active a { background:#3e3e3e; color:#fff; }\r\n\t\t\t#tabs-btns li.li4.active { border-bottom:1px solid #e7e7e7; }\r\n\t\t\t\t#tabs-btns li.li4.active a { background:#e7e7e7; }\r\n\t#tabs-wrapper { border-bottom:1px solid #434343; border-top:1px solid #434343; position:relative; top:-1px; }\r\n\t.tab-cont { padding:40px 0; display:none; }\r\n\t\t.tab-cont h2 { color:#fff; display:block; font-size:60px; letter-spacing:-1px; margin-bottom:30px; line-height:1em;\r\n\t\tfont-family:\"FairpNarMedIta\"; }\r\n\t\t.tab-cont p { text-align:justify; width:620px; float:left; }\r\n\t\t.tab-cont .btn { display:block; float:right; width:296px; height:53px; line-height:53px; border:1px solid #fff; background:url(../images/arrow3.png) 265px center no-repeat;\r\n\t\tpadding-left:25px; font-size:14px; color:#fff; -webkit-transition: all 400ms ease;\r\n\t\t-moz-transition: all 400ms ease; -ms-transition: all 400ms ease; -o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t.tab-cont .btn:hover { background:rgba(255,255,255,0.2) url(../images/arrow3.png) 265px center no-repeat; }\r\n\t\t#tab4 h2, #tab4 p { color:#3e3e3e; }\r\n\t\t#tab4 .btn { border:1px solid #3e3e3e; background:url(../images/arrow4.png) 265px center no-repeat; color:#3e3e3e; }\r\n\t#tab1 { background:#6e5971; }\r\n\t#tab2 { background:#66a682; }\r\n\t#tab3 { background:#3e3e3e; }\r\n\t#tab4 { background:#e7e7e7; }\r\n\r\n/* Section3 */\r\n#section3 { padding:80px 0 40px; }\r\n\t#blog { width:620px; float:left; }\r\n\t\t#blog h3 { font-size:21px; color:#4b4b4c; line-height:1em; padding-bottom:18px; border-bottom:1px solid #d4d4d4; margin-bottom:20px;\r\n\t\t font-family: \"mic-32-new-web-n5\",\"mic-32-new-web\",sans-serif; font-style: normal; font-weight: 500; }\r\n\t\t.post { margin-bottom:20px; overflow:hidden; }\r\n\t\t\t.post h4 { font-size:16px; font-weight:bold; color:#545455; line-height:1em; margin-bottom:20px; }\r\n\t\t\t.post p { font-size:15px; color:#707070; margin-bottom:15px; }\r\n\t\t\t.post .more { float:right; display:block; border:1px solid #4c4c4d; width:95px; height:32px; text-align:center; font-weight:bold; color:#4b4b4c; font-size:12px;\r\n\t\t\tline-height:30px; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t\t\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t\t.post .more:hover { background:#eaeaea; }\r\n\t#sidebar { width:296px; float:right; }\r\n\t\t#sidebar h3 { font-size:21px; color:#4b4b4c; line-height:1em; padding-bottom:18px; border-bottom:1px solid #d4d4d4; margin-bottom:20px;\r\n\t\tfont-family: \"mic-32-new-web-n5\",\"mic-32-new-web\",sans-serif; font-style: normal; font-weight: 500; }\r\n\t\t#sidebar p { color:#4c4c4c; font-size:15px; margin-bottom:18px;  }\r\n\t\t#sidebar a { display:block; line-height:52px; background:#4c4c4c; font-size:16px; font-weight:bold; color:#fff; text-align:center; -webkit-transition: all 400ms ease;\r\n\t\t-moz-transition: all 400ms ease; -ms-transition: all 400ms ease; -o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t#sidebar a:hover { background:#363333; }\r\n\r\n\r\n/* ==========================================================================\r\n   Footer\r\n   ========================================================================== */\r\nfooter { padding:70px 0 55px; background:url(../images/bg.png); }\r\n\t#logo-footer { position:absolute; top:-9px; left:0; width:52px; height:81px; background:url(../images/logo-footer.png); }\r\n\tfooter ul { display:block; text-align:right; padding-bottom:12px; border-bottom:1px solid #b4b5b3; margin-bottom:15px; }\r\n\t\tfooter ul li { display:inline-block; margin-left:20px; }\r\n\t\t\tfooter li a { font-size:14px; color:#454545; line-height:1.4em; }\r\n\t\t\t\tfooter li a:hover { text-decoration:underline; }\r\n\tfooter .social { display:block; width:30px; height:30px; margin-left:10px; float:right; text-indent:-999999px; overflow:hidden; }\r\n\t\t.social1 { background:url(../images/icons.png) -60px 0; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t\t\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t.social1:hover { background:#cde5f2 url(../images/icons.png) -60px 0; }\r\n\t\t.social2 { background:url(../images/icons.png) -30px 0; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t\t\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t.social2:hover { background:#cde5f2 url(../images/icons.png) -30px 0; }\r\n\t\t.social3 { background:url(../images/icons.png) 0 0; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t\t\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t.social3:hover { background:#cde5f2 url(../images/icons.png) 0 0; }\r\n\r\n/* ==========================================================================\r\n   SpaceBase\r\n   ========================================================================== */\r\n#inner-head { background:#989898; padding:70px 0 50px; }\r\n\t#inner-head .container { position:relative; min-height:405px; }\r\n\t#inner-head h1 { font-size:98px; color:#fff; font-family:\"FairpNarMedIta\"; font-weight:normal; line-height:1em; margin-bottom:30px; }\r\n\t#inner-head span { line-height:1em; font-size:32px; display:block; line-height:1em; margin-bottom:20px;\r\n\tfont-family: \"mic-32-new-web-n5\",\"mic-32-new-web\",sans-serif; font-style: normal; font-weight: 300; }\r\n\t#inner-head p { font-size:15px; color:#fff; max-width:530px; margin-bottom:40px; }\r\n\t.btn-download { line-height:1em; padding:60px 80px 15px; background:#393939 url(../images/download-icon.png) center 15px no-repeat; font-size:14px;\r\n\tdisplay:inline-block; color:#fff; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t.btn-download:hover { color:#fff; background:#454545 url(../images/download-icon.png) center 15px no-repeat; }\r\n\t\r\n\t.product-icon-wrap { position:absolute; top:0; right:0; width:370px; height:412px; }\r\n\t\t.product-icon { width:370px; height:362px; background:url(../images/part3.png); position:absolute; top:0; left:0;\r\n\t\t -webkit-animation: iconanim 2.6s linear; -webkit-animation-iteration-count: infinite; -moz-animation: iconanim 2.6s linear; -moz-animation-iteration-count: infinite; }\r\n\t\t.product-shadow { width:352px; height:33px; background:url(../images/spacebase_big_shadow.png); bottom:0; left:5px; position:absolute;\r\n\t\t-webkit-animation: shadowanim 2.6s linear; -webkit-animation-iteration-count: infinite; -moz-animation: shadowanim 2.6s linear; -moz-animation-iteration-count: infinite; }\r\n\t\t\r\n\t@-webkit-keyframes iconanim {\r\n\t  0% { top:0; }\r\n\t  25% { top:-10px; }\r\n\t  50% { top:0; }\r\n\t  75% { top:10px; }\r\n\t  100% { top:0; }\r\n\t}\r\n\t\r\n\t@-moz-keyframes iconanim {\r\n\t  0% { top:0; }\r\n\t  25% { top:-10px; }\r\n\t  50% { top:0; }\r\n\t  75% { top:10px; }\r\n\t  100% { top:0; }\r\n\t}\r\n\t\r\n\t@-o-keyframes iconanim {\r\n\t  0% { top:0; }\r\n\t  25% { top:-10px; }\r\n\t  50% { top:0; }\r\n\t  75% { top:10px; }\r\n\t  100% { top:0; }\r\n\t}\r\n\t\r\n\t@keyframes iconanim {\r\n\t  0% { top:0; }\r\n\t  25% { top:-10px; }\r\n\t  50% { top:0; }\r\n\t  75% { top:10px; }\r\n\t  100% { top:0; }\r\n\t}\r\n\t\r\n\t@-webkit-keyframes shadowanim {\r\n\t  0% { -webkit-transform: scale(1); }\r\n\t  25% { -webkit-transform: scale(0.8); }\r\n\t  50% { -webkit-transform: scale(1); }\r\n\t  75% { -webkit-transform: scale(1.2); }\r\n\t  100% { -webkit-transform: scale(1); }\r\n\t}\r\n\t\r\n\t@-moz-keyframes shadowanim {\r\n\t  0% { -moz-transform: scale(1); }\r\n\t  25% { -moz-transform: scale(0.9); }\r\n\t  50% { -moz-transform: scale(1); }\r\n\t  75% { -moz-transform: scale(1.1); }\r\n\t  100% { -moz-transform: scale(1); }\r\n\t}\r\n\t\r\n\t@-o-keyframes shadowanim {\r\n\t  0% { -o-transform: scale(1); }\r\n\t  25% { -o-transform: scale(0.9); }\r\n\t  50% { -o-transform: scale(1); }\r\n\t  75% { -o-transform: scale(1.1); }\r\n\t  100% { -o-transform: scale(1); }\r\n\t}\r\n\t\r\n\t@keyframes shadowanim {\r\n\t  0% { transform: scale(1); }\r\n\t  25% { transform: scale(0.9); }\r\n\t  50% { transform: scale(1); }\r\n\t  75% { transform: scale(1.1); }\r\n\t  100% { transform: scale(1); }\r\n\t}\t\r\n\r\n.white-sect { background:#fff; color:#49647b; position:relative; }\r\n\t.white-sect .row { padding:95px 0 130px; }\r\n\t.bar-arrow { height:53px; width:100%; background:#393939 url(../images/arrow6.png) top center no-repeat; margin-bottom:40px; }\r\n\t.subnav { width:433px; position:absolute; top:53px; left:50%; margin-left:-216px; z-index:2; overflow:hidden; z-index:10000; }\r\n\t\t.subnav li { display:block; float:left; border-bottom:1px solid #393939; background:#fff;  }\r\n\t\t\t.subnav li.li1 a { border-left:1px solid #393939; padding:0 28px; }\r\n\t\t\t.subnav li.li2 a { padding:0 22px; }\r\n\t\t\t.subnav li.li3 a { padding:0 8px; }\r\n\t\t\t.subnav a { display:block; line-height:39px; padding:0 25px; text-align:center; font-size:15px; color:#393939;\r\n\t\t\tborder-right:1px solid #393939; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t\t\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n.row { margin:0 -50px; overflow:hidden; }\r\n\t.col4 { width:33.33333333%; float:left; padding:0 50px; }\r\n\t.box-col { text-align:center; }\r\n\t\t.box-col .icon { width:131px; height:131px; display:block; overflow:hidden; text-indent:-999999px; margin:0 auto 35px;  }\r\n\t\t.box-col .icon1 { background:url(../images/icon1.png); }\r\n\t\t.box-col .icon2 { background:url(../images/icon2.png); }\r\n\t\t.box-col .icon3 { background:url(../images/icon3.png); }\r\n\t\t.box-col h3 { margin-bottom:40px; font-size:18px; color:#6B6B6B; font-weight:bold; line-height:1.4em; }\r\n\t\t.box-col p { font-size:14px; line-height:1.5em; margin:0; text-align:justify; color:#6B6B6B }\r\n\r\n.gray-sect { background:#f2f2f3; border-bottom:1px solid #cccccc; border-top:1px solid #cccccc; }\r\n.pad45 { padding:45px 0; }\r\n.padd50-100 { padding:50px 0 100px; }\r\n.padd45-70 { padding:45px 0 70px;  }\r\n\t.gray-sect h2 { font-size:32px; color:#49647B; line-height:1em; margin-bottom:40px; font-weight:bold; }\r\n\t.accordion-wrapper { border:1px solid #d6d6d6; }\r\n\t.acc { border-bottom:1px solid #d6d6d6; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t\t\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t.acc.last { border:0 none; }\r\n\t.acc.active { background:#393939; }\r\n\t\t.acc h4 { font-size:15px; color:#6B6B6B; font-weight:bold; line-height:1em; padding:18px 20px; background:url(../images/cross.png) 98% 18px no-repeat;\r\n\t\tcursor:pointer; position:relative; -webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease;\r\n\t\t\t-o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t.acc h4:hover { background:#d7d7d7 url(../images/cross.png) 98% 18px no-repeat; } \r\n\t\t\t.acc.active h4 { color:#fff; background:url(../images/x.png) 98% 18px no-repeat; }\r\n\t\t.acc-cont { display:none; padding:50px; }\r\n\t\t\t.acc-cont p { line-height:1.5em; margin:0; font-size:15px; }\r\n\r\n#is-spacebar-for-you { text-align:center; }\r\n\t#is-spacebar-for-you h2 { font-size:32px; color:#49647B; line-height:1em; margin-bottom:35px; font-weight:bold; }\r\n\t#is-spacebar-for-you p { font-size:15px; line-height:1.5em; margin:0 0 55px 0; color:#6B6B6B; }\r\n\t#is-spacebar-for-you h5 { font-size:15px; color:#6B6B6B; line-height:1em; margin-bottom:60px; font-weight:bold; }\r\n.samples-wrapper { border:1px solid #83a096; background:#f4f4f4; margin-bottom:100px; }\r\n\t.sample { border-bottom:1px solid #83a096; text-align:left; }\r\n\t.sample.last { border:0 none; }\r\n\t.sample-cont { float:left; width:680px; padding:25px 15px 0 35px; }\r\n\t\t.sample2 .sample-cont { padding-top:45px; }\r\n\t\t.sample.last .sample-cont { padding-top:60px; }\r\n\t.sample img { float:right; border-left:1px solid #bcbcbc; padding-left:2px; }\r\n\t.sample h3 { font-size:32px; color:#6B6B6B; font-family: \"mic-32-new-web-n5\",\"mic-32-new-web\",sans-serif; font-style: normal; font-weight: 500; line-height:1em;\r\n\tmargin-bottom:20px;  }\r\n\t#is-spacebar-for-you .sample p { font-size:15px; margin:0; line-height:2em; }\r\n\r\n.doc-banner { border:1px solid #393939; width:530px; height:125px; position:relative; margin:0 auto; text-align:left; }\r\n\t.doc-banner h4 { font-size:24px; color:#49647B; line-height:1.2em; padding:32px 0 0 30px; font-weight:bold; }\r\n\t\t.doc-banner h4 a { display:block; text-decoration:none; color:#49647B; text-transform:none; }\r\n\t\t\t.doc-banner h4 a:hover { text-decoration:underline; }\r\n\t.doc-banner .btn-download { position:absolute; top:0; right:0; height:100%; width:185px; padding:0; text-align:center; padding-top:84px; font-size:15px;\r\n\t background:#393939 url(../images/download-icon.png) center 30px no-repeat;  }\r\n\t \t.doc-banner .btn-download:hover {  background:#454545 url(../images/download-icon.png) center 30px no-repeat; }\r\n\t\t\r\n\t.dark .doc-banner-alt .btn-icon { background:#393939 url(../images/icon-doc.png) center center no-repeat;  }\r\n\t \t.dark .doc-banner-alt .btn-icon:hover {  background:#454545 url(../images/icon-doc.png) center center no-repeat; }   \t\r\n\t.dark .doc-banner-alt .btn-icon2 { background:#393939 url(../images/download-icon.png) center center no-repeat;  }\r\n\t\t\t.dark .doc-banner-alt .btn-icon2:hover {  background:#454545 url(../images/download-icon.png) center center no-repeat; }  \t\r\n\t\t\r\n/* ==========================================================================\r\n   Comsat\r\n   ========================================================================== */\r\n.purple #inner-head { background:#c4abc8; padding:35px 0 0; }\r\n\t.purple #inner-head .container { position:relative; min-height:490px; }   \r\n\t\r\n\t.purple .product-icon-wrap { top:0; right:0; width:417px; height:474px; }\r\n\t\t.purple .product-icon { width:417px; height:419px; background:url(../images/comsat_big.png) no-repeat; top:0; left:0; }\r\n\t\t.purple .product-shadow { width:352px; height:33px; bottom:0; left:35px; }\r\n\t\r\n\t.purple #inner-head h1 { margin-top:30px; }\r\n\t.purple .bar-arrow { background:#6e5971 url(../images/arrow6.png) top center no-repeat; }\r\n\t.purple .subnav { width:238px; margin-left:-118px; }\r\n\t.col6 { width:50%; float:left; padding:0 50px; }\r\n\t\t.box-col .icon4 { background:url(../images/icon4.png); }\r\n\t\t.box-col .icon5 { background:url(../images/icon5.png); }\t\r\n\t\t.purple .box-col h3 { color:#6b6b6b; }\r\n\t\t.purple .box-col p { color:#6b6b6b }\t\r\n\t.purple .gray-sect h2 { color:#49647b; }\r\n\t.table-style { border:1px solid #d6d6d6; }\t\r\n\t\t.table-style li { border-bottom:1px solid #d6d6d6; color:#6b6b6b; font-weight:bold; font-size:15px; line-height:1.3em; padding:16px 20px; }\r\n\t\t.table-style li.last { border:0 none; }\r\n\t.row-alt, .white-sect .row-alt.row { margin:0 -20px; padding:0; }\r\n\t\t.row-alt .col6 { padding:0 20px; }\r\n.doc-banner-alt { border:1px solid #393939; width:100%; height:125px; position:relative; text-align:left; }\r\n\t.doc-banner-alt h4 { font-size:24px; color:#49647b; line-height:1.2em; padding:32px 0 0 30px; font-weight:bold; }\r\n\t\t.doc-banner-alt h4 a { display:inline-block; text-decoration:none; color:#49647b; text-transform:none; }\r\n\t\t\t.doc-banner-alt h4 a:hover { text-decoration:underline; }\t\t\r\n\t.doc-banner-alt .btn-icon { position:absolute; top:-1px; right:-1px; bottom:-1px; width:185px; padding:0; text-indent:-99999px; overflow:hidden;\r\n\t background:#6e5971 url(../images/icon-doc.png) center center no-repeat;\r\n\t -webkit-transition: all 300ms ease; -moz-transition: all 300ms ease;-ms-transition: all 300ms ease;-o-transition: all 300ms ease;transition: all 300ms ease;  }\r\n\t \t.doc-banner-alt .btn-icon:hover {  background:#c4abc8 url(../images/icon-doc.png) center center no-repeat; }   \r\n\t.doc-banner-alt .btn-icon2 { background:#6e5971 url(../images/icon-git.png) center center no-repeat;  }\r\n\t\t\t.doc-banner-alt .btn-icon2:hover {  background:#c4abc8 url(../images/icon-git.png) center center no-repeat; }  \r\n\t\t\t\r\n/* ==========================================================================\r\n   Galaxy\r\n   ========================================================================== */\r\n.gray #inner-head { background:#f0f0f0; padding:70px 0 0; }\r\n\t.gray #inner-head .container { position:relative; min-height:455px; color:#707070; }   \r\n\t\r\n\t.gray .product-icon-wrap { top:0; right:0; width:295px; height:420px; }\r\n\t\t.gray .product-icon { width:295px; height:287px; background:url(../images/galaxy_big.png) no-repeat; top:0; left:0; }\r\n\t\t.gray .product-shadow { width:260px; height:33px; bottom:0; left:15px; background:url(../images/galaxy_shadow.png) no-repeat; }\r\n\t\r\n\t.gray #inner-head h1 { color:#909090; }\r\n\t.gray #inner-head p { color:#707070; }\r\n\t.gray #inner-head span { margin-bottom:45px; }\r\n\t.gray .bar-arrow { background:#9b9b9b url(../images/arrow6.png) top center no-repeat; }\r\n\t.gray .subnav { width:238px; margin-left:-118px; }\r\n\t\t.box-col .icon6 { background:url(../images/icon6.png); }\r\n\t\t.box-col .icon7 { background:url(../images/icon7.png); }\t\r\n\t\t.gray .box-col h3 { color:#6b6b6b; }\r\n\t\t.gray .box-col p { color:#6b6b6b }\r\n\t.gray .white-sect .row { padding:95px 0 60px; }\t\r\n\t.gray .white-sect .row-alt.row { margin:0 -20px; padding:70px 0 60px; }\r\n\t.gray .acc.active { background:#b1b1b1; }\r\n\t\t.gray .acc h4 { color:#6b6b6b; }\r\n\t\t\t.gray .acc.active h4 { color:#fff; }\r\n\t.gray .gray-sect h2 { color:#49647b; } \r\n\t.gray .doc-banner-alt .btn-icon { background:#9b9b9b url(../images/icon-doc.png) center center no-repeat;  }\r\n\t \t.gray .doc-banner-alt .btn-icon:hover {  background:#f0f0f0 url(../images/icon-doc.png) center center no-repeat; }   \t\r\n\t.gray .doc-banner-alt .btn-icon2 { background:#9b9b9b url(../images/icon-git.png) center center no-repeat;  }\r\n\t\t\t.gray .doc-banner-alt .btn-icon2:hover {  background:#f0f0f0 url(../images/icon-git.png) center center no-repeat; }  \t\t\r\n\t\t\t\r\n/* ==========================================================================\r\n   Quasar\r\n   ========================================================================== */\r\n.green #inner-head { background:#9dc2bc; padding:70px 0 0; }\r\n\t.green #inner-head .container { position:relative; min-height:455px; }   \r\n\t\r\n\t.green .product-icon-wrap { top:0; right:0; width:318px; height:433px; }\r\n\t\t.green .product-icon { width:318px; height:314px; background:url(../images/quasar_big.png) no-repeat; top:0; left:0; }\r\n\t\t.green .product-shadow { width:260px; height:33px; bottom:0; left:15px; background:url(../images/galaxy_shadow.png) no-repeat; }\r\n\t\r\n\t.green .bar-arrow { background:#228372 url(../images/arrow6.png) top center no-repeat; }\r\n\t.green .subnav { width:238px; margin-left:-118px; }\r\n\t\t.box-col .icon8 { background:url(../images/icon8.png); }\r\n\t\t.box-col .icon9 { background:url(../images/icon9.png); }\t\r\n\t\t.box-col .icon10 { background:url(../images/icon10.png); }\r\n\t\t.green .box-col h3 { color:#6b6b6b; }\r\n\t\t.green .box-col p { color:#6b6b6b }\r\n\t.green .white-sect .row { padding:95px 0 60px; }\r\n\t.green .white-sect .row-alt.row { margin:0 -20px; padding:0; }\t\r\n\t.green .gray-sect h2 { color:#49647b; } \r\n\t.green .doc-banner-alt .btn-icon { background:#228372 url(../images/icon-doc.png) center center no-repeat;  }\r\n\t \t.green .doc-banner-alt .btn-icon:hover {  background:#9dc2bc url(../images/icon-doc.png) center center no-repeat; }   \t\r\n\t.green .doc-banner-alt .btn-icon2 { background:#228372 url(../images/icon-git.png) center center no-repeat;  }\r\n\t\t\t.green .doc-banner-alt .btn-icon2:hover {  background:#9dc2bc url(../images/icon-git.png) center center no-repeat; }  \t\t\t\t\r\n\r\n/* ==========================================================================\r\n   Documentation - About pages\r\n   ========================================================================== */\r\n#main { padding:75px 0 100px; background:#fff; }\r\n\t.text { color:#3a3a3a; }\r\n\t.text-560 { margin:0 auto; width:100%; max-width:560px; }\r\n\t\t.text h1 { font-size:32px; color:#3a3a3a; font-weight:bold; line-height:1em; margin-bottom:40px; text-align:center; }\r\n\t\t.text h3 { font-size:15px; color:#3a3a3a; font-weight:bold; line-height:1em; margin-bottom:50px; text-align:center; }\r\n\t\t.text p { font-size:15px; color:#3a3a3a; text-align:center; margin-bottom:40px; }\r\n\t.products-boxes { overflow:hidden; margin-bottom:40px; }\r\n\t\t.products-boxes li { display:block; float:left; margin-right:20px; width:184px; }\r\n\t\t\t.products-boxes li.li5 { margin:0; }\r\n\t\t\t.products-boxes li a { display:block; width:184px; height:184px; line-height:184px; text-align:center; font-family: \"FairpNarMedIta\",sans-serif;\r\n\t\t\tcolor:#fff; font-size:32px;\r\n\t\t\t-webkit-transition: all 300ms ease; -moz-transition: all 300ms ease;-ms-transition: all 300ms ease;-o-transition: all 300ms ease;transition: all 300ms ease; }\r\n\t\t\t.products-boxes li.li1 a { background:#805875; }\r\n\t\t\t\t.products-boxes li.li1 a:hover { background:#402c3a; }\r\n\t\t\t.products-boxes li.li2 a { background:#49beb0; }\r\n\t\t\t\t.products-boxes li.li2 a:hover { background:#245f58; }\r\n\t\t\t.products-boxes li.li3 a { background:#a4a4a4; }\r\n\t\t\t\t.products-boxes li.li3 a:hover { background:#525252; }\r\n\t\t\t.products-boxes li.li4 a { background:#393939; }\r\n\t\t\t\t.products-boxes li.li4 a:hover { background:#161616; }\r\n\t\t\t.products-boxes li.li5 a { background:#f4f4f4; color:#a4a4a4; border:1px solid #dedede; }\r\n\t\t\t\t.products-boxes li.li5 a:hover { background:#7a7a7a; color:#fff; }\r\n\t.contact-box { position:relative; padding-top:70px; }\r\n\t\t.contact-box h2 { line-height:1em; font-family: \"mic-32-new-web-n5\",\"mic-32-new-web\",sans-serif; font-size:21px; color:#4b4b4b; padding-bottom:18px;\r\n\t\tborder-bottom:1px solid #bfbfbf; margin-bottom:20px; }\r\n\t\t.contact-box p { float:left; width:290px; color:#4b4b4b; font-size:15px; line-height:1.5em; }\r\n\t\t.contact-box .btn { display:block; float:right; width:193px; height:53px; line-height:53px; background:#4b4b4b;\r\n\t\tfont-size:16px; color:#fff; -webkit-transition: all 400ms ease; font-weight:bold; text-align:center;\r\n\t\t-moz-transition: all 400ms ease; -ms-transition: all 400ms ease; -o-transition: all 400ms ease; transition: all 400ms ease;  }\r\n\t\t\t.contact-box .btn:hover { background:#454545; }\r\n\t.team { width:570px; margin:0 auto 65px; }\r\n\t\t.person { width:248px; height:248px; float:left; position:relative; }\r\n\t\t.person.last { float:right; }\r\n\t\t.person-details { position:absolute; top:0; left:0; width:100%; height:100%; background:rgba(65,181,227,0.9); opacity:0;\r\n\t\t-webkit-transition: all 400ms ease; -moz-transition: all 400ms ease; -ms-transition: all 400ms ease; -o-transition: all 400ms ease; transition: all 400ms ease; }\r\n\t\t\t.person-details h3 { font-weight:bold; font-size:21px; line-height:1em; margin-bottom:8px; color:#fff; font-family:Arial, Helvetica, sans-serif; padding:15px 0 0 15px; }\r\n\t\t\t.person-details span { display:block; line-height:1em; font-size:15px; color:#fff; padding-left:15px; margin-bottom:30px; }\r\n\t\t\t.person-details p { color:#fff; font-size:15px; padding:0 15px 15px; }\r\n\t\t.person:hover .person-details { opacity:1; }\r\n\t.investors { width:570px; margin:0 auto; border:1px solid #c2c2c2; margin-bottom:10px; }\r\n\r\n\r\n/* ==========================================================================\r\n   Support Page\r\n   ========================================================================== */\r\n.text-620 { margin:0 auto; width:100%; max-width:620px; }\r\n\t.anchor-big { font-size:19px; font-weight:bold; color:#515151; padding-top:7px; display:inline-block; }\r\n\t\t.anchor-big:hover { text-decoration:underline; }\r\n.contact-wbox { padding:30px 0 50px; background:#f0f3f1; border-bottom:1px solid #cccccc; border-top:1px solid #cccccc; margin-top:60px; }\r\n\t.contact-box-inner { padding:0 110px 0 490px; background:url(../images/spacebase_sm.png) 80px 18px no-repeat; }\r\n\t\t.contact-box-inner h2 { color:#767676; font-size:92px; line-height:1em; border:0 none; font-family:\"FairpNarMedIta\"; margin-bottom:25px; padding:0; }\r\n\t\t.contact-box-inner p { font-size:15px; color:#6b6b6b; text-align:justify; margin-bottom:34px; float:none; width:auto; }\r\n\t\t.btn-contact { display:block; width:400px; height:63px; line-height:63px; background:#fff; border:1px solid #959595; text-indent:95px; font-size:17px;\r\n\t\tfont-weight:bold; color:#6b6b6b; position:relative; } \r\n\t\t\t.btn-contact span.icon { position:absolute; top:-1px; right:-1px; bottom:-1px; width:93px; background:url(../images/icon-email.png); display:block;\r\n\t\t\ttext-indent:-999999px; overflow:hidden; }\r\n.bar-arrow2 { background-color:#6b6b6b; margin-top:2px; }\r\n#packages-wrapper { position:relative; }\r\n\t#packages-wrapper h3 { text-align:center; font-size:20px; font-weight:bold; color:#3a3a3a; line-height:1em; margin-bottom:30px; }\r\n\t.package-box { width:625px; margin:0 auto 45px; overflow:hidden; }\r\n\t\t.package-box.last { margin-bottom:0; }\r\n\t\t.package-icon { width:215px; height:194px; float:left; background:#41b6e4 url(../images/icon-package3.png) center center no-repeat; }\r\n\t\t\t.package-icon2 { background:#41b6e4 url(../images/icon-package2.png) center center no-repeat;  }\r\n\t\t\t.package-icon3 { background:#41b6e4 url(../images/icon-package1.png) center center no-repeat;  }\r\n\t\t.package-cont { width:410px; float:left; border:1px solid #959595; }\r\n\t\t\t.package-cont h4 { line-height:52px; background:#909090; font-weight:bold; font-size:18px; color:#fff; text-indent:22px; text-transform:uppercase; }\r\n\t\t\t.package-cont li { display:block; line-height:35px; overflow:hidden; padding-left:25px; font-size:14px; color:#6b6b6b; }\r\n\t\t\t\t.package-cont li.li-alt { background:#e6f6fc; }\r\n\t\t\t\t.package-cont li strong { float:left; display:block; width:57%; }\r\n\t\t\t\t.package-cont li span { float:left; display:block; width:43%; }\r\n\r\n/* ==========================================================================\r\n   Documentation Page\r\n   ========================================================================== */\r\n#docs-cont { background:url(../images/bg-docs.png) repeat-y; position:relative; min-height:700px; margin-top:27px; }\r\n.sidebar { width:245px; position:absolute; top:0; left:0; height:100%; }\r\n\t.side-title { padding-left:53px; height:68px; background:url(../images/icon-title.png) no-repeat; width:245px; float:left; }\r\n\t\t.side-title h2 { background:#a4a4a4; line-height:68px; text-align:center; font-weight:bold; font-size:18px; text-transform:uppercase; }\r\n\t#docs-sidemenu { display:block; width:245px; }\r\n\t\t#docs-sidemenu.scrolling { overflow-y:scroll; bottom:0; top:123px; position:fixed; left:0; }\r\n\t\t#docs-sidemenu.scrolling-big { bottom:0; top:123px; position:fixed; left:0; }\r\n\t\t#docs-sidemenu.stay { bottom:0; top:auto; position:absolute; left:0!important; }\r\n\t\t#docs-sidemenu.stay-big { bottom:auto; top:123px; position:absolute; left:0!important; }\r\n\t\t#docs-sidemenu li { display:block; width:245px; }\r\n\t\t\t#docs-sidemenu.scrolling li { width:100%; }\t\r\n\t\t\t#docs-sidemenu li a:hover, #docs-sidemenu li.current>a { font-weight:bold; }\r\n\t\t\t#docs-sidemenu li.li1>a { background:#dcedf4; line-height:29px; display:block; margin-bottom:8px; padding:0 10px; font-size:14px;\r\n\t\t\tfont-weight:bold; color:#393939; text-transform:uppercase; }\r\n\t\t\t#docs-sidemenu li.li1>ul { margin-bottom:10px; padding-left:12px; }\r\n\t\t\t\t#docs-sidemenu li.li1>ul a { color:#4d4f4f; font-size:13px; line-height:1.1em; }\r\n\t\t\t\t\t#docs-sidemenu li.li1>ul a.cat-link { color:#3a3a3a; font-size:16px; font-weight:bold; line-height:2em; }\r\n\t\t\t\t#docs-sidemenu li.li1>ul ul { }\r\n\t\r\n.main { width:743px; float:right; }\r\n\t#docs-cont .main { min-height:700px; }\r\n\t#docs-menu { float:right; margin-right:1px; }\r\n\t\t#docs-menu li { display:block; float:left; width:128px; height:69px; }\r\n\t\t\t#docs-menu li a { display:block; width:128px; height:69px; line-height:69px; text-align:center; font-family: \"FairpNarMedIta\",sans-serif;\r\n\t\t\tcolor:#fff; font-size:25px;\r\n\t\t\t-webkit-transition: all 300ms ease; -moz-transition: all 300ms ease;-ms-transition: all 300ms ease;-o-transition: all 300ms ease;transition: all 300ms ease; }\r\n\t\t\t#docs-menu li.li1 a { background:#805875; }\r\n\t\t\t\t#docs-menu li.li1 a:hover { background:#402c3a; }\r\n\t\t\t#docs-menu li.li2 a { background:#49beb0; }\r\n\t\t\t\t#docs-menu li.li2 a:hover { background:#245f58; }\r\n\t\t\t#docs-menu li.li3 a { background:#a4a4a4; }\r\n\t\t\t\t#docs-menu li.li3 a:hover, #docs-menu li.li3.on a { background:#525252; }\r\n\t\t\t#docs-menu li.li4 a { background:#393939; }\r\n\t\t\t\t#docs-menu li.li4 a:hover { background:#161616; }\r\n\t\t\t#docs-menu li.li5 a { background:#fff; color:#a4a4a4; border:1px solid #959595; width:126px; }\r\n\t\t\t\t#docs-menu li.li5 a:hover { background:#7a7a7a; color:#fff; border:1px solid #7a7a7a; }\r\n\t\r\n\t#docs-cont .main { padding:40px 20px; border-bottom:1px solid #c6c6c6; margin-right:3px; }\r\n\t.doc-text { margin-bottom:30px; color:#3a3a3a; }\r\n\t\t.doc-text h1 { font-size:24px; color:#3a3a3a; line-height:1.2em; margin-bottom:14px; font-weight:bold; }\r\n\t\t.doc-text h2 { font-size:22px; color:#3a3a3a; line-height:1.2em; margin-bottom:14px; font-weight:bold; }\r\n\t\t.doc-text h3 { font-size:18px; color:#3a3a3a; line-height:1.2em; margin-bottom:4px; font-weight:bold; }\r\n\t\t.doc-text h4 { font-size:15px; color:#3a3a3a; line-height:1.2em; margin-bottom:4px; font-weight:bold; }\r\n\t\t.doc-text p { font-size:14px; color:#3a3a3a; line-height:1.5em; margin-bottom:10px; }\r\n\t\t.doc-text a { font-size:14px; color:#0088cc; text-decoration:underline; }\r\n\t\t\t.doc-text a:hover { text-decoration:none; }\r\n\t\t.doc-text ul, .doc-text ol { margin-bottom:10px; }\r\n\t\t.doc-text li { list-style:disc; list-style-position:inside; font-size:15px; color:#3a3a3a; line-height:1.5em; }\r\n\t\t.doc-text ol li { list-style:decimal; list-style-position:inside; }\r\n\t\t.sep { padding-bottom:20px; border-top:1px solid #d6d6d6; margin-top:20px; }\r\n\t\t.alert { margin-bottom:20px; padding:9px; }\r\n\t\t\t.alert-info { background:#dfeff5; border:1px solid #94b7c4; font-size:15px; color:#237798; }\r\n\t\t\t.alert-warn { background:#fcf8e3; border:1px solid #dcccae; font-size:15px; color:#b38d4a; }\r\n\r\n#doumentation-bottom-bar { height:68px; background:#dcdcdc; color:#fff; overflow:hidden; position:fixed; top:90px; left:0; width:100%; }\r\n\t.fixed-head #doumentation-bottom-bar { top:55px; }\r\n\t#doumentation-bottom-bar h3 { position:relative; float:left; font-size:25px; font-family: \"FairpNarMedIta\",sans-serif; background:#b0b0b0; line-height:68px; padding:0 30px; }\r\n\t\t#doumentation-bottom-bar a { margin-top:12px; display:block; line-height:46px; border-right:1px solid #c0c0c0; width:154px; float:left; text-align:center; }\r\n\t\t\t#doumentation-bottom-bar a span { display:inline-block; padding-left:37px; line-height:30px; font-size:11px; color:#979797; }\r\n\t\t\t.btn-1 span { background:url(../images/icon-doc1.png) left center no-repeat; }\r\n\t\t\t\t.btn-1:hover span { background:url(../images/icon-doc11.png) left center no-repeat; }\r\n\t\t\t.btn-2 span { background:url(../images/icon-doc2.png) left center no-repeat; }\r\n\t\t\t\t.btn-2:hover span { background:url(../images/icon-doc21.png) left center no-repeat; }\r\n\t\t\t.btn-3 span { background:url(../images/icon-doc3.png) left center no-repeat; }\r\n\t\t\t\t.btn-3:hover span { background:url(../images/icon-doc31.png) left center no-repeat; }\r\n\t\t\t.btn-4 span { background:url(../images/icon-doc4.png) left center no-repeat; }\r\n\t\t\t\t.btn-4:hover span { background:url(../images/icon-doc41.png) left center no-repeat; }\r\n\t\t\t#doumentation-bottom-bar a.btn-4 { border:0 none; }\r\n\t\t\t#doumentation-bottom-bar a:hover span { color:#000; }\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\nlayout: default\ntitle: Comsat\ndescription: \"Comsat integrates lightweight threads and actors with the JVM web stack.\"\n---\n\n# Overview\n\nCOMSAT (or Comsat) is a set of open source libraries that integrate [Quasar](http://puniverse.github.io/quasar/) with various web or enterprise technologies (like HTTP services and database access). With Comsat, you can write web applications that are scalable and performing and, at the same time, are simple to code and maintain.\n\nComsat is not a web framework. In fact, it does not add new APIs at all (with one exception, Web Actors, mentioned later). It provides implementation to popular (and often, standard) APIs like Servlet, JAX-RS, and JDBC, that can be used efficiently within Quasar fibers.\n\nComsat does provide one new API that you may choose to use: Web Actors. Web actors let you define a Quasar actor that receives and responds to HTTP requests and web socket messages. The Web Actors API is rather minimal, and is intended to do one job and do it well: simplify two-way communication between your server and the client.\n\n[Parallel Universe]: http://paralleluniverse.co\n\n## News\n\n### April 6, 2016\n\nCOMSAT [0.7.0](https://github.com/puniverse/comsat/releases/tag/v0.7.0) has been released.\n\n### February 10, 2016\n\nCOMSAT [0.6.0](https://github.com/puniverse/comsat/releases/tag/v0.6.0) has been released.\n\n### August 28, 2015\n\nCOMSAT [0.5.0](https://github.com/puniverse/comsat/releases/tag/v0.5.0) has been released.\n\n### July 1, 2015\n\nCOMSAT [0.4.0](https://github.com/puniverse/comsat/releases/tag/v0.4.0) has been released.\n\n### December 23, 2014\n\nCOMSAT [0.3.0](https://github.com/puniverse/comsat/releases/tag/v0.3.0) has been released.\n\n### July 23, 2014\n\nCOMSAT [0.2.0](https://github.com/puniverse/comsat/releases/tag/v0.2.0) has been released.\n\n### January 22, 2014\n\nCOMSAT [0.1.0](https://github.com/puniverse/comsat/releases/tag/v0.1.0) has been released.\n\n# Getting Started\n\n### System requirements\n\nJava 7 is required to use COMSAT.\n\n### Using Comsat with [Maven](https://maven.apache.org) and [Gradle](http://www.gradle.org) {#maven}\n\nFirst, you need the `quasar-core` dependency. With Maven:\n\n~~~ xml\n<dependency>\n    <groupId>co.paralleluniverse</groupId>\n    <artifactId>quasar-core</artifactId>\n    <version>0.7.2</version>\n</dependency>\n~~~\n\nor, for JDK8:\n\n~~~ xml\n<dependency>\n    <groupId>co.paralleluniverse</groupId>\n    <artifactId>quasar-core</artifactId>\n    <version>0.7.2</version>\n    <classifier>jdk8</classifier>\n</dependency>\n~~~\n\nThe corresponding Gradle dependencies are respectively `co.paralleluniverse:quasar-core:0.7.2` or, for JDK8, `co.paralleluniverse:quasar-core:0.7.2@jdk8`.\n\nThen add the following Maven/Gradle dependencies:\n\n| Feature                                                                                                                   | Artifact\n|---------------------------------------------------------------------------------------------------------------------------|--------------------------\n| Servlet integration for defining fiber-per-request servlets.                                                              | `co.paralleluniverse:comsat-servlet:0.7.0`\n| A fiber-blocking Clojure [Ring](https://github.com/ring-clojure/ring) adapter based on Jetty 9.3.                         | `co.paralleluniverse:comsat-ring-jetty9:0.7.0`\n| [HTTP Kit](http://www.http-kit.org/client.html)-based fiber-blocking HTTP client.                                         | `co.paralleluniverse:comsat-httpkit:0.7.0`\n| [Jersey server](https://jersey.java.net/) integration for defining REST services.                                         | `co.paralleluniverse:comsat-jersey-server:0.7.0`\n| [Dropwizard](http://dropwizard.io/) integration including Jersey, ApacheHttpClient and JDBI.                              | `co.paralleluniverse:comsat-dropwizard:0.7.0`\n| [Spring Framework](http://projects.spring.io/spring-framework/) Web MVC fiber-blocking controller methods integration.    | `co.paralleluniverse:comsat-spring-webmvc:0.7.0`\n| [Spring Boot](http://projects.spring.io/spring-boot/) auto-configuration support for Web MVC controllers.                 | `co.paralleluniverse:comsat-spring-boot:0.7.0`\n| [Spring Security](http://projects.spring.io/spring-security/) configuration support for fibers.                           | `co.paralleluniverse:comsat-spring-security:0.7.0`\n| [JAX-RS client](https://jersey.java.net/documentation/latest/client.html) integration for HTTP calls with fibers.         | `co.paralleluniverse:comsat-jax-rs-client:0.7.0`\n| [ApacheHttpClient](http://hc.apache.org/httpcomponents-client-ga/) integration for HTTP calls with fibers.                | `co.paralleluniverse:comsat-httpclient:0.7.0`\n| [Retrofit](http://square.github.io/retrofit/) integration with fibers.                                                    | `co.paralleluniverse:comsat-retrofit:0.7.0`\n| [JDBI](http://jdbi.org/) integration with fibers.                                                                         | `co.paralleluniverse:comsat-jdbi:0.7.0`\n| JDBC integration with fibers.                                                                                             | `co.paralleluniverse:comsat-jdbc:0.7.0`\n| [jOOQ](http://www.jooq.org/) integration with fibers.                                                                     | `co.paralleluniverse:comsat-jooq:0.7.0`\n| MongoDB fiber-blocking integration for the [Allanbank API](http://www.allanbank.com/mongodb-async-driver/index.html).     | `co.paralleluniverse:comsat-mongodb-allanbank:0.7.0`\n| [OkHttp](https://github.com/square/okhttp) HTTP+SPDY client integration.                                                  | `co.paralleluniverse:comsat-okhttp:0.7.0`\n| The Web Actors API.                                                                                                       | `co.paralleluniverse:comsat-actors-api:0.7.0`\n| Deploy HTTP, SSE and WebSocket Web Actors as [Undertow](http://undertow.io/) handlers.                                    | `co.paralleluniverse:comsat-actors-undertow:0.7.0`\n| Deploy HTTP, SSE and WebSocket Web Actors as [Netty](http://netty.io/) handlers.                                          | `co.paralleluniverse:comsat-actors-netty:0.7.0`\n| Deploy HTTP, SSE and WebSocket Web Actors in J2EE 7 Servlet and WebSocket (JSR-356) embedded and standalone containers.   | `co.paralleluniverse:comsat-actors-servlet:0.7.0`\n| Use Comsat in the Tomcat servlet container without java agent.                                                            | `co.paralleluniverse:comsat-tomcat-loader:0.7.0[:jdk8]` (for JDK 8 optionally add the `jdk8` classifier)\n| Use Comsat in the Jetty servlet container without the java agent.                                                         | `co.paralleluniverse:comsat-jetty-loader:0.7.0[:jdk8]` (for JDK 8 optionally add the `jdk8` classifier)\n| [Spring Framework](http://projects.spring.io/spring-framework/) Web integration allows using fiber-blocking controllers.  | `co.paralleluniverse:comsat-spring-web:0.7.0`\n| [Apache Kafka](http://kafka.apache.org/) producer integration module.                                                     | `co.paralleluniverse:comsat-kafka:0.7.0`\n| [Apache Shiro](http://shiro.apache.org/) integration module.                                                              | `co.paralleluniverse:comsat-shiro:0.7.0`\n\n## Examples\n\nA [Gradle template](https://github.com/puniverse/comsat-gradle-template) project and a [Maven archetype](https://github.com/puniverse/comsat-mvn-archetype) using various integration modules and featuring setup with both Dropwizard and standalone Tomcat are available for jumpstart and study. Both have a `without-comsat` branch which is useful to clearly see the (minimal, if any) porting effort required (branches comparison works very well for this purporse).\n\nThere's a [Comsat-Ring Clojure Leiningen template](https://github.com/puniverse/comsat-ring-template) as well which includes an `auto-instrument` branch that doesn't need any explicit suspendable-marking code (`suspendable!`, `defsfn`, `sfn` etc.) thanks to [Pulsar's new auto-instrumentation feature](http://docs.paralleluniverse.co/pulsar/#automatic-instrumentation).\n\nThis GitHub project contains examples covering most of the COMSAT functionality: [puniverse/comsat-examples](https://github.com/puniverse/comsat-examples).\n\nFinally there are several regularly updated third-party bootstrap projects: [Comsat + Dropwizard + jOOQ](https://github.com/circlespainter/comsat-jooq-gradle-template), [Comsat Web Actors Stock Quotes (ported from Akka)](https://github.com/circlespainter/quasar-stocks), [Spring MVC + Tomcat standalone servlet container](https://github.com/circlespainter/spring4-mvc-gradle-annotation-hello-world).\n\n### Enabling Comsat\n\nComsat runs code in [Quasar](http://docs.paralleluniverse.co/quasar/) fibers, which rely on bytecode instrumentation. This instrumentation is done in one of three ways: via a Java agent that must be loaded into the Servlet container; with a custom class-loader available for Tomcat and Jetty; or at compilation time.\n\nAOT instrumentation is an advanced topic explained in the [Quasar documentation](http://docs.paralleluniverse.co/quasar/index.html#instrumentation).\n\nWhen using AOT instrumentation alone, all of your fiber-blocking dependencies will need to have been AOT-compiled already. Please note that some Comsat modules, such as `comast-jersey-server`, rely on dynamic instrumentation of third-party libraries and so they cannot be used with AOT instrumentation alone.\n\n#### The Java Agent\n\nTo use the Java agent, the following must be added to the java command line (or use your favorite build tool to add this as a JVM argument) when launching the process:\n\n~~~ sh\n-javaagent:path-to-quasar-jar.jar\n~~~\n\nJava agent instrumentation works with standalone Java applications and embedded Servlet containers but at present it cannot be used with standalone Servlet containers.\n\n#### In Tomcat\n\nIf you're using Tomcat as your embedded or standalone Servlet container, a custom class-loader is available for use instead of the Java Agent. You'll need to put `comsat-tomcat-loader-{{site.version}}.jar` (or, for JDK8, `comsat-tomcat-loader-{{site.version}}-jdk8.jar`) into Tomcat's `common/lib` directory.\n\nThen, include the following in your webapp's `META-INF/context.xml`:\n\n~~~ xml\n{% include_snippet loader ./comsat-test-war/src/main/webapp/META-INF/context.xml %}\n~~~\n\nThe Tomcat instrumenting class-loader has been verified to work with Tomcat 7.0.62 and Tomcat 8.0.23 standalone Servlet containers.\n\n#### In Jetty\n\nIf you're using Jetty as your embedded Servlet container, you have the option to use a custom class-loader instead of the Java agent. You'll need to put `comsat-jetty-loader-{{site.version}}.jar` (or, for JDK8, `comsat-jetty-loader-{{site.version}}-jdk8.jar`) into Jetty's `lib` directory.\n\nThen, include a `<Set name=\"classLoader\">` tag in your webapp's context xml:\n\n~~~ xml\n{% include_snippet context xml ./comsat-jetty-loader/src/test/resources/webapps/dep.xml %}\n~~~\n\n### Building Comsat {#build}\n\nInstall [Gradle](http://www.gradle.org), then clone the repository:\n\n    git clone https://github.com/puniverse/comsat.git\n\nand finally run:\n\n    gradle install\n\nThe full testsuite can be run with `gradle build`.\n\n# User Manual\n\n{% capture javadoc %}{{site.baseurl}}/javadoc/co/paralleluniverse{% endcapture %}\n\n## Comsat Integration\n\n### Servlets\n\nComsat supports the Servlet 3.x specification (Java EE 6) and enables you to write servlets that can scale to many concurrent visitors, even if servicing each requests takes a very long time, or requires calling many other services. Under the hood, Comsat does this by turning each servlet request into an asynchronous request, and then services each on a separate [fiber](http://puniverse.github.io/quasar/manual/core.html#fibers). Calls to other web services or to a database can be fiber- rather than thread-blocking. As a result, Comsat can serve many thousands of concurrent requests with only a handful of OS threads. You, on the other hand, don't need to adopt a cumbersome asynchronous programming model. You can write the servlet code as you normally would, making synchronous (fiber-blocking) calls, provided that you use Comsat implementations.\n\nTo write a Comsat (fiber-per-request) servlet, simply extend [`FiberHttpServlet`]({{javadoc}}/fibers/servlet/FiberHttpServlet.html) rather than the usual `javax.servlet.HttpServlet`, and either annotate it with `@WebServlet`, declare it in `web.xml` or use the programmatic [initializer API](http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html). Note how the `service` and all the `doXXX` methods are [suspendable](http://puniverse.github.io/quasar/manual/core.html#fibers) since they're annotated with `@Suspendable`, although they don't declare throwing `SuspendExecution` in order to retain full servlet API compatibility.\n\nYou can deploy your servlet as you normally would, either as a WAR file (remember to enable async support for it), or in an embedded servlet container.\n\nIt is recommended that you then configure your servlet container to limit the number of threads in its thread pool to some small number, as all these threads do is create the fiber (which runs in the fiber thread pool) and return.\n\nExample:\n\n~~~ java\n{% include_snippet FiberHttpServlet example ./comsat-servlet/src/test/java/co/paralleluniverse/fibers/servlet/FiberHttpServletTest.java %}\n~~~\n\nThen you can simply add it as a regular servlet to you favorite servlet container, e.g. for embedded Jetty:\n\n~~~ java\n{% include_snippet servlet registration ./comsat-servlet/src/test/java/co/paralleluniverse/fibers/servlet/FiberHttpServletTest.java %}\n~~~\n\nTo learn about writing servlets, you can refer to the [Java Servlets tutorial](http://docs.oracle.com/javaee/6/tutorial/doc/bnafd.html).\n\nFinally some options can be configured globally via system properties or per-servlet through standard servlet configuration attributes:\n\n * `co.paralleluniverse.fibers.servlet.FiberHttpServlet.asyncTimeout` (ms): defines the asynchronous request's timeout (default = 120 seconds).\n * The following features are enabled by default and together they can add up to 8% overhead:\n   * `co.paralleluniverse.fibers.servlet.FiberHttpServlet.disableSyncExceptions`: if present or `true` as a system property or if `true` as a servlet config option it will disable the translation of exceptions to standard synchronous server exceptions via `dispatch`.\n   * `co.paralleluniverse.fibers.servlet.FiberHttpServlet.disableSyncForward`: if present or `true` as a system property or if `true` as a servlet config option it will disable the translation of async forward requests to standard synchronous forwards.\n * The following workarounds are enabled by default only when running in their respective servlet container and they can add up to 3% overhead:\n   * `co.paralleluniverse.fibers.servlet.FiberHttpServlet.disableJettyAsyncFixes`\n   * `co.paralleluniverse.fibers.servlet.FiberHttpServlet.disableTomcatAsyncFixes`\n\n\"Overhead\" here means \"percentage of execution time\" and it has been measured in benchmarks with no request processing (immediate response) and `localhost` network on an Linux Ubuntu Trusty box.\n\n### REST Services\n\nYou can easily create Comsat REST services with the [JAX-RS API](https://jax-rs-spec.java.net/nonav/2.0/apidocs/index.html), the standard Java REST service API. Comsat integrates with [Jersey](https://jersey.java.net/), the reference JAX-RS implementation.\n\nAll you need to do in order to enjoy Comsat's scalabilty, is replace the line\n\n~~~ xml\n<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>\n~~~\n\nin your `web.xml` file, which is how you would normally use Jersey in a Servlet container, with:\n\n~~~ xml\n<servlet-class>co.paralleluniverse.fibers.jersey.ServletContainer</servlet-class>\n<async-supported>true</async-supported>\n~~~\n\nYour resource methods (the ones you annotate with `@GET`, `@PUT`, `@POST` etc.) can now be made suspendable by declaring `throws SuspendExecution`. Comsat would then run each request in a fiber. Your resource methods are free to use Comsat's JDBC implementation, or Comsat's JAX-RS client.\n\nHere is an example of REST resource declaration:\n\n~~~ java\n{% include_snippet REST resource example ./comsat-jersey-server/src/test/java/co/paralleluniverse/fibers/jersey/TestResource.java %}\n~~~\n\nAnd then initialization of the jersey container:\n\n~~~ java\n{% include_snippet jersey registration ./comsat-jersey-server/src/test/java/co/paralleluniverse/fibers/jersey/FiberServletContainerTest.java %}\n~~~\nTo learn about writing REST services with JAX-RS, please refer to the [Jersey User Guide](https://jersey.java.net/documentation/latest/user-guide.html).\n\n{:.alert .alert-info}\n**Note**: [Web Actors](webactors.html) are a great way to write REST services, as well as web-socket services, for interactive web applications.\n\n### Clojure Ring\n\nThe Comsat Ring adapter is a fiber-blocking adapter based on Jetty 9: it will make your Ring handler run in a fiber rather than in a thread, boosting efficiency without requiring handler logic changes.\n\nComsat Ring is based on Pulsar, so it is necessary that the handler's fiber-blocking logic and all functions calling it are declared suspendable through either the `sfn` / `defsfn` macros or the `suspendable!` call (please refer to [Pulsar docs](http://docs.paralleluniverse.co/pulsar/#fibers) for details). This often means declaring suspendable the handler itself and middlewares applied to it. You can avoid making suspendable the resulting handler passed to the adapter though, as latter will do it for you.\n\nSo rather than:\n\n~~~ clojure\n(ns myapp.core\n  (:use ring.adapter.jetty))\n\n(defn- hello-world [request]\n  (Thread/sleep 100)\n  {:status  200\n   :headers {\"Content-Type\" \"text/plain\"}\n   :body    \"Hello World\"})\n\n(defn run [] (run-jetty hello-world {:port 8080}))\n~~~\n\nJust setup Pulsar as described in the [docs](http://docs.paralleluniverse.co/pulsar/#lein), remembering to add the `[co.paralleluniverse/comsat-ring-jetty9 \"{{site.version}}\"]` dependency, and change your `use` or `require` clauses slightly:\n\n~~~ clojure\n(ns myapp.core\n  (:use co.paralleluniverse.fiber.ring.jetty9)\n  (:import (co.paralleluniverse.fibers Fiber))\n  (:require [co.paralleluniverse.pulsar.core :as pc]))\n\n(pc/defsfn hello-world [request]\n  (Fiber/sleep 100)\n  {:status  200\n   :headers {\"Content-Type\" \"text/plain\"}\n   :body    \"Hello World\"})\n\n(defn run [] (run-jetty hello-world {:port 8080}))\n~~~\n\nYour handler is now running inside fibers rather than threads.\n\n### Clojure HTTP Kit Client\n\n[HTTP Kit](http://www.http-kit.org/) is a minimalist, efficient, Ring-compatible HTTP client/server for Clojure that supports async operation. The client API is an async subset of [clj-http](https://github.com/dakrone/clj-http) and the `comsat-httpkit` integration converts it back to straightforward fiber-blocking `clj-http` through the `await` function. Being only 18 lines of code, this integration also shows how easy it is to integrate Clojure async APIs with Pulsar.\n\nJust add `comsat-httpkit` to your dependencies and `require` the `co.paralleluniverse.fiber.httpkit.client` namespace. You can then use `request`, `get`, `delete`, `head`, `post`, `put`, `options`, `patch` inside your fibers as you would use `clj-http` (currently limited to the `clj-http` features supported by HTTP Kit):\n\n~~~ clojure\n(ns myapp\n  (:require\n    [co.paralleluniverse.fiber.httpkit.client :refer :all]\n    [co.paralleluniverse.pulsar.core :refer [fiber]]))\n\n(defn -main []\n  (println @(fiber (get \"http://google.com\"))))\n~~~\n\nHave also a look at the testsuite ported from HTTP Kit.\n\n### HTTP Clients\n\n#### Apache Http Client\nThe fiber blocking version of the Apache Http Client can be used with `FiberHttpClientBuilder`.\nFor example:\n\n~~~ java\n{% include_snippet client configuration ./comsat-httpclient/src/test/java/co/paralleluniverse/fibers/httpclient/FiberHttpClientBuilderTest.java %}\n~~~\n\nAfter that you can call the regular API from fibers:\n\n~~~ java\n{% include_snippet http call ./comsat-httpclient/src/test/java/co/paralleluniverse/fibers/httpclient/FiberHttpClientBuilderTest.java %}\n~~~\n\nIf you prefer to use the future API you should build a regular `HttpAsyncClient `and then wrap it with `FiberCloseableHttpAsyncClient.wrap`, for example\n\n~~~ java\n{% include_snippet client configuration ./comsat-httpclient/src/test/java/co/paralleluniverse/fibers/httpasyncclient/FiberHttpAsyncClientTest.java %}\n~~~\n\nThen you can use it as follows:\n\n~~~ java\n{% include_snippet future calls ./comsat-httpclient/src/test/java/co/paralleluniverse/fibers/httpasyncclient/FiberHttpAsyncClientTest.java %}\n~~~\n\n#### Jersey Http Client\n\nComsat's integrated HTTP client is a JAX-RS client (specifically, a Jersey client). To create a client instance compatible with Quasar fibers, use the [`AsyncClientBuilder`]({{javadoc}}/fibers/ws/rs/client/AsyncClientBuilder.html) class:\n\n~~~ java\nClient client = AsyncClientBuilder.newClient();\n~~~\n\nYou can also pass a configuration:\n\n~~~ java\nClient client = AsyncClientBuilder.newClient(config);\n~~~\n\nor use the builder API:\n\n~~~ java\n{% include_snippet client creation ./comsat-jax-rs-client/src/test/java/co/paralleluniverse/fibers/ws/rs/client/AsyncClientBuilderTest.java %}\n~~~\n\nThen the usage is like the regular API, for example:\n\n~~~ java\n{% include_snippet http call ./comsat-jax-rs-client/src/test/java/co/paralleluniverse/fibers/ws/rs/client/AsyncClientBuilderTest.java %}\n~~~\n\nTo learn how to use the HTTP client, please refer to the [Jersey documentation](https://jersey.java.net/documentation/latest/user-guide.html#client), or the [JAX-RS client Javadoc](http://docs.oracle.com/javaee/7/api/javax/ws/rs/client/package-summary.html).\n\nAll of the JAX-RS API is supported, and blocking calls are fiber- rather than thread-blocking. If you want to execute several requests in parallel, you may use any of the \"async\" methods that return a `Future`:\n\n~~~ java\nFuture response = resourceTarget.request(\"text/plain\").header(\"Foo\", \"bar\").async().get(String.class);\n~~~\n\nCalling `Future.get()` would also just block the fiber and not any OS thread.\n\n{:.alert .alert-info}\n**Note**: A method that makes use of the API and runs in a fiber must be declared [suspendable](http://puniverse.github.io/quasar/manual/core.html#fibers) (normally by declaring `throws SuspendExecution`).\n\n{:.alert .alert-warn}\n**Note**: the Jersey client's current implementation (since 2.5) has a significant disadvantage w.r.t ApacheHttpClient because it uses one thread per http call. Therefore it is not recommended until this is fixed.\n\n#### Retrofit\n\n[`Retrofit`](http://square.github.io/retrofit/) lets you access REST API through java interface. In order to use it from fibers you should first declare a `Suspendable` interface:\n\n~~~ java\n{% include_snippet interface ./comsat-retrofit/src/test/java/co/paralleluniverse/fibers/retrofit/FiberRestAdapterBuilderTest.java %}\n~~~\n\nThis interface can then be registered with `FiberRestAdapterBuilder` and then used from fibers:\n\n~~~ java\n{% include_snippet registration ./comsat-retrofit/src/test/java/co/paralleluniverse/fibers/retrofit/FiberRestAdapterBuilderTest.java %}// ...\n// usage from fiber context\n{% include_snippet usage ./comsat-retrofit/src/test/java/co/paralleluniverse/fibers/retrofit/FiberRestAdapterBuilderTest.java %}\n~~~\n\n#### OkHttp\n\nComsat integrates with [OkHttp](https://github.com/square/okhttp), a modern HTTP+SPDY client and offers fiber-blocking `OkHttpClient` and `Call` implementation.\n\nBuild fiber-friendly, fully OkHttp-compatible `FiberOkHttpClient` and `FiberCall` as follows:\n\n~~~ java\nRequest req = ...;\nOkHttpClient client = new FiberOkHttpClient();\nCall call = client.newCall(req);\n~~~\n\nOkHttp's `urlconnection` and `apache` modules are supported as well: just pass an `FiberOkHttpClient` instance when building `OkUrlFactory` and `OkApacheClient`:\n\n~~~ java\nOkUrlFactory factory = new OkUrlFactory(new FiberOkHttpClient());\nOkApacheClient client = new OkApacheClient(new FiberOkHttpClient());\n~~~\n\n### DB Access\n\n#### JDBC\n\nThe `comsat-jdbc` project makes the JDBC API more efficient when using Quasar fibers (or fiber-backed actors). To use JDBC in fibers, simply wrap your database driver's `DataSource` with [`FiberDataSource`]({{javadoc}}/fibers/jdbc/FiberDataSource.html), and use it to obtain connections. For example:\n\n~~~ java\n{% include_snippet DataSource wrapping ./comsat-jdbc/src/test/java/co/paralleluniverse/fibers/jdbc/FiberDataSourceTest.java %}\n~~~\n\nThen the DataSource can be used with the regular API from fibers, For example:\n\n~~~ java\n{% include_snippet DataSource usage ./comsat-jdbc/src/test/java/co/paralleluniverse/fibers/jdbc/FiberDataSourceTest.java %}// ...\n// usage in fiber context\n{% include_snippet connection usage ./comsat-jdbc/src/test/java/co/paralleluniverse/fibers/jdbc/FiberConnectionTest.java %}\n~~~\n\n{:.alert .alert-info}\n**Note**: A method that makes use of the API and runs in a fiber must be declared [suspendable](http://puniverse.github.io/quasar/manual/core.html#fibers) (normally by declaring `throws SuspendExecution`).\n\nNormally, Comsat transforms asynchronous (callback based) API into fiber-blocking operations. JDBC, however, has no asynchronous API. `comsat-jdbc` simply runs the actual thread-blocking JDBC operations in a thread pool, and blocks the calling fiber until the operation has completed execution in the thread pool. As a result, you will not get any scalability benefits by calling your database in fibers (unlike, say, calling web services), because an OS thread will still block on every JDBC call. In practice, though, it matters little, as your database is likely to be a narrower bottleneck than the OS scheduler anyway.\n\n{:.alert .alert-warn}\n**Note**: Your application may only make direct use of the Comsat JDBC data source, because methods calling the API must be declared suspendable (or run on regular threads). Database access frameworks (like various ORM solutions) that make use of JDBC cannot use this data source and be used in Quasar fibers. In the future, we will provide separate integration module for some popular database access libraries.\n\nIf you want to learn how to use JDBC, the [JDBC tutorial](http://docs.oracle.com/javase/tutorial/jdbc/basics/) is a good resource.\n\n#### JDBC Deployment Via JNDI\n\nServlets often make use of JDBC data sources exposed through JNDI. If you do that, you can declare a COMSAT (i.e. a fiber-aware) JDBC data source through JNDI that will wrap your native data source. To do so, use the `co.paralleluniverse.fibers.jdbc.FiberDataSourceFactory` DataSource factory, and pass in the number of threads you'd like COMSAT to use in the JDBC worker pool.\n\nIn order to do that first you have to include `comsat-jdbc-{{site.version}}.jar` in your container's runtime classpath, by putting it into the container's `lib` directory.\n\nIf you're using `TOMCAT`, the following example is a snippet of `META-INF/context.xml` that will declare a DataSource under the `jdbc/fiberdb` name, which wraps a native DB declared under the `jdbc/globalds` name:\n\n~~~ xml\n<Context path=\"/\">\n...\n{% include_snippet fiber ds ./comsat-test-war/src/main/webapp/META-INF/context.xml %}</Context>\n~~~\n\nIn order to do the same thing with `Jetty`, you have to include similar definition in your `WEB-INF/jetty-env.xml`:\n\n~~~ xml\n{% include_snippet fiber ds ./comsat-test-war/src/main/webapp/WEB-INF/jetty-env.xml %}\n~~~\n\n#### JDBI\n\nTo use the powerful API of [JDBI](http://jdbi.org/) to access databases you first have to create an `IDBI` instance using the `FiberDBI` class:\n\n~~~ java\n{% include_snippet creation ./comsat-jdbi/src/test/java/co/paralleluniverse/fibers/jdbi/FiberFluentAPITest.java %}\n~~~\n\nThe created instance can be used both with the Fluent API as well as with the `SqlObject` API. First the fluent API example:\n\n~~~ java\n{% include_snippet usage ./comsat-jdbi/src/test/java/co/paralleluniverse/fibers/jdbi/FiberFluentAPITest.java %}\n~~~\n\nAs for the `SqlObject` API, declare first a `Suspendable` interface. Here is an example:\n\n~~~ java\n{% include_snippet interface ./comsat-jdbi/src/test/java/co/paralleluniverse/fibers/jdbi/FiberSqlObjectAPITest.java %}\n~~~\n\nThe interface now can be registered and used as usual from fibers:\n\n~~~ java\n{% include_snippet registration ./comsat-jdbi/src/test/java/co/paralleluniverse/fibers/jdbi/FiberSqlObjectAPITest.java %}//...\n// usage in fiber context\n{% include_snippet usage ./comsat-jdbi/src/test/java/co/paralleluniverse/fibers/jdbi/FiberSqlObjectAPITest.java %}\n~~~\n\n#### jOOQ\n\n[JOOQ](http://www.jooq.org/) is a comprehensive solution to access SQL databases. In order to use jOOQ from fibers, all you have to do is to provide a connection originated from `FiberDataSource`, for example:\n\n~~~ java\n{% include_snippet creation ./comsat-jooq/src/test/java/co/paralleluniverse/fibers/jooq/JooqContextTest.java %}// ...\n// mapper definition\n{% include_snippet mapper ./comsat-jooq/src/test/java/co/paralleluniverse/fibers/jooq/JooqContextTest.java %}// ...\n// usage in fiber context\n{% include_snippet usage ./comsat-jooq/src/test/java/co/paralleluniverse/fibers/jooq/JooqContextTest.java %}\n~~~\n\n#### MongoDB\n\nComsat integrates with MongoDB and offers a fiber-blocking [allanbank API](http://www.allanbank.com/mongodb-async-driver/index.html).\n\nThis is how you get a fiber-friendly `MongoDatabase` instance, which you can then use regularly from fibers:\n\n~~~ java\nMongoClient mongoClient = FiberMongoFactory.createClient( \"mongodb://localhost:\" + port + \"/test?maxConnectionCount=10\" ).asSerializedClient();\nMongoDatabase mongoDb = mongoClient.getDatabase(\"mydb\");\n~~~\n\n### Dropwizard\n\n[Dropwizard](http://dropwizard.io/) is a Java framework for developing ops-friendly, high-performance, RESTful web services.\n\nOnly few changes are needed in order to use dropwizard with fibers.\n\nFirst the YAML configuration file:\n\n~~~ yaml\n{% include_snippet server ./comsat-dropwizard/src/test/resources/server.yml %}\n~~~\n\nThe number of concurrent threads needed for the `comsat-dropwizard` container will be low even if the number of concurrent connection is high because threads will just hand the established connections to newly created fibers. 50 to 200 threads will be enough but you should increase the queue size. You also need to configure an adequate `requestLog` appender (or disable it). Next is the `httpClient` configuration:\n\n~~~ yaml\n{% include_snippet httpclient ./comsat-dropwizard/src/test/resources/server.yml %}\n~~~\n\nYou should also increase `maxConnections`.\n\nThe DB configuration will be as usual (and, as usual, you should include the DB driver in your runtime classpath):\n\n~~~ yaml\n{% include_snippet db ./comsat-dropwizard/src/test/resources/server.yml %}\n~~~\n\nAs for the code:\n\n~~~ java\n{% include_snippet app ./comsat-dropwizard/src/test/java/co/paralleluniverse/fibers/dropwizard/MyDropwizardApp.java %}\n~~~\n\nInstead of extending the regular `io.dropwizard.Application` class, you should extend the Comsat's `FiberApplication`. Your regular `run` function should be named `fiberRun` instead. The creation of the HTTP client should be through `FiberHttpClientBuilder` and the creation of `jdbi` should be through `FiberDBIFactory`.\n\n### Spring\n\n[Spring Framework](http://projects.spring.io/spring-framework/) is a popular Dependency Injection engine; it integrates with many enterprise Java tools and libraries and complements them with uniform and easy-to-use APIs.\n\n[Spring Boot](http://projects.spring.io/spring-boot/) adds fast project bootstrap facilities, convention over configuration, auto-configuration based on classpath (and other conditions) and embedded Tomcat and Jetty containers integration. It also provides [Actuator](http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready), a set of ready-to-use facilities for production environments like auditing, health-checks, metrics and JMX monitoring/management through JMX's native protocol, HTTP, SSH or telnet.\n\n[Spring Security](http://projects.spring.io/spring-security/) is a comprehensive Java security framework encompassing authentication and authorization for traditional and web applications, and the de-facto standard for securing Spring-based projects.\n\nComsat provides the ability to write fiber-blocking Spring Web MVC controllers with (optional) Spring Boot auto-configuration and (still optional) Spring Security context inheritance for fibers.\n\n#### Fiber-blocking Spring Web MVC controllers\n\nAdding support for fiber-blocking Spring Web MVC controllers is as easy as replacing in your Spring configuration class the `@EnableWebMvc` annotation with `@Import(FiberWebMvcConfigurationSupport.class)`, for example:\n\n~~~ java\n{% include_snippet import ./comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-traditional/src/main/java/comsat/sample/traditional/SampleTraditionalApplication.java %}\n~~~\n\n...And declaring your controller methods as suspendable, as you would normally do with any fiber-blocking method:\n\n~~~ java\n{% include_snippet suspendable ./comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/main/java/comsat/sample/actuator/SampleController.java %}\n~~~\n\nSpring Web MVC controller methods that have not been annotated (nor otherwise instrumented) to be suspendable will be invoked in thread-blocking mode rather than fiber-blocking.\n\n#### Spring Security support\n\nBy default, Spring Security stores the server-side security context for the current user in a Java `ThreadLocal`. For suspendable Spring Web MVC controllers to inherit the security context, the strategy Spring uses mut be reconfigured to use Java's `InheritableThreadLocal` instead (please be aware that this is JVM-level global setting).\n\nThis is as easy as adding an `@Import` for the `co.paralleluniverse.springframework.security.config.FiberSecurityContextHolderConfig` configuration class:\n\n~~~ java\n{% include_snippet import ./comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-actuator/src/main/java/comsat/sample/actuator/SampleActuatorApplication.java %}\n~~~\n\nAt present there is one small caveat to consider when using Spring method security: as Spring will proxy secured methods so that all declared exceptions (including `SuspendExecution`) are catched individually, Quasar will refuse to instrument them. In this specific case `SuspendExecution` should not be declared but catched in the method body, and the method signature should be annotated with `@Suspendable` instead.\n\n#### Spring Boot auto-configuration support\n\nIf you prefer using auto-configuration, it is enough to use the `FiberSpringBootApplication` or `FiberSecureSpringBootApplication` annotation instead, depending if you want to use Spring Security and its support for fibers:\n\n~~~ java\n{% include_snippet import ./comsat-spring/comsat-spring-boot/comsat-spring-boot-sample-web-groovy-templates/src/main/java/comsat/sample/ui/SampleGroovyTemplateApplication.java %}\n~~~\n\n## Web Actors\n\nWeb Actors are [Quasar actors](http://puniverse.github.io/quasar/manual/actors.html) that receive and respond to messages from web clients. Web actors support HTTP, WebSocket and SSE (Server-Sent Events) messages and are a convenient, efficient, and natural method to implement backends for interactive web applications.\n\nWeb Actors are deployed on a web server. Currently they can be deployed as a [Netty](http://netty.io/) handler, as an [Undertow](http://undertow.io/) handler as well as in any JavaEE 7 servlet container.\n\n### Netty deployment\n\nDeploying web actors on top of Netty is as easy as inserting one of two Netty handlers in your pipeline: either `AutoWebActorHandler` or `WebActorHandler`.\n\n`AutoWebActorHandler` will automatically scan the classpath for classes with the `@WebActor` annotation upon first use and  will then instantiate and start the appropriate actor class (among detected ones) once per client session. Its constructor requires no arguments but optionally a user-specified classloader and/or a map containing per-class actor constructor parameters can be provided.\n\nThe only other requirement is that your channel pipeline contains separate `HttpRequestDecoder` and `HttpResponseEncoder` instances rather than a single `HttpServerCodec` because the `HttpResponseEncoder` needs to be dynamically removed when an SSE exchange starts. If you prefer, as an alternative you can pass to `AutoWebActorHandler`'s constructor the name of the installed `HttpResponseEncoder`.\n\nHere's an example server setup using `AutoWebActorHandler` without construction arguments (have a look at `comsat-actors-netty`'s tests for further insight):\n\n~~~ java\nfinal NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);\nfinal NioEventLoopGroup workerGroup = new NioEventLoopGroup();\nfinal ServerBootstrap b = new ServerBootstrap();\nb.group(bossGroup, workerGroup)\n    .channel(NioServerSocketChannel.class)\n    .handler(new LoggingHandler(LogLevel.INFO))\n    .childHandler(new ChannelInitializer<SocketChannel>() {\n        @Override\n        public void initChannel(SocketChannel ch) throws Exception {\n            ChannelPipeline pipeline = ch.pipeline();\n            pipeline.addLast(new HttpRequestDecoder());\n            pipeline.addLast(new HttpResponseEncoder());\n            pipeline.addLast(new HttpObjectAggregator(65536));\n\n            pipeline.addLast(new AutoWebActorHandler());\n        }\n    });\n\nfinal ChannelFuture ch = b.bind(INET_PORT).sync();\n~~~\n\n`WebActorHandler` needs (and enables by default) cookie-based client session tracking only for SSE exchanges but it can enabled for all requests through the `co.paralleluniverse.comsat.webactors.netty.WebActorHandler.HttpChannelAdapter.trackSession` system property (legal values are `sse` and `always`). The cookie name will be `JSESSIONID` as in most server-side HTTP Java APIs with session support (e.g. servlets).\n\nThe Netty WebActor backend will always include the `Date` header by default but this behaviour can be configured through the `co.paralleluniverse.comsat.webactors.netty.WebActorHandler.HttpChannelAdapter.omitDateHeader` system property\n\nThe session duration for the default implementation is 60 seconds but it can be configured through the `co.paralleluniverse.comsat.webactors.netty.WebActorHandler.DefaultContextImpl.durationMillis` system property.\n\n### Undertow deployment\n\nDeploying web actors on top of Undertow is as easy as using one of two Undertow handlers: either `AutoWebActorHandler` or `WebActorHandler`.\n\n`AutoWebActorHandler` will automatically scan the classpath for classes with the `@WebActor` annotation upon first use and will then instantiate and start the appropriate actor class (among detected ones) once per client session (or connection if there's no session, see below). Its constructor requires no arguments but optionally a user-specified classloader and/or a map containing per-class actor constructor parameters can be provided.\n\nHere's an example server setup using `AutoWebActorHandler` without construction arguments (have a look at `comsat-actors-undertow`'s tests for more insight):\n\n~~~ java\nfinal SessionManager sessionManager = new InMemorySessionManager(\"SESSION_MANAGER\", 1, true);\nfinal SessionCookieConfig sessionConfig = new SessionCookieConfig();\nsessionConfig.setMaxAge(60);\nfinal SessionAttachmentHandler sessionAttachmentHandler =\n    new SessionAttachmentHandler(sessionManager, sessionConfig);\n\nserver = Undertow.builder().addHttpListener(INET_PORT, \"localhost\")\n     .setHandler(sessionAttachmentHandler.setNext(new AutoWebActorHandler())).build();\n\nserver.start();\n~~~\n\nNotice that the session handler is installed as well: `AutoWebActorHandler` will use Undertow sessions if available, else it will create a new actor instance for every exchange.\n\nIf not using Undertow sessions please consider that `WebActorHandler` assumes the same actor will manage a whole SSE session.\n\nThe actor context validity is 60 seconds by default but it can be configured through the `co.paralleluniverse.comsat.webactors.undertow.WebActorHandler.DefaultContextImpl.durationMillis` system property.\n\n### Servlet deployment\n\nA web actor is attached to a servlet web session. It can be spawned and attached manually (say, after the user logs in and the session is authenticated). The manual attachment API unfortunately is container dependent. A web actor can also be spawned and attached automatically by letting COMSAT spawn and attach a web actor to every newly created session and this method will be described below. Because a web actor consumes very few resources, spawning them automatically is sufficient in all but the most extreme circumstances.\n\nFor automatic deployment, all you have to do is define an actor class (one that extends `BasicActor` or `Actor`), and annotate it with the [`WebActor`]({{javadoc}}comsat/webactors/WebActor.html) annotation. For example:\n\n~~~ java\n@WebActor(name=\"chat\", httpUrlPatterns=\"/chat\", webSocketUrlPatterns=\"/chat/ws\")\npublic class ChatActor extends BasicActor<WebMessage, Void> {\n    @Override\n    protected Void doRun() {\n        // ...\n    }\n}\n~~~\n\nIn this example, all HTTP requests to the `/chat` resource, as well as all websocket messages to `/chat/ws` will be received as messages by the actor. A new `ChatActor` will be spawned for every new HTTP session.\n\n#### Embedded containers\n\nIf you use embedded container, you have to register `WebActorInitializer` as a `ServletContextListener` to your servlet container. It will scan and register the web actors according to the `@WebActor` annotation:\n\n~~~ java\n{% include_snippet WebActorInitializer ./comsat-actors-servlet/src/test/java/co/paralleluniverse/comsat/webactors/servlet/WebActorServletTest.java %}\n~~~\n\nWeb actors may use websockets. In order to do that the container has to be configured to support it and unfortunately there's no standard mechanism for that yet. With Jetty you have to include the `javax-websocket-server-impl` jar and call the following method before you start the container:\n\n~~~ java\nWebSocketServerContainerInitializer.configureContext(context);\n~~~\n\nWith Tomcat you have to include the `tomcat-embed-websocket` jar and register `ServletContainerInitilizer`:\n\n~~~ java\ncontext.addServletContainerInitializer(new WsSci(), null);\n~~~\n\nWith Undertow you'll need the `undertow-websockets-jsr` jar; the setup is then a bit more involved as Undertow's `ServerWebSocketContainer` requires several construction arguments.\n\nYou can find an example for each of the servers above in the `comsat-test-utils` project [here](https://github.com/puniverse/comsat/tree/master/comsat-test-utils/src/main/java/co/paralleluniverse/embedded/containers): each embedded server utility class has an `enableWebsockets` method that performs the websockets setup.\n\nFor further details about the Web Actors API see the [Javadoc]({{javadoc}}/comsat/webactors/WebActor.html).\n\n### Basic Operation\n\nA web actor will receive messages of type [`WebMessage`]({{javadoc}}/comsat/webactors/WebMessage.html), which is the supertype of all messages that can be received from or sent to a web client. The class encapsulates a message body which can be either text or binary, and a *sender*, which, following a common actor pattern, is the actor that sent the message.\n\nFor messages received from the web client, the *sender* is a virtual actor representing the web client. You can perform normal actor operations on it, like `watch` to detect actor death; their semantics depend on the specific type of the message.\n\nA single web actor instance may handle HTTP requests, emit SSE events, and handle one or more WebSocket connections.\n\n### HTTP (REST Services)\n\nA web actor is attached to one or more HTTP resources (as specified by `@WebActor`'s `httpUrlPatterns` property), and an actor instance is associated with a single HTTP session. Every HTTP request to the resource, associated with the session, will be received by the actor as an [`HttpRequest`]({{javadoc}}/comsat/webactors/HttpRequest.html) message. The actor can then respond with an [`HttpResponse`]({{javadoc}}/comsat/webactors/HttpResponse.html) message, which it sends to the request's sender.\n\nAll HTTP request messages to a specific web actor instance will come from the same sender. If you `watch` that sender actor, it will emit an `ExitMessage` (signifying its death), when the session is terminated.\n\nWhen you respond to an `HttpRequest` with an `HttpResponse`, by default, the request stream will close. If, however, you wish to send the response's body in parts (e.g., for SSE, discussed in the next section), you may call `HttpRequest.openChannel`, which will return a Quasar *channel* that can be used to send [`WebDataMessage`]({{javadoc}}comsat/webactors/WebDataMessage.html)s messages to the stream. The stream will flush after each `WebDataMessage`'s body has been written to it. If `openChannel` has been called, the HTTP response stream will be closed when `close` is called on the returned channel.\n\nPlease refer to the [Javadoc]({{javadoc}}/comsat/webactors/HttpRequest.html) for details.\n\n### SSE\n\nSSE, or [Server-Sent Events](http://dev.w3.org/html5/eventsource/), is an HTML5 standard, supported by most modern browsers, for pushing discrete messages to the web client, without it sending new HTTP requests for each one. A good tutorial by Eric Bidelman on SSE can be found [here](http://www.html5rocks.com/en/tutorials/eventsource/basics/). An SSE stream is initiated with an HTTP request; then, each event message is written to the response stream and flushed, only the messages need to be encoded according to the SSE standard. SSE also specifies that if the connection is closed, the client will attempt to reconnect with a new request after a timeout, that can be set by the server.\n\nThe [`SSE`]({{javadoc}}/comsat/webactors/SSE.html) class contains a set of static utility methods that encode the events according to the SSE standard, and ensure that the response headers are set correctly (in terms of character encoding, etc.).\n\nTo start an SSE stream in response to an `HttpRequest`, do the following:\n\n~~~ java\nrequest.getFrom().send(new HttpResponse(self(), SSE.startSSE(request)));\n~~~\n\nThis will set `HttpResponse`'s `startActor` flag, which will leave the response stream open and send back an [`HttpStreamOpened`]({{javadoc}}/comsat/webactors/HttpStreamOpened.html) message from a newly created actor representing the SSE stream. Once you receive the message, you send SSE events by sending `WebDataMessage`s to that actor:\n\n~~~ java\nsseActor.send(new WebDataMessage(self(), SSE.event(\"this is an SSE event!\")));\n~~~\n\nTo close the stream, you send a `co.paralleluniverse.actors.ShutdownMessage` to the SSE actor like so:\n\n~~~ java\nco.paralleluniverse.actors.ActorUtil.sendOrInterrupt(sseActor, new ShutdownMessage());\n~~~\n\nIt might be convenient (and elegant) to wrap the channel returned by `openStream` with a *mapping channel* (see the Quasar docs) that will transform a message class representing the event into an SSE-encoded `WebDataMessage`.\n\n### WebSockets\n\n[WebSocket](http://en.wikipedia.org/wiki/WebSocket) is a new web protocol for low(ish)-latency, bi-directional communication between the client and the server. Web sockets are extremely useful for interactive web applications, and they fit beautifully with COMSAT Web Actors.\n\nA web actor may register itself to handle web socket connections by declaring which WebSocket URIs it is interested in, in the `@WebActor` annotations `webSocketUrlPatterns` property. Such a web actor will handle all web socket sessions at those URIs associated with the actor instance's HTTP session (a web socket is also associated with an HTTP session).\n\nWhen the client connects to a web socket, the web actor will receive a [`WebSocketOpened`]({{javadoc}}/comsat/webactors/WebSocketOpened.html) message, and each following message will be received as a [`WebDataMessage`]({{javadoc}}comsat/webactors/WebDataMessage.html). The actor can send messages to the client by replying to the sender with `WebDataMessage`s of its own.\n\nThe virtual actor that's the *sender* of the messages received from the client represents the WebSocket session; i.e., each open web socket will have a different actor as the sender of the messages. That virtual actor dies when the web socket connection closes.\n\n### Apache Kafka\n\n[Apache Kafka](http://kafka.apache.org/) is a fast publish-subscribe messaging solution rethought as a distributed commit log.\n\nThe `comsat-kafka` module provides a [Kafka Producer](https://kafka.apache.org/090/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html) with an asynchronous [`send`](https://kafka.apache.org/090/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html#send(org.apache.kafka.clients.producer.ProducerRecord,%20org.apache.kafka.clients.producer.Callback)) method that will return a Quasar [`SettableFuture`](http://docs.paralleluniverse.co/quasar/javadoc/index.html). A Quasar `SettableFuture` can block fibers in addition to threads.\n\n### Apache Shiro\n\n[Apache Shiro](http://shiro.apache.org/) is a security framework that performs authentication, authorization, cryptography, and session management.\n\nThe `comsat-shiro` module adds instrumentation to some Shiro methods (via `suspendables` and `suspendable-supers`) so that developer-provided [Shiro Realms](http://shiro.apache.org/realm.html) can perform fiber-blocking calls when queried by fibers using [SecurityUtils](http://shiro.apache.org/static/1.2.1/apidocs/org/apache/shiro/SecurityUtils.html):\n\n~~~ java\n    SecurityUtils.getSubject().login(...);\n    boolean isAuthorized = SecurityUtils.getSubject().isAuthenticated();\n    if (isAuthorized) {\n        isAuthorized = SecurityUtils.getSubject().hasRole(\"someRole\")\n            && SecurityUtils.getSubject().isPermitted(\"some:permission\");\n    }\n~~~\n"
  },
  {
    "path": "docs/js/main.js",
    "content": "$(document).ready(function() {\t\r\n\t/****************************** mobile device detection ***************************/\r\n\tvar isMobile = {\r\n\t\tAndroid: function() {\r\n\t\t\treturn navigator.userAgent.match(/Android/i);\r\n\t\t},\r\n\t\tBlackBerry: function() {\r\n\t\t\treturn navigator.userAgent.match(/BlackBerry/i);\r\n\t\t},\r\n\t\tiOS: function() {\r\n\t\t\treturn navigator.userAgent.match(/iPhone|iPad|iPod/i);\r\n\t\t},\r\n\t\tOpera: function() {\r\n\t\t\treturn navigator.userAgent.match(/Opera Mini/i);\r\n\t\t},\r\n\t\tWindows: function() {\r\n\t\t\treturn navigator.userAgent.match(/IEMobile/i);\r\n\t\t},\r\n\t\tany: function() {\r\n\t\t\treturn (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());\r\n\t\t}\r\n\t};\t\r\n\t\r\n\t$('#nav').superfish();\r\n\t\r\n\tif(!isMobile.any()){\r\n\t\t$(window).scroll(function() {\r\n\t\t\tvar offset = window.pageYOffset;\r\n\t\t\t\r\n\t\t\t//console.log(offset);\r\n\t\t\t// -x+(offset/y) -x is for the starting point | y is for the speed smaller value is faster\r\n\t\t\t\r\n\t\t\tif($('body').hasClass('documentation'))\r\n\t\t\t\tvar top_offset = 10;\r\n\t\t\telse\r\n\t\t\t\tvar top_offset = 120;\r\n\t\t\t\r\n\t\t\tif(offset>top_offset){\r\n\t\t\t\t$('body').addClass('fixed-head');\r\n\t\t\t} else {\r\n\t\t\t\t$('body').removeClass('fixed-head reverse-scroll');\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif(offset<3586){\r\n\t\t\t\t$('body').addClass('fixed');\r\n\t\t\t\t$('body').removeClass('noscroll');\r\n\t\t\t\t\r\n\t\t\t\t//intro animation\r\n\t\t\t\tif( offset < 70 ){\r\n\t\t\t\t\t$('#intro').stop().animate({\"top\" : 255},'ease');\t\r\n\t\t\t\t} else if( offset > 70 ){\r\n\t\t\t\t\t$('#intro').stop().animate({\"top\" : 900},'ease');\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t//first part\r\n\t\t\t\t//start from 70px scroll\r\n\t\t\t\tif( offset > 100 ){\r\n\t\t\t\t\t$('#part1').stop().animate({\"top\" : 0, \"right\" : 5},'ease');\t\r\n\t\t\t\t} else if( offset < 500 ) {\r\n\t\t\t\t\t$('#part1').stop().animate({\"top\" : -680, \"right\" : -680},'ease');\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t//first part | title\r\n\t\t\t\t//start from 150px scroll\r\n\t\t\t\tif( offset > 500 && offset < 800 ){\r\n\t\t\t\t\t$('#title1').stop().animate({\"opacity\" : 1});\t\r\n\t\t\t\t} else {\r\n\t\t\t\t\t$('#title1').stop().animate({\"opacity\" : 0});\r\n\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t//second part\r\n\t\t\t\t//start from 200px scroll\r\n\t\t\t\tif( offset > 800 ){\t\t\t\t\t\r\n\t\t\t\t\t$('#part2').stop().animate({\"top\" : 17, \"right\" : 8},'ease');\r\n\t\t\t\t} else if( offset < 1200 ) {\r\n\t\t\t\t\t$('#part2').stop().animate({\"top\" : -680, \"right\" : -680},'ease');\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t//second part | title\r\n\t\t\t\t//start from 230px scroll\r\n\t\t\t\tif( offset > 1200 && offset < 1500 ){\r\n\t\t\t\t\t$('#title2').stop().animate({\"opacity\" : 1});\t\r\n\t\t\t\t} else {\r\n\t\t\t\t\t$('#title2').stop().animate({\"opacity\" : 0});\r\n\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t//third part\r\n\t\t\t\t//start from 200px scroll\r\n\t\t\t\tif( offset > 1500 ){\r\n\t\t\t\t\t$('#part3').stop().animate({\"top\" : 23, \"right\" : 8},'ease');\r\n\t\t\t\t} else if( offset < 1900 ) {\r\n\t\t\t\t\t$('#part3').stop().animate({\"top\" : -680, \"right\" : -680},'ease');\t\r\n\t\t\t\t}\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t//third part | title\r\n\t\t\t\t//start from 250px scroll\r\n\t\t\t\tif( offset > 1900 && offset < 2200 ){\r\n\t\t\t\t\t$('#title3').stop().animate({\"opacity\" : 1});\t\r\n\t\t\t\t} else {\r\n\t\t\t\t\t$('#title3').stop().animate({\"opacity\" : 0});\r\n\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t//fourth part\r\n\t\t\t\t//start from 200px scroll\r\n\t\t\t\tif( offset > 2200 ){\r\n\t\t\t\t\t$('#part4').stop().animate({\"top\" : 20, \"right\" : 0},'ease');\r\n\t\t\t\t} else if( offset < 2600 ) {\r\n\t\t\t\t\t$('#part4').stop().animate({\"top\" : -680, \"right\" : -680},'ease');\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t//engine move\r\n\t\t\t\tif( offset > 2600 && offset < 3300 ){\r\n\t\t\t\t\t$('#engine').stop().animate({\"right\" : 340});\t\r\n\t\t\t\t} else {\r\n\t\t\t\t\t$('#engine').stop().animate({\"right\" : 0});\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t//fourth part | title\r\n\t\t\t\t//start from 230px scroll\r\n\t\t\t\tif( offset > 2900 && offset < 3300 ){\r\n\t\t\t\t\t$('#title4').stop().animate({\"opacity\" : 1});\t\r\n\t\t\t\t} else {\r\n\t\t\t\t\t$('#title4').stop().animate({\"opacity\" : 0});\r\n\t\t\t\t}\t\t\t\r\n\r\n\t\t\t\t//fadein title\r\n\t\t\t\tif(offset > 3300)\r\n\t\t\t\t\t$('#banner-title').fadeIn();\t\r\n\t\t\t\telse\r\n\t\t\t\t\t$('#banner-title').fadeOut();\r\n\t\t\t\t\r\n\t\t\t\t//fadein arrow\r\n\t\t\t\tif(offset > 3400)\r\n\t\t\t\t\t$('#section1 .scroll-to-arrow').stop().animate({\"opacity\":1});\r\n\t\t\t\telse if(offset < 3400)\r\n\t\t\t\t\t$('#section1 .scroll-to-arrow').stop().animate({\"opacity\":0});\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t} else {\r\n\t\t\t\t$('body').removeClass('fixed');\r\n\t\t\t}\r\n\t\t\r\n\t\t});\t\r\n\t\t\r\n\t\tvar offset = window.pageYOffset;\t\r\n\t\tif(offset>3586) {\r\n\t\t\t$('body').addClass('noscroll reverse-scroll');\t\r\n\t\t}\r\n\t} else {\r\n\t\t$('body').addClass('noscroll reverse-scroll mobile');\t\r\n\t}\r\n\t\r\n\t\r\n\t$('#tabs-btns a').click(function(){\r\n\t\tif( !$(this).parent().hasClass('active') ){\r\n\t\t\t$('#tabs-btns li').removeClass('active');\r\n\t\t\t$(this).parent().addClass('active');\r\n\t\t\t$('.tab-cont').hide();\r\n\t\t\t$($(this).attr('href')).fadeIn();\r\n\t\t}\r\n\t\treturn false;\r\n\t});\r\n\t$('#tabs-btns li:first-child a').trigger('click');\r\n\t\r\n\t$('.scroll-to').click(function(){\r\n\t\t$('html,body').animate({scrollTop: $( $(this).attr('href') ).offset().top - 55},500);\r\n\t\treturn false;\r\n\t});\r\n\t\r\n\t$('.acc h4').click(function() {\t\t\r\n\t\tif( $(this).next().is(':visible')==false ){\r\n\t\t\t$('.acc-cont').slideUp();\r\n\t\t\t$(this).next().slideDown();\r\n\t\t\t$('.acc').removeClass('active');\t\t\t\r\n\t\t\t$(this).parent().addClass('active');\r\n\t\t}else{\r\n\t\t\t$(this).next().slideUp();\r\n\t\t\t$(this).parent().removeClass('active');\r\n\t\t}\t\t\r\n\t\treturn false;\r\n\t});\t\r\n\t$('.acc:first h4').trigger('click');\t\r\n\t\r\n\tif( $('.subnav').length ){\r\n\t\t$(\".subnav\").hcSticky({top: 55,noContainer:true});\r\n\t}\r\n\r\n\tvar menuHeight = $(\"#docs-sidemenu\").height();\r\n\tfunction startScrolling(){\r\n\t\t//console.log(menuHeight + ' ' + $(window).height())\r\n\t\tif(menuHeight+123 > $(window).height())\r\n\t\t\t$(\"#docs-sidemenu\").addClass('scrolling').removeClass('stay');\r\n\t\telse\r\n\t\t\t$(\"#docs-sidemenu\").addClass('scrolling-big').removeClass('stay');\r\n\t}\r\n\tfunction stopScrolling(){\r\n\t\t$(\"#docs-sidemenu\").removeClass('scrolling').removeClass('scrolling-big');\t\r\n\t}\r\n\tfunction stickBottom(){\r\n\t\t$(\"#docs-sidemenu\").removeClass('scrolling').removeClass('scrolling-big').addClass('stay');\r\n\t}\t\r\n\t\r\n\t//$(\"#docs-sidemenu\").hcSticky({top: 123,onStart:startScrolling,onStop:stopScrolling});\r\n\t\r\n\tfunction makeSidebarSticky(){\r\n\t\tvar offset = window.pageYOffset;\r\n\t\tvar bottom = parseInt($(document).scrollTop())+parseInt($(window).height());\r\n\t\tvar docHeight = $(document).outerHeight();\r\n\t\tvar sidebarBottomOffset = $('.sidebar').offset().top + $('.sidebar').height();\r\n\t\tvar est = $(window).height() - menuHeight-123;\r\n\t\t\r\n\t\t$(\"#docs-sidemenu\").css({\"left\": $('.sidebar').offset().left});\r\n\t\tif(offset>=75){\r\n\t\t\tif(bottom + ($(document).outerHeight() - sidebarBottomOffset ) > docHeight && menuHeight>$(window).height()){\r\n\t\t\t\tstickBottom();\r\n\t\t\t} else if(bottom + ($(document).outerHeight() - sidebarBottomOffset - est ) > docHeight && menuHeight<$(window).height()){\r\n\t\t\t\tstickBottom();\r\n\t\t\t} else {\r\n\t\t\t\tstartScrolling();\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tstopScrolling();\r\n\t\t}\t\t\r\n\t}\r\n\t\r\n\t$(window).scroll(makeSidebarSticky).resize(makeSidebarSticky).load(makeSidebarSticky);\r\n\t\r\n\t\r\n\r\n\t$('#docs-sidemenu').onePageNav({\r\n\t\tcurrentClass: 'current',\r\n\t\tchangeHash: false,\r\n\t\tscrollSpeed: 100,\r\n\t\tscrollOffset: 127,\r\n\t\tscrollThreshold: 0.05\r\n\t});\r\n\t\r\n\tif(window.location.hash) {\r\n\t  var hash = window.location.hash.substring(1);\r\n\t  $(window).load(function(){\r\n\t  \t$('html,body').animate({scrollTop: $( '#'+hash ).offset().top - 127},500);\r\n\t  });\r\n\t}\r\n\t//$(window).load(function(){ $('#docs-cont .sidebar').height( $('#docs-cont .main').outerHeight() ); });\r\n\t\r\n\t\t\t\t\r\n});\r\n"
  },
  {
    "path": "docs/js/plugins.js",
    "content": "// Avoid `console` errors in browsers that lack a console.\r\n(function() {\r\n    var method;\r\n    var noop = function () {};\r\n    var methods = [\r\n        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',\r\n        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',\r\n        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',\r\n        'timeStamp', 'trace', 'warn'\r\n    ];\r\n    var length = methods.length;\r\n    var console = (window.console = window.console || {});\r\n\r\n    while (length--) {\r\n        method = methods[length];\r\n\r\n        // Only stub undefined methods.\r\n        if (!console[method]) {\r\n            console[method] = noop;\r\n        }\r\n    }\r\n}());\r\n\r\n// All the plugins/helpers\r\n\r\n/*\r\n * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/\r\n *\r\n * Uses the built In easIng capabilities added In jQuery 1.1\r\n * to offer multiple easIng options\r\n *\r\n * Copyright (c) 2007 George Smith\r\n * Licensed under the MIT License:\r\n *   http://www.opensource.org/licenses/mit-license.php\r\n */\r\n\r\n// t: current time, b: begInnIng value, c: change In value, d: duration\r\njQuery.easing['jswing'] = jQuery.easing['swing'];\r\n\r\njQuery.extend( jQuery.easing,\r\n{\r\n\tdef: 'easeOutQuad',\r\n\tswing: function (x, t, b, c, d) {\r\n\t\t//alert(jQuery.easing.default);\r\n\t\treturn jQuery.easing[jQuery.easing.def](x, t, b, c, d);\r\n\t},\r\n\teaseInQuad: function (x, t, b, c, d) {\r\n\t\treturn c*(t/=d)*t + b;\r\n\t},\r\n\teaseOutQuad: function (x, t, b, c, d) {\r\n\t\treturn -c *(t/=d)*(t-2) + b;\r\n\t},\r\n\teaseInOutQuad: function (x, t, b, c, d) {\r\n\t\tif ((t/=d/2) < 1) return c/2*t*t + b;\r\n\t\treturn -c/2 * ((--t)*(t-2) - 1) + b;\r\n\t},\r\n\teaseInCubic: function (x, t, b, c, d) {\r\n\t\treturn c*(t/=d)*t*t + b;\r\n\t},\r\n\teaseOutCubic: function (x, t, b, c, d) {\r\n\t\treturn c*((t=t/d-1)*t*t + 1) + b;\r\n\t},\r\n\teaseInOutCubic: function (x, t, b, c, d) {\r\n\t\tif ((t/=d/2) < 1) return c/2*t*t*t + b;\r\n\t\treturn c/2*((t-=2)*t*t + 2) + b;\r\n\t},\r\n\teaseInQuart: function (x, t, b, c, d) {\r\n\t\treturn c*(t/=d)*t*t*t + b;\r\n\t},\r\n\teaseOutQuart: function (x, t, b, c, d) {\r\n\t\treturn -c * ((t=t/d-1)*t*t*t - 1) + b;\r\n\t},\r\n\teaseInOutQuart: function (x, t, b, c, d) {\r\n\t\tif ((t/=d/2) < 1) return c/2*t*t*t*t + b;\r\n\t\treturn -c/2 * ((t-=2)*t*t*t - 2) + b;\r\n\t},\r\n\teaseInQuint: function (x, t, b, c, d) {\r\n\t\treturn c*(t/=d)*t*t*t*t + b;\r\n\t},\r\n\teaseOutQuint: function (x, t, b, c, d) {\r\n\t\treturn c*((t=t/d-1)*t*t*t*t + 1) + b;\r\n\t},\r\n\teaseInOutQuint: function (x, t, b, c, d) {\r\n\t\tif ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;\r\n\t\treturn c/2*((t-=2)*t*t*t*t + 2) + b;\r\n\t},\r\n\teaseInSine: function (x, t, b, c, d) {\r\n\t\treturn -c * Math.cos(t/d * (Math.PI/2)) + c + b;\r\n\t},\r\n\teaseOutSine: function (x, t, b, c, d) {\r\n\t\treturn c * Math.sin(t/d * (Math.PI/2)) + b;\r\n\t},\r\n\teaseInOutSine: function (x, t, b, c, d) {\r\n\t\treturn -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;\r\n\t},\r\n\teaseInExpo: function (x, t, b, c, d) {\r\n\t\treturn (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;\r\n\t},\r\n\teaseOutExpo: function (x, t, b, c, d) {\r\n\t\treturn (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;\r\n\t},\r\n\teaseInOutExpo: function (x, t, b, c, d) {\r\n\t\tif (t==0) return b;\r\n\t\tif (t==d) return b+c;\r\n\t\tif ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;\r\n\t\treturn c/2 * (-Math.pow(2, -10 * --t) + 2) + b;\r\n\t},\r\n\teaseInCirc: function (x, t, b, c, d) {\r\n\t\treturn -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;\r\n\t},\r\n\teaseOutCirc: function (x, t, b, c, d) {\r\n\t\treturn c * Math.sqrt(1 - (t=t/d-1)*t) + b;\r\n\t},\r\n\teaseInOutCirc: function (x, t, b, c, d) {\r\n\t\tif ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;\r\n\t\treturn c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;\r\n\t},\r\n\teaseInElastic: function (x, t, b, c, d) {\r\n\t\tvar s=1.70158;var p=0;var a=c;\r\n\t\tif (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;\r\n\t\tif (a < Math.abs(c)) { a=c; var s=p/4; }\r\n\t\telse var s = p/(2*Math.PI) * Math.asin (c/a);\r\n\t\treturn -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;\r\n\t},\r\n\teaseOutElastic: function (x, t, b, c, d) {\r\n\t\tvar s=1.70158;var p=0;var a=c;\r\n\t\tif (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;\r\n\t\tif (a < Math.abs(c)) { a=c; var s=p/4; }\r\n\t\telse var s = p/(2*Math.PI) * Math.asin (c/a);\r\n\t\treturn a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;\r\n\t},\r\n\teaseInOutElastic: function (x, t, b, c, d) {\r\n\t\tvar s=1.70158;var p=0;var a=c;\r\n\t\tif (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);\r\n\t\tif (a < Math.abs(c)) { a=c; var s=p/4; }\r\n\t\telse var s = p/(2*Math.PI) * Math.asin (c/a);\r\n\t\tif (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;\r\n\t\treturn a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;\r\n\t},\r\n\teaseInBack: function (x, t, b, c, d, s) {\r\n\t\tif (s == undefined) s = 1.70158;\r\n\t\treturn c*(t/=d)*t*((s+1)*t - s) + b;\r\n\t},\r\n\teaseOutBack: function (x, t, b, c, d, s) {\r\n\t\tif (s == undefined) s = 1.70158;\r\n\t\treturn c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;\r\n\t},\r\n\teaseInOutBack: function (x, t, b, c, d, s) {\r\n\t\tif (s == undefined) s = 1.70158; \r\n\t\tif ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;\r\n\t\treturn c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;\r\n\t},\r\n\teaseInBounce: function (x, t, b, c, d) {\r\n\t\treturn c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;\r\n\t},\r\n\teaseOutBounce: function (x, t, b, c, d) {\r\n\t\tif ((t/=d) < (1/2.75)) {\r\n\t\t\treturn c*(7.5625*t*t) + b;\r\n\t\t} else if (t < (2/2.75)) {\r\n\t\t\treturn c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;\r\n\t\t} else if (t < (2.5/2.75)) {\r\n\t\t\treturn c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;\r\n\t\t} else {\r\n\t\t\treturn c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;\r\n\t\t}\r\n\t},\r\n\teaseInOutBounce: function (x, t, b, c, d) {\r\n\t\tif (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;\r\n\t\treturn jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;\r\n\t}\r\n});\r\n\r\n/*\r\n * jQuery Superfish Menu Plugin\r\n * Copyright (c) 2013 Joel Birch\r\n *\r\n * Dual licensed under the MIT and GPL licenses:\r\n *\thttp://www.opensource.org/licenses/mit-license.php\r\n *\thttp://www.gnu.org/licenses/gpl.html\r\n */\r\n\r\n(function ($) {\r\n\t\"use strict\";\r\n\r\n\tvar methods = (function () {\r\n\t\t// private properties and methods go here\r\n\t\tvar c = {\r\n\t\t\t\tbcClass: 'sf-breadcrumb',\r\n\t\t\t\tmenuClass: 'sf-js-enabled',\r\n\t\t\t\tanchorClass: 'sf-with-ul',\r\n\t\t\t\tmenuArrowClass: 'sf-arrows'\r\n\t\t\t},\r\n\t\t\tios = (function () {\r\n\t\t\t\tvar ios = /iPhone|iPad|iPod/i.test(navigator.userAgent);\r\n\t\t\t\tif (ios) {\r\n\t\t\t\t\t// iOS clicks only bubble as far as body children\r\n\t\t\t\t\t$(window).load(function () {\r\n\t\t\t\t\t\t$('body').children().on('click', $.noop);\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t\treturn ios;\r\n\t\t\t})(),\r\n\t\t\twp7 = (function () {\r\n\t\t\t\tvar style = document.documentElement.style;\r\n\t\t\t\treturn ('behavior' in style && 'fill' in style && /iemobile/i.test(navigator.userAgent));\r\n\t\t\t})(),\r\n\t\t\ttoggleMenuClasses = function ($menu, o) {\r\n\t\t\t\tvar classes = c.menuClass;\r\n\t\t\t\tif (o.cssArrows) {\r\n\t\t\t\t\tclasses += ' ' + c.menuArrowClass;\r\n\t\t\t\t}\r\n\t\t\t\t$menu.toggleClass(classes);\r\n\t\t\t},\r\n\t\t\tsetPathToCurrent = function ($menu, o) {\r\n\t\t\t\treturn $menu.find('li.' + o.pathClass).slice(0, o.pathLevels)\r\n\t\t\t\t\t.addClass(o.hoverClass + ' ' + c.bcClass)\r\n\t\t\t\t\t\t.filter(function () {\r\n\t\t\t\t\t\t\treturn ($(this).children(o.popUpSelector).hide().show().length);\r\n\t\t\t\t\t\t}).removeClass(o.pathClass);\r\n\t\t\t},\r\n\t\t\ttoggleAnchorClass = function ($li) {\r\n\t\t\t\t$li.children('a').toggleClass(c.anchorClass);\r\n\t\t\t},\r\n\t\t\ttoggleTouchAction = function ($menu) {\r\n\t\t\t\tvar touchAction = $menu.css('ms-touch-action');\r\n\t\t\t\ttouchAction = (touchAction === 'pan-y') ? 'auto' : 'pan-y';\r\n\t\t\t\t$menu.css('ms-touch-action', touchAction);\r\n\t\t\t},\r\n\t\t\tapplyHandlers = function ($menu, o) {\r\n\t\t\t\tvar targets = 'li:has(' + o.popUpSelector + ')';\r\n\t\t\t\tif ($.fn.hoverIntent && !o.disableHI) {\r\n\t\t\t\t\t$menu.hoverIntent(over, out, targets);\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\t$menu\r\n\t\t\t\t\t\t.on('mouseenter.superfish', targets, over)\r\n\t\t\t\t\t\t.on('mouseleave.superfish', targets, out);\r\n\t\t\t\t}\r\n\t\t\t\tvar touchevent = 'MSPointerDown.superfish';\r\n\t\t\t\tif (!ios) {\r\n\t\t\t\t\ttouchevent += ' touchend.superfish';\r\n\t\t\t\t}\r\n\t\t\t\tif (wp7) {\r\n\t\t\t\t\ttouchevent += ' mousedown.superfish';\r\n\t\t\t\t}\r\n\t\t\t\t$menu\r\n\t\t\t\t\t.on('focusin.superfish', 'li', over)\r\n\t\t\t\t\t.on('focusout.superfish', 'li', out)\r\n\t\t\t\t\t.on(touchevent, 'a', o, touchHandler);\r\n\t\t\t},\r\n\t\t\ttouchHandler = function (e) {\r\n\t\t\t\tvar $this = $(this),\r\n\t\t\t\t\t$ul = $this.siblings(e.data.popUpSelector);\r\n\r\n\t\t\t\tif ($ul.length > 0 && $ul.is(':hidden')) {\r\n\t\t\t\t\t$this.one('click.superfish', false);\r\n\t\t\t\t\tif (e.type === 'MSPointerDown') {\r\n\t\t\t\t\t\t$this.trigger('focus');\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t$.proxy(over, $this.parent('li'))();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tover = function () {\r\n\t\t\t\tvar $this = $(this),\r\n\t\t\t\t\to = getOptions($this);\r\n\t\t\t\tclearTimeout(o.sfTimer);\r\n\t\t\t\t$this.siblings().superfish('hide').end().superfish('show');\r\n\t\t\t},\r\n\t\t\tout = function () {\r\n\t\t\t\tvar $this = $(this),\r\n\t\t\t\t\to = getOptions($this);\r\n\t\t\t\tif (ios) {\r\n\t\t\t\t\t$.proxy(close, $this, o)();\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tclearTimeout(o.sfTimer);\r\n\t\t\t\t\to.sfTimer = setTimeout($.proxy(close, $this, o), o.delay);\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tclose = function (o) {\r\n\t\t\t\to.retainPath = ($.inArray(this[0], o.$path) > -1);\r\n\t\t\t\tthis.superfish('hide');\r\n\r\n\t\t\t\tif (!this.parents('.' + o.hoverClass).length) {\r\n\t\t\t\t\to.onIdle.call(getMenu(this));\r\n\t\t\t\t\tif (o.$path.length) {\r\n\t\t\t\t\t\t$.proxy(over, o.$path)();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tgetMenu = function ($el) {\r\n\t\t\t\treturn $el.closest('.' + c.menuClass);\r\n\t\t\t},\r\n\t\t\tgetOptions = function ($el) {\r\n\t\t\t\treturn getMenu($el).data('sf-options');\r\n\t\t\t};\r\n\r\n\t\treturn {\r\n\t\t\t// public methods\r\n\t\t\thide: function (instant) {\r\n\t\t\t\tif (this.length) {\r\n\t\t\t\t\tvar $this = this,\r\n\t\t\t\t\t\to = getOptions($this);\r\n\t\t\t\t\tif (!o) {\r\n\t\t\t\t\t\treturn this;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar not = (o.retainPath === true) ? o.$path : '',\r\n\t\t\t\t\t\t$ul = $this.find('li.' + o.hoverClass).add(this).not(not).removeClass(o.hoverClass).children(o.popUpSelector),\r\n\t\t\t\t\t\tspeed = o.speedOut;\r\n\r\n\t\t\t\t\tif (instant) {\r\n\t\t\t\t\t\t$ul.show();\r\n\t\t\t\t\t\tspeed = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\to.retainPath = false;\r\n\t\t\t\t\to.onBeforeHide.call($ul);\r\n\t\t\t\t\t$ul.stop(true, true).animate(o.animationOut, speed, function () {\r\n\t\t\t\t\t\tvar $this = $(this);\r\n\t\t\t\t\t\to.onHide.call($this);\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t\treturn this;\r\n\t\t\t},\r\n\t\t\tshow: function () {\r\n\t\t\t\tvar o = getOptions(this);\r\n\t\t\t\tif (!o) {\r\n\t\t\t\t\treturn this;\r\n\t\t\t\t}\r\n\t\t\t\tvar $this = this.addClass(o.hoverClass),\r\n\t\t\t\t\t$ul = $this.children(o.popUpSelector);\r\n\r\n\t\t\t\to.onBeforeShow.call($ul);\r\n\t\t\t\t$ul.stop(true, true).animate(o.animation, o.speed, function () {\r\n\t\t\t\t\to.onShow.call($ul);\r\n\t\t\t\t});\r\n\t\t\t\treturn this;\r\n\t\t\t},\r\n\t\t\tdestroy: function () {\r\n\t\t\t\treturn this.each(function () {\r\n\t\t\t\t\tvar $this = $(this),\r\n\t\t\t\t\t\to = $this.data('sf-options'),\r\n\t\t\t\t\t\t$hasPopUp;\r\n\t\t\t\t\tif (!o) {\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t$hasPopUp = $this.find(o.popUpSelector).parent('li');\r\n\t\t\t\t\tclearTimeout(o.sfTimer);\r\n\t\t\t\t\ttoggleMenuClasses($this, o);\r\n\t\t\t\t\ttoggleAnchorClass($hasPopUp);\r\n\t\t\t\t\ttoggleTouchAction($this);\r\n\t\t\t\t\t// remove event handlers\r\n\t\t\t\t\t$this.off('.superfish').off('.hoverIntent');\r\n\t\t\t\t\t// clear animation's inline display style\r\n\t\t\t\t\t$hasPopUp.children(o.popUpSelector).attr('style', function (i, style) {\r\n\t\t\t\t\t\treturn style.replace(/display[^;]+;?/g, '');\r\n\t\t\t\t\t});\r\n\t\t\t\t\t// reset 'current' path classes\r\n\t\t\t\t\to.$path.removeClass(o.hoverClass + ' ' + c.bcClass).addClass(o.pathClass);\r\n\t\t\t\t\t$this.find('.' + o.hoverClass).removeClass(o.hoverClass);\r\n\t\t\t\t\to.onDestroy.call($this);\r\n\t\t\t\t\t$this.removeData('sf-options');\r\n\t\t\t\t});\r\n\t\t\t},\r\n\t\t\tinit: function (op) {\r\n\t\t\t\treturn this.each(function () {\r\n\t\t\t\t\tvar $this = $(this);\r\n\t\t\t\t\tif ($this.data('sf-options')) {\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar o = $.extend({}, $.fn.superfish.defaults, op),\r\n\t\t\t\t\t\t$hasPopUp = $this.find(o.popUpSelector).parent('li');\r\n\t\t\t\t\to.$path = setPathToCurrent($this, o);\r\n\r\n\t\t\t\t\t$this.data('sf-options', o);\r\n\r\n\t\t\t\t\ttoggleMenuClasses($this, o);\r\n\t\t\t\t\ttoggleAnchorClass($hasPopUp);\r\n\t\t\t\t\ttoggleTouchAction($this);\r\n\t\t\t\t\tapplyHandlers($this, o);\r\n\r\n\t\t\t\t\t$hasPopUp.not('.' + c.bcClass).superfish('hide', true);\r\n\r\n\t\t\t\t\to.onInit.call(this);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t};\r\n\t})();\r\n\r\n\t$.fn.superfish = function (method, args) {\r\n\t\tif (methods[method]) {\r\n\t\t\treturn methods[method].apply(this, Array.prototype.slice.call(arguments, 1));\r\n\t\t}\r\n\t\telse if (typeof method === 'object' || ! method) {\r\n\t\t\treturn methods.init.apply(this, arguments);\r\n\t\t}\r\n\t\telse {\r\n\t\t\treturn $.error('Method ' +  method + ' does not exist on jQuery.fn.superfish');\r\n\t\t}\r\n\t};\r\n\r\n\t$.fn.superfish.defaults = {\r\n\t\tpopUpSelector: 'ul,.sf-mega', // within menu context\r\n\t\thoverClass: 'sfHover',\r\n\t\tpathClass: 'overrideThisToUse',\r\n\t\tpathLevels: 1,\r\n\t\tdelay: 800,\r\n\t\tanimation: {opacity: 'show'},\r\n\t\tanimationOut: {opacity: 'hide'},\r\n\t\tspeed: 'normal',\r\n\t\tspeedOut: 'fast',\r\n\t\tcssArrows: true,\r\n\t\tdisableHI: false,\r\n\t\tonInit: $.noop,\r\n\t\tonBeforeShow: $.noop,\r\n\t\tonShow: $.noop,\r\n\t\tonBeforeHide: $.noop,\r\n\t\tonHide: $.noop,\r\n\t\tonIdle: $.noop,\r\n\t\tonDestroy: $.noop\r\n\t};\r\n\r\n\t// soon to be deprecated\r\n\t$.fn.extend({\r\n\t\thideSuperfishUl: methods.hide,\r\n\t\tshowSuperfishUl: methods.show\r\n\t});\r\n\r\n})(jQuery);\r\n\r\n\r\n// jQuery hcSticky\r\n// =============\r\n// Version: 1.1.96\r\n// Copyright: Some Web Media\r\n// Author: Some Web Guy\r\n// Author URL: http://twitter.com/some_web_guy\r\n// Website: http://someweblog.com/\r\n// Plugin URL: http://someweblog.com/hcsticky-jquery-floating-sticky-plugin/\r\n// License: Released under the MIT License www.opensource.org/licenses/mit-license.php\r\n// Description: Makes elements on your page float as you scroll\r\n\r\n(function($, undefined){\r\n    /*----------------------------------------------------\r\n                        GLOBAL FUNCTIONS\r\n    ----------------------------------------------------*/\r\n    \r\n    // check for scroll direction and speed\r\n    var getScroll = function() {\r\n\tvar pageXOffset = window.pageXOffset !== undefined ? window.pageXOffset : window.document.documentElement.scrollLeft;\r\n\tvar pageYOffset = window.pageYOffset !== undefined ? window.pageYOffset : window.document.documentElement.scrollTop;\r\n\t\r\n        if (typeof getScroll.x == 'undefined') {\r\n            getScroll.x = pageXOffset;\r\n            getScroll.y = pageYOffset;\r\n        }\r\n        if (typeof getScroll.distanceX == 'undefined') {\r\n            getScroll.distanceX = pageXOffset;\r\n            getScroll.distanceY = pageYOffset;\r\n        } else {\r\n            getScroll.distanceX = pageXOffset - getScroll.x;\r\n            getScroll.distanceY = pageYOffset - getScroll.y;\r\n        }\r\n        var diffX = getScroll.x - pageXOffset,\r\n            diffY = getScroll.y - pageYOffset;\r\n        getScroll.direction = diffX < 0 ? 'right' :\r\n            diffX > 0 ? 'left' :\r\n            diffY <= 0 ? 'down' :\r\n            diffY > 0 ? 'up' : 'first';\r\n        getScroll.x = pageXOffset;\r\n        getScroll.y = pageYOffset;\r\n    };\r\n    $(window).on('scroll', getScroll);\r\n    \r\n    // get original css (auto, %)\r\n    var getCSS = function(el,style) {\r\n\t// check if we already cloned this element\r\n        if (typeof el.cssClone == 'undefined') {\r\n            el.cssClone = el.clone().css('display','none');\r\n\t    // change the name of cloned radio buttons, otherwise selections get screwed\r\n\t    el.cssClone.find('input:radio').attr('name','sfd4fgdf');\r\n\t    // insert clone to DOM\r\n            el.after(el.cssClone);\r\n        }\r\n        var clone = el.cssClone[0];\r\n        if(typeof style != 'undefined') {\r\n            var value;\r\n            if (clone.currentStyle) {\r\n\t\t// regex e.g. padding-left to paddingLeft\r\n                value = clone.currentStyle[style.replace(/-\\w/g, function(s){return s.toUpperCase().replace('-','')})];\r\n            } else if (window.getComputedStyle) {\r\n                value = document.defaultView.getComputedStyle(clone,null).getPropertyValue(style);\r\n            }\r\n\t    // check for margin:auto\r\n            value = (/margin/g.test(style)) ? ((parseInt(value) === el[0].offsetLeft) ? value : 'auto') : value;\r\n        }\r\n        return {\r\n            value: value || null,\r\n            remove: function() {\r\n                el.cssClone.remove();\r\n            }\r\n        };\r\n    };\r\n    \r\n    /*----------------------------------------------------\r\n                        JQUERY PLUGIN\r\n    ----------------------------------------------------*/\r\n    \r\n    $.fn.extend({\r\n        \r\n        hcSticky: function(options, reinit){\r\n            \r\n\t    // check if selected element exist in DOM, user doesn't have to worry about that\r\n\t    if (this.length == 0)\r\n\t\treturn this;\r\n\t    \r\n            var settings = options || {},\r\n                running = (this.data('hcSticky')) ? true : false,\r\n                $window = $(window),\r\n                $document = $(document);\r\n            \r\n            if (typeof settings == 'string') {\r\n                switch(settings){\r\n                    case 'reinit':\r\n                        // detach scroll event\r\n                        $window.off('scroll', this.data('hcSticky').f);\r\n                        // call itself to start again\r\n                        return this.hcSticky({},true);\r\n                        break;\r\n                    case 'off':\r\n                        this.data('hcSticky', $.extend(this.data('hcSticky'),{on:false}));\r\n                        break;\r\n                    case 'on':\r\n                        this.data('hcSticky', $.extend(this.data('hcSticky'),{on:true}));\r\n                        break;\r\n                }\r\n                return this;\r\n            } else if (typeof settings == 'object') {\r\n                if (!running) {\r\n                    // these are the default settings\r\n                    this.data('hcSticky', $.extend({\r\n                        top: 0,\r\n                        bottom: 0,\r\n                        bottomEnd: 0,\r\n                        bottomLimiter: null,\r\n                        innerTop: 0,\r\n                        innerSticker: null,\r\n                        className: 'sticky',\r\n                        wrapperClassName: 'wrapper-sticky',\r\n                        noContainer: false,\r\n\t\t\tparent: null,\r\n\t\t\tresponsive: true,\r\n                        followScroll: true,\r\n\t\t\tonStart: function(){},\r\n\t\t\tonStop: function(){},\r\n                        on: true\r\n                    }, settings));\r\n                    // check for bottom limiter\r\n                    var $bottom_limiter = this.data('hcSticky').bottomLimiter;\r\n                    if ($bottom_limiter !== null && this.data('hcSticky').noContainer) {\r\n                        this.data('hcSticky', $.extend(this.data('hcSticky'),{bottomEnd:$document.height() - $($bottom_limiter).offset().top}));\r\n                    }\r\n                } else {\r\n                    // update existing settings\r\n                    this.data('hcSticky', $.extend(this.data('hcSticky'),settings));\r\n                }\r\n                // if already running and not reinited don't go further all we needed was to update settings\r\n                if (running && !reinit) {\r\n                    return this;\r\n                }\r\n            }\r\n\t    \r\n\t    // do our thing\r\n            return this.each(function(){\r\n                \r\n                var $this = $(this),\r\n\t\t    $parent = $this.data('hcSticky').parent ? $($this.data('hcSticky').parent) : $this.parent(),\r\n\t\t    // get wrapper if already created, if not create it\r\n\t\t    $wrapper = (function(){\r\n                            // wrapper exists\r\n                            var $this_wrapper = $this.parent('.'+$this.data('hcSticky').wrapperClassName);\r\n                            if ($this_wrapper.length > 0) {\r\n                                $this_wrapper.css({\r\n                                    'height': $this.outerHeight(true),\r\n                                    'width': (function(){\r\n                                        // check if wrapper already has width in %\r\n                                        var width = getCSS($this_wrapper,'width').value;\r\n                                        getCSS($this_wrapper).remove();\r\n                                        if (width.indexOf('%') >= 0 || width == 'auto') {\r\n                                            $this.css('width',$this_wrapper.width());\r\n                                            return width;\r\n                                        } else {\r\n                                            return $this.outerWidth(true);\r\n                                        }\r\n                                    })()\r\n                                });\r\n                                return $this_wrapper;\r\n                            } else {\r\n                                return false;\r\n                            }\r\n                        })() || (function(){\r\n                            // wrapper doesn't exist, create it\r\n                            var $this_wrapper = $('<div>',{'class':$this.data('hcSticky').wrapperClassName}).css({\r\n                                'height': $this.outerHeight(true),\r\n                                'width': (function(){\r\n                                    // check if element has width in %\r\n                                    var width = getCSS($this,'width').value;\r\n                                    if (width.indexOf('%') >= 0 || width == 'auto') {\r\n                                        $this.css('width',parseFloat($this.css('width')));\r\n                                        return width;\r\n                                    } else {\r\n                                        // check if margin is set to 'auto'\r\n                                        var margin = getCSS($this,'margin-left').value;\r\n                                        return (margin == 'auto') ? $this.outerWidth() : $this.outerWidth(true);\r\n                                    }\r\n                                })(),\r\n                                'margin': (getCSS($this,'margin-left').value) ? 'auto' : null,\r\n                                'position': (function(){\r\n                                    var position = $this.css('position');\r\n                                    return position == 'static' ? 'relative' : position;\r\n                                })(),\r\n                                'float': $this.css('float') || null,\r\n                                'left': getCSS($this,'left').value,\r\n                                'right': getCSS($this,'right').value,\r\n                                'top': getCSS($this,'top').value,\r\n                                'bottom': getCSS($this,'bottom').value\r\n                            });\r\n                            $this.wrap($this_wrapper);\r\n                            // return appended element\r\n                            return $this.parent();\r\n                        }\r\n                    )(),\r\n                    // functions for attachiung and detaching sticky\r\n                    setFixed = function(args){\r\n\t\t\t// check if already floating\r\n\t\t\tif ($this.hasClass($this.data('hcSticky').className))\r\n\t\t\t    return;\r\n                        args = args || {};\r\n                        $this.css({\r\n                            position: 'fixed',\r\n                            top: args.top || 0,\r\n                            left: args.left || $wrapper.offset().left\r\n                        }).addClass($this.data('hcSticky').className);\r\n\t\t\t// run function for start event of sticky\r\n\t\t\t$this.data('hcSticky').onStart.apply(this);\r\n                    },\r\n                    reset = function(args){\r\n                        args = args || {};\r\n                        $this.css({\r\n                            position: args.position || 'absolute',\r\n                            top: args.top || 0,\r\n                            left: args.left || 0\r\n                        }).removeClass($this.data('hcSticky').className);\r\n\t\t\t// run function for stop event of sticky\r\n\t\t\t$this.data('hcSticky').onStop.apply(this);\r\n                    };\r\n                \r\n                // clear clone element we created for geting real css value\r\n                getCSS($this).remove();\r\n                // reset sticky content\r\n                $this.css({top:'auto',bottom:'auto',left:'auto',right:'auto'});\r\n                \r\n\t\t// before anything, check if element height is bigger than the content\r\n\t\tif ($this.outerHeight(true) > $parent.height())\r\n\t\t    return this;\r\n\t\t// also attach event on entire page load, maybe some images inside element has been delayd, so chek widths again\r\n\t\t$(window).load(function(){\r\n\t\t    if ($this.outerHeight(true) > $parent.height()) {\r\n\t\t\t$wrapper.css('height', $this.outerHeight(true));\r\n\t\t\t$this.hcSticky('reinit');\r\n\t\t    }\r\n\t\t});\r\n\t\t\r\n                // start the magic\r\n                var f = function(init){\r\n                    \r\n                    // get referring element\r\n                    $referrer = ($this.data('hcSticky').noContainer) ? $document : ($this.data('hcSticky').parent ? $($this.data('hcSticky').parent) : $wrapper.parent());\r\n                    \r\n                    // check if we need to run sticky\r\n                    if (!$this.data('hcSticky').on || $this.outerHeight(true) >= $referrer.height())\r\n                        return;\r\n\r\n                    var top_spacing = ($this.data('hcSticky').innerSticker) ? $($this.data('hcSticky').innerSticker).position().top : (($this.data('hcSticky').innerTop) ? $this.data('hcSticky').innerTop : 0),\r\n                        //wrapper_inner_top = $wrapper.offset().top + ($this.data('hcSticky').noContainer ? 0 : (parseInt($referrer.css('borderTopWidth')) + parseInt($referrer.css('padding-top')) + parseInt($referrer.css('margin-top')))), \r\n\t\t\twrapper_inner_top = $wrapper.offset().top,\r\n                        bottom_limit = $referrer.height() - $this.data('hcSticky').bottomEnd + ($this.data('hcSticky').noContainer ? 0 : wrapper_inner_top),\r\n                        top_limit = $wrapper.offset().top - $this.data('hcSticky').top + top_spacing,\r\n                        this_height = $this.outerHeight(true) + $this.data('hcSticky').bottom,\r\n                        window_height = $window.height(),\r\n                        offset_top = $window.scrollTop(),\r\n                        this_document_top = $this.offset().top,\r\n                        this_window_top = this_document_top - offset_top,\r\n                        bottom_distance; // this is for later\r\n                    \r\n                    \r\n                    if (offset_top >= top_limit) {\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t//********************* this is my fix *******************************************************\r\n\t\t\t\t\t\t//if (bottom_limit + $this.data('hcSticky').bottom - ($this.data('hcSticky').followScroll ? 0 : $this.data('hcSticky').top) <= offset_top + this_height - top_spacing - ((this_height - top_spacing > window_height - (top_limit - top_spacing) && $this.data('hcSticky').followScroll) ? (((bottom_distance = this_height - window_height - top_spacing) > 0) ? bottom_distance : 0) : 0)) {\r\n                        // I have no idea what am I checking here, but it works\r\n\t\t\t// http://geek-and-poke.com/geekandpoke/2012/7/27/simply-explained.html\r\n                        //if (bottom_limit + $this.data('hcSticky').bottom - $this.data('hcSticky').top <= offset_top + this_height - top_spacing - ((this_height - top_spacing > window_height - (top_limit - top_spacing) && $this.data('hcSticky').followScroll) ? (((bottom_distance = this_height - window_height - top_spacing) > 0) ? bottom_distance : 0) : 0)) {\r\n\t\t\tif (bottom_limit + $this.data('hcSticky').bottom - ($this.data('hcSticky').followScroll ? 0 : $this.data('hcSticky').top) <= offset_top + $this.data('hcSticky').top + this_height - top_spacing - ((this_height - top_spacing > window_height - (top_limit - top_spacing) && $this.data('hcSticky').followScroll) ? (((bottom_distance = this_height - window_height - top_spacing) > 0) ? bottom_distance : 0) : 0)) {\r\n                            // bottom reached end\r\n                            reset({\r\n                                top: bottom_limit - this_height + $this.data('hcSticky').bottom - wrapper_inner_top\r\n                            });\r\n                        } else if (this_height - top_spacing > window_height && $this.data('hcSticky').followScroll ) {\r\n\r\n                            // sidebar bigger than window with follow scroll on\r\n                            if (this_window_top + this_height <= window_height) {\r\n                                if (getScroll.direction == 'down') {\r\n                                    // scroll down\r\n                                    setFixed({\r\n                                        top: window_height - this_height\r\n                                    });\r\n                                } else {\r\n                                    // scroll up\r\n                                    if (this_window_top < 0 && $this.css('position') == 'fixed') {\r\n                                        reset({\r\n                                            top: this_document_top - (top_limit + $this.data('hcSticky').top - top_spacing) - getScroll.distanceY\r\n                                        });\r\n                                    }\r\n                                }\r\n                            // sidebar smaller than window or follow scroll turned off\r\n                            } else {\r\n                                if (getScroll.direction == 'up' && this_document_top >= offset_top + $this.data('hcSticky').top - top_spacing) {\r\n                                    // scroll up\r\n                                    \r\n                                    setFixed({\r\n                                        top: $this.data('hcSticky').top - top_spacing\r\n                                    });\r\n                                } else if (getScroll.direction == 'down' && this_document_top + this_height > window_height && $this.css('position') == 'fixed') {\r\n                                    // scroll down\r\n                                    reset({\r\n                                        top: this_document_top - (top_limit + $this.data('hcSticky').top - top_spacing) - getScroll.distanceY\r\n                                    });\r\n                                }\r\n                            }\r\n                        } else {\r\n                            // starting (top) fixed position\r\n                            setFixed({\r\n                                top: $this.data('hcSticky').top - top_spacing \r\n                            });\r\n                        }\r\n                    } else {\r\n                        // reset bar\r\n                        reset();\r\n                    }\r\n\r\n                    // just in case someone set \"top\" larger than elements style top\r\n                    if (init === true) {\r\n\t\t\t$this.css('top', ($this.css('position') == 'fixed') ? $this.data('hcSticky').top - top_spacing : 0);\r\n                        //$this.css('top', ($this.css('position') == 'fixed') ? $wrapper.offset().top : 0);\r\n                    }\r\n\r\n                };\r\n\t\t\r\n\t\t// store resize data in case responsive is on\r\n                var resize_timeout = false,\r\n\t\t    $resize_clone = false;\r\n\t\t\r\n\t\tfunction onResize(){\r\n\t\t    // check for width change (css media queries)\r\n\t\t    if ($this.data('hcSticky').responsive) {\r\n\t\t\t// clone element and make it invisible\r\n\t\t\tif (!$resize_clone) {\r\n\t\t\t    $resize_clone = $this.clone().attr('style','').css({visibility:'hidden',height:0,overflow:'hidden',paddingTop:0,paddingBottom:0,marginTop:0,marginBottom:0});\r\n\t\t\t    $wrapper.after($resize_clone);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tif (getCSS($resize_clone,'width').value != getCSS($wrapper,'width').value)\r\n\t\t\t    $wrapper.width(getCSS($resize_clone,'width').value);\r\n\t\t\t// remove wrapper clone\r\n\t\t\tgetCSS($wrapper).remove();\r\n\t\t\t\r\n\t\t\t// clear previous timeout\r\n\t\t\tif (resize_timeout) {\r\n\t\t\t    clearTimeout(resize_timeout);\r\n\t\t\t}\r\n\t\t\t// timedout destroing of cloned elements\r\n\t\t\tresize_timeout = setTimeout(function(){\r\n\t\t\t    // clear timeout id\r\n\t\t\t    resize_timeout = false;\r\n\t\t\t    // destroy cloned elements\r\n\t\t\t    getCSS($resize_clone).remove();\r\n\t\t\t    $resize_clone.remove();\r\n\t\t\t    $resize_clone = false;\r\n\t\t\t}, 100);\r\n\t\t    }\r\n\t\t    \r\n\t\t    // set left position\r\n                    if ($this.css('position') == 'fixed') {\r\n                        $this.css('left', $wrapper.offset().left);\r\n                    } else {\r\n                        $this.css('left', 0);\r\n                    }\r\n\t\t    // recalculate inner element width (maybe original width was in %)\r\n\t\t    if ($this.width() != $wrapper.width())\r\n\t\t\t$this.css('width', $wrapper.width());\r\n                }\r\n\t\t// attach resize event\r\n                $window.on('resize', onResize);\r\n                \r\n                // set scroll empty function in case we need to reinit plugin\r\n                $this.data('hcSticky', $.extend($this.data('hcSticky'),{f:function(){}}));\r\n                // set scroll function\r\n                $this.data('hcSticky', $.extend($this.data('hcSticky'),{f:f}));\r\n                // run it for the first time to disable glitching\r\n                $this.data('hcSticky').f(true);\r\n                // attach function to scroll event\r\n                $window.on('scroll', $this.data('hcSticky').f);\r\n\t\t\r\n            });\r\n        }\r\n    });\r\n\r\n})(jQuery);\r\n\t    \r\n\r\n\r\n/**\r\n * Copyright (c) 2007-2012 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com\r\n * Dual licensed under MIT and GPL.\r\n * @author Ariel Flesler\r\n * @version 1.4.3\r\n */\r\n;(function($){var h=$.scrollTo=function(a,b,c){$(window).scrollTo(a,b,c)};h.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:true};h.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(e,f,g){if(typeof f=='object'){g=f;f=0}if(typeof g=='function')g={onAfter:g};if(e=='max')e=9e9;g=$.extend({},h.defaults,g);f=f||g.duration;g.queue=g.queue&&g.axis.length>1;if(g.queue)f/=2;g.offset=both(g.offset);g.over=both(g.over);return this._scrollable().each(function(){if(!e)return;var d=this,$elem=$(d),targ=e,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=)?\\d+(\\.\\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}$.each(g.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=h.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(g.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=g.offset[pos]||0;if(g.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*g.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(g.limit&&/^\\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&g.queue){if(old!=attr[key])animate(g.onAfterFirst);delete attr[key]}});animate(g.onAfter);function animate(a){$elem.animate(attr,f,g.easing,a&&function(){a.call(this,e,g)})}}).end()};h.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);\r\n\r\n/*\r\n * jQuery One Page Nav Plugin\r\n * http://github.com/davist11/jQuery-One-Page-Nav\r\n *\r\n * Copyright (c) 2010 Trevor Davis (http://trevordavis.net)\r\n * Dual licensed under the MIT and GPL licenses.\r\n * Uses the same license as jQuery, see:\r\n * http://jquery.org/license\r\n *\r\n * @version 2.2\r\n *\r\n * Example usage:\r\n * $('#nav').onePageNav({\r\n *   currentClass: 'current',\r\n *   changeHash: false,\r\n *   scrollSpeed: 750\r\n * });\r\n */\r\n\r\n;(function($, window, document, undefined){\r\n\r\n\t// our plugin constructor\r\n\tvar OnePageNav = function(elem, options){\r\n\t\tthis.elem = elem;\r\n\t\tthis.$elem = $(elem);\r\n\t\tthis.options = options;\r\n\t\tthis.metadata = this.$elem.data('plugin-options');\r\n\t\tthis.$nav = this.$elem.find('a');\r\n\t\tthis.$win = $(window);\r\n\t\tthis.sections = {};\r\n\t\tthis.didScroll = false;\r\n\t\tthis.$doc = $(document);\r\n\t\tthis.docHeight = this.$doc.height();\r\n\t};\r\n\r\n\t// the plugin prototype\r\n\tOnePageNav.prototype = {\r\n\t\tdefaults: {\r\n\t\t\tcurrentClass: 'current',\r\n\t\t\tchangeHash: false,\r\n\t\t\teasing: 'swing',\r\n\t\t\tfilter: '',\r\n\t\t\tscrollSpeed: 750,\r\n\t\t\tscrollOffset: 0,\r\n\t\t\tscrollThreshold: 0.5,\r\n\t\t\tbegin: false,\r\n\t\t\tend: false,\r\n\t\t\tscrollChange: false\r\n\t\t},\r\n\r\n\t\tinit: function() {\r\n\t\t\tvar self = this;\r\n\t\t\t\r\n\t\t\t// Introduce defaults that can be extended either\r\n\t\t\t// globally or using an object literal.\r\n\t\t\tself.config = $.extend({}, self.defaults, self.options, self.metadata);\r\n\t\t\t\r\n\t\t\t//Filter any links out of the nav\r\n\t\t\tif(self.config.filter !== '') {\r\n\t\t\t\tself.$nav = self.$nav.filter(self.config.filter);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t//Handle clicks on the nav\r\n\t\t\tself.$nav.on('click.onePageNav', $.proxy(self.handleClick, self));\r\n\r\n\t\t\t//Get the section positions\r\n\t\t\tself.getPositions();\r\n\t\t\t\r\n\t\t\t//Handle scroll changes\r\n\t\t\tself.bindInterval();\r\n\t\t\t\r\n\t\t\t//Update the positions on resize too\r\n\t\t\tself.$win.on('resize.onePageNav', $.proxy(self.getPositions, self));\r\n\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\t\r\n\t\tadjustNav: function(self, $parent) {\r\n\t\t\tself.$elem.find('.' + self.config.currentClass).removeClass(self.config.currentClass);\r\n\t\t\t$parent.addClass(self.config.currentClass);\r\n\t\t\t//console.log();\r\n\t\t\t//my hack to auto scroll to selected\r\n\t\t\tself.$elem.scrollTo( self.$elem.find('.' + self.config.currentClass), 300 );\r\n\t\t},\r\n\t\t\r\n\t\tbindInterval: function() {\r\n\t\t\tvar self = this;\r\n\t\t\tvar docHeight;\r\n\t\t\t\r\n\t\t\tself.$win.on('scroll.onePageNav', function() {\r\n\t\t\t\tself.didScroll = true;\r\n\t\t\t});\r\n\t\t\t\r\n\t\t\tself.t = setInterval(function() {\r\n\t\t\t\tdocHeight = self.$doc.height();\r\n\t\t\t\t\r\n\t\t\t\t//If it was scrolled\r\n\t\t\t\tif(self.didScroll) {\r\n\t\t\t\t\tself.didScroll = false;\r\n\t\t\t\t\tself.scrollChange();\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\t//If the document height changes\r\n\t\t\t\tif(docHeight !== self.docHeight) {\r\n\t\t\t\t\tself.docHeight = docHeight;\r\n\t\t\t\t\tself.getPositions();\r\n\t\t\t\t}\r\n\t\t\t}, 250);\r\n\t\t},\r\n\t\t\r\n\t\tgetHash: function($link) {\r\n\t\t\treturn $link.attr('href').split('#')[1];\r\n\t\t},\r\n\t\t\r\n\t\tgetPositions: function() {\r\n\t\t\tvar self = this;\r\n\t\t\tvar linkHref;\r\n\t\t\tvar topPos;\r\n\t\t\tvar $target;\r\n\t\t\t\r\n\t\t\tself.$nav.each(function() {\r\n\t\t\t\tlinkHref = self.getHash($(this));\r\n\t\t\t\t$target = $('#' + linkHref);\r\n\r\n\t\t\t\tif($target.length) {\r\n\t\t\t\t\ttopPos = $target.offset().top;\r\n\t\t\t\t\tself.sections[linkHref] = Math.round(topPos) - self.config.scrollOffset;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t},\r\n\t\t\r\n\t\tgetSection: function(windowPos) {\r\n\t\t\tvar returnValue = null;\r\n\t\t\tvar windowHeight = Math.round(this.$win.height() * this.config.scrollThreshold);\r\n\r\n\t\t\tfor(var section in this.sections) {\r\n\t\t\t\tif((this.sections[section] - windowHeight) < windowPos) {\r\n\t\t\t\t\treturnValue = section;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn returnValue;\r\n\t\t},\r\n\t\t\r\n\t\thandleClick: function(e) {\r\n\t\t\tvar self = this;\r\n\t\t\tvar $link = $(e.currentTarget);\r\n\t\t\tvar $parent = $link.parent();\r\n\t\t\tvar newLoc = '#' + self.getHash($link);\r\n\r\n\r\n\r\n\t\t\t\tif(!$parent.hasClass(self.config.currentClass)) {\r\n\t\t\t\t\t//Start callback\r\n\t\t\t\t\tif(self.config.begin) {\r\n\t\t\t\t\t\tself.config.begin();\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\t//Change the highlighted nav item\r\n\t\t\t\t\tself.adjustNav(self, $parent);\r\n\t\t\t\t\t\r\n\t\t\t\t\t//Removing the auto-adjust on scroll\r\n\t\t\t\t\tself.unbindInterval();\r\n\t\t\t\t\t\r\n\t\t\t\t\t//Scroll to the correct position\r\n\t\t\t\t\t$.scrollTo(newLoc, self.config.scrollSpeed, {\r\n\t\t\t\t\t\taxis: 'y',\r\n\t\t\t\t\t\teasing: self.config.easing,\r\n\t\t\t\t\t\toffset: {\r\n\t\t\t\t\t\t\ttop: -self.config.scrollOffset\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tonAfter: function() {\r\n\t\t\t\t\t\t\t//Do we need to change the hash?\r\n\t\t\t\t\t\t\tif(self.config.changeHash) {\r\n\t\t\t\t\t\t\t\twindow.location.hash = newLoc;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t//Add the auto-adjust on scroll back in\r\n\t\t\t\t\t\t\tself.bindInterval();\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t//End callback\r\n\t\t\t\t\t\t\tif(self.config.end) {\r\n\t\t\t\t\t\t\t\tself.config.end();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\r\n\t\t},\r\n\t\t\r\n\t\tscrollChange: function() {\r\n\t\t\tvar windowTop = this.$win.scrollTop();\r\n\t\t\tvar position = this.getSection(windowTop);\r\n\t\t\tvar $parent;\r\n\t\t\t\r\n\t\t\t//If the position is set\r\n\t\t\tif(position !== null) {\r\n\t\t\t\t$parent = this.$elem.find('a[href$=\"#' + position + '\"]').parent();\r\n\t\t\t\t\r\n\t\t\t\t//If it's not already the current section\r\n\t\t\t\tif(!$parent.hasClass(this.config.currentClass)) {\r\n\t\t\t\t\t//Change the highlighted nav item\r\n\t\t\t\t\tthis.adjustNav(this, $parent);\r\n\t\t\t\t\t\r\n\t\t\t\t\t//If there is a scrollChange callback\r\n\t\t\t\t\tif(this.config.scrollChange) {\r\n\t\t\t\t\t\tthis.config.scrollChange($parent);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\t\r\n\t\tunbindInterval: function() {\r\n\t\t\tclearInterval(this.t);\r\n\t\t\tthis.$win.unbind('scroll.onePageNav');\r\n\t\t}\r\n\t};\r\n\r\n\tOnePageNav.defaults = OnePageNav.prototype.defaults;\r\n\r\n\t$.fn.onePageNav = function(options) {\r\n\t\treturn this.each(function() {\r\n\t\t\tnew OnePageNav(this, options).init();\r\n\t\t});\r\n\t};\r\n\t\r\n})( jQuery, window , document );\r\n\r\n\r\n"
  },
  {
    "path": "docs/js/vendor/html5shiv.js",
    "content": "/**\n* @preserve HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n*/\n;(function(window, document) {\n/*jshint evil:true */\n  /** version */\n  var version = '3.7.0';\n\n  /** Preset options */\n  var options = window.html5 || {};\n\n  /** Used to skip problem elements */\n  var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;\n\n  /** Not all elements can be cloned in IE **/\n  var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;\n\n  /** Detect whether the browser supports default html5 styles */\n  var supportsHtml5Styles;\n\n  /** Name of the expando, to work with multiple documents or to re-shiv one document */\n  var expando = '_html5shiv';\n\n  /** The id for the the documents expando */\n  var expanID = 0;\n\n  /** Cached data for each document */\n  var expandoData = {};\n\n  /** Detect whether the browser supports unknown elements */\n  var supportsUnknownElements;\n\n  (function() {\n    try {\n        var a = document.createElement('a');\n        a.innerHTML = '<xyz></xyz>';\n        //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles\n        supportsHtml5Styles = ('hidden' in a);\n\n        supportsUnknownElements = a.childNodes.length == 1 || (function() {\n          // assign a false positive if unable to shiv\n          (document.createElement)('a');\n          var frag = document.createDocumentFragment();\n          return (\n            typeof frag.cloneNode == 'undefined' ||\n            typeof frag.createDocumentFragment == 'undefined' ||\n            typeof frag.createElement == 'undefined'\n          );\n        }());\n    } catch(e) {\n      // assign a false positive if detection fails => unable to shiv\n      supportsHtml5Styles = true;\n      supportsUnknownElements = true;\n    }\n\n  }());\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Creates a style sheet with the given CSS text and adds it to the document.\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @param {String} cssText The CSS text.\n   * @returns {StyleSheet} The style element.\n   */\n  function addStyleSheet(ownerDocument, cssText) {\n    var p = ownerDocument.createElement('p'),\n        parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;\n\n    p.innerHTML = 'x<style>' + cssText + '</style>';\n    return parent.insertBefore(p.lastChild, parent.firstChild);\n  }\n\n  /**\n   * Returns the value of `html5.elements` as an array.\n   * @private\n   * @returns {Array} An array of shived element node names.\n   */\n  function getElements() {\n    var elements = html5.elements;\n    return typeof elements == 'string' ? elements.split(' ') : elements;\n  }\n\n    /**\n   * Returns the data associated to the given document\n   * @private\n   * @param {Document} ownerDocument The document.\n   * @returns {Object} An object of data.\n   */\n  function getExpandoData(ownerDocument) {\n    var data = expandoData[ownerDocument[expando]];\n    if (!data) {\n        data = {};\n        expanID++;\n        ownerDocument[expando] = expanID;\n        expandoData[expanID] = data;\n    }\n    return data;\n  }\n\n  /**\n   * returns a shived element for the given nodeName and document\n   * @memberOf html5\n   * @param {String} nodeName name of the element\n   * @param {Document} ownerDocument The context document.\n   * @returns {Object} The shived element.\n   */\n  function createElement(nodeName, ownerDocument, data){\n    if (!ownerDocument) {\n        ownerDocument = document;\n    }\n    if(supportsUnknownElements){\n        return ownerDocument.createElement(nodeName);\n    }\n    if (!data) {\n        data = getExpandoData(ownerDocument);\n    }\n    var node;\n\n    if (data.cache[nodeName]) {\n        node = data.cache[nodeName].cloneNode();\n    } else if (saveClones.test(nodeName)) {\n        node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();\n    } else {\n        node = data.createElem(nodeName);\n    }\n\n    // Avoid adding some elements to fragments in IE < 9 because\n    // * Attributes like `name` or `type` cannot be set/changed once an element\n    //   is inserted into a document/fragment\n    // * Link elements with `src` attributes that are inaccessible, as with\n    //   a 403 response, will cause the tab/window to crash\n    // * Script elements appended to fragments will execute when their `src`\n    //   or `text` property is set\n    return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;\n  }\n\n  /**\n   * returns a shived DocumentFragment for the given document\n   * @memberOf html5\n   * @param {Document} ownerDocument The context document.\n   * @returns {Object} The shived DocumentFragment.\n   */\n  function createDocumentFragment(ownerDocument, data){\n    if (!ownerDocument) {\n        ownerDocument = document;\n    }\n    if(supportsUnknownElements){\n        return ownerDocument.createDocumentFragment();\n    }\n    data = data || getExpandoData(ownerDocument);\n    var clone = data.frag.cloneNode(),\n        i = 0,\n        elems = getElements(),\n        l = elems.length;\n    for(;i<l;i++){\n        clone.createElement(elems[i]);\n    }\n    return clone;\n  }\n\n  /**\n   * Shivs the `createElement` and `createDocumentFragment` methods of the document.\n   * @private\n   * @param {Document|DocumentFragment} ownerDocument The document.\n   * @param {Object} data of the document.\n   */\n  function shivMethods(ownerDocument, data) {\n    if (!data.cache) {\n        data.cache = {};\n        data.createElem = ownerDocument.createElement;\n        data.createFrag = ownerDocument.createDocumentFragment;\n        data.frag = data.createFrag();\n    }\n\n\n    ownerDocument.createElement = function(nodeName) {\n      //abort shiv\n      if (!html5.shivMethods) {\n          return data.createElem(nodeName);\n      }\n      return createElement(nodeName, ownerDocument, data);\n    };\n\n    ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +\n      'var n=f.cloneNode(),c=n.createElement;' +\n      'h.shivMethods&&(' +\n        // unroll the `createElement` calls\n        getElements().join().replace(/[\\w\\-]+/g, function(nodeName) {\n          data.createElem(nodeName);\n          data.frag.createElement(nodeName);\n          return 'c(\"' + nodeName + '\")';\n        }) +\n      ');return n}'\n    )(html5, data.frag);\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * Shivs the given document.\n   * @memberOf html5\n   * @param {Document} ownerDocument The document to shiv.\n   * @returns {Document} The shived document.\n   */\n  function shivDocument(ownerDocument) {\n    if (!ownerDocument) {\n        ownerDocument = document;\n    }\n    var data = getExpandoData(ownerDocument);\n\n    if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {\n      data.hasCSS = !!addStyleSheet(ownerDocument,\n        // corrects block display not defined in IE6/7/8/9\n        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +\n        // adds styling not present in IE6/7/8/9\n        'mark{background:#FF0;color:#000}' +\n        // hides non-rendered elements\n        'template{display:none}'\n      );\n    }\n    if (!supportsUnknownElements) {\n      shivMethods(ownerDocument, data);\n    }\n    return ownerDocument;\n  }\n\n  /*--------------------------------------------------------------------------*/\n\n  /**\n   * The `html5` object is exposed so that more elements can be shived and\n   * existing shiving can be detected on iframes.\n   * @type Object\n   * @example\n   *\n   * // options can be changed before the script is included\n   * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };\n   */\n  var html5 = {\n\n    /**\n     * An array or space separated string of node names of the elements to shiv.\n     * @memberOf html5\n     * @type Array|String\n     */\n    'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',\n\n    /**\n     * current version of html5shiv\n     */\n    'version': version,\n\n    /**\n     * A flag to indicate that the HTML5 style sheet should be inserted.\n     * @memberOf html5\n     * @type Boolean\n     */\n    'shivCSS': (options.shivCSS !== false),\n\n    /**\n     * Is equal to true if a browser supports creating unknown/HTML5 elements\n     * @memberOf html5\n     * @type boolean\n     */\n    'supportsUnknownElements': supportsUnknownElements,\n\n    /**\n     * A flag to indicate that the document's `createElement` and `createDocumentFragment`\n     * methods should be overwritten.\n     * @memberOf html5\n     * @type Boolean\n     */\n    'shivMethods': (options.shivMethods !== false),\n\n    /**\n     * A string to describe the type of `html5` object (\"default\" or \"default print\").\n     * @memberOf html5\n     * @type String\n     */\n    'type': 'default',\n\n    // shivs the document according to the specified `html5` object options\n    'shivDocument': shivDocument,\n\n    //creates a shived element\n    createElement: createElement,\n\n    //creates a shived documentFragment\n    createDocumentFragment: createDocumentFragment\n  };\n\n  /*--------------------------------------------------------------------------*/\n\n  // expose html5\n  window.html5 = html5;\n\n  // shiv the document\n  shivDocument(document);\n\n}(this, document));\n"
  },
  {
    "path": "gradle-app.setting",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<root> \n  <setting name=\"task-tab\"> \n    <setting name=\"show-description\" value=\"true\"/> \n  </setting>  \n  <setting name=\"favorites-tab\"/>  \n  <setting name=\"command_line-tab\"/>  \n  <setting name=\"setup-tab\"> \n    <setting name=\"setup\"> \n      <setting name=\"custom-gradle-executor\"/>  \n      <setting name=\"current-directory\" value=\"/Users/pron/Projects/comsat\"/>  \n      <setting name=\"log-level\" value=\"LIFECYCLE\"/> \n    </setting> \n  </setting>  \n  <setting name=\"main_panel\"> \n    <setting name=\"current-tab\" value=\"Task Tree\"/> \n  </setting>  \n  <setting name=\"Application_window-id\"> \n    <setting name=\"window_x\" value=\"161\"/>  \n    <setting name=\"window_y\" value=\"59\"/>  \n    <setting name=\"window_width\" value=\"800\"/>  \n    <setting name=\"window_height\" value=\"800\"/>  \n    <setting name=\"extended-state\" value=\"0\"/> \n  </setting> \n</root>\n"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'comsat'\n\ninclude 'comsat-servlet'\ninclude 'comsat-jersey-server'\ninclude 'comsat-actors-api'\ninclude 'comsat-actors-netty'\ninclude 'comsat-actors-servlet'\n// include 'comsat-actors-netty'\ninclude 'comsat-actors-undertow'\ninclude 'comsat-tomcat-loader'\ninclude 'comsat-jetty-loader'\ninclude 'comsat-jdbc'\ninclude 'comsat-jdbi'\ninclude 'comsat-jooq'\ninclude 'comsat-dropwizard'\ninclude 'comsat-retrofit'\ninclude 'comsat-httpclient'\ninclude 'comsat-okhttp'\ninclude 'comsat-jax-rs-client'\ninclude 'comsat-mongodb-allanbank'\ninclude 'comsat-test-utils'\ninclude 'comsat-test-war'\n\ninclude 'comsat-spring'\ninclude 'comsat-spring:comsat-spring-webmvc'\ninclude 'comsat-spring:comsat-spring-security'\ninclude 'comsat-spring:comsat-spring-boot'\ninclude 'comsat-spring:comsat-spring-boot-security'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-actuator'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-actuator-async'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-actuator-log4j'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-actuator-log4j2'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-actuator-ui'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-data-jpa'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-jetty'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-jetty-ssl'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-jetty8'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-jetty8-ssl'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-jpa'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-servlet'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-tomcat'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-tomcat-jsp'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-tomcat-multi-connectors'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-tomcat-ssl'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-tomcat7-jsp'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-traditional'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-undertow'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-undertow-ssl'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-freemarker'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-groovy-templates'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-jsp'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-method-security'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-mustache'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-secure'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-secure-custom'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-secure-jdbc'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-static'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-ui'\ninclude 'comsat-spring:comsat-spring-boot:comsat-spring-boot-sample-web-velocity'\ninclude 'comsat-kafka'\ninclude 'comsat-shiro'\n\n"
  },
  {
    "path": "travis/build_clj.sh",
    "content": "#!/bin/bash\nstart=$(date +%s)\necho -e \"Current repo: $TRAVIS_REPO_SLUG Commit: $TRAVIS_COMMIT\\n\"\n\nfunction error_exit\n{\n        echo -e \"\\e[01;31m$1\\e[00m\" 1>&2\n        exit 1\n}\n\necho -e \"Building Clojure parts...\"\n\necho -e \"Building 'comsat-ring-jetty9'...\"\ncd comsat-ring-jetty9\nlein test || error_exit \"Error building 'comsat-ring-jetty9'\"\ncd ..\n\necho -e \"Building 'comsat-httpkit'...\"\ncd comsat-httpkit\nlein test || error_exit \"Error building 'comsat-clj-http'\"\ncd ..\n\nend=$(date +%s)\nelapsed=$(( $end - $start ))\nminutes=$(( $elapsed / 60 ))\nseconds=$(( $elapsed % 60 ))\necho \"Buid-clj process finished in $minutes minute(s) and $seconds seconds\"\n"
  },
  {
    "path": "travis/post_build.sh",
    "content": "#!/bin/bash\nstart=$(date +%s)\necho -e \"Current repo: $TRAVIS_REPO_SLUG Commit: $TRAVIS_COMMIT\\n\"\n\nemail=\"info@paralleluniverse.co\"\nusername=\"PU Bot\"\nsite_dir=docs/_site\n\nfunction error_exit\n{\n\techo -e \"\\e[01;31m$1\\e[00m\" 1>&2\n\texit 1\n}\n\nif [ \"$TRAVIS_BRANCH\" == \"$DOCS_BRANCH\" ]; then\n\techo -e \"Installing Jekyll...\\n\"\n\tgem install kramdown\n\tgem install jekyll -v 2.5.3\n\tgem install typogruby\n\tgem install nokogiri\n\n\tif [ ! -z \"$GEN_APIDOCS\" ]; then\n\t\techo -e \"Generating API docs...\\n\"\n\t\techo -e \"Running: $GEN_APIDOCS\\n\"\n\t\teval $GEN_APIDOCS\n\tfi\n\n\t# build site\n\techo -e \"Building Jekyll site...\\n\"\n\tcd docs\n\tjekyll build || error_exit \"Error building Jekyll site\"\n\tcd ..\n\n\techo -e \"Updating gh-pages...\\n\"\n    # Any command that using GH_OAUTH_TOKEN must pipe the output to /dev/null to not expose your oauth token\n    git submodule add -b gh-pages https://${GH_OAUTH_TOKEN}@github.com/$TRAVIS_REPO_SLUG site > /dev/null 2>&1\n    cd site\n\tgit checkout gh-pages || git checkout -b gh-pages\n    git rm -r .\n    cp -R ../$site_dir/* .\n    cp ../$site_dir/.* .\n    touch .nojekyll\n    git add -f .\n    git config user.email $email\n    git config user.name $username\n    git commit -am \"Travis build $TRAVIS_BUILD_NUMBER, commit $TRAVIS_COMMIT, pushed to gh-pages\"\n    # Any command that using GH_OAUTH_TOKEN must pipe the output to /dev/null to not expose your oauth token\n    git push https://${GH_OAUTH_TOKEN}@github.com/$TRAVIS_REPO_SLUG HEAD:gh-pages > /dev/null 2>&1 || error_exit \"Error updating gh-pages\"\n\n\t#git checkout -B gh-pages\n\t#git add -f dist/.\n\t#git commit -q -m \"Travis build $TRAVIS_BUILD_NUMBER pushed to gh-pages\"\n\t#git push -fq upstream gh-pages 2> /dev/null || error_exit \"Error updating gh-pages\"\n\n\techo -e \"Finished updating gh-pages\\n\"\nfi\n\nend=$(date +%s)\nelapsed=$(( $end - $start ))\nminutes=$(( $elapsed / 60 ))\nseconds=$(( $elapsed % 60 ))\necho \"Post-build process finished in $minutes minute(s) and $seconds seconds\"\n"
  }
]