{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8a16a9fe",
   "metadata": {},
   "source": [
    "# Summarize Search Results"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f90b531",
   "metadata": {},
   "source": [
    "The CDA provides a custom python tool for searching CDA data. [`Q`](usage/#q) (short for Query) offers several ways to search and filter data, and several input modes:\n",
    "\n",
    "---\n",
    "- **<a href=\"../../QuickStart/usage/#q\">Q.()</a>** builds a query that can be used by `run()` or `count()`\n",
    "- **<a href=\"../../QuickStart/usage/#qrun\">Q.run()</a>** returns data for the specified search \n",
    "- **<a href=\"../../QuickStart/usage/#qcount\">Q.count()</a>** returns summary information (counts) data that fit the specified search\n",
    "- **<a href=\"../../QuickStart/usage/#columns\">columns()</a>** returns entity field names\n",
    "- **<a href=\"../../QuickStart/usage/#unique_terms\">unique_terms()</a>** returns entity field contents\n",
    "\n",
    "---\n",
    "                                                                    \n",
    "Before we do any work, we need to import several functions from cdapython:\n",
    "- `Q` and `query` which power the search\n",
    "- `columns` which lets us view entity field names\n",
    "- `unique_terms` which lets view entity field contents\n",
    "\n",
    "We're also importing functions from several other packages to make viewing and manipulating tables easier. The `opt.` settings are pre-configuring how itables should display our tables, with scrolling and paging enabled.\n",
    "Finally, we're telling cdapython to report it's version so we can be sure we're using the one we mean to:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5245b7b0",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */\n",
       "!function(e,t){\"use strict\";\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(C,e){\"use strict\";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return\"function\"==typeof e&&\"number\"!=typeof e.nodeType&&\"function\"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement(\"script\");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?n[o.call(e)]||\"object\":typeof e}var f=\"3.6.0\",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&\"length\"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],\"__proto__\"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:\"jQuery\"+(f+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||\"[object Object]\"!==o.call(e))&&(!(t=r(e))||\"function\"==typeof(n=v.call(t,\"constructor\")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,\"string\"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),\"function\"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){n[\"[object \"+t+\"]\"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S=\"sizzle\"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),j=function(e,t){return e===t&&(l=!0),0},D={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",M=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",I=\"(?:\\\\\\\\[\\\\da-fA-F]{1,6}\"+M+\"?|\\\\\\\\[^\\\\r\\\\n\\\\f]|[\\\\w-]|[^\\0-\\\\x7f])+\",W=\"\\\\[\"+M+\"*(\"+I+\")(?:\"+M+\"*([*^$|!~]?=)\"+M+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+I+\"))|)\"+M+\"*\\\\]\",F=\":(\"+I+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+W+\")*)|.*)\\\\)|)\",B=new RegExp(M+\"+\",\"g\"),$=new RegExp(\"^\"+M+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+M+\"+$\",\"g\"),_=new RegExp(\"^\"+M+\"*,\"+M+\"*\"),z=new RegExp(\"^\"+M+\"*([>+~]|\"+M+\")\"+M+\"*\"),U=new RegExp(M+\"|>\"),X=new RegExp(F),V=new RegExp(\"^\"+I+\"$\"),G={ID:new RegExp(\"^#(\"+I+\")\"),CLASS:new RegExp(\"^\\\\.(\"+I+\")\"),TAG:new RegExp(\"^(\"+I+\"|[*])\"),ATTR:new RegExp(\"^\"+W),PSEUDO:new RegExp(\"^\"+F),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+M+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+M+\"*(?:([+-]|)\"+M+\"*(\\\\d+)|))\"+M+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+R+\")$\",\"i\"),needsContext:new RegExp(\"^\"+M+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+M+\"*((?:-\\\\d)?\\\\d*)\"+M+\"*\\\\)|)(?=[^-]|$)\",\"i\")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\\d$/i,K=/^[^{]+\\{\\s*\\[native \\w/,Z=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ee=/[+~]/,te=new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\"+M+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),ne=function(e,t){var n=\"0x\"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"\\ufffd\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+\" \"]&&(!v||!v.test(t))&&(1!==p||\"object\"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute(\"id\"))?s=s.replace(re,ie):e.setAttribute(\"id\",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?\"#\"+s:\":scope\")+\" \"+xe(l[o]);c=l.join(\",\")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute(\"id\")}}}return g(t.replace($,\"$1\"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+\" \")>b.cacheLength&&delete e[r.shift()],e[t+\" \"]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split(\"|\"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return\"input\"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return(\"input\"===t||\"button\"===t)&&e.type===n}}function ge(t){return function(e){return\"form\"in e?e.parentNode&&!1===e.disabled?\"label\"in e?\"label\"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:\"label\"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||\"HTML\")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",oe,!1):n.attachEvent&&n.attachEvent(\"onunload\",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement(\"div\")),\"undefined\"!=typeof e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),d.attributes=ce(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute(\"id\")===t}},b.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return t&&t.value===n}},b.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode(\"id\"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode(\"id\"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=\"<a id='\"+S+\"'></a><select id='\"+S+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+M+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+M+\"*(?:value|\"+R+\")\"),e.querySelectorAll(\"[id~=\"+S+\"-]\").length||v.push(\"~=\"),(t=C.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+M+\"*name\"+M+\"*=\"+M+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+S+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.push(\"[\\\\r\\\\n\\\\f]\")}),ce(function(e){e.innerHTML=\"<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>\";var t=C.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&v.push(\"name\"+M+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,\"*\"),c.call(e,\"[s!='']:x\"),s.push(\"!=\",F)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!=C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!=C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&D.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+\"\").replace(re,ie)},se.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(j),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n=\"\",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if(\"string\"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||\"\").replace(te,ne),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+\" \"];return t||(t=new RegExp(\"(^|\"+M+\")\"+e+\"(\"+M+\"|$)\"))&&m(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?\"!=\"===r:!r||(t+=\"\",\"=\"===r?t===i:\"!=\"===r?t!==i:\"^=\"===r?i&&0===t.indexOf(i):\"*=\"===r?i&&-1<t.indexOf(i):\"$=\"===r?i&&t.slice(-i.length)===i:\"~=\"===r?-1<(\" \"+t.replace(B,\" \")+\" \").indexOf(i):\"|=\"===r&&(t===i||t.slice(0,i.length+1)===i+\"-\"))}},CHILD:function(h,e,t,g,v){var y=\"nth\"!==h.slice(0,3),m=\"last\"!==h.slice(-4),x=\"of-type\"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?\"nextSibling\":\"previousSibling\",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l=\"only\"===h&&!u&&\"nextSibling\"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[k,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[k,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error(\"unsupported pseudo: \"+e);return a[S]?a(o):1<a.length?(t=[e,e,\"\",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace($,\"$1\"));return s[S]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||\"\")||se.error(\"unsupported lang: \"+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute(\"xml:lang\")||e.getAttribute(\"lang\"))return(t=t.toLowerCase())===n||0===t.indexOf(n+\"-\")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&!!e.checked||\"option\"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&\"button\"===e.type||\"button\"===t},text:function(e){var t;return\"input\"===e.nodeName.toLowerCase()&&\"text\"===e.type&&(null==(t=e.getAttribute(\"type\"))||\"text\"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&\"parentNode\"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[k,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[S]||(e[S]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===k&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[S]&&(v=Ce(v)),y&&!y[S]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||\"*\",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[\" \"],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[S]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace($,\"$1\"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+\" \"];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace($,\" \")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=A[e+\" \"];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[S]?i.push(a):o.push(a);(a=A(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l=\"0\",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG(\"*\",i),h=k+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t==C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument==C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(k=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(k=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&\"ID\"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=S.split(\"\").sort(j).join(\"\")===S,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement(\"fieldset\"))}),ce(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||fe(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||fe(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute(\"disabled\")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);S.find=d,S.expr=d.selectors,S.expr[\":\"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;var h=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&S(e).is(n))break;r.push(e)}return r},T=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?S.grep(e,function(e){return-1<i.call(n,e)!==r}):S.filter(n,e,r)}S.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?S.find.matchesSelector(r,e)?[r]:[]:S.find.matches(e,S.grep(t,function(e){return 1===e.nodeType}))},S.fn.extend({find:function(e){var t,n,r=this.length,i=this;if(\"string\"!=typeof e)return this.pushStack(S(e).filter(function(){for(t=0;t<r;t++)if(S.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)S.find(e,i[t],n);return 1<r?S.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,\"string\"==typeof e&&k.test(e)?S(e):e||[],!1).length}});var D,q=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,\"string\"==typeof e){if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(S.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a=\"string\"!=typeof e&&S(e);if(!k.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&S.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?S.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?i.call(S(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(S.uniqueSort(S.merge(this.get(),S(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),S.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return h(e,\"parentNode\")},parentsUntil:function(e,t,n){return h(e,\"parentNode\",n)},next:function(e){return O(e,\"nextSibling\")},prev:function(e){return O(e,\"previousSibling\")},nextAll:function(e){return h(e,\"nextSibling\")},prevAll:function(e){return h(e,\"previousSibling\")},nextUntil:function(e,t,n){return h(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return h(e,\"previousSibling\",n)},siblings:function(e){return T((e.parentNode||{}).firstChild,e)},children:function(e){return T(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(A(e,\"template\")&&(e=e.content||e),S.merge([],e.childNodes))}},function(r,i){S.fn[r]=function(e,t){var n=S.map(this,i,e);return\"Until\"!==r.slice(-5)&&(t=e),t&&\"string\"==typeof t&&(n=S.filter(t,n)),1<this.length&&(H[r]||S.uniqueSort(n),L.test(r)&&n.reverse()),this.pushStack(n)}});var P=/[^\\x20\\t\\r\\n\\f]+/g;function R(e){return e}function M(e){throw e}function I(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}S.Callbacks=function(r){var e,n;r=\"string\"==typeof r?(e=r,n={},S.each(e.match(P)||[],function(e,t){n[t]=!0}),n):S.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:\"\")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){S.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&\"string\"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return S.each(arguments,function(e,t){var n;while(-1<(n=S.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<S.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t=\"\",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=\"\"),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},S.extend({Deferred:function(e){var o=[[\"notify\",\"progress\",S.Callbacks(\"memory\"),S.Callbacks(\"memory\"),2],[\"resolve\",\"done\",S.Callbacks(\"once memory\"),S.Callbacks(\"once memory\"),0,\"resolved\"],[\"reject\",\"fail\",S.Callbacks(\"once memory\"),S.Callbacks(\"once memory\"),1,\"rejected\"]],i=\"pending\",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},\"catch\":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return S.Deferred(function(r){S.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+\"With\"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError(\"Thenable self-resolution\");t=e&&(\"object\"==typeof e||\"function\"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,R,s),l(u,o,M,s)):(u++,t.call(e,l(u,o,R,s),l(u,o,M,s),l(u,o,R,o.notifyWith))):(a!==R&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){S.Deferred.exceptionHook&&S.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==M&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(S.Deferred.getStackHook&&(t.stackTrace=S.Deferred.getStackHook()),C.setTimeout(t))}}return S.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:R,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:R)),o[2][3].add(l(0,e,m(n)?n:M))}).promise()},promise:function(e){return null!=e?S.extend(e,a):a}},s={};return S.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+\"With\"](this===s?void 0:this,arguments),this},s[t[0]+\"With\"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=S.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(I(e,o.done(a(t)).resolve,o.reject,!n),\"pending\"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)I(i[t],a(t),o.reject);return o.promise()}});var W=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;S.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&W.test(e.name)&&C.console.warn(\"jQuery.Deferred exception: \"+e.message,e.stack,t)},S.readyException=function(e){C.setTimeout(function(){throw e})};var F=S.Deferred();function B(){E.removeEventListener(\"DOMContentLoaded\",B),C.removeEventListener(\"load\",B),S.ready()}S.fn.ready=function(e){return F.then(e)[\"catch\"](function(e){S.readyException(e)}),this},S.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--S.readyWait:S.isReady)||(S.isReady=!0)!==e&&0<--S.readyWait||F.resolveWith(E,[S])}}),S.ready.then=F.then,\"complete\"===E.readyState||\"loading\"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(S.ready):(E.addEventListener(\"DOMContentLoaded\",B),C.addEventListener(\"load\",B));var $=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===w(n))for(s in i=!0,n)$(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(S(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},_=/^-ms-/,z=/-([a-z])/g;function U(e,t){return t.toUpperCase()}function X(e){return e.replace(_,\"ms-\").replace(z,U)}var V=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function G(){this.expando=S.expando+G.uid++}G.uid=1,G.prototype={cache:function(e){var t=e[this.expando];return t||(t={},V(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if(\"string\"==typeof t)i[X(t)]=n;else for(r in t)i[X(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][X(t)]},access:function(e,t,n){return void 0===t||t&&\"string\"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(X):(t=X(t))in r?[t]:t.match(P)||[]).length;while(n--)delete r[t[n]]}(void 0===t||S.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!S.isEmptyObject(t)}};var Y=new G,Q=new G,J=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,K=/[A-Z]/g;function Z(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r=\"data-\"+t.replace(K,\"-$&\").toLowerCase(),\"string\"==typeof(n=e.getAttribute(r))){try{n=\"true\"===(i=n)||\"false\"!==i&&(\"null\"===i?null:i===+i+\"\"?+i:J.test(i)?JSON.parse(i):i)}catch(e){}Q.set(e,t,n)}else n=void 0;return n}S.extend({hasData:function(e){return Q.hasData(e)||Y.hasData(e)},data:function(e,t,n){return Q.access(e,t,n)},removeData:function(e,t){Q.remove(e,t)},_data:function(e,t,n){return Y.access(e,t,n)},_removeData:function(e,t){Y.remove(e,t)}}),S.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=Q.get(o),1===o.nodeType&&!Y.get(o,\"hasDataAttrs\"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf(\"data-\")&&(r=X(r.slice(5)),Z(o,r,i[r]));Y.set(o,\"hasDataAttrs\",!0)}return i}return\"object\"==typeof n?this.each(function(){Q.set(this,n)}):$(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=Q.get(o,n))?t:void 0!==(t=Z(o,n))?t:void 0;this.each(function(){Q.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){Q.remove(this,e)})}}),S.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=Y.get(e,t),n&&(!r||Array.isArray(n)?r=Y.access(e,t,S.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=S.queue(e,t),r=n.length,i=n.shift(),o=S._queueHooks(e,t);\"inprogress\"===i&&(i=n.shift(),r--),i&&(\"fx\"===t&&n.unshift(\"inprogress\"),delete o.stop,i.call(e,function(){S.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+\"queueHooks\";return Y.get(e,n)||Y.access(e,n,{empty:S.Callbacks(\"once memory\").add(function(){Y.remove(e,[t+\"queue\",n])})})}}),S.fn.extend({queue:function(t,n){var e=2;return\"string\"!=typeof t&&(n=t,t=\"fx\",e--),arguments.length<e?S.queue(this[0],t):void 0===n?this:this.each(function(){var e=S.queue(this,t,n);S._queueHooks(this,t),\"fx\"===t&&\"inprogress\"!==e[0]&&S.dequeue(this,t)})},dequeue:function(e){return this.each(function(){S.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=S.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";while(a--)(n=Y.get(o[a],e+\"queueHooks\"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var ee=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,te=new RegExp(\"^(?:([+-])=|)(\"+ee+\")([a-z%]*)$\",\"i\"),ne=[\"Top\",\"Right\",\"Bottom\",\"Left\"],re=E.documentElement,ie=function(e){return S.contains(e.ownerDocument,e)},oe={composed:!0};re.getRootNode&&(ie=function(e){return S.contains(e.ownerDocument,e)||e.getRootNode(oe)===e.ownerDocument});var ae=function(e,t){return\"none\"===(e=t||e).style.display||\"\"===e.style.display&&ie(e)&&\"none\"===S.css(e,\"display\")};function se(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return S.css(e,t,\"\")},u=s(),l=n&&n[3]||(S.cssNumber[t]?\"\":\"px\"),c=e.nodeType&&(S.cssNumber[t]||\"px\"!==l&&+u)&&te.exec(S.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)S.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,S.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ue={};function le(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?(\"none\"===n&&(l[c]=Y.get(r,\"display\")||null,l[c]||(r.style.display=\"\")),\"\"===r.style.display&&ae(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ue[s])||(o=a.body.appendChild(a.createElement(s)),u=S.css(o,\"display\"),o.parentNode.removeChild(o),\"none\"===u&&(u=\"block\"),ue[s]=u)))):\"none\"!==n&&(l[c]=\"none\",Y.set(r,\"display\",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}S.fn.extend({show:function(){return le(this,!0)},hide:function(){return le(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?S(this).show():S(this).hide()})}});var ce,fe,pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)/i,he=/^$|^module$|\\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement(\"div\")),(fe=E.createElement(\"input\")).setAttribute(\"type\",\"radio\"),fe.setAttribute(\"checked\",\"checked\"),fe.setAttribute(\"name\",\"t\"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML=\"<textarea>x</textarea>\",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML=\"<option></option>\",y.option=!!ce.lastChild;var ge={thead:[1,\"<table>\",\"</table>\"],col:[2,\"<table><colgroup>\",\"</colgroup></table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:[0,\"\",\"\"]};function ve(e,t){var n;return n=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Y.set(e[n],\"globalEval\",!t||Y.get(t[n],\"globalEval\"))}ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td,y.option||(ge.optgroup=ge.option=[1,\"<select multiple='multiple'>\",\"</select>\"]);var me=/<|&#?\\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if(\"object\"===w(o))S.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement(\"div\")),s=(de.exec(o)||[\"\",\"\"])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+S.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;S.merge(p,a.childNodes),(a=f.firstChild).textContent=\"\"}else p.push(t.createTextNode(o));f.textContent=\"\",d=0;while(o=p[d++])if(r&&-1<S.inArray(o,r))i&&i.push(o);else if(l=ie(o),a=ve(f.appendChild(o),\"script\"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||\"\")&&n.push(o)}return f}var be=/^([^.]*)(?:\\.(.+)|)/;function we(){return!0}function Te(){return!1}function Ce(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==(\"focus\"===t)}function Ee(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){for(s in\"string\"!=typeof n&&(r=r||n,n=void 0),t)Ee(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Te;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return S().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=S.guid++)),e.each(function(){S.event.add(this,t,i,r,n)})}function Se(e,i,o){o?(Y.set(e,i,!1),S.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Y.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(S.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Y.set(this,i,r),t=o(this,i),this[i](),r!==(n=Y.get(this,i))||t?Y.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n&&n.value}else r.length&&(Y.set(this,i,{value:S.event.trigger(S.extend(r[0],S.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Y.get(e,i)&&S.event.add(e,i,we)}S.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.get(t);if(V(t)){n.handler&&(n=(o=n).handler,i=o.selector),i&&S.find.matchesSelector(re,i),n.guid||(n.guid=S.guid++),(u=v.events)||(u=v.events=Object.create(null)),(a=v.handle)||(a=v.handle=function(e){return\"undefined\"!=typeof S&&S.event.triggered!==e.type?S.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||\"\").match(P)||[\"\"]).length;while(l--)d=g=(s=be.exec(e[l])||[])[1],h=(s[2]||\"\").split(\".\").sort(),d&&(f=S.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=S.event.special[d]||{},c=S.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&S.expr.match.needsContext.test(i),namespace:h.join(\".\")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),S.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.hasData(e)&&Y.get(e);if(v&&(u=v.events)){l=(t=(t||\"\").match(P)||[\"\"]).length;while(l--)if(d=g=(s=be.exec(t[l])||[])[1],h=(s[2]||\"\").split(\".\").sort(),d){f=S.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&(\"**\"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||S.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)S.event.remove(e,d+t[l],n,r,!0);S.isEmptyObject(u)&&Y.remove(e,\"handle events\")}},dispatch:function(e){var t,n,r,i,o,a,s=new Array(arguments.length),u=S.event.fix(e),l=(Y.get(this,\"events\")||Object.create(null))[u.type]||[],c=S.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++)s[t]=arguments[t];if(u.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,u)){a=S.event.handlers.call(this,u,l),t=0;while((i=a[t++])&&!u.isPropagationStopped()){u.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!u.isImmediatePropagationStopped())u.rnamespace&&!1!==o.namespace&&!u.rnamespace.test(o.namespace)||(u.handleObj=o,u.data=o.data,void 0!==(r=((S.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s))&&!1===(u.result=r)&&(u.preventDefault(),u.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!(\"click\"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&(\"click\"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+\" \"]&&(a[i]=r.needsContext?-1<S(i,this).index(l):S.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(S.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[S.expando]?e:new S.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,\"input\")&&Se(t,\"click\",we),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,\"input\")&&Se(t,\"click\"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,\"input\")&&Y.get(t,\"click\")||A(t,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},S.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},S.Event=function(e,t){if(!(this instanceof S.Event))return new S.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?we:Te,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&S.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[S.expando]=!0},S.Event.prototype={constructor:S.Event,isDefaultPrevented:Te,isPropagationStopped:Te,isImmediatePropagationStopped:Te,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=we,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=we,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=we,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},S.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,\"char\":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:!0},S.event.addProp),S.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){S.event.special[e]={setup:function(){return Se(this,e,Ce),!1},trigger:function(){return Se(this,e),!0},_default:function(){return!0},delegateType:t}}),S.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,i){S.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||S.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),S.fn.extend({on:function(e,t,n,r){return Ee(this,e,t,n,r)},one:function(e,t,n,r){return Ee(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,S(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&\"function\"!=typeof t||(n=t,t=void 0),!1===n&&(n=Te),this.each(function(){S.event.remove(this,e,n,t)})}});var ke=/<script|<style|<link/i,Ae=/checked\\s*(?:[^=]|=\\s*.checked.)/i,Ne=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;function je(e,t){return A(e,\"table\")&&A(11!==t.nodeType?t:t.firstChild,\"tr\")&&S(e).children(\"tbody\")[0]||e}function De(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function qe(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,\"handle events\"),s)for(n=0,r=s[i].length;n<r;n++)S.event.add(t,i,s[i][n]);Q.hasData(e)&&(o=Q.access(e),a=S.extend({},o),Q.set(t,a))}}function He(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&\"string\"==typeof d&&!y.checkClone&&Ae.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),He(t,r,i,o)});if(f&&(t=(e=xe(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=S.map(ve(e,\"script\"),De)).length;c<f;c++)u=e,c!==p&&(u=S.clone(u,!0,!0),s&&S.merge(a,ve(u,\"script\"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,S.map(a,qe),c=0;c<s;c++)u=a[c],he.test(u.type||\"\")&&!Y.access(u,\"globalEval\")&&S.contains(l,u)&&(u.src&&\"module\"!==(u.type||\"\").toLowerCase()?S._evalUrl&&!u.noModule&&S._evalUrl(u.src,{nonce:u.nonce||u.getAttribute(\"nonce\")},l):b(u.textContent.replace(Ne,\"\"),u,l))}return n}function Oe(e,t,n){for(var r,i=t?S.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||S.cleanData(ve(r)),r.parentNode&&(n&&ie(r)&&ye(ve(r,\"script\")),r.parentNode.removeChild(r));return e}S.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=ie(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||S.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,\"input\"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:\"input\"!==l&&\"textarea\"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Le(o[r],a[r]);else Le(e,c);return 0<(a=ve(c,\"script\")).length&&ye(a,!f&&ve(e,\"script\")),c},cleanData:function(e){for(var t,n,r,i=S.event.special,o=0;void 0!==(n=e[o]);o++)if(V(n)){if(t=n[Y.expando]){if(t.events)for(r in t.events)i[r]?S.event.remove(n,r):S.removeEvent(n,r,t.handle);n[Y.expando]=void 0}n[Q.expando]&&(n[Q.expando]=void 0)}}}),S.fn.extend({detach:function(e){return Oe(this,e,!0)},remove:function(e){return Oe(this,e)},text:function(e){return $(this,function(e){return void 0===e?S.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return He(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||je(this,e).appendChild(e)})},prepend:function(){return He(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=je(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return He(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return He(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(S.cleanData(ve(e,!1)),e.textContent=\"\");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return S.clone(this,e,t)})},html:function(e){return $(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if(\"string\"==typeof e&&!ke.test(e)&&!ge[(de.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=S.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(S.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return He(this,arguments,function(e){var t=this.parentNode;S.inArray(this,n)<0&&(S.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),S.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,a){S.fn[e]=function(e){for(var t,n=[],r=S(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),S(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var Pe=new RegExp(\"^(\"+ee+\")(?!px)[a-z%]+$\",\"i\"),Re=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Me=function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r},Ie=new RegExp(ne.join(\"|\"),\"i\");function We(e,t,n){var r,i,o,a,s=e.style;return(n=n||Re(e))&&(\"\"!==(a=n.getPropertyValue(t)||n[t])||ie(e)||(a=S.style(e,t)),!y.pixelBoxStyles()&&Pe.test(a)&&Ie.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+\"\":a}function Fe(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(l){u.style.cssText=\"position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0\",l.style.cssText=\"position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%\",re.appendChild(u).appendChild(l);var e=C.getComputedStyle(l);n=\"1%\"!==e.top,s=12===t(e.marginLeft),l.style.right=\"60%\",o=36===t(e.right),r=36===t(e.width),l.style.position=\"absolute\",i=12===t(l.offsetWidth/3),re.removeChild(u),l=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s,u=E.createElement(\"div\"),l=E.createElement(\"div\");l.style&&(l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",y.clearCloneStyle=\"content-box\"===l.style.backgroundClip,S.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),s},scrollboxSize:function(){return e(),i},reliableTrDimensions:function(){var e,t,n,r;return null==a&&(e=E.createElement(\"table\"),t=E.createElement(\"tr\"),n=E.createElement(\"div\"),e.style.cssText=\"position:absolute;left:-11111px;border-collapse:separate\",t.style.cssText=\"border:1px solid\",t.style.height=\"1px\",n.style.height=\"9px\",n.style.display=\"block\",re.appendChild(e).appendChild(t).appendChild(n),r=C.getComputedStyle(t),a=parseInt(r.height,10)+parseInt(r.borderTopWidth,10)+parseInt(r.borderBottomWidth,10)===t.offsetHeight,re.removeChild(e)),a}}))}();var Be=[\"Webkit\",\"Moz\",\"ms\"],$e=E.createElement(\"div\").style,_e={};function ze(e){var t=S.cssProps[e]||_e[e];return t||(e in $e?e:_e[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Be.length;while(n--)if((e=Be[n]+t)in $e)return e}(e)||e)}var Ue=/^(none|table(?!-c[ea]).+)/,Xe=/^--/,Ve={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Ge={letterSpacing:\"0\",fontWeight:\"400\"};function Ye(e,t,n){var r=te.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||\"px\"):t}function Qe(e,t,n,r,i,o){var a=\"width\"===t?1:0,s=0,u=0;if(n===(r?\"border\":\"content\"))return 0;for(;a<4;a+=2)\"margin\"===n&&(u+=S.css(e,n+ne[a],!0,i)),r?(\"content\"===n&&(u-=S.css(e,\"padding\"+ne[a],!0,i)),\"margin\"!==n&&(u-=S.css(e,\"border\"+ne[a]+\"Width\",!0,i))):(u+=S.css(e,\"padding\"+ne[a],!0,i),\"padding\"!==n?u+=S.css(e,\"border\"+ne[a]+\"Width\",!0,i):s+=S.css(e,\"border\"+ne[a]+\"Width\",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e[\"offset\"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function Je(e,t,n){var r=Re(e),i=(!y.boxSizingReliable()||n)&&\"border-box\"===S.css(e,\"boxSizing\",!1,r),o=i,a=We(e,t,r),s=\"offset\"+t[0].toUpperCase()+t.slice(1);if(Pe.test(a)){if(!n)return a;a=\"auto\"}return(!y.boxSizingReliable()&&i||!y.reliableTrDimensions()&&A(e,\"tr\")||\"auto\"===a||!parseFloat(a)&&\"inline\"===S.css(e,\"display\",!1,r))&&e.getClientRects().length&&(i=\"border-box\"===S.css(e,\"boxSizing\",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+Qe(e,t,n||(i?\"border\":\"content\"),o,r,a)+\"px\"}function Ke(e,t,n,r,i){return new Ke.prototype.init(e,t,n,r,i)}S.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=We(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=X(t),u=Xe.test(t),l=e.style;if(u||(t=ze(s)),a=S.cssHooks[t]||S.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];\"string\"===(o=typeof n)&&(i=te.exec(n))&&i[1]&&(n=se(e,t,i),o=\"number\"),null!=n&&n==n&&(\"number\"!==o||u||(n+=i&&i[3]||(S.cssNumber[s]?\"\":\"px\")),y.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(l[t]=\"inherit\"),a&&\"set\"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=X(t);return Xe.test(t)||(t=ze(s)),(a=S.cssHooks[t]||S.cssHooks[s])&&\"get\"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=We(e,t,r)),\"normal\"===i&&t in Ge&&(i=Ge[t]),\"\"===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),S.each([\"height\",\"width\"],function(e,u){S.cssHooks[u]={get:function(e,t,n){if(t)return!Ue.test(S.css(e,\"display\"))||e.getClientRects().length&&e.getBoundingClientRect().width?Je(e,u,n):Me(e,Ve,function(){return Je(e,u,n)})},set:function(e,t,n){var r,i=Re(e),o=!y.scrollboxSize()&&\"absolute\"===i.position,a=(o||n)&&\"border-box\"===S.css(e,\"boxSizing\",!1,i),s=n?Qe(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e[\"offset\"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-Qe(e,u,\"border\",!1,i)-.5)),s&&(r=te.exec(t))&&\"px\"!==(r[3]||\"px\")&&(e.style[u]=t,t=S.css(e,u)),Ye(0,t,s)}}}),S.cssHooks.marginLeft=Fe(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(We(e,\"marginLeft\"))||e.getBoundingClientRect().left-Me(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+\"px\"}),S.each({margin:\"\",padding:\"\",border:\"Width\"},function(i,o){S.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r=\"string\"==typeof e?e.split(\" \"):[e];t<4;t++)n[i+ne[t]+o]=r[t]||r[t-2]||r[0];return n}},\"margin\"!==i&&(S.cssHooks[i+o].set=Ye)}),S.fn.extend({css:function(e,t){return $(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Re(e),i=t.length;a<i;a++)o[t[a]]=S.css(e,t[a],!1,r);return o}return void 0!==n?S.style(e,t,n):S.css(e,t)},e,t,1<arguments.length)}}),((S.Tween=Ke).prototype={constructor:Ke,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||S.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(S.cssNumber[n]?\"\":\"px\")},cur:function(){var e=Ke.propHooks[this.prop];return e&&e.get?e.get(this):Ke.propHooks._default.get(this)},run:function(e){var t,n=Ke.propHooks[this.prop];return this.options.duration?this.pos=t=S.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Ke.propHooks._default.set(this),this}}).init.prototype=Ke.prototype,(Ke.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=S.css(e.elem,e.prop,\"\"))&&\"auto\"!==t?t:0},set:function(e){S.fx.step[e.prop]?S.fx.step[e.prop](e):1!==e.elem.nodeType||!S.cssHooks[e.prop]&&null==e.elem.style[ze(e.prop)]?e.elem[e.prop]=e.now:S.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=Ke.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},S.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},S.fx=Ke.prototype.init,S.fx.step={};var Ze,et,tt,nt,rt=/^(?:toggle|show|hide)$/,it=/queueHooks$/;function ot(){et&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(ot):C.setTimeout(ot,S.fx.interval),S.fx.tick())}function at(){return C.setTimeout(function(){Ze=void 0}),Ze=Date.now()}function st(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i[\"margin\"+(n=ne[r])]=i[\"padding\"+n]=e;return t&&(i.opacity=i.width=e),i}function ut(e,t,n){for(var r,i=(lt.tweeners[t]||[]).concat(lt.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function lt(o,e,t){var n,a,r=0,i=lt.prefilters.length,s=S.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=Ze||at(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:S.extend({},e),opts:S.extend(!0,{specialEasing:{},easing:S.easing._default},t),originalProperties:e,originalOptions:t,startTime:Ze||at(),duration:t.duration,tweens:[],createTween:function(e,t){var n=S.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=X(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=S.cssHooks[r])&&\"expand\"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=lt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(S._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return S.map(c,ut,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),S.fx.timer(S.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}S.Animation=S.extend(lt,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return se(n.elem,e,te.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=[\"*\"]):e=e.match(P);for(var n,r=0,i=e.length;r<i;r++)n=e[r],lt.tweeners[n]=lt.tweeners[n]||[],lt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f=\"width\"in t||\"height\"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),v=Y.get(e,\"fxshow\");for(r in n.queue||(null==(a=S._queueHooks(e,\"fx\")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,S.queue(e,\"fx\").length||a.empty.fire()})})),t)if(i=t[r],rt.test(i)){if(delete t[r],o=o||\"toggle\"===i,i===(g?\"hide\":\"show\")){if(\"show\"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||S.style(e,r)}if((u=!S.isEmptyObject(t))||!S.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Y.get(e,\"display\")),\"none\"===(c=S.css(e,\"display\"))&&(l?c=l:(le([e],!0),l=e.style.display||l,c=S.css(e,\"display\"),le([e]))),(\"inline\"===c||\"inline-block\"===c&&null!=l)&&\"none\"===S.css(e,\"float\")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l=\"none\"===c?\"\":c)),h.display=\"inline-block\")),n.overflow&&(h.overflow=\"hidden\",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?\"hidden\"in v&&(g=v.hidden):v=Y.access(e,\"fxshow\",{display:l}),o&&(v.hidden=!g),g&&le([e],!0),p.done(function(){for(r in g||le([e]),Y.remove(e,\"fxshow\"),d)S.style(e,r,d[r])})),u=ut(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?lt.prefilters.unshift(e):lt.prefilters.push(e)}}),S.speed=function(e,t,n){var r=e&&\"object\"==typeof e?S.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return S.fx.off?r.duration=0:\"number\"!=typeof r.duration&&(r.duration in S.fx.speeds?r.duration=S.fx.speeds[r.duration]:r.duration=S.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&S.dequeue(this,r.queue)},r},S.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=S.isEmptyObject(t),o=S.speed(e,n,r),a=function(){var e=lt(this,S.extend({},t),o);(i||Y.get(this,\"finish\"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return\"string\"!=typeof i&&(o=e,e=i,i=void 0),e&&this.queue(i||\"fx\",[]),this.each(function(){var e=!0,t=null!=i&&i+\"queueHooks\",n=S.timers,r=Y.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&it.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||S.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||\"fx\"),this.each(function(){var e,t=Y.get(this),n=t[a+\"queue\"],r=t[a+\"queueHooks\"],i=S.timers,o=n?n.length:0;for(t.finish=!0,S.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),S.each([\"toggle\",\"show\",\"hide\"],function(e,r){var i=S.fn[r];S.fn[r]=function(e,t,n){return null==e||\"boolean\"==typeof e?i.apply(this,arguments):this.animate(st(r,!0),e,t,n)}}),S.each({slideDown:st(\"show\"),slideUp:st(\"hide\"),slideToggle:st(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,r){S.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),S.timers=[],S.fx.tick=function(){var e,t=0,n=S.timers;for(Ze=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||S.fx.stop(),Ze=void 0},S.fx.timer=function(e){S.timers.push(e),S.fx.start()},S.fx.interval=13,S.fx.start=function(){et||(et=!0,ot())},S.fx.stop=function(){et=null},S.fx.speeds={slow:600,fast:200,_default:400},S.fn.delay=function(r,e){return r=S.fx&&S.fx.speeds[r]||r,e=e||\"fx\",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},tt=E.createElement(\"input\"),nt=E.createElement(\"select\").appendChild(E.createElement(\"option\")),tt.type=\"checkbox\",y.checkOn=\"\"!==tt.value,y.optSelected=nt.selected,(tt=E.createElement(\"input\")).value=\"t\",tt.type=\"radio\",y.radioValue=\"t\"===tt.value;var ct,ft=S.expr.attrHandle;S.fn.extend({attr:function(e,t){return $(this,S.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){S.removeAttr(this,e)})}}),S.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?S.prop(e,t,n):(1===o&&S.isXMLDoc(e)||(i=S.attrHooks[t.toLowerCase()]||(S.expr.match.bool.test(t)?ct:void 0)),void 0!==n?null===n?void S.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:null==(r=S.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&\"radio\"===t&&A(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(P);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ct={set:function(e,t,n){return!1===t?S.removeAttr(e,n):e.setAttribute(n,n),n}},S.each(S.expr.match.bool.source.match(/\\w+/g),function(e,t){var a=ft[t]||S.find.attr;ft[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=ft[o],ft[o]=r,r=null!=a(e,t,n)?o:null,ft[o]=i),r}});var pt=/^(?:input|select|textarea|button)$/i,dt=/^(?:a|area)$/i;function ht(e){return(e.match(P)||[]).join(\" \")}function gt(e){return e.getAttribute&&e.getAttribute(\"class\")||\"\"}function vt(e){return Array.isArray(e)?e:\"string\"==typeof e&&e.match(P)||[]}S.fn.extend({prop:function(e,t){return $(this,S.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[S.propFix[e]||e]})}}),S.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&S.isXMLDoc(e)||(t=S.propFix[t]||t,i=S.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=S.find.attr(e,\"tabindex\");return t?parseInt(t,10):pt.test(e.nodeName)||dt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),y.optSelected||(S.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),S.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){S.propFix[this.toLowerCase()]=this}),S.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).addClass(t.call(this,e,gt(this)))});if((e=vt(t)).length)while(n=this[u++])if(i=gt(n),r=1===n.nodeType&&\" \"+ht(i)+\" \"){a=0;while(o=e[a++])r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");i!==(s=ht(r))&&n.setAttribute(\"class\",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).removeClass(t.call(this,e,gt(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if((e=vt(t)).length)while(n=this[u++])if(i=gt(n),r=1===n.nodeType&&\" \"+ht(i)+\" \"){a=0;while(o=e[a++])while(-1<r.indexOf(\" \"+o+\" \"))r=r.replace(\" \"+o+\" \",\" \");i!==(s=ht(r))&&n.setAttribute(\"class\",s)}return this},toggleClass:function(i,t){var o=typeof i,a=\"string\"===o||Array.isArray(i);return\"boolean\"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){S(this).toggleClass(i.call(this,e,gt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=S(this),r=vt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&\"boolean\"!==o||((e=gt(this))&&Y.set(this,\"__className__\",e),this.setAttribute&&this.setAttribute(\"class\",e||!1===i?\"\":Y.get(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;t=\" \"+e+\" \";while(n=this[r++])if(1===n.nodeType&&-1<(\" \"+ht(gt(n))+\" \").indexOf(t))return!0;return!1}});var yt=/\\r/g;S.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,S(this).val()):n)?t=\"\":\"number\"==typeof t?t+=\"\":Array.isArray(t)&&(t=S.map(t,function(e){return null==e?\"\":e+\"\"})),(r=S.valHooks[this.type]||S.valHooks[this.nodeName.toLowerCase()])&&\"set\"in r&&void 0!==r.set(this,t,\"value\")||(this.value=t))})):t?(r=S.valHooks[t.type]||S.valHooks[t.nodeName.toLowerCase()])&&\"get\"in r&&void 0!==(e=r.get(t,\"value\"))?e:\"string\"==typeof(e=t.value)?e.replace(yt,\"\"):null==e?\"\":e:void 0}}),S.extend({valHooks:{option:{get:function(e){var t=S.find.attr(e,\"value\");return null!=t?t:ht(S.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a=\"select-one\"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,\"optgroup\"))){if(t=S(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=S.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<S.inArray(S.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),S.each([\"radio\",\"checkbox\"],function(){S.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<S.inArray(S(e).val(),t)}},y.checkOn||(S.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})}),y.focusin=\"onfocusin\"in C;var mt=/^(?:focusinfocus|focusoutblur)$/,xt=function(e){e.stopPropagation()};S.extend(S.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,\"type\")?e.type:e,h=v.call(e,\"namespace\")?e.namespace.split(\".\"):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!mt.test(d+S.event.triggered)&&(-1<d.indexOf(\".\")&&(d=(h=d.split(\".\")).shift(),h.sort()),u=d.indexOf(\":\")<0&&\"on\"+d,(e=e[S.expando]?e:new S.Event(d,\"object\"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join(\".\"),e.rnamespace=e.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:S.makeArray(t,[e]),c=S.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,mt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Y.get(o,\"events\")||Object.create(null))[e.type]&&Y.get(o,\"handle\"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&V(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!V(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),S.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,xt),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,xt),S.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=S.extend(new S.Event,n,{type:e,isSimulated:!0});S.event.trigger(r,null,t)}}),S.fn.extend({trigger:function(e,t){return this.each(function(){S.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return S.event.trigger(e,t,n,!0)}}),y.focusin||S.each({focus:\"focusin\",blur:\"focusout\"},function(n,r){var i=function(e){S.event.simulate(r,e.target,S.event.fix(e))};S.event.special[r]={setup:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r);t||e.addEventListener(n,i,!0),Y.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r)-1;t?Y.access(e,r,t):(e.removeEventListener(n,i,!0),Y.remove(e,r))}}});var bt=C.location,wt={guid:Date.now()},Tt=/\\?/;S.parseXML=function(e){var t,n;if(!e||\"string\"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,\"text/xml\")}catch(e){}return n=t&&t.getElementsByTagName(\"parsererror\")[0],t&&!n||S.error(\"Invalid XML: \"+(n?S.map(n.childNodes,function(e){return e.textContent}).join(\"\\n\"):e)),t};var Ct=/\\[\\]$/,Et=/\\r?\\n/g,St=/^(?:submit|button|image|reset|file)$/i,kt=/^(?:input|select|textarea|keygen)/i;function At(n,e,r,i){var t;if(Array.isArray(e))S.each(e,function(e,t){r||Ct.test(n)?i(n,t):At(n+\"[\"+(\"object\"==typeof t&&null!=t?e:\"\")+\"]\",t,r,i)});else if(r||\"object\"!==w(e))i(n,e);else for(t in e)At(n+\"[\"+t+\"]\",e[t],r,i)}S.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(null==n?\"\":n)};if(null==e)return\"\";if(Array.isArray(e)||e.jquery&&!S.isPlainObject(e))S.each(e,function(){i(this.name,this.value)});else for(n in e)At(n,e[n],t,i);return r.join(\"&\")},S.fn.extend({serialize:function(){return S.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=S.prop(this,\"elements\");return e?S.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!S(this).is(\":disabled\")&&kt.test(this.nodeName)&&!St.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=S(this).val();return null==n?null:Array.isArray(n)?S.map(n,function(e){return{name:t.name,value:e.replace(Et,\"\\r\\n\")}}):{name:t.name,value:n.replace(Et,\"\\r\\n\")}}).get()}});var Nt=/%20/g,jt=/#.*$/,Dt=/([?&])_=[^&]*/,qt=/^(.*?):[ \\t]*([^\\r\\n]*)$/gm,Lt=/^(?:GET|HEAD)$/,Ht=/^\\/\\//,Ot={},Pt={},Rt=\"*/\".concat(\"*\"),Mt=E.createElement(\"a\");function It(o){return function(e,t){\"string\"!=typeof e&&(t=e,e=\"*\");var n,r=0,i=e.toLowerCase().match(P)||[];if(m(t))while(n=i[r++])\"+\"===n[0]?(n=n.slice(1)||\"*\",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function Wt(t,i,o,a){var s={},u=t===Pt;function l(e){var r;return s[e]=!0,S.each(t[e]||[],function(e,t){var n=t(i,o,a);return\"string\"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s[\"*\"]&&l(\"*\")}function Ft(e,t){var n,r,i=S.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&S.extend(!0,e,r),e}Mt.href=bt.href,S.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:bt.href,type:\"GET\",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(bt.protocol),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Rt,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":JSON.parse,\"text xml\":S.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Ft(Ft(e,S.ajaxSettings),t):Ft(S.ajaxSettings,e)},ajaxPrefilter:It(Ot),ajaxTransport:It(Pt),ajax:function(e,t){\"object\"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=S.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?S(y):S.event,x=S.Deferred(),b=S.Callbacks(\"once memory\"),w=v.statusCode||{},a={},s={},u=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=qt.exec(p))n[t[1].toLowerCase()+\" \"]=(n[t[1].toLowerCase()+\" \"]||[]).concat(t[2])}t=n[e.toLowerCase()+\" \"]}return null==t?null:t.join(\", \")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||bt.href)+\"\").replace(Ht,bt.protocol+\"//\"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||\"*\").toLowerCase().match(P)||[\"\"],null==v.crossDomain){r=E.createElement(\"a\");try{r.href=v.url,r.href=r.href,v.crossDomain=Mt.protocol+\"//\"+Mt.host!=r.protocol+\"//\"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&\"string\"!=typeof v.data&&(v.data=S.param(v.data,v.traditional)),Wt(Ot,v,t,T),h)return T;for(i in(g=S.event&&v.global)&&0==S.active++&&S.event.trigger(\"ajaxStart\"),v.type=v.type.toUpperCase(),v.hasContent=!Lt.test(v.type),f=v.url.replace(jt,\"\"),v.hasContent?v.data&&v.processData&&0===(v.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&(v.data=v.data.replace(Nt,\"+\")):(o=v.url.slice(f.length),v.data&&(v.processData||\"string\"==typeof v.data)&&(f+=(Tt.test(f)?\"&\":\"?\")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Dt,\"$1\"),o=(Tt.test(f)?\"&\":\"?\")+\"_=\"+wt.guid+++o),v.url=f+o),v.ifModified&&(S.lastModified[f]&&T.setRequestHeader(\"If-Modified-Since\",S.lastModified[f]),S.etag[f]&&T.setRequestHeader(\"If-None-Match\",S.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader(\"Content-Type\",v.contentType),T.setRequestHeader(\"Accept\",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+(\"*\"!==v.dataTypes[0]?\", \"+Rt+\"; q=0.01\":\"\"):v.accepts[\"*\"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u=\"abort\",b.add(v.complete),T.done(v.success),T.fail(v.error),c=Wt(Pt,v,t,T)){if(T.readyState=1,g&&m.trigger(\"ajaxSend\",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort(\"timeout\")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,\"No Transport\");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||\"\",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while(\"*\"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+\" \"+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),!i&&-1<S.inArray(\"script\",v.dataTypes)&&S.inArray(\"json\",v.dataTypes)<0&&(v.converters[\"text script\"]=function(){}),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(!(a=l[u+\" \"+o]||l[\"* \"+o]))for(i in l)if((s=i.split(\" \"))[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e[\"throws\"])t=a(t);else try{t=a(t)}catch(e){return{state:\"parsererror\",error:a?e:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader(\"Last-Modified\"))&&(S.lastModified[f]=u),(u=T.getResponseHeader(\"etag\"))&&(S.etag[f]=u)),204===e||\"HEAD\"===v.type?l=\"nocontent\":304===e?l=\"notmodified\":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l=\"error\",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+\"\",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?\"ajaxSuccess\":\"ajaxError\",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger(\"ajaxComplete\",[T,v]),--S.active||S.event.trigger(\"ajaxStop\")))}return T},getJSON:function(e,t,n){return S.get(e,t,n,\"json\")},getScript:function(e,t){return S.get(e,void 0,t,\"script\")}}),S.each([\"get\",\"post\"],function(e,i){S[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),S.ajax(S.extend({url:e,type:i,dataType:r,data:t,success:n},S.isPlainObject(e)&&e))}}),S.ajaxPrefilter(function(e){var t;for(t in e.headers)\"content-type\"===t.toLowerCase()&&(e.contentType=e.headers[t]||\"\")}),S._evalUrl=function(e,t,n){return S.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,converters:{\"text script\":function(){}},dataFilter:function(e){S.globalEval(e,t,n)}})},S.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=S(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){S(this).wrapInner(n.call(this,e))}):this.each(function(){var e=S(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){S(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not(\"body\").each(function(){S(this).replaceWith(this.childNodes)}),this}}),S.expr.pseudos.hidden=function(e){return!S.expr.pseudos.visible(e)},S.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},S.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Bt={0:200,1223:204},$t=S.ajaxSettings.xhr();y.cors=!!$t&&\"withCredentials\"in $t,y.ajax=$t=!!$t,S.ajaxTransport(function(i){var o,a;if(y.cors||$t&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e[\"X-Requested-With\"]||(e[\"X-Requested-With\"]=\"XMLHttpRequest\"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,\"abort\"===e?r.abort():\"error\"===e?\"number\"!=typeof r.status?t(0,\"error\"):t(r.status,r.statusText):t(Bt[r.status]||r.status,r.statusText,\"text\"!==(r.responseType||\"text\")||\"string\"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o(\"error\"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o(\"abort\");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),S.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),S.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return S.globalEval(e),e}}}),S.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\")}),S.ajaxTransport(\"script\",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=S(\"<script>\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",i=function(e){r.remove(),i=null,e&&t(\"error\"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\\?(?=&|$)|\\?\\?/;S.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=zt.pop()||S.expando+\"_\"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Ut.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return o||S.error(r+\" was not called\"),o[0]},e.dataTypes[0]=\"json\",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),\"script\"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument(\"\").body).innerHTML=\"<form></form><form></form>\",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(\" \");return-1<s&&(r=ht(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),0<a.length&&S.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?S(\"<div>\").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,\"position\"),c=S(e),f={};\"static\"===l&&(e.style.position=\"relative\"),s=c.offset(),o=S.css(e,\"top\"),u=S.css(e,\"left\"),(\"absolute\"===l||\"fixed\"===l)&&-1<(o+u).indexOf(\"auto\")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),\"using\"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if(\"fixed\"===S.css(r,\"position\"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&\"static\"===S.css(e,\"position\"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,\"borderTopWidth\",!0),i.left+=S.css(e,\"borderLeftWidth\",!0))}return{top:t.top-i.top-S.css(r,\"marginTop\",!0),left:t.left-i.left-S.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&\"static\"===S.css(e,\"position\"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,i){var o=\"pageYOffset\"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each([\"top\",\"left\"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+\"px\":t})}),S.each({Height:\"height\",Width:\"width\"},function(a,s){S.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),i=r||(!0===e||!0===t?\"margin\":\"border\");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf(\"outer\")?e[\"inner\"+a]:e.document.documentElement[\"client\"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body[\"scroll\"+a],r[\"scroll\"+a],e.body[\"offset\"+a],r[\"offset\"+a],r[\"client\"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each(\"blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu\".split(\" \"),function(e,n){S.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}});var Xt=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;S.proxy=function(e,t){var n,r,i;if(\"string\"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||S.guid++,i},S.holdReady=function(e){e?S.readyWait++:S.ready(!0)},S.isArray=Array.isArray,S.parseJSON=JSON.parse,S.nodeName=A,S.isFunction=m,S.isWindow=x,S.camelCase=X,S.type=w,S.now=Date.now,S.isNumeric=function(e){var t=S.type(e);return(\"number\"===t||\"string\"===t)&&!isNaN(e-parseFloat(e))},S.trim=function(e){return null==e?\"\":(e+\"\").replace(Xt,\"\")},\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return S});var Vt=C.jQuery,Gt=C.$;return S.noConflict=function(e){return C.$===S&&(C.$=Gt),e&&C.jQuery===S&&(C.jQuery=Vt),S},\"undefined\"==typeof e&&(C.jQuery=C.$=S),S});\n"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<script type=\"module\">\n",
       "  window.__itables_render = async (table_id, dt_args) => {\n",
       "    await initializeDataTables();\n",
       "    $(table_id).DataTable(dt_args);\n",
       "  };\n",
       "\n",
       "  async function initializeDataTables() {\n",
       "    if ($.prototype.DataTable) {\n",
       "      return;\n",
       "    }\n",
       "    const dt = (await import(\"data:text/javascript;base64,LyohIERhdGFUYWJsZXMgMS4xMi4xCiAqIMKpMjAwOC0yMDIyIFNwcnlNZWRpYSBMdGQgLSBkYXRhdGFibGVzLm5ldC9saWNlbnNlCiAqLwoKLy8gRVNNIGV4cG9ydCBvZiBEYXRhVGFibGVzCmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uICgkLCByb290KSB7CglpZiAoISByb290KSB7CgkJcm9vdCA9IHdpbmRvdzsKCX0KCglpZiAoISAkKSB7CgkJJCA9IHdpbmRvdy5qUXVlcnk7Cgl9CgoJCgl2YXIgRGF0YVRhYmxlID0gZnVuY3Rpb24gKCBzZWxlY3Rvciwgb3B0aW9ucyApCgl7CgkJLy8gV2hlbiBjcmVhdGluZyB3aXRoIGBuZXdgLCBjcmVhdGUgYSBuZXcgRGF0YVRhYmxlLCByZXR1cm5pbmcgdGhlIEFQSSBpbnN0YW5jZQoJCWlmICh0aGlzIGluc3RhbmNlb2YgRGF0YVRhYmxlKSB7CgkJCXJldHVybiAkKHNlbGVjdG9yKS5EYXRhVGFibGUob3B0aW9ucyk7CgkJfQoJCWVsc2UgewoJCQkvLyBBcmd1bWVudCBzd2l0Y2hpbmcKCQkJb3B0aW9ucyA9IHNlbGVjdG9yOwoJCX0KCQoJCS8qKgoJCSAqIFBlcmZvcm0gYSBqUXVlcnkgc2VsZWN0b3IgYWN0aW9uIG9uIHRoZSB0YWJsZSdzIFRSIGVsZW1lbnRzIChmcm9tIHRoZSB0Ym9keSkgYW5kCgkJICogcmV0dXJuIHRoZSByZXN1bHRpbmcgalF1ZXJ5IG9iamVjdC4KCQkgKiAgQHBhcmFtIHtzdHJpbmd8bm9kZXxqUXVlcnl9IHNTZWxlY3RvciBqUXVlcnkgc2VsZWN0b3Igb3Igbm9kZSBjb2xsZWN0aW9uIHRvIGFjdCBvbgoJCSAqICBAcGFyYW0ge29iamVjdH0gW29PcHRzXSBPcHRpb25hbCBwYXJhbWV0ZXJzIGZvciBtb2RpZnlpbmcgdGhlIHJvd3MgdG8gYmUgaW5jbHVkZWQKCQkgKiAgQHBhcmFtIHtzdHJpbmd9IFtvT3B0cy5maWx0ZXI9bm9uZV0gU2VsZWN0IFRSIGVsZW1lbnRzIHRoYXQgbWVldCB0aGUgY3VycmVudCBmaWx0ZXIKCQkgKiAgICBjcml0ZXJpb24gKCJhcHBsaWVkIikgb3IgYWxsIFRSIGVsZW1lbnRzIChpLmUuIG5vIGZpbHRlcikuCgkJICogIEBwYXJhbSB7c3RyaW5nfSBbb09wdHMub3JkZXI9Y3VycmVudF0gT3JkZXIgb2YgdGhlIFRSIGVsZW1lbnRzIGluIHRoZSBwcm9jZXNzZWQgYXJyYXkuCgkJICogICAgQ2FuIGJlIGVpdGhlciAnY3VycmVudCcsIHdoZXJlYnkgdGhlIGN1cnJlbnQgc29ydGluZyBvZiB0aGUgdGFibGUgaXMgdXNlZCwgb3IKCQkgKiAgICAnb3JpZ2luYWwnIHdoZXJlYnkgdGhlIG9yaWdpbmFsIG9yZGVyIHRoZSBkYXRhIHdhcyByZWFkIGludG8gdGhlIHRhYmxlIGlzIHVzZWQuCgkJICogIEBwYXJhbSB7c3RyaW5nfSBbb09wdHMucGFnZT1hbGxdIExpbWl0IHRoZSBzZWxlY3Rpb24gdG8gdGhlIGN1cnJlbnRseSBkaXNwbGF5ZWQgcGFnZQoJCSAqICAgICgiY3VycmVudCIpIG9yIG5vdCAoImFsbCIpLiBJZiAnY3VycmVudCcgaXMgZ2l2ZW4sIHRoZW4gb3JkZXIgaXMgYXNzdW1lZCB0byBiZQoJCSAqICAgICdjdXJyZW50JyBhbmQgZmlsdGVyIGlzICdhcHBsaWVkJywgcmVnYXJkbGVzcyBvZiB3aGF0IHRoZXkgbWlnaHQgYmUgZ2l2ZW4gYXMuCgkJICogIEByZXR1cm5zIHtvYmplY3R9IGpRdWVyeSBvYmplY3QsIGZpbHRlcmVkIGJ5IHRoZSBnaXZlbiBzZWxlY3Rvci4KCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKgoJCSAqICAgICAgLy8gSGlnaGxpZ2h0IGV2ZXJ5IHNlY29uZCByb3cKCQkgKiAgICAgIG9UYWJsZS4kKCd0cjpvZGQnKS5jc3MoJ2JhY2tncm91bmRDb2xvcicsICdibHVlJyk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKgoJCSAqICAgICAgLy8gRmlsdGVyIHRvIHJvd3Mgd2l0aCAnV2Via2l0JyBpbiB0aGVtLCBhZGQgYSBiYWNrZ3JvdW5kIGNvbG91ciBhbmQgdGhlbgoJCSAqICAgICAgLy8gcmVtb3ZlIHRoZSBmaWx0ZXIsIHRodXMgaGlnaGxpZ2h0aW5nIHRoZSAnV2Via2l0JyByb3dzIG9ubHkuCgkJICogICAgICBvVGFibGUuZm5GaWx0ZXIoJ1dlYmtpdCcpOwoJCSAqICAgICAgb1RhYmxlLiQoJ3RyJywgeyJzZWFyY2giOiAiYXBwbGllZCJ9KS5jc3MoJ2JhY2tncm91bmRDb2xvcicsICdibHVlJyk7CgkJICogICAgICBvVGFibGUuZm5GaWx0ZXIoJycpOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLiQgPSBmdW5jdGlvbiAoIHNTZWxlY3Rvciwgb09wdHMgKQoJCXsKCQkJcmV0dXJuIHRoaXMuYXBpKHRydWUpLiQoIHNTZWxlY3Rvciwgb09wdHMgKTsKCQl9OwoJCQoJCQoJCS8qKgoJCSAqIEFsbW9zdCBpZGVudGljYWwgdG8gJCBpbiBvcGVyYXRpb24sIGJ1dCBpbiB0aGlzIGNhc2UgcmV0dXJucyB0aGUgZGF0YSBmb3IgdGhlIG1hdGNoZWQKCQkgKiByb3dzIC0gYXMgc3VjaCwgdGhlIGpRdWVyeSBzZWxlY3RvciB1c2VkIHNob3VsZCBtYXRjaCBUUiByb3cgbm9kZXMgb3IgVEQvVEggY2VsbCBub2RlcwoJCSAqIHJhdGhlciB0aGFuIGFueSBkZXNjZW5kYW50cywgc28gdGhlIGRhdGEgY2FuIGJlIG9idGFpbmVkIGZvciB0aGUgcm93L2NlbGwuIElmIG1hdGNoaW5nCgkJICogcm93cyBhcmUgZm91bmQsIHRoZSBkYXRhIHJldHVybmVkIGlzIHRoZSBvcmlnaW5hbCBkYXRhIGFycmF5L29iamVjdCB0aGF0IHdhcyB1c2VkIHRvCgkJICogY3JlYXRlIHRoZSByb3cgKG9yIGEgZ2VuZXJhdGVkIGFycmF5IGlmIGZyb20gYSBET00gc291cmNlKS4KCQkgKgoJCSAqIFRoaXMgbWV0aG9kIGlzIG9mdGVuIHVzZWZ1bCBpbi1jb21iaW5hdGlvbiB3aXRoICQgd2hlcmUgYm90aCBmdW5jdGlvbnMgYXJlIGdpdmVuIHRoZQoJCSAqIHNhbWUgcGFyYW1ldGVycyBhbmQgdGhlIGFycmF5IGluZGV4ZXMgd2lsbCBtYXRjaCBpZGVudGljYWxseS4KCQkgKiAgQHBhcmFtIHtzdHJpbmd8bm9kZXxqUXVlcnl9IHNTZWxlY3RvciBqUXVlcnkgc2VsZWN0b3Igb3Igbm9kZSBjb2xsZWN0aW9uIHRvIGFjdCBvbgoJCSAqICBAcGFyYW0ge29iamVjdH0gW29PcHRzXSBPcHRpb25hbCBwYXJhbWV0ZXJzIGZvciBtb2RpZnlpbmcgdGhlIHJvd3MgdG8gYmUgaW5jbHVkZWQKCQkgKiAgQHBhcmFtIHtzdHJpbmd9IFtvT3B0cy5maWx0ZXI9bm9uZV0gU2VsZWN0IGVsZW1lbnRzIHRoYXQgbWVldCB0aGUgY3VycmVudCBmaWx0ZXIKCQkgKiAgICBjcml0ZXJpb24gKCJhcHBsaWVkIikgb3IgYWxsIGVsZW1lbnRzIChpLmUuIG5vIGZpbHRlcikuCgkJICogIEBwYXJhbSB7c3RyaW5nfSBbb09wdHMub3JkZXI9Y3VycmVudF0gT3JkZXIgb2YgdGhlIGRhdGEgaW4gdGhlIHByb2Nlc3NlZCBhcnJheS4KCQkgKiAgICBDYW4gYmUgZWl0aGVyICdjdXJyZW50Jywgd2hlcmVieSB0aGUgY3VycmVudCBzb3J0aW5nIG9mIHRoZSB0YWJsZSBpcyB1c2VkLCBvcgoJCSAqICAgICdvcmlnaW5hbCcgd2hlcmVieSB0aGUgb3JpZ2luYWwgb3JkZXIgdGhlIGRhdGEgd2FzIHJlYWQgaW50byB0aGUgdGFibGUgaXMgdXNlZC4KCQkgKiAgQHBhcmFtIHtzdHJpbmd9IFtvT3B0cy5wYWdlPWFsbF0gTGltaXQgdGhlIHNlbGVjdGlvbiB0byB0aGUgY3VycmVudGx5IGRpc3BsYXllZCBwYWdlCgkJICogICAgKCJjdXJyZW50Iikgb3Igbm90ICgiYWxsIikuIElmICdjdXJyZW50JyBpcyBnaXZlbiwgdGhlbiBvcmRlciBpcyBhc3N1bWVkIHRvIGJlCgkJICogICAgJ2N1cnJlbnQnIGFuZCBmaWx0ZXIgaXMgJ2FwcGxpZWQnLCByZWdhcmRsZXNzIG9mIHdoYXQgdGhleSBtaWdodCBiZSBnaXZlbiBhcy4KCQkgKiAgQHJldHVybnMge2FycmF5fSBEYXRhIGZvciB0aGUgbWF0Y2hlZCBlbGVtZW50cy4gSWYgYW55IGVsZW1lbnRzLCBhcyBhIHJlc3VsdCBvZiB0aGUKCQkgKiAgICBzZWxlY3Rvciwgd2VyZSBub3QgVFIsIFREIG9yIFRIIGVsZW1lbnRzIGluIHRoZSBEYXRhVGFibGUsIHRoZXkgd2lsbCBoYXZlIGEgbnVsbAoJCSAqICAgIGVudHJ5IGluIHRoZSBhcnJheS4KCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKgoJCSAqICAgICAgLy8gR2V0IHRoZSBkYXRhIGZyb20gdGhlIGZpcnN0IHJvdyBpbiB0aGUgdGFibGUKCQkgKiAgICAgIHZhciBkYXRhID0gb1RhYmxlLl8oJ3RyOmZpcnN0Jyk7CgkJICoKCQkgKiAgICAgIC8vIERvIHNvbWV0aGluZyB1c2VmdWwgd2l0aCB0aGUgZGF0YQoJCSAqICAgICAgYWxlcnQoICJGaXJzdCBjZWxsIGlzOiAiK2RhdGFbMF0gKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCQkgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqCgkJICogICAgICAvLyBGaWx0ZXIgdG8gJ1dlYmtpdCcgYW5kIGdldCBhbGwgZGF0YSBmb3IKCQkgKiAgICAgIG9UYWJsZS5mbkZpbHRlcignV2Via2l0Jyk7CgkJICogICAgICB2YXIgZGF0YSA9IG9UYWJsZS5fKCd0cicsIHsic2VhcmNoIjogImFwcGxpZWQifSk7CgkJICoKCQkgKiAgICAgIC8vIERvIHNvbWV0aGluZyB3aXRoIHRoZSBkYXRhCgkJICogICAgICBhbGVydCggZGF0YS5sZW5ndGgrIiByb3dzIG1hdGNoZWQgdGhlIHNlYXJjaCIgKTsKCQkgKiAgICB9ICk7CgkJICovCgkJdGhpcy5fID0gZnVuY3Rpb24gKCBzU2VsZWN0b3IsIG9PcHRzICkKCQl7CgkJCXJldHVybiB0aGlzLmFwaSh0cnVlKS5yb3dzKCBzU2VsZWN0b3IsIG9PcHRzICkuZGF0YSgpOwoJCX07CgkJCgkJCgkJLyoqCgkJICogQ3JlYXRlIGEgRGF0YVRhYmxlcyBBcGkgaW5zdGFuY2UsIHdpdGggdGhlIGN1cnJlbnRseSBzZWxlY3RlZCB0YWJsZXMgZm9yCgkJICogdGhlIEFwaSdzIGNvbnRleHQuCgkJICogQHBhcmFtIHtib29sZWFufSBbdHJhZGl0aW9uYWw9ZmFsc2VdIFNldCB0aGUgQVBJIGluc3RhbmNlJ3MgY29udGV4dCB0byBiZQoJCSAqICAgb25seSB0aGUgdGFibGUgcmVmZXJyZWQgdG8gYnkgdGhlIGBEYXRhVGFibGUuZXh0LmlBcGlJbmRleGAgb3B0aW9uLCBhcyB3YXMKCQkgKiAgIHVzZWQgaW4gdGhlIEFQSSBwcmVzZW50ZWQgYnkgRGF0YVRhYmxlcyAxLjktIChpLmUuIHRoZSB0cmFkaXRpb25hbCBtb2RlKSwKCQkgKiAgIG9yIGlmIGFsbCB0YWJsZXMgY2FwdHVyZWQgaW4gdGhlIGpRdWVyeSBvYmplY3Qgc2hvdWxkIGJlIHVzZWQuCgkJICogQHJldHVybiB7RGF0YVRhYmxlcy5BcGl9CgkJICovCgkJdGhpcy5hcGkgPSBmdW5jdGlvbiAoIHRyYWRpdGlvbmFsICkKCQl7CgkJCXJldHVybiB0cmFkaXRpb25hbCA/CgkJCQluZXcgX0FwaSgKCQkJCQlfZm5TZXR0aW5nc0Zyb21Ob2RlKCB0aGlzWyBfZXh0LmlBcGlJbmRleCBdICkKCQkJCSkgOgoJCQkJbmV3IF9BcGkoIHRoaXMgKTsKCQl9OwoJCQoJCQoJCS8qKgoJCSAqIEFkZCBhIHNpbmdsZSBuZXcgcm93IG9yIG11bHRpcGxlIHJvd3Mgb2YgZGF0YSB0byB0aGUgdGFibGUuIFBsZWFzZSBub3RlCgkJICogdGhhdCB0aGlzIGlzIHN1aXRhYmxlIGZvciBjbGllbnQtc2lkZSBwcm9jZXNzaW5nIG9ubHkgLSBpZiB5b3UgYXJlIHVzaW5nCgkJICogc2VydmVyLXNpZGUgcHJvY2Vzc2luZyAoaS5lLiAiYlNlcnZlclNpZGUiOiB0cnVlKSwgdGhlbiB0byBhZGQgZGF0YSwgeW91CgkJICogbXVzdCBhZGQgaXQgdG8gdGhlIGRhdGEgc291cmNlLCBpLmUuIHRoZSBzZXJ2ZXItc2lkZSwgdGhyb3VnaCBhbiBBamF4IGNhbGwuCgkJICogIEBwYXJhbSB7YXJyYXl8b2JqZWN0fSBkYXRhIFRoZSBkYXRhIHRvIGJlIGFkZGVkIHRvIHRoZSB0YWJsZS4gVGhpcyBjYW4gYmU6CgkJICogICAgPHVsPgoJCSAqICAgICAgPGxpPjFEIGFycmF5IG9mIGRhdGEgLSBhZGQgYSBzaW5nbGUgcm93IHdpdGggdGhlIGRhdGEgcHJvdmlkZWQ8L2xpPgoJCSAqICAgICAgPGxpPjJEIGFycmF5IG9mIGFycmF5cyAtIGFkZCBtdWx0aXBsZSByb3dzIGluIGEgc2luZ2xlIGNhbGw8L2xpPgoJCSAqICAgICAgPGxpPm9iamVjdCAtIGRhdGEgb2JqZWN0IHdoZW4gdXNpbmcgPGk+bURhdGE8L2k+PC9saT4KCQkgKiAgICAgIDxsaT5hcnJheSBvZiBvYmplY3RzIC0gbXVsdGlwbGUgZGF0YSBvYmplY3RzIHdoZW4gdXNpbmcgPGk+bURhdGE8L2k+PC9saT4KCQkgKiAgICA8L3VsPgoJCSAqICBAcGFyYW0ge2Jvb2x9IFtyZWRyYXc9dHJ1ZV0gcmVkcmF3IHRoZSB0YWJsZSBvciBub3QKCQkgKiAgQHJldHVybnMge2FycmF5fSBBbiBhcnJheSBvZiBpbnRlZ2VycywgcmVwcmVzZW50aW5nIHRoZSBsaXN0IG9mIGluZGV4ZXMgaW4KCQkgKiAgICA8aT5hb0RhdGE8L2k+ICh7QGxpbmsgRGF0YVRhYmxlLm1vZGVscy5vU2V0dGluZ3N9KSB0aGF0IGhhdmUgYmVlbiBhZGRlZCB0bwoJCSAqICAgIHRoZSB0YWJsZS4KCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gR2xvYmFsIHZhciBmb3IgY291bnRlcgoJCSAqICAgIHZhciBnaUNvdW50ID0gMjsKCQkgKgoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKiAgICBmdW5jdGlvbiBmbkNsaWNrQWRkUm93KCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKS5mbkFkZERhdGEoIFsKCQkgKiAgICAgICAgZ2lDb3VudCsiLjEiLAoJCSAqICAgICAgICBnaUNvdW50KyIuMiIsCgkJICogICAgICAgIGdpQ291bnQrIi4zIiwKCQkgKiAgICAgICAgZ2lDb3VudCsiLjQiIF0KCQkgKiAgICAgICk7CgkJICoKCQkgKiAgICAgIGdpQ291bnQrKzsKCQkgKiAgICB9CgkJICovCgkJdGhpcy5mbkFkZERhdGEgPSBmdW5jdGlvbiggZGF0YSwgcmVkcmF3ICkKCQl7CgkJCXZhciBhcGkgPSB0aGlzLmFwaSggdHJ1ZSApOwoJCQoJCQkvKiBDaGVjayBpZiB3ZSB3YW50IHRvIGFkZCBtdWx0aXBsZSByb3dzIG9yIG5vdCAqLwoJCQl2YXIgcm93cyA9IEFycmF5LmlzQXJyYXkoZGF0YSkgJiYgKCBBcnJheS5pc0FycmF5KGRhdGFbMF0pIHx8ICQuaXNQbGFpbk9iamVjdChkYXRhWzBdKSApID8KCQkJCWFwaS5yb3dzLmFkZCggZGF0YSApIDoKCQkJCWFwaS5yb3cuYWRkKCBkYXRhICk7CgkJCgkJCWlmICggcmVkcmF3ID09PSB1bmRlZmluZWQgfHwgcmVkcmF3ICkgewoJCQkJYXBpLmRyYXcoKTsKCQkJfQoJCQoJCQlyZXR1cm4gcm93cy5mbGF0dGVuKCkudG9BcnJheSgpOwoJCX07CgkJCgkJCgkJLyoqCgkJICogVGhpcyBmdW5jdGlvbiB3aWxsIG1ha2UgRGF0YVRhYmxlcyByZWNhbGN1bGF0ZSB0aGUgY29sdW1uIHNpemVzLCBiYXNlZCBvbiB0aGUgZGF0YQoJCSAqIGNvbnRhaW5lZCBpbiB0aGUgdGFibGUgYW5kIHRoZSBzaXplcyBhcHBsaWVkIHRvIHRoZSBjb2x1bW5zIChpbiB0aGUgRE9NLCBDU1Mgb3IKCQkgKiB0aHJvdWdoIHRoZSBzV2lkdGggcGFyYW1ldGVyKS4gVGhpcyBjYW4gYmUgdXNlZnVsIHdoZW4gdGhlIHdpZHRoIG9mIHRoZSB0YWJsZSdzCgkJICogcGFyZW50IGVsZW1lbnQgY2hhbmdlcyAoZm9yIGV4YW1wbGUgYSB3aW5kb3cgcmVzaXplKS4KCQkgKiAgQHBhcmFtIHtib29sZWFufSBbYlJlZHJhdz10cnVlXSBSZWRyYXcgdGhlIHRhYmxlIG9yIG5vdCwgeW91IHdpbGwgdHlwaWNhbGx5IHdhbnQgdG8KCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInNTY3JvbGxZIjogIjIwMHB4IiwKCQkgKiAgICAgICAgImJQYWdpbmF0ZSI6IGZhbHNlCgkJICogICAgICB9ICk7CgkJICoKCQkgKiAgICAgICQod2luZG93KS5vbigncmVzaXplJywgZnVuY3Rpb24gKCkgewoJCSAqICAgICAgICBvVGFibGUuZm5BZGp1c3RDb2x1bW5TaXppbmcoKTsKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJdGhpcy5mbkFkanVzdENvbHVtblNpemluZyA9IGZ1bmN0aW9uICggYlJlZHJhdyApCgkJewoJCQl2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKS5jb2x1bW5zLmFkanVzdCgpOwoJCQl2YXIgc2V0dGluZ3MgPSBhcGkuc2V0dGluZ3MoKVswXTsKCQkJdmFyIHNjcm9sbCA9IHNldHRpbmdzLm9TY3JvbGw7CgkJCgkJCWlmICggYlJlZHJhdyA9PT0gdW5kZWZpbmVkIHx8IGJSZWRyYXcgKSB7CgkJCQlhcGkuZHJhdyggZmFsc2UgKTsKCQkJfQoJCQllbHNlIGlmICggc2Nyb2xsLnNYICE9PSAiIiB8fCBzY3JvbGwuc1kgIT09ICIiICkgewoJCQkJLyogSWYgbm90IHJlZHJhd2luZywgYnV0IHNjcm9sbGluZywgd2Ugd2FudCB0byBhcHBseSB0aGUgbmV3IGNvbHVtbiBzaXplcyBhbnl3YXkgKi8KCQkJCV9mblNjcm9sbERyYXcoIHNldHRpbmdzICk7CgkJCX0KCQl9OwoJCQoJCQoJCS8qKgoJCSAqIFF1aWNrbHkgYW5kIHNpbXBseSBjbGVhciBhIHRhYmxlCgkJICogIEBwYXJhbSB7Ym9vbH0gW2JSZWRyYXc9dHJ1ZV0gcmVkcmF3IHRoZSB0YWJsZSBvciBub3QKCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKgoJCSAqICAgICAgLy8gSW1tZWRpYXRlbHkgJ251a2UnIHRoZSBjdXJyZW50IHJvd3MgKHBlcmhhcHMgd2FpdGluZyBmb3IgYW4gQWpheCBjYWxsYmFjay4uLikKCQkgKiAgICAgIG9UYWJsZS5mbkNsZWFyVGFibGUoKTsKCQkgKiAgICB9ICk7CgkJICovCgkJdGhpcy5mbkNsZWFyVGFibGUgPSBmdW5jdGlvbiggYlJlZHJhdyApCgkJewoJCQl2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKS5jbGVhcigpOwoJCQoJCQlpZiAoIGJSZWRyYXcgPT09IHVuZGVmaW5lZCB8fCBiUmVkcmF3ICkgewoJCQkJYXBpLmRyYXcoKTsKCQkJfQoJCX07CgkJCgkJCgkJLyoqCgkJICogVGhlIGV4YWN0IG9wcG9zaXRlIG9mICdvcGVuaW5nJyBhIHJvdywgdGhpcyBmdW5jdGlvbiB3aWxsIGNsb3NlIGFueSByb3dzIHdoaWNoCgkJICogYXJlIGN1cnJlbnRseSAnb3BlbicuCgkJICogIEBwYXJhbSB7bm9kZX0gblRyIHRoZSB0YWJsZSByb3cgdG8gJ2Nsb3NlJwoJCSAqICBAcmV0dXJucyB7aW50fSAwIG9uIHN1Y2Nlc3MsIG9yIDEgaWYgZmFpbGVkIChjYW4ndCBmaW5kIHRoZSByb3cpCgkJICogIEBkdG9wdCBBUEkKCQkgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTAKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgewoJCSAqICAgICAgdmFyIG9UYWJsZTsKCQkgKgoJCSAqICAgICAgLy8gJ29wZW4nIGFuIGluZm9ybWF0aW9uIHJvdyB3aGVuIGEgcm93IGlzIGNsaWNrZWQgb24KCQkgKiAgICAgICQoJyNleGFtcGxlIHRib2R5IHRyJykuY2xpY2soIGZ1bmN0aW9uICgpIHsKCQkgKiAgICAgICAgaWYgKCBvVGFibGUuZm5Jc09wZW4odGhpcykgKSB7CgkJICogICAgICAgICAgb1RhYmxlLmZuQ2xvc2UoIHRoaXMgKTsKCQkgKiAgICAgICAgfSBlbHNlIHsKCQkgKiAgICAgICAgICBvVGFibGUuZm5PcGVuKCB0aGlzLCAiVGVtcG9yYXJ5IHJvdyBvcGVuZWQiLCAiaW5mb19yb3ciICk7CgkJICogICAgICAgIH0KCQkgKiAgICAgIH0gKTsKCQkgKgoJCSAqICAgICAgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKiAgICB9ICk7CgkJICovCgkJdGhpcy5mbkNsb3NlID0gZnVuY3Rpb24oIG5UciApCgkJewoJCQl0aGlzLmFwaSggdHJ1ZSApLnJvdyggblRyICkuY2hpbGQuaGlkZSgpOwoJCX07CgkJCgkJCgkJLyoqCgkJICogUmVtb3ZlIGEgcm93IGZvciB0aGUgdGFibGUKCQkgKiAgQHBhcmFtIHttaXhlZH0gdGFyZ2V0IFRoZSBpbmRleCBvZiB0aGUgcm93IGZyb20gYW9EYXRhIHRvIGJlIGRlbGV0ZWQsIG9yCgkJICogICAgdGhlIFRSIGVsZW1lbnQgeW91IHdhbnQgdG8gZGVsZXRlCgkJICogIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gW2NhbGxCYWNrXSBDYWxsYmFjayBmdW5jdGlvbgoJCSAqICBAcGFyYW0ge2Jvb2x9IFtyZWRyYXc9dHJ1ZV0gUmVkcmF3IHRoZSB0YWJsZSBvciBub3QKCQkgKiAgQHJldHVybnMge2FycmF5fSBUaGUgcm93IHRoYXQgd2FzIGRlbGV0ZWQKCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKgoJCSAqICAgICAgLy8gSW1tZWRpYXRlbHkgcmVtb3ZlIHRoZSBmaXJzdCByb3cKCQkgKiAgICAgIG9UYWJsZS5mbkRlbGV0ZVJvdyggMCApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuRGVsZXRlUm93ID0gZnVuY3Rpb24oIHRhcmdldCwgY2FsbGJhY2ssIHJlZHJhdyApCgkJewoJCQl2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKTsKCQkJdmFyIHJvd3MgPSBhcGkucm93cyggdGFyZ2V0ICk7CgkJCXZhciBzZXR0aW5ncyA9IHJvd3Muc2V0dGluZ3MoKVswXTsKCQkJdmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGFbIHJvd3NbMF1bMF0gXTsKCQkKCQkJcm93cy5yZW1vdmUoKTsKCQkKCQkJaWYgKCBjYWxsYmFjayApIHsKCQkJCWNhbGxiYWNrLmNhbGwoIHRoaXMsIHNldHRpbmdzLCBkYXRhICk7CgkJCX0KCQkKCQkJaWYgKCByZWRyYXcgPT09IHVuZGVmaW5lZCB8fCByZWRyYXcgKSB7CgkJCQlhcGkuZHJhdygpOwoJCQl9CgkJCgkJCXJldHVybiBkYXRhOwoJCX07CgkJCgkJCgkJLyoqCgkJICogUmVzdG9yZSB0aGUgdGFibGUgdG8gaXQncyBvcmlnaW5hbCBzdGF0ZSBpbiB0aGUgRE9NIGJ5IHJlbW92aW5nIGFsbCBvZiBEYXRhVGFibGVzCgkJICogZW5oYW5jZW1lbnRzLCBhbHRlcmF0aW9ucyB0byB0aGUgRE9NIHN0cnVjdHVyZSBvZiB0aGUgdGFibGUgYW5kIGV2ZW50IGxpc3RlbmVycy4KCQkgKiAgQHBhcmFtIHtib29sZWFufSBbcmVtb3ZlPWZhbHNlXSBDb21wbGV0ZWx5IHJlbW92ZSB0aGUgdGFibGUgZnJvbSB0aGUgRE9NCgkJICogIEBkdG9wdCBBUEkKCQkgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTAKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgewoJCSAqICAgICAgLy8gVGhpcyBleGFtcGxlIGlzIGZhaXJseSBwb2ludGxlc3MgaW4gcmVhbGl0eSwgYnV0IHNob3dzIGhvdyBmbkRlc3Ryb3kgY2FuIGJlIHVzZWQKCQkgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqICAgICAgb1RhYmxlLmZuRGVzdHJveSgpOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuRGVzdHJveSA9IGZ1bmN0aW9uICggcmVtb3ZlICkKCQl7CgkJCXRoaXMuYXBpKCB0cnVlICkuZGVzdHJveSggcmVtb3ZlICk7CgkJfTsKCQkKCQkKCQkvKioKCQkgKiBSZWRyYXcgdGhlIHRhYmxlCgkJICogIEBwYXJhbSB7Ym9vbH0gW2NvbXBsZXRlPXRydWVdIFJlLWZpbHRlciBhbmQgcmVzb3J0IChpZiBlbmFibGVkKSB0aGUgdGFibGUgYmVmb3JlIHRoZSBkcmF3LgoJCSAqICBAZHRvcHQgQVBJCgkJICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCQkgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqCgkJICogICAgICAvLyBSZS1kcmF3IHRoZSB0YWJsZSAtIHlvdSB3b3VsZG4ndCB3YW50IHRvIGRvIGl0IGhlcmUsIGJ1dCBpdCdzIGFuIGV4YW1wbGUgOi0pCgkJICogICAgICBvVGFibGUuZm5EcmF3KCk7CgkJICogICAgfSApOwoJCSAqLwoJCXRoaXMuZm5EcmF3ID0gZnVuY3Rpb24oIGNvbXBsZXRlICkKCQl7CgkJCS8vIE5vdGUgdGhhdCB0aGlzIGlzbid0IGFuIGV4YWN0IG1hdGNoIHRvIHRoZSBvbGQgY2FsbCB0byBfZm5EcmF3IC0gaXQgdGFrZXMKCQkJLy8gaW50byBhY2NvdW50IHRoZSBuZXcgZGF0YSwgYnV0IGNhbiBob2xkIHBvc2l0aW9uLgoJCQl0aGlzLmFwaSggdHJ1ZSApLmRyYXcoIGNvbXBsZXRlICk7CgkJfTsKCQkKCQkKCQkvKioKCQkgKiBGaWx0ZXIgdGhlIGlucHV0IGJhc2VkIG9uIGRhdGEKCQkgKiAgQHBhcmFtIHtzdHJpbmd9IHNJbnB1dCBTdHJpbmcgdG8gZmlsdGVyIHRoZSB0YWJsZSBvbgoJCSAqICBAcGFyYW0ge2ludHxudWxsfSBbaUNvbHVtbl0gQ29sdW1uIHRvIGxpbWl0IGZpbHRlcmluZyB0bwoJCSAqICBAcGFyYW0ge2Jvb2x9IFtiUmVnZXg9ZmFsc2VdIFRyZWF0IGFzIHJlZ3VsYXIgZXhwcmVzc2lvbiBvciBub3QKCQkgKiAgQHBhcmFtIHtib29sfSBbYlNtYXJ0PXRydWVdIFBlcmZvcm0gc21hcnQgZmlsdGVyaW5nIG9yIG5vdAoJCSAqICBAcGFyYW0ge2Jvb2x9IFtiU2hvd0dsb2JhbD10cnVlXSBTaG93IHRoZSBpbnB1dCBnbG9iYWwgZmlsdGVyIGluIGl0J3MgaW5wdXQgYm94KGVzKQoJCSAqICBAcGFyYW0ge2Jvb2x9IFtiQ2FzZUluc2Vuc2l0aXZlPXRydWVdIERvIGNhc2UtaW5zZW5zaXRpdmUgbWF0Y2hpbmcgKHRydWUpIG9yIG5vdCAoZmFsc2UpCgkJICogIEBkdG9wdCBBUEkKCQkgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTAKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgewoJCSAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7CgkJICoKCQkgKiAgICAgIC8vIFNvbWV0aW1lIGxhdGVyIC0gZmlsdGVyLi4uCgkJICogICAgICBvVGFibGUuZm5GaWx0ZXIoICd0ZXN0IHN0cmluZycgKTsKCQkgKiAgICB9ICk7CgkJICovCgkJdGhpcy5mbkZpbHRlciA9IGZ1bmN0aW9uKCBzSW5wdXQsIGlDb2x1bW4sIGJSZWdleCwgYlNtYXJ0LCBiU2hvd0dsb2JhbCwgYkNhc2VJbnNlbnNpdGl2ZSApCgkJewoJCQl2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKTsKCQkKCQkJaWYgKCBpQ29sdW1uID09PSBudWxsIHx8IGlDb2x1bW4gPT09IHVuZGVmaW5lZCApIHsKCQkJCWFwaS5zZWFyY2goIHNJbnB1dCwgYlJlZ2V4LCBiU21hcnQsIGJDYXNlSW5zZW5zaXRpdmUgKTsKCQkJfQoJCQllbHNlIHsKCQkJCWFwaS5jb2x1bW4oIGlDb2x1bW4gKS5zZWFyY2goIHNJbnB1dCwgYlJlZ2V4LCBiU21hcnQsIGJDYXNlSW5zZW5zaXRpdmUgKTsKCQkJfQoJCQoJCQlhcGkuZHJhdygpOwoJCX07CgkJCgkJCgkJLyoqCgkJICogR2V0IHRoZSBkYXRhIGZvciB0aGUgd2hvbGUgdGFibGUsIGFuIGluZGl2aWR1YWwgcm93IG9yIGFuIGluZGl2aWR1YWwgY2VsbCBiYXNlZCBvbiB0aGUKCQkgKiBwcm92aWRlZCBwYXJhbWV0ZXJzLgoJCSAqICBAcGFyYW0ge2ludHxub2RlfSBbc3JjXSBBIFRSIHJvdyBub2RlLCBURC9USCBjZWxsIG5vZGUgb3IgYW4gaW50ZWdlci4gSWYgZ2l2ZW4gYXMKCQkgKiAgICBhIFRSIG5vZGUgdGhlbiB0aGUgZGF0YSBzb3VyY2UgZm9yIHRoZSB3aG9sZSByb3cgd2lsbCBiZSByZXR1cm5lZC4gSWYgZ2l2ZW4gYXMgYQoJCSAqICAgIFREL1RIIGNlbGwgbm9kZSB0aGVuIGlDb2wgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQgYW5kIHRoZSBkYXRhIGZvciB0aGUKCQkgKiAgICBjZWxsIHJldHVybmVkLiBJZiBnaXZlbiBhcyBhbiBpbnRlZ2VyLCB0aGVuIHRoaXMgaXMgdHJlYXRlZCBhcyB0aGUgYW9EYXRhIGludGVybmFsCgkJICogICAgZGF0YSBpbmRleCBmb3IgdGhlIHJvdyAoc2VlIGZuR2V0UG9zaXRpb24pIGFuZCB0aGUgZGF0YSBmb3IgdGhhdCByb3cgdXNlZC4KCQkgKiAgQHBhcmFtIHtpbnR9IFtjb2xdIE9wdGlvbmFsIGNvbHVtbiBpbmRleCB0aGF0IHlvdSB3YW50IHRoZSBkYXRhIG9mLgoJCSAqICBAcmV0dXJucyB7YXJyYXl8b2JqZWN0fHN0cmluZ30gSWYgbVJvdyBpcyB1bmRlZmluZWQsIHRoZW4gdGhlIGRhdGEgZm9yIGFsbCByb3dzIGlzCgkJICogICAgcmV0dXJuZWQuIElmIG1Sb3cgaXMgZGVmaW5lZCwganVzdCBkYXRhIGZvciB0aGF0IHJvdywgYW5kIGlzIGlDb2wgaXMKCQkgKiAgICBkZWZpbmVkLCBvbmx5IGRhdGEgZm9yIHRoZSBkZXNpZ25hdGVkIGNlbGwgaXMgcmV0dXJuZWQuCgkJICogIEBkdG9wdCBBUEkKCQkgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTAKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFJvdyBkYXRhCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqCgkJICogICAgICBvVGFibGUuJCgndHInKS5jbGljayggZnVuY3Rpb24gKCkgewoJCSAqICAgICAgICB2YXIgZGF0YSA9IG9UYWJsZS5mbkdldERhdGEoIHRoaXMgKTsKCQkgKiAgICAgICAgLy8gLi4uIGRvIHNvbWV0aGluZyB3aXRoIHRoZSBhcnJheSAvIG9iamVjdCBvZiBkYXRhIGZvciB0aGUgcm93CgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gSW5kaXZpZHVhbCBjZWxsIGRhdGEKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCQkgKiAgICAgIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7CgkJICoKCQkgKiAgICAgIG9UYWJsZS4kKCd0ZCcpLmNsaWNrKCBmdW5jdGlvbiAoKSB7CgkJICogICAgICAgIHZhciBzRGF0YSA9IG9UYWJsZS5mbkdldERhdGEoIHRoaXMgKTsKCQkgKiAgICAgICAgYWxlcnQoICdUaGUgY2VsbCBjbGlja2VkIG9uIGhhZCB0aGUgdmFsdWUgb2YgJytzRGF0YSApOwoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuR2V0RGF0YSA9IGZ1bmN0aW9uKCBzcmMsIGNvbCApCgkJewoJCQl2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKTsKCQkKCQkJaWYgKCBzcmMgIT09IHVuZGVmaW5lZCApIHsKCQkJCXZhciB0eXBlID0gc3JjLm5vZGVOYW1lID8gc3JjLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgOiAnJzsKCQkKCQkJCXJldHVybiBjb2wgIT09IHVuZGVmaW5lZCB8fCB0eXBlID09ICd0ZCcgfHwgdHlwZSA9PSAndGgnID8KCQkJCQlhcGkuY2VsbCggc3JjLCBjb2wgKS5kYXRhKCkgOgoJCQkJCWFwaS5yb3coIHNyYyApLmRhdGEoKSB8fCBudWxsOwoJCQl9CgkJCgkJCXJldHVybiBhcGkuZGF0YSgpLnRvQXJyYXkoKTsKCQl9OwoJCQoJCQoJCS8qKgoJCSAqIEdldCBhbiBhcnJheSBvZiB0aGUgVFIgbm9kZXMgdGhhdCBhcmUgdXNlZCBpbiB0aGUgdGFibGUncyBib2R5LiBOb3RlIHRoYXQgeW91IHdpbGwKCQkgKiB0eXBpY2FsbHkgd2FudCB0byB1c2UgdGhlICckJyBBUEkgbWV0aG9kIGluIHByZWZlcmVuY2UgdG8gdGhpcyBhcyBpdCBpcyBtb3JlCgkJICogZmxleGlibGUuCgkJICogIEBwYXJhbSB7aW50fSBbaVJvd10gT3B0aW9uYWwgcm93IGluZGV4IGZvciB0aGUgVFIgZWxlbWVudCB5b3Ugd2FudAoJCSAqICBAcmV0dXJucyB7YXJyYXl8bm9kZX0gSWYgaVJvdyBpcyB1bmRlZmluZWQsIHJldHVybnMgYW4gYXJyYXkgb2YgYWxsIFRSIGVsZW1lbnRzCgkJICogICAgaW4gdGhlIHRhYmxlJ3MgYm9keSwgb3IgaVJvdyBpcyBkZWZpbmVkLCBqdXN0IHRoZSBUUiBlbGVtZW50IHJlcXVlc3RlZC4KCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKgoJCSAqICAgICAgLy8gR2V0IHRoZSBub2RlcyBmcm9tIHRoZSB0YWJsZQoJCSAqICAgICAgdmFyIG5Ob2RlcyA9IG9UYWJsZS5mbkdldE5vZGVzKCApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuR2V0Tm9kZXMgPSBmdW5jdGlvbiggaVJvdyApCgkJewoJCQl2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKTsKCQkKCQkJcmV0dXJuIGlSb3cgIT09IHVuZGVmaW5lZCA/CgkJCQlhcGkucm93KCBpUm93ICkubm9kZSgpIDoKCQkJCWFwaS5yb3dzKCkubm9kZXMoKS5mbGF0dGVuKCkudG9BcnJheSgpOwoJCX07CgkJCgkJCgkJLyoqCgkJICogR2V0IHRoZSBhcnJheSBpbmRleGVzIG9mIGEgcGFydGljdWxhciBjZWxsIGZyb20gaXQncyBET00gZWxlbWVudAoJCSAqIGFuZCBjb2x1bW4gaW5kZXggaW5jbHVkaW5nIGhpZGRlbiBjb2x1bW5zCgkJICogIEBwYXJhbSB7bm9kZX0gbm9kZSB0aGlzIGNhbiBlaXRoZXIgYmUgYSBUUiwgVEQgb3IgVEggaW4gdGhlIHRhYmxlJ3MgYm9keQoJCSAqICBAcmV0dXJucyB7aW50fSBJZiBuTm9kZSBpcyBnaXZlbiBhcyBhIFRSLCB0aGVuIGEgc2luZ2xlIGluZGV4IGlzIHJldHVybmVkLCBvcgoJCSAqICAgIGlmIGdpdmVuIGFzIGEgY2VsbCwgYW4gYXJyYXkgb2YgW3JvdyBpbmRleCwgY29sdW1uIGluZGV4ICh2aXNpYmxlKSwKCQkgKiAgICBjb2x1bW4gaW5kZXggKGFsbCldIGlzIGdpdmVuLgoJCSAqICBAZHRvcHQgQVBJCgkJICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlIHRib2R5IHRkJykuY2xpY2soIGZ1bmN0aW9uICgpIHsKCQkgKiAgICAgICAgLy8gR2V0IHRoZSBwb3NpdGlvbiBvZiB0aGUgY3VycmVudCBkYXRhIGZyb20gdGhlIG5vZGUKCQkgKiAgICAgICAgdmFyIGFQb3MgPSBvVGFibGUuZm5HZXRQb3NpdGlvbiggdGhpcyApOwoJCSAqCgkJICogICAgICAgIC8vIEdldCB0aGUgZGF0YSBhcnJheSBmb3IgdGhpcyByb3cKCQkgKiAgICAgICAgdmFyIGFEYXRhID0gb1RhYmxlLmZuR2V0RGF0YSggYVBvc1swXSApOwoJCSAqCgkJICogICAgICAgIC8vIFVwZGF0ZSB0aGUgZGF0YSBhcnJheSBhbmQgcmV0dXJuIHRoZSB2YWx1ZQoJCSAqICAgICAgICBhRGF0YVsgYVBvc1sxXSBdID0gJ2NsaWNrZWQnOwoJCSAqICAgICAgICB0aGlzLmlubmVySFRNTCA9ICdjbGlja2VkJzsKCQkgKiAgICAgIH0gKTsKCQkgKgoJCSAqICAgICAgLy8gSW5pdCBEYXRhVGFibGVzCgkJICogICAgICBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuR2V0UG9zaXRpb24gPSBmdW5jdGlvbiggbm9kZSApCgkJewoJCQl2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKTsKCQkJdmFyIG5vZGVOYW1lID0gbm9kZS5ub2RlTmFtZS50b1VwcGVyQ2FzZSgpOwoJCQoJCQlpZiAoIG5vZGVOYW1lID09ICdUUicgKSB7CgkJCQlyZXR1cm4gYXBpLnJvdyggbm9kZSApLmluZGV4KCk7CgkJCX0KCQkJZWxzZSBpZiAoIG5vZGVOYW1lID09ICdURCcgfHwgbm9kZU5hbWUgPT0gJ1RIJyApIHsKCQkJCXZhciBjZWxsID0gYXBpLmNlbGwoIG5vZGUgKS5pbmRleCgpOwoJCQoJCQkJcmV0dXJuIFsKCQkJCQljZWxsLnJvdywKCQkJCQljZWxsLmNvbHVtblZpc2libGUsCgkJCQkJY2VsbC5jb2x1bW4KCQkJCV07CgkJCX0KCQkJcmV0dXJuIG51bGw7CgkJfTsKCQkKCQkKCQkvKioKCQkgKiBDaGVjayB0byBzZWUgaWYgYSByb3cgaXMgJ29wZW4nIG9yIG5vdC4KCQkgKiAgQHBhcmFtIHtub2RlfSBuVHIgdGhlIHRhYmxlIHJvdyB0byBjaGVjawoJCSAqICBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgcm93IGlzIGN1cnJlbnRseSBvcGVuLCBmYWxzZSBvdGhlcndpc2UKCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlOwoJCSAqCgkJICogICAgICAvLyAnb3BlbicgYW4gaW5mb3JtYXRpb24gcm93IHdoZW4gYSByb3cgaXMgY2xpY2tlZCBvbgoJCSAqICAgICAgJCgnI2V4YW1wbGUgdGJvZHkgdHInKS5jbGljayggZnVuY3Rpb24gKCkgewoJCSAqICAgICAgICBpZiAoIG9UYWJsZS5mbklzT3Blbih0aGlzKSApIHsKCQkgKiAgICAgICAgICBvVGFibGUuZm5DbG9zZSggdGhpcyApOwoJCSAqICAgICAgICB9IGVsc2UgewoJCSAqICAgICAgICAgIG9UYWJsZS5mbk9wZW4oIHRoaXMsICJUZW1wb3Jhcnkgcm93IG9wZW5lZCIsICJpbmZvX3JvdyIgKTsKCQkgKiAgICAgICAgfQoJCSAqICAgICAgfSApOwoJCSAqCgkJICogICAgICBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuSXNPcGVuID0gZnVuY3Rpb24oIG5UciApCgkJewoJCQlyZXR1cm4gdGhpcy5hcGkoIHRydWUgKS5yb3coIG5UciApLmNoaWxkLmlzU2hvd24oKTsKCQl9OwoJCQoJCQoJCS8qKgoJCSAqIFRoaXMgZnVuY3Rpb24gd2lsbCBwbGFjZSBhIG5ldyByb3cgZGlyZWN0bHkgYWZ0ZXIgYSByb3cgd2hpY2ggaXMgY3VycmVudGx5CgkJICogb24gZGlzcGxheSBvbiB0aGUgcGFnZSwgd2l0aCB0aGUgSFRNTCBjb250ZW50cyB0aGF0IGlzIHBhc3NlZCBpbnRvIHRoZQoJCSAqIGZ1bmN0aW9uLiBUaGlzIGNhbiBiZSB1c2VkLCBmb3IgZXhhbXBsZSwgdG8gYXNrIGZvciBjb25maXJtYXRpb24gdGhhdCBhCgkJICogcGFydGljdWxhciByZWNvcmQgc2hvdWxkIGJlIGRlbGV0ZWQuCgkJICogIEBwYXJhbSB7bm9kZX0gblRyIFRoZSB0YWJsZSByb3cgdG8gJ29wZW4nCgkJICogIEBwYXJhbSB7c3RyaW5nfG5vZGV8alF1ZXJ5fSBtSHRtbCBUaGUgSFRNTCB0byBwdXQgaW50byB0aGUgcm93CgkJICogIEBwYXJhbSB7c3RyaW5nfSBzQ2xhc3MgQ2xhc3MgdG8gZ2l2ZSB0aGUgbmV3IFREIGNlbGwKCQkgKiAgQHJldHVybnMge25vZGV9IFRoZSByb3cgb3BlbmVkLiBOb3RlIHRoYXQgaWYgdGhlIHRhYmxlIHJvdyBwYXNzZWQgaW4gYXMgdGhlCgkJICogICAgZmlyc3QgcGFyYW1ldGVyLCBpcyBub3QgZm91bmQgaW4gdGhlIHRhYmxlLCB0aGlzIG1ldGhvZCB3aWxsIHNpbGVudGx5CgkJICogICAgcmV0dXJuLgoJCSAqICBAZHRvcHQgQVBJCgkJICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCQkgKiAgICAgIHZhciBvVGFibGU7CgkJICoKCQkgKiAgICAgIC8vICdvcGVuJyBhbiBpbmZvcm1hdGlvbiByb3cgd2hlbiBhIHJvdyBpcyBjbGlja2VkIG9uCgkJICogICAgICAkKCcjZXhhbXBsZSB0Ym9keSB0cicpLmNsaWNrKCBmdW5jdGlvbiAoKSB7CgkJICogICAgICAgIGlmICggb1RhYmxlLmZuSXNPcGVuKHRoaXMpICkgewoJCSAqICAgICAgICAgIG9UYWJsZS5mbkNsb3NlKCB0aGlzICk7CgkJICogICAgICAgIH0gZWxzZSB7CgkJICogICAgICAgICAgb1RhYmxlLmZuT3BlbiggdGhpcywgIlRlbXBvcmFyeSByb3cgb3BlbmVkIiwgImluZm9fcm93IiApOwoJCSAqICAgICAgICB9CgkJICogICAgICB9ICk7CgkJICoKCQkgKiAgICAgIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7CgkJICogICAgfSApOwoJCSAqLwoJCXRoaXMuZm5PcGVuID0gZnVuY3Rpb24oIG5UciwgbUh0bWwsIHNDbGFzcyApCgkJewoJCQlyZXR1cm4gdGhpcy5hcGkoIHRydWUgKQoJCQkJLnJvdyggblRyICkKCQkJCS5jaGlsZCggbUh0bWwsIHNDbGFzcyApCgkJCQkuc2hvdygpCgkJCQkuY2hpbGQoKVswXTsKCQl9OwoJCQoJCQoJCS8qKgoJCSAqIENoYW5nZSB0aGUgcGFnaW5hdGlvbiAtIHByb3ZpZGVzIHRoZSBpbnRlcm5hbCBsb2dpYyBmb3IgcGFnaW5hdGlvbiBpbiBhIHNpbXBsZSBBUEkKCQkgKiBmdW5jdGlvbi4gV2l0aCB0aGlzIGZ1bmN0aW9uIHlvdSBjYW4gaGF2ZSBhIERhdGFUYWJsZXMgdGFibGUgZ28gdG8gdGhlIG5leHQsCgkJICogcHJldmlvdXMsIGZpcnN0IG9yIGxhc3QgcGFnZXMuCgkJICogIEBwYXJhbSB7c3RyaW5nfGludH0gbUFjdGlvbiBQYWdpbmcgYWN0aW9uIHRvIHRha2U6ICJmaXJzdCIsICJwcmV2aW91cyIsICJuZXh0IiBvciAibGFzdCIKCQkgKiAgICBvciBwYWdlIG51bWJlciB0byBqdW1wIHRvIChpbnRlZ2VyKSwgbm90ZSB0aGF0IHBhZ2UgMCBpcyB0aGUgZmlyc3QgcGFnZS4KCQkgKiAgQHBhcmFtIHtib29sfSBbYlJlZHJhdz10cnVlXSBSZWRyYXcgdGhlIHRhYmxlIG9yIG5vdAoJCSAqICBAZHRvcHQgQVBJCgkJICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCQkgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqICAgICAgb1RhYmxlLmZuUGFnZUNoYW5nZSggJ25leHQnICk7CgkJICogICAgfSApOwoJCSAqLwoJCXRoaXMuZm5QYWdlQ2hhbmdlID0gZnVuY3Rpb24gKCBtQWN0aW9uLCBiUmVkcmF3ICkKCQl7CgkJCXZhciBhcGkgPSB0aGlzLmFwaSggdHJ1ZSApLnBhZ2UoIG1BY3Rpb24gKTsKCQkKCQkJaWYgKCBiUmVkcmF3ID09PSB1bmRlZmluZWQgfHwgYlJlZHJhdyApIHsKCQkJCWFwaS5kcmF3KGZhbHNlKTsKCQkJfQoJCX07CgkJCgkJCgkJLyoqCgkJICogU2hvdyBhIHBhcnRpY3VsYXIgY29sdW1uCgkJICogIEBwYXJhbSB7aW50fSBpQ29sIFRoZSBjb2x1bW4gd2hvc2UgZGlzcGxheSBzaG91bGQgYmUgY2hhbmdlZAoJCSAqICBAcGFyYW0ge2Jvb2x9IGJTaG93IFNob3cgKHRydWUpIG9yIGhpZGUgKGZhbHNlKSB0aGUgY29sdW1uCgkJICogIEBwYXJhbSB7Ym9vbH0gW2JSZWRyYXc9dHJ1ZV0gUmVkcmF3IHRoZSB0YWJsZSBvciBub3QKCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKgoJCSAqICAgICAgLy8gSGlkZSB0aGUgc2Vjb25kIGNvbHVtbiBhZnRlciBpbml0aWFsaXNhdGlvbgoJCSAqICAgICAgb1RhYmxlLmZuU2V0Q29sdW1uVmlzKCAxLCBmYWxzZSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuU2V0Q29sdW1uVmlzID0gZnVuY3Rpb24gKCBpQ29sLCBiU2hvdywgYlJlZHJhdyApCgkJewoJCQl2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKS5jb2x1bW4oIGlDb2wgKS52aXNpYmxlKCBiU2hvdyApOwoJCQoJCQlpZiAoIGJSZWRyYXcgPT09IHVuZGVmaW5lZCB8fCBiUmVkcmF3ICkgewoJCQkJYXBpLmNvbHVtbnMuYWRqdXN0KCkuZHJhdygpOwoJCQl9CgkJfTsKCQkKCQkKCQkvKioKCQkgKiBHZXQgdGhlIHNldHRpbmdzIGZvciBhIHBhcnRpY3VsYXIgdGFibGUgZm9yIGV4dGVybmFsIG1hbmlwdWxhdGlvbgoJCSAqICBAcmV0dXJucyB7b2JqZWN0fSBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdC4gU2VlCgkJICogICAge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfQoJCSAqICBAZHRvcHQgQVBJCgkJICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCQkgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqICAgICAgdmFyIG9TZXR0aW5ncyA9IG9UYWJsZS5mblNldHRpbmdzKCk7CgkJICoKCQkgKiAgICAgIC8vIFNob3cgYW4gZXhhbXBsZSBwYXJhbWV0ZXIgZnJvbSB0aGUgc2V0dGluZ3MKCQkgKiAgICAgIGFsZXJ0KCBvU2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgKTsKCQkgKiAgICB9ICk7CgkJICovCgkJdGhpcy5mblNldHRpbmdzID0gZnVuY3Rpb24oKQoJCXsKCQkJcmV0dXJuIF9mblNldHRpbmdzRnJvbU5vZGUoIHRoaXNbX2V4dC5pQXBpSW5kZXhdICk7CgkJfTsKCQkKCQkKCQkvKioKCQkgKiBTb3J0IHRoZSB0YWJsZSBieSBhIHBhcnRpY3VsYXIgY29sdW1uCgkJICogIEBwYXJhbSB7aW50fSBpQ29sIHRoZSBkYXRhIGluZGV4IHRvIHNvcnQgb24uIE5vdGUgdGhhdCB0aGlzIHdpbGwgbm90IG1hdGNoIHRoZQoJCSAqICAgICdkaXNwbGF5IGluZGV4JyBpZiB5b3UgaGF2ZSBoaWRkZW4gZGF0YSBlbnRyaWVzCgkJICogIEBkdG9wdCBBUEkKCQkgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTAKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgewoJCSAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7CgkJICoKCQkgKiAgICAgIC8vIFNvcnQgaW1tZWRpYXRlbHkgd2l0aCBjb2x1bW5zIDAgYW5kIDEKCQkgKiAgICAgIG9UYWJsZS5mblNvcnQoIFsgWzAsJ2FzYyddLCBbMSwnYXNjJ10gXSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuU29ydCA9IGZ1bmN0aW9uKCBhYVNvcnQgKQoJCXsKCQkJdGhpcy5hcGkoIHRydWUgKS5vcmRlciggYWFTb3J0ICkuZHJhdygpOwoJCX07CgkJCgkJCgkJLyoqCgkJICogQXR0YWNoIGEgc29ydCBsaXN0ZW5lciB0byBhbiBlbGVtZW50IGZvciBhIGdpdmVuIGNvbHVtbgoJCSAqICBAcGFyYW0ge25vZGV9IG5Ob2RlIHRoZSBlbGVtZW50IHRvIGF0dGFjaCB0aGUgc29ydCBsaXN0ZW5lciB0bwoJCSAqICBAcGFyYW0ge2ludH0gaUNvbHVtbiB0aGUgY29sdW1uIHRoYXQgYSBjbGljayBvbiB0aGlzIG5vZGUgd2lsbCBzb3J0IG9uCgkJICogIEBwYXJhbSB7ZnVuY3Rpb259IFtmbkNhbGxiYWNrXSBjYWxsYmFjayBmdW5jdGlvbiB3aGVuIHNvcnQgaXMgcnVuCgkJICogIEBkdG9wdCBBUEkKCQkgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTAKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkgewoJCSAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7CgkJICoKCQkgKiAgICAgIC8vIFNvcnQgb24gY29sdW1uIDEsIHdoZW4gJ3NvcnRlcicgaXMgY2xpY2tlZCBvbgoJCSAqICAgICAgb1RhYmxlLmZuU29ydExpc3RlbmVyKCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc29ydGVyJyksIDEgKTsKCQkgKiAgICB9ICk7CgkJICovCgkJdGhpcy5mblNvcnRMaXN0ZW5lciA9IGZ1bmN0aW9uKCBuTm9kZSwgaUNvbHVtbiwgZm5DYWxsYmFjayApCgkJewoJCQl0aGlzLmFwaSggdHJ1ZSApLm9yZGVyLmxpc3RlbmVyKCBuTm9kZSwgaUNvbHVtbiwgZm5DYWxsYmFjayApOwoJCX07CgkJCgkJCgkJLyoqCgkJICogVXBkYXRlIGEgdGFibGUgY2VsbCBvciByb3cgLSB0aGlzIG1ldGhvZCB3aWxsIGFjY2VwdCBlaXRoZXIgYSBzaW5nbGUgdmFsdWUgdG8KCQkgKiB1cGRhdGUgdGhlIGNlbGwgd2l0aCwgYW4gYXJyYXkgb2YgdmFsdWVzIHdpdGggb25lIGVsZW1lbnQgZm9yIGVhY2ggY29sdW1uIG9yCgkJICogYW4gb2JqZWN0IGluIHRoZSBzYW1lIGZvcm1hdCBhcyB0aGUgb3JpZ2luYWwgZGF0YSBzb3VyY2UuIFRoZSBmdW5jdGlvbiBpcwoJCSAqIHNlbGYtcmVmZXJlbmNpbmcgaW4gb3JkZXIgdG8gbWFrZSB0aGUgbXVsdGkgY29sdW1uIHVwZGF0ZXMgZWFzaWVyLgoJCSAqICBAcGFyYW0ge29iamVjdHxhcnJheXxzdHJpbmd9IG1EYXRhIERhdGEgdG8gdXBkYXRlIHRoZSBjZWxsL3JvdyB3aXRoCgkJICogIEBwYXJhbSB7bm9kZXxpbnR9IG1Sb3cgVFIgZWxlbWVudCB5b3Ugd2FudCB0byB1cGRhdGUgb3IgdGhlIGFvRGF0YSBpbmRleAoJCSAqICBAcGFyYW0ge2ludH0gW2lDb2x1bW5dIFRoZSBjb2x1bW4gdG8gdXBkYXRlLCBnaXZlIGFzIG51bGwgb3IgdW5kZWZpbmVkIHRvCgkJICogICAgdXBkYXRlIGEgd2hvbGUgcm93LgoJCSAqICBAcGFyYW0ge2Jvb2x9IFtiUmVkcmF3PXRydWVdIFJlZHJhdyB0aGUgdGFibGUgb3Igbm90CgkJICogIEBwYXJhbSB7Ym9vbH0gW2JBY3Rpb249dHJ1ZV0gUGVyZm9ybSBwcmUtZHJhdyBhY3Rpb25zIG9yIG5vdAoJCSAqICBAcmV0dXJucyB7aW50fSAwIG9uIHN1Y2Nlc3MsIDEgb24gZXJyb3IKCQkgKiAgQGR0b3B0IEFQSQoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7CgkJICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTsKCQkgKiAgICAgIG9UYWJsZS5mblVwZGF0ZSggJ0V4YW1wbGUgdXBkYXRlJywgMCwgMCApOyAvLyBTaW5nbGUgY2VsbAoJCSAqICAgICAgb1RhYmxlLmZuVXBkYXRlKCBbJ2EnLCAnYicsICdjJywgJ2QnLCAnZSddLCAkKCd0Ym9keSB0cicpWzBdICk7IC8vIFJvdwoJCSAqICAgIH0gKTsKCQkgKi8KCQl0aGlzLmZuVXBkYXRlID0gZnVuY3Rpb24oIG1EYXRhLCBtUm93LCBpQ29sdW1uLCBiUmVkcmF3LCBiQWN0aW9uICkKCQl7CgkJCXZhciBhcGkgPSB0aGlzLmFwaSggdHJ1ZSApOwoJCQoJCQlpZiAoIGlDb2x1bW4gPT09IHVuZGVmaW5lZCB8fCBpQ29sdW1uID09PSBudWxsICkgewoJCQkJYXBpLnJvdyggbVJvdyApLmRhdGEoIG1EYXRhICk7CgkJCX0KCQkJZWxzZSB7CgkJCQlhcGkuY2VsbCggbVJvdywgaUNvbHVtbiApLmRhdGEoIG1EYXRhICk7CgkJCX0KCQkKCQkJaWYgKCBiQWN0aW9uID09PSB1bmRlZmluZWQgfHwgYkFjdGlvbiApIHsKCQkJCWFwaS5jb2x1bW5zLmFkanVzdCgpOwoJCQl9CgkJCgkJCWlmICggYlJlZHJhdyA9PT0gdW5kZWZpbmVkIHx8IGJSZWRyYXcgKSB7CgkJCQlhcGkuZHJhdygpOwoJCQl9CgkJCXJldHVybiAwOwoJCX07CgkJCgkJCgkJLyoqCgkJICogUHJvdmlkZSBhIGNvbW1vbiBtZXRob2QgZm9yIHBsdWctaW5zIHRvIGNoZWNrIHRoZSB2ZXJzaW9uIG9mIERhdGFUYWJsZXMgYmVpbmcgdXNlZCwgaW4gb3JkZXIKCQkgKiB0byBlbnN1cmUgY29tcGF0aWJpbGl0eS4KCQkgKiAgQHBhcmFtIHtzdHJpbmd9IHNWZXJzaW9uIFZlcnNpb24gc3RyaW5nIHRvIGNoZWNrIGZvciwgaW4gdGhlIGZvcm1hdCAiWC5ZLloiLiBOb3RlIHRoYXQgdGhlCgkJICogICAgZm9ybWF0cyAiWCIgYW5kICJYLlkiIGFyZSBhbHNvIGFjY2VwdGFibGUuCgkJICogIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoaXMgdmVyc2lvbiBvZiBEYXRhVGFibGVzIGlzIGdyZWF0ZXIgb3IgZXF1YWwgdG8gdGhlIHJlcXVpcmVkCgkJICogICAgdmVyc2lvbiwgb3IgZmFsc2UgaWYgdGhpcyB2ZXJzaW9uIG9mIERhdGFUYWxlcyBpcyBub3Qgc3VpdGFibGUKCQkgKiAgQG1ldGhvZAoJCSAqICBAZHRvcHQgQVBJCgkJICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCQkgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJCSAqICAgICAgYWxlcnQoIG9UYWJsZS5mblZlcnNpb25DaGVjayggJzEuOS4wJyApICk7CgkJICogICAgfSApOwoJCSAqLwoJCXRoaXMuZm5WZXJzaW9uQ2hlY2sgPSBfZXh0LmZuVmVyc2lvbkNoZWNrOwoJCQoJCgkJdmFyIF90aGF0ID0gdGhpczsKCQl2YXIgZW1wdHlJbml0ID0gb3B0aW9ucyA9PT0gdW5kZWZpbmVkOwoJCXZhciBsZW4gPSB0aGlzLmxlbmd0aDsKCQoJCWlmICggZW1wdHlJbml0ICkgewoJCQlvcHRpb25zID0ge307CgkJfQoJCgkJdGhpcy5vQXBpID0gdGhpcy5pbnRlcm5hbCA9IF9leHQuaW50ZXJuYWw7CgkKCQkvLyBFeHRlbmQgd2l0aCBvbGQgc3R5bGUgcGx1Zy1pbiBBUEkgbWV0aG9kcwoJCWZvciAoIHZhciBmbiBpbiBEYXRhVGFibGUuZXh0LmludGVybmFsICkgewoJCQlpZiAoIGZuICkgewoJCQkJdGhpc1tmbl0gPSBfZm5FeHRlcm5BcGlGdW5jKGZuKTsKCQkJfQoJCX0KCQoJCXRoaXMuZWFjaChmdW5jdGlvbigpIHsKCQkJLy8gRm9yIGVhY2ggaW5pdGlhbGlzYXRpb24gd2Ugd2FudCB0byBnaXZlIGl0IGEgY2xlYW4gaW5pdGlhbGlzYXRpb24KCQkJLy8gb2JqZWN0IHRoYXQgY2FuIGJlIGJhc2hlZCBhcm91bmQKCQkJdmFyIG8gPSB7fTsKCQkJdmFyIG9Jbml0ID0gbGVuID4gMSA/IC8vIG9wdGltaXNhdGlvbiBmb3Igc2luZ2xlIHRhYmxlIGNhc2UKCQkJCV9mbkV4dGVuZCggbywgb3B0aW9ucywgdHJ1ZSApIDoKCQkJCW9wdGlvbnM7CgkKCQkJLypnbG9iYWwgb0luaXQsX3RoYXQsZW1wdHlJbml0Ki8KCQkJdmFyIGk9MCwgaUxlbiwgaiwgakxlbiwgaywga0xlbjsKCQkJdmFyIHNJZCA9IHRoaXMuZ2V0QXR0cmlidXRlKCAnaWQnICk7CgkJCXZhciBiSW5pdEhhbmRlZE9mZiA9IGZhbHNlOwoJCQl2YXIgZGVmYXVsdHMgPSBEYXRhVGFibGUuZGVmYXVsdHM7CgkJCXZhciAkdGhpcyA9ICQodGhpcyk7CgkJCQoJCQkKCQkJLyogU2FuaXR5IGNoZWNrICovCgkJCWlmICggdGhpcy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpICE9ICd0YWJsZScgKQoJCQl7CgkJCQlfZm5Mb2coIG51bGwsIDAsICdOb24tdGFibGUgbm9kZSBpbml0aWFsaXNhdGlvbiAoJyt0aGlzLm5vZGVOYW1lKycpJywgMiApOwoJCQkJcmV0dXJuOwoJCQl9CgkJCQoJCQkvKiBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBmb3IgdGhlIGRlZmF1bHRzICovCgkJCV9mbkNvbXBhdE9wdHMoIGRlZmF1bHRzICk7CgkJCV9mbkNvbXBhdENvbHMoIGRlZmF1bHRzLmNvbHVtbiApOwoJCQkKCQkJLyogQ29udmVydCB0aGUgY2FtZWwtY2FzZSBkZWZhdWx0cyB0byBIdW5nYXJpYW4gKi8KCQkJX2ZuQ2FtZWxUb0h1bmdhcmlhbiggZGVmYXVsdHMsIGRlZmF1bHRzLCB0cnVlICk7CgkJCV9mbkNhbWVsVG9IdW5nYXJpYW4oIGRlZmF1bHRzLmNvbHVtbiwgZGVmYXVsdHMuY29sdW1uLCB0cnVlICk7CgkJCQoJCQkvKiBTZXR0aW5nIHVwIHRoZSBpbml0aWFsaXNhdGlvbiBvYmplY3QgKi8KCQkJX2ZuQ2FtZWxUb0h1bmdhcmlhbiggZGVmYXVsdHMsICQuZXh0ZW5kKCBvSW5pdCwgJHRoaXMuZGF0YSgpICksIHRydWUgKTsKCQkJCgkJCQoJCQkKCQkJLyogQ2hlY2sgdG8gc2VlIGlmIHdlIGFyZSByZS1pbml0aWFsaXNpbmcgYSB0YWJsZSAqLwoJCQl2YXIgYWxsU2V0dGluZ3MgPSBEYXRhVGFibGUuc2V0dGluZ3M7CgkJCWZvciAoIGk9MCwgaUxlbj1hbGxTZXR0aW5ncy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKQoJCQl7CgkJCQl2YXIgcyA9IGFsbFNldHRpbmdzW2ldOwoJCQkKCQkJCS8qIEJhc2UgY2hlY2sgb24gdGFibGUgbm9kZSAqLwoJCQkJaWYgKAoJCQkJCXMublRhYmxlID09IHRoaXMgfHwKCQkJCQkocy5uVEhlYWQgJiYgcy5uVEhlYWQucGFyZW50Tm9kZSA9PSB0aGlzKSB8fAoJCQkJCShzLm5URm9vdCAmJiBzLm5URm9vdC5wYXJlbnROb2RlID09IHRoaXMpCgkJCQkpIHsKCQkJCQl2YXIgYlJldHJpZXZlID0gb0luaXQuYlJldHJpZXZlICE9PSB1bmRlZmluZWQgPyBvSW5pdC5iUmV0cmlldmUgOiBkZWZhdWx0cy5iUmV0cmlldmU7CgkJCQkJdmFyIGJEZXN0cm95ID0gb0luaXQuYkRlc3Ryb3kgIT09IHVuZGVmaW5lZCA/IG9Jbml0LmJEZXN0cm95IDogZGVmYXVsdHMuYkRlc3Ryb3k7CgkJCQoJCQkJCWlmICggZW1wdHlJbml0IHx8IGJSZXRyaWV2ZSApCgkJCQkJewoJCQkJCQlyZXR1cm4gcy5vSW5zdGFuY2U7CgkJCQkJfQoJCQkJCWVsc2UgaWYgKCBiRGVzdHJveSApCgkJCQkJewoJCQkJCQlzLm9JbnN0YW5jZS5mbkRlc3Ryb3koKTsKCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJCWVsc2UKCQkJCQl7CgkJCQkJCV9mbkxvZyggcywgMCwgJ0Nhbm5vdCByZWluaXRpYWxpc2UgRGF0YVRhYmxlJywgMyApOwoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJfQoJCQkKCQkJCS8qIElmIHRoZSBlbGVtZW50IHdlIGFyZSBpbml0aWFsaXNpbmcgaGFzIHRoZSBzYW1lIElEIGFzIGEgdGFibGUgd2hpY2ggd2FzIHByZXZpb3VzbHkKCQkJCSAqIGluaXRpYWxpc2VkLCBidXQgdGhlIHRhYmxlIG5vZGVzIGRvbid0IG1hdGNoIChmcm9tIGJlZm9yZSkgdGhlbiB3ZSBkZXN0cm95IHRoZSBvbGQKCQkJCSAqIGluc3RhbmNlIGJ5IHNpbXBseSBkZWxldGluZyBpdC4gVGhpcyBpcyB1bmRlciB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSB0YWJsZSBoYXMgYmVlbgoJCQkJICogZGVzdHJveWVkIGJ5IG90aGVyIG1ldGhvZHMuIEFueW9uZSB1c2luZyBub24taWQgc2VsZWN0b3JzIHdpbGwgbmVlZCB0byBkbyB0aGlzIG1hbnVhbGx5CgkJCQkgKi8KCQkJCWlmICggcy5zVGFibGVJZCA9PSB0aGlzLmlkICkKCQkJCXsKCQkJCQlhbGxTZXR0aW5ncy5zcGxpY2UoIGksIDEgKTsKCQkJCQlicmVhazsKCQkJCX0KCQkJfQoJCQkKCQkJLyogRW5zdXJlIHRoZSB0YWJsZSBoYXMgYW4gSUQgLSByZXF1aXJlZCBmb3IgYWNjZXNzaWJpbGl0eSAqLwoJCQlpZiAoIHNJZCA9PT0gbnVsbCB8fCBzSWQgPT09ICIiICkKCQkJewoJCQkJc0lkID0gIkRhdGFUYWJsZXNfVGFibGVfIisoRGF0YVRhYmxlLmV4dC5fdW5pcXVlKyspOwoJCQkJdGhpcy5pZCA9IHNJZDsKCQkJfQoJCQkKCQkJLyogQ3JlYXRlIHRoZSBzZXR0aW5ncyBvYmplY3QgZm9yIHRoaXMgdGFibGUgYW5kIHNldCBzb21lIG9mIHRoZSBkZWZhdWx0IHBhcmFtZXRlcnMgKi8KCQkJdmFyIG9TZXR0aW5ncyA9ICQuZXh0ZW5kKCB0cnVlLCB7fSwgRGF0YVRhYmxlLm1vZGVscy5vU2V0dGluZ3MsIHsKCQkJCSJzRGVzdHJveVdpZHRoIjogJHRoaXNbMF0uc3R5bGUud2lkdGgsCgkJCQkic0luc3RhbmNlIjogICAgIHNJZCwKCQkJCSJzVGFibGVJZCI6ICAgICAgc0lkCgkJCX0gKTsKCQkJb1NldHRpbmdzLm5UYWJsZSA9IHRoaXM7CgkJCW9TZXR0aW5ncy5vQXBpICAgPSBfdGhhdC5pbnRlcm5hbDsKCQkJb1NldHRpbmdzLm9Jbml0ICA9IG9Jbml0OwoJCQkKCQkJYWxsU2V0dGluZ3MucHVzaCggb1NldHRpbmdzICk7CgkJCQoJCQkvLyBOZWVkIHRvIGFkZCB0aGUgaW5zdGFuY2UgYWZ0ZXIgdGhlIGluc3RhbmNlIGFmdGVyIHRoZSBzZXR0aW5ncyBvYmplY3QgaGFzIGJlZW4gYWRkZWQKCQkJLy8gdG8gdGhlIHNldHRpbmdzIGFycmF5LCBzbyB3ZSBjYW4gc2VsZiByZWZlcmVuY2UgdGhlIHRhYmxlIGluc3RhbmNlIGlmIG1vcmUgdGhhbiBvbmUKCQkJb1NldHRpbmdzLm9JbnN0YW5jZSA9IChfdGhhdC5sZW5ndGg9PT0xKSA/IF90aGF0IDogJHRoaXMuZGF0YVRhYmxlKCk7CgkJCQoJCQkvLyBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgYmVmb3JlIHdlIGFwcGx5IGFsbCB0aGUgZGVmYXVsdHMKCQkJX2ZuQ29tcGF0T3B0cyggb0luaXQgKTsKCQkJX2ZuTGFuZ3VhZ2VDb21wYXQoIG9Jbml0Lm9MYW5ndWFnZSApOwoJCQkKCQkJLy8gSWYgdGhlIGxlbmd0aCBtZW51IGlzIGdpdmVuLCBidXQgdGhlIGluaXQgZGlzcGxheSBsZW5ndGggaXMgbm90LCB1c2UgdGhlIGxlbmd0aCBtZW51CgkJCWlmICggb0luaXQuYUxlbmd0aE1lbnUgJiYgISBvSW5pdC5pRGlzcGxheUxlbmd0aCApCgkJCXsKCQkJCW9Jbml0LmlEaXNwbGF5TGVuZ3RoID0gQXJyYXkuaXNBcnJheSggb0luaXQuYUxlbmd0aE1lbnVbMF0gKSA/CgkJCQkJb0luaXQuYUxlbmd0aE1lbnVbMF1bMF0gOiBvSW5pdC5hTGVuZ3RoTWVudVswXTsKCQkJfQoJCQkKCQkJLy8gQXBwbHkgdGhlIGRlZmF1bHRzIGFuZCBpbml0IG9wdGlvbnMgdG8gbWFrZSBhIHNpbmdsZSBpbml0IG9iamVjdCB3aWxsIGFsbAoJCQkvLyBvcHRpb25zIGRlZmluZWQgZnJvbSBkZWZhdWx0cyBhbmQgaW5zdGFuY2Ugb3B0aW9ucy4KCQkJb0luaXQgPSBfZm5FeHRlbmQoICQuZXh0ZW5kKCB0cnVlLCB7fSwgZGVmYXVsdHMgKSwgb0luaXQgKTsKCQkJCgkJCQoJCQkvLyBNYXAgdGhlIGluaXRpYWxpc2F0aW9uIG9wdGlvbnMgb250byB0aGUgc2V0dGluZ3Mgb2JqZWN0CgkJCV9mbk1hcCggb1NldHRpbmdzLm9GZWF0dXJlcywgb0luaXQsIFsKCQkJCSJiUGFnaW5hdGUiLAoJCQkJImJMZW5ndGhDaGFuZ2UiLAoJCQkJImJGaWx0ZXIiLAoJCQkJImJTb3J0IiwKCQkJCSJiU29ydE11bHRpIiwKCQkJCSJiSW5mbyIsCgkJCQkiYlByb2Nlc3NpbmciLAoJCQkJImJBdXRvV2lkdGgiLAoJCQkJImJTb3J0Q2xhc3NlcyIsCgkJCQkiYlNlcnZlclNpZGUiLAoJCQkJImJEZWZlclJlbmRlciIKCQkJXSApOwoJCQlfZm5NYXAoIG9TZXR0aW5ncywgb0luaXQsIFsKCQkJCSJhc1N0cmlwZUNsYXNzZXMiLAoJCQkJImFqYXgiLAoJCQkJImZuU2VydmVyRGF0YSIsCgkJCQkiZm5Gb3JtYXROdW1iZXIiLAoJCQkJInNTZXJ2ZXJNZXRob2QiLAoJCQkJImFhU29ydGluZyIsCgkJCQkiYWFTb3J0aW5nRml4ZWQiLAoJCQkJImFMZW5ndGhNZW51IiwKCQkJCSJzUGFnaW5hdGlvblR5cGUiLAoJCQkJInNBamF4U291cmNlIiwKCQkJCSJzQWpheERhdGFQcm9wIiwKCQkJCSJpU3RhdGVEdXJhdGlvbiIsCgkJCQkic0RvbSIsCgkJCQkiYlNvcnRDZWxsc1RvcCIsCgkJCQkiaVRhYkluZGV4IiwKCQkJCSJmblN0YXRlTG9hZENhbGxiYWNrIiwKCQkJCSJmblN0YXRlU2F2ZUNhbGxiYWNrIiwKCQkJCSJyZW5kZXJlciIsCgkJCQkic2VhcmNoRGVsYXkiLAoJCQkJInJvd0lkIiwKCQkJCVsgImlDb29raWVEdXJhdGlvbiIsICJpU3RhdGVEdXJhdGlvbiIgXSwgLy8gYmFja3dhcmRzIGNvbXBhdAoJCQkJWyAib1NlYXJjaCIsICJvUHJldmlvdXNTZWFyY2giIF0sCgkJCQlbICJhb1NlYXJjaENvbHMiLCAiYW9QcmVTZWFyY2hDb2xzIiBdLAoJCQkJWyAiaURpc3BsYXlMZW5ndGgiLCAiX2lEaXNwbGF5TGVuZ3RoIiBdCgkJCV0gKTsKCQkJX2ZuTWFwKCBvU2V0dGluZ3Mub1Njcm9sbCwgb0luaXQsIFsKCQkJCVsgInNTY3JvbGxYIiwgInNYIiBdLAoJCQkJWyAic1Njcm9sbFhJbm5lciIsICJzWElubmVyIiBdLAoJCQkJWyAic1Njcm9sbFkiLCAic1kiIF0sCgkJCQlbICJiU2Nyb2xsQ29sbGFwc2UiLCAiYkNvbGxhcHNlIiBdCgkJCV0gKTsKCQkJX2ZuTWFwKCBvU2V0dGluZ3Mub0xhbmd1YWdlLCBvSW5pdCwgImZuSW5mb0NhbGxiYWNrIiApOwoJCQkKCQkJLyogQ2FsbGJhY2sgZnVuY3Rpb25zIHdoaWNoIGFyZSBhcnJheSBkcml2ZW4gKi8KCQkJX2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvRHJhd0NhbGxiYWNrJywgICAgICAgb0luaXQuZm5EcmF3Q2FsbGJhY2ssICAgICAgJ3VzZXInICk7CgkJCV9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb1NlcnZlclBhcmFtcycsICAgICAgIG9Jbml0LmZuU2VydmVyUGFyYW1zLCAgICAgICd1c2VyJyApOwoJCQlfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCAnYW9TdGF0ZVNhdmVQYXJhbXMnLCAgICBvSW5pdC5mblN0YXRlU2F2ZVBhcmFtcywgICAndXNlcicgKTsKCQkJX2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvU3RhdGVMb2FkUGFyYW1zJywgICAgb0luaXQuZm5TdGF0ZUxvYWRQYXJhbXMsICAgJ3VzZXInICk7CgkJCV9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb1N0YXRlTG9hZGVkJywgICAgICAgIG9Jbml0LmZuU3RhdGVMb2FkZWQsICAgICAgICd1c2VyJyApOwoJCQlfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCAnYW9Sb3dDYWxsYmFjaycsICAgICAgICBvSW5pdC5mblJvd0NhbGxiYWNrLCAgICAgICAndXNlcicgKTsKCQkJX2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvUm93Q3JlYXRlZENhbGxiYWNrJywgb0luaXQuZm5DcmVhdGVkUm93LCAgICAgICAgJ3VzZXInICk7CgkJCV9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb0hlYWRlckNhbGxiYWNrJywgICAgIG9Jbml0LmZuSGVhZGVyQ2FsbGJhY2ssICAgICd1c2VyJyApOwoJCQlfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCAnYW9Gb290ZXJDYWxsYmFjaycsICAgICBvSW5pdC5mbkZvb3RlckNhbGxiYWNrLCAgICAndXNlcicgKTsKCQkJX2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvSW5pdENvbXBsZXRlJywgICAgICAgb0luaXQuZm5Jbml0Q29tcGxldGUsICAgICAgJ3VzZXInICk7CgkJCV9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb1ByZURyYXdDYWxsYmFjaycsICAgIG9Jbml0LmZuUHJlRHJhd0NhbGxiYWNrLCAgICd1c2VyJyApOwoJCQkKCQkJb1NldHRpbmdzLnJvd0lkRm4gPSBfZm5HZXRPYmplY3REYXRhRm4oIG9Jbml0LnJvd0lkICk7CgkJCQoJCQkvKiBCcm93c2VyIHN1cHBvcnQgZGV0ZWN0aW9uICovCgkJCV9mbkJyb3dzZXJEZXRlY3QoIG9TZXR0aW5ncyApOwoJCQkKCQkJdmFyIG9DbGFzc2VzID0gb1NldHRpbmdzLm9DbGFzc2VzOwoJCQkKCQkJJC5leHRlbmQoIG9DbGFzc2VzLCBEYXRhVGFibGUuZXh0LmNsYXNzZXMsIG9Jbml0Lm9DbGFzc2VzICk7CgkJCSR0aGlzLmFkZENsYXNzKCBvQ2xhc3Nlcy5zVGFibGUgKTsKCQkJCgkJCQoJCQlpZiAoIG9TZXR0aW5ncy5pSW5pdERpc3BsYXlTdGFydCA9PT0gdW5kZWZpbmVkICkKCQkJewoJCQkJLyogRGlzcGxheSBzdGFydCBwb2ludCwgdGFraW5nIGludG8gYWNjb3VudCB0aGUgc2F2ZSBzYXZpbmcgKi8KCQkJCW9TZXR0aW5ncy5pSW5pdERpc3BsYXlTdGFydCA9IG9Jbml0LmlEaXNwbGF5U3RhcnQ7CgkJCQlvU2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgPSBvSW5pdC5pRGlzcGxheVN0YXJ0OwoJCQl9CgkJCQoJCQlpZiAoIG9Jbml0LmlEZWZlckxvYWRpbmcgIT09IG51bGwgKQoJCQl7CgkJCQlvU2V0dGluZ3MuYkRlZmVyTG9hZGluZyA9IHRydWU7CgkJCQl2YXIgdG1wID0gQXJyYXkuaXNBcnJheSggb0luaXQuaURlZmVyTG9hZGluZyApOwoJCQkJb1NldHRpbmdzLl9pUmVjb3Jkc0Rpc3BsYXkgPSB0bXAgPyBvSW5pdC5pRGVmZXJMb2FkaW5nWzBdIDogb0luaXQuaURlZmVyTG9hZGluZzsKCQkJCW9TZXR0aW5ncy5faVJlY29yZHNUb3RhbCA9IHRtcCA/IG9Jbml0LmlEZWZlckxvYWRpbmdbMV0gOiBvSW5pdC5pRGVmZXJMb2FkaW5nOwoJCQl9CgkJCQoJCQkvKiBMYW5ndWFnZSBkZWZpbml0aW9ucyAqLwoJCQl2YXIgb0xhbmd1YWdlID0gb1NldHRpbmdzLm9MYW5ndWFnZTsKCQkJJC5leHRlbmQoIHRydWUsIG9MYW5ndWFnZSwgb0luaXQub0xhbmd1YWdlICk7CgkJCQoJCQlpZiAoIG9MYW5ndWFnZS5zVXJsICkKCQkJewoJCQkJLyogR2V0IHRoZSBsYW5ndWFnZSBkZWZpbml0aW9ucyBmcm9tIGEgZmlsZSAtIGJlY2F1c2UgdGhpcyBBamF4IGNhbGwgbWFrZXMgdGhlIGxhbmd1YWdlCgkJCQkgKiBnZXQgYXN5bmMgdG8gdGhlIHJlbWFpbmRlciBvZiB0aGlzIGZ1bmN0aW9uIHdlIHVzZSBiSW5pdEhhbmRlZE9mZiB0byBpbmRpY2F0ZSB0aGF0CgkJCQkgKiBfZm5Jbml0aWFsaXNlIHdpbGwgYmUgZmlyZWQgYnkgdGhlIHJldHVybmVkIEFqYXggaGFuZGxlciwgcmF0aGVyIHRoYW4gdGhlIGNvbnN0cnVjdG9yCgkJCQkgKi8KCQkJCSQuYWpheCggewoJCQkJCWRhdGFUeXBlOiAnanNvbicsCgkJCQkJdXJsOiBvTGFuZ3VhZ2Uuc1VybCwKCQkJCQlzdWNjZXNzOiBmdW5jdGlvbiAoIGpzb24gKSB7CgkJCQkJCV9mbkNhbWVsVG9IdW5nYXJpYW4oIGRlZmF1bHRzLm9MYW5ndWFnZSwganNvbiApOwoJCQkJCQlfZm5MYW5ndWFnZUNvbXBhdCgganNvbiApOwoJCQkJCQkkLmV4dGVuZCggdHJ1ZSwgb0xhbmd1YWdlLCBqc29uLCBvU2V0dGluZ3Mub0luaXQub0xhbmd1YWdlICk7CgkJCQoJCQkJCQlfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgbnVsbCwgJ2kxOG4nLCBbb1NldHRpbmdzXSk7CgkJCQkJCV9mbkluaXRpYWxpc2UoIG9TZXR0aW5ncyApOwoJCQkJCX0sCgkJCQkJZXJyb3I6IGZ1bmN0aW9uICgpIHsKCQkJCQkJLy8gRXJyb3Igb2NjdXJyZWQgbG9hZGluZyBsYW5ndWFnZSBmaWxlLCBjb250aW51ZSBvbiBhcyBiZXN0IHdlIGNhbgoJCQkJCQlfZm5Jbml0aWFsaXNlKCBvU2V0dGluZ3MgKTsKCQkJCQl9CgkJCQl9ICk7CgkJCQliSW5pdEhhbmRlZE9mZiA9IHRydWU7CgkJCX0KCQkJZWxzZSB7CgkJCQlfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgbnVsbCwgJ2kxOG4nLCBbb1NldHRpbmdzXSk7CgkJCX0KCQkJCgkJCS8qCgkJCSAqIFN0cmlwZXMKCQkJICovCgkJCWlmICggb0luaXQuYXNTdHJpcGVDbGFzc2VzID09PSBudWxsICkKCQkJewoJCQkJb1NldHRpbmdzLmFzU3RyaXBlQ2xhc3NlcyA9WwoJCQkJCW9DbGFzc2VzLnNTdHJpcGVPZGQsCgkJCQkJb0NsYXNzZXMuc1N0cmlwZUV2ZW4KCQkJCV07CgkJCX0KCQkJCgkJCS8qIFJlbW92ZSByb3cgc3RyaXBlIGNsYXNzZXMgaWYgdGhleSBhcmUgYWxyZWFkeSBvbiB0aGUgdGFibGUgcm93ICovCgkJCXZhciBzdHJpcGVDbGFzc2VzID0gb1NldHRpbmdzLmFzU3RyaXBlQ2xhc3NlczsKCQkJdmFyIHJvd09uZSA9ICR0aGlzLmNoaWxkcmVuKCd0Ym9keScpLmZpbmQoJ3RyJykuZXEoMCk7CgkJCWlmICggJC5pbkFycmF5KCB0cnVlLCAkLm1hcCggc3RyaXBlQ2xhc3NlcywgZnVuY3Rpb24oZWwsIGkpIHsKCQkJCXJldHVybiByb3dPbmUuaGFzQ2xhc3MoZWwpOwoJCQl9ICkgKSAhPT0gLTEgKSB7CgkJCQkkKCd0Ym9keSB0cicsIHRoaXMpLnJlbW92ZUNsYXNzKCBzdHJpcGVDbGFzc2VzLmpvaW4oJyAnKSApOwoJCQkJb1NldHRpbmdzLmFzRGVzdHJveVN0cmlwZXMgPSBzdHJpcGVDbGFzc2VzLnNsaWNlKCk7CgkJCX0KCQkJCgkJCS8qCgkJCSAqIENvbHVtbnMKCQkJICogU2VlIGlmIHdlIHNob3VsZCBsb2FkIGNvbHVtbnMgYXV0b21hdGljYWxseSBvciB1c2UgZGVmaW5lZCBvbmVzCgkJCSAqLwoJCQl2YXIgYW5UaHMgPSBbXTsKCQkJdmFyIGFvQ29sdW1uc0luaXQ7CgkJCXZhciBuVGhlYWQgPSB0aGlzLmdldEVsZW1lbnRzQnlUYWdOYW1lKCd0aGVhZCcpOwoJCQlpZiAoIG5UaGVhZC5sZW5ndGggIT09IDAgKQoJCQl7CgkJCQlfZm5EZXRlY3RIZWFkZXIoIG9TZXR0aW5ncy5hb0hlYWRlciwgblRoZWFkWzBdICk7CgkJCQlhblRocyA9IF9mbkdldFVuaXF1ZVRocyggb1NldHRpbmdzICk7CgkJCX0KCQkJCgkJCS8qIElmIG5vdCBnaXZlbiBhIGNvbHVtbiBhcnJheSwgZ2VuZXJhdGUgb25lIHdpdGggbnVsbHMgKi8KCQkJaWYgKCBvSW5pdC5hb0NvbHVtbnMgPT09IG51bGwgKQoJCQl7CgkJCQlhb0NvbHVtbnNJbml0ID0gW107CgkJCQlmb3IgKCBpPTAsIGlMZW49YW5UaHMubGVuZ3RoIDsgaTxpTGVuIDsgaSsrICkKCQkJCXsKCQkJCQlhb0NvbHVtbnNJbml0LnB1c2goIG51bGwgKTsKCQkJCX0KCQkJfQoJCQllbHNlCgkJCXsKCQkJCWFvQ29sdW1uc0luaXQgPSBvSW5pdC5hb0NvbHVtbnM7CgkJCX0KCQkJCgkJCS8qIEFkZCB0aGUgY29sdW1ucyAqLwoJCQlmb3IgKCBpPTAsIGlMZW49YW9Db2x1bW5zSW5pdC5sZW5ndGggOyBpPGlMZW4gOyBpKysgKQoJCQl7CgkJCQlfZm5BZGRDb2x1bW4oIG9TZXR0aW5ncywgYW5UaHMgPyBhblRoc1tpXSA6IG51bGwgKTsKCQkJfQoJCQkKCQkJLyogQXBwbHkgdGhlIGNvbHVtbiBkZWZpbml0aW9ucyAqLwoJCQlfZm5BcHBseUNvbHVtbkRlZnMoIG9TZXR0aW5ncywgb0luaXQuYW9Db2x1bW5EZWZzLCBhb0NvbHVtbnNJbml0LCBmdW5jdGlvbiAoaUNvbCwgb0RlZikgewoJCQkJX2ZuQ29sdW1uT3B0aW9ucyggb1NldHRpbmdzLCBpQ29sLCBvRGVmICk7CgkJCX0gKTsKCQkJCgkJCS8qIEhUTUw1IGF0dHJpYnV0ZSBkZXRlY3Rpb24gLSBidWlsZCBhbiBtRGF0YSBvYmplY3QgYXV0b21hdGljYWxseSBpZiB0aGUKCQkJICogYXR0cmlidXRlcyBhcmUgZm91bmQKCQkJICovCgkJCWlmICggcm93T25lLmxlbmd0aCApIHsKCQkJCXZhciBhID0gZnVuY3Rpb24gKCBjZWxsLCBuYW1lICkgewoJCQkJCXJldHVybiBjZWxsLmdldEF0dHJpYnV0ZSggJ2RhdGEtJytuYW1lICkgIT09IG51bGwgPyBuYW1lIDogbnVsbDsKCQkJCX07CgkJCQoJCQkJJCggcm93T25lWzBdICkuY2hpbGRyZW4oJ3RoLCB0ZCcpLmVhY2goIGZ1bmN0aW9uIChpLCBjZWxsKSB7CgkJCQkJdmFyIGNvbCA9IG9TZXR0aW5ncy5hb0NvbHVtbnNbaV07CgkJCQoJCQkJCWlmICggY29sLm1EYXRhID09PSBpICkgewoJCQkJCQl2YXIgc29ydCA9IGEoIGNlbGwsICdzb3J0JyApIHx8IGEoIGNlbGwsICdvcmRlcicgKTsKCQkJCQkJdmFyIGZpbHRlciA9IGEoIGNlbGwsICdmaWx0ZXInICkgfHwgYSggY2VsbCwgJ3NlYXJjaCcgKTsKCQkJCgkJCQkJCWlmICggc29ydCAhPT0gbnVsbCB8fCBmaWx0ZXIgIT09IG51bGwgKSB7CgkJCQkJCQljb2wubURhdGEgPSB7CgkJCQkJCQkJXzogICAgICBpKycuZGlzcGxheScsCgkJCQkJCQkJc29ydDogICBzb3J0ICE9PSBudWxsICAgPyBpKycuQGRhdGEtJytzb3J0ICAgOiB1bmRlZmluZWQsCgkJCQkJCQkJdHlwZTogICBzb3J0ICE9PSBudWxsICAgPyBpKycuQGRhdGEtJytzb3J0ICAgOiB1bmRlZmluZWQsCgkJCQkJCQkJZmlsdGVyOiBmaWx0ZXIgIT09IG51bGwgPyBpKycuQGRhdGEtJytmaWx0ZXIgOiB1bmRlZmluZWQKCQkJCQkJCX07CgkJCQoJCQkJCQkJX2ZuQ29sdW1uT3B0aW9ucyggb1NldHRpbmdzLCBpICk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9ICk7CgkJCX0KCQkJCgkJCXZhciBmZWF0dXJlcyA9IG9TZXR0aW5ncy5vRmVhdHVyZXM7CgkJCXZhciBsb2FkZWRJbml0ID0gZnVuY3Rpb24gKCkgewoJCQkJLyoKCQkJCSAqIFNvcnRpbmcKCQkJCSAqIEB0b2RvIEZvciBtb2R1bGFyaXNhdGlvbiAoMS4xMSkgdGhpcyBuZWVkcyB0byBkbyBpbnRvIGEgc29ydCBzdGFydCB1cCBoYW5kbGVyCgkJCQkgKi8KCQkJCgkJCQkvLyBJZiBhYVNvcnRpbmcgaXMgbm90IGRlZmluZWQsIHRoZW4gd2UgdXNlIHRoZSBmaXJzdCBpbmRpY2F0b3IgaW4gYXNTb3J0aW5nCgkJCQkvLyBpbiBjYXNlIHRoYXQgaGFzIGJlZW4gYWx0ZXJlZCwgc28gdGhlIGRlZmF1bHQgc29ydCByZWZsZWN0cyB0aGF0IG9wdGlvbgoJCQkJaWYgKCBvSW5pdC5hYVNvcnRpbmcgPT09IHVuZGVmaW5lZCApIHsKCQkJCQl2YXIgc29ydGluZyA9IG9TZXR0aW5ncy5hYVNvcnRpbmc7CgkJCQkJZm9yICggaT0wLCBpTGVuPXNvcnRpbmcubGVuZ3RoIDsgaTxpTGVuIDsgaSsrICkgewoJCQkJCQlzb3J0aW5nW2ldWzFdID0gb1NldHRpbmdzLmFvQ29sdW1uc1sgaSBdLmFzU29ydGluZ1swXTsKCQkJCQl9CgkJCQl9CgkJCQoJCQkJLyogRG8gYSBmaXJzdCBwYXNzIG9uIHRoZSBzb3J0aW5nIGNsYXNzZXMgKGFsbG93cyBhbnkgc2l6ZSBjaGFuZ2VzIHRvIGJlIHRha2VuIGludG8KCQkJCSAqIGFjY291bnQsIGFuZCBhbHNvIHdpbGwgYXBwbHkgc29ydGluZyBkaXNhYmxlZCBjbGFzc2VzIGlmIGRpc2FibGVkCgkJCQkgKi8KCQkJCV9mblNvcnRpbmdDbGFzc2VzKCBvU2V0dGluZ3MgKTsKCQkJCgkJCQlpZiAoIGZlYXR1cmVzLmJTb3J0ICkgewoJCQkJCV9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb0RyYXdDYWxsYmFjaycsIGZ1bmN0aW9uICgpIHsKCQkJCQkJaWYgKCBvU2V0dGluZ3MuYlNvcnRlZCApIHsKCQkJCQkJCXZhciBhU29ydCA9IF9mblNvcnRGbGF0dGVuKCBvU2V0dGluZ3MgKTsKCQkJCQkJCXZhciBzb3J0ZWRDb2x1bW5zID0ge307CgkJCQoJCQkJCQkJJC5lYWNoKCBhU29ydCwgZnVuY3Rpb24gKGksIHZhbCkgewoJCQkJCQkJCXNvcnRlZENvbHVtbnNbIHZhbC5zcmMgXSA9IHZhbC5kaXI7CgkJCQkJCQl9ICk7CgkJCQoJCQkJCQkJX2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsIG51bGwsICdvcmRlcicsIFtvU2V0dGluZ3MsIGFTb3J0LCBzb3J0ZWRDb2x1bW5zXSApOwoJCQkJCQkJX2ZuU29ydEFyaWEoIG9TZXR0aW5ncyApOwoJCQkJCQl9CgkJCQkJfSApOwoJCQkJfQoJCQkKCQkJCV9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb0RyYXdDYWxsYmFjaycsIGZ1bmN0aW9uICgpIHsKCQkJCQlpZiAoIG9TZXR0aW5ncy5iU29ydGVkIHx8IF9mbkRhdGFTb3VyY2UoIG9TZXR0aW5ncyApID09PSAnc3NwJyB8fCBmZWF0dXJlcy5iRGVmZXJSZW5kZXIgKSB7CgkJCQkJCV9mblNvcnRpbmdDbGFzc2VzKCBvU2V0dGluZ3MgKTsKCQkJCQl9CgkJCQl9LCAnc2MnICk7CgkJCQoJCQkKCQkJCS8qCgkJCQkgKiBGaW5hbCBpbml0CgkJCQkgKiBDYWNoZSB0aGUgaGVhZGVyLCBib2R5IGFuZCBmb290ZXIgYXMgcmVxdWlyZWQsIGNyZWF0aW5nIHRoZW0gaWYgbmVlZGVkCgkJCQkgKi8KCQkJCgkJCQkvLyBXb3JrIGFyb3VuZCBmb3IgV2Via2l0IGJ1ZyA4Mzg2NyAtIHN0b3JlIHRoZSBjYXB0aW9uLXNpZGUgYmVmb3JlIHJlbW92aW5nIGZyb20gZG9jCgkJCQl2YXIgY2FwdGlvbnMgPSAkdGhpcy5jaGlsZHJlbignY2FwdGlvbicpLmVhY2goIGZ1bmN0aW9uICgpIHsKCQkJCQl0aGlzLl9jYXB0aW9uU2lkZSA9ICQodGhpcykuY3NzKCdjYXB0aW9uLXNpZGUnKTsKCQkJCX0gKTsKCQkJCgkJCQl2YXIgdGhlYWQgPSAkdGhpcy5jaGlsZHJlbigndGhlYWQnKTsKCQkJCWlmICggdGhlYWQubGVuZ3RoID09PSAwICkgewoJCQkJCXRoZWFkID0gJCgnPHRoZWFkLz4nKS5hcHBlbmRUbygkdGhpcyk7CgkJCQl9CgkJCQlvU2V0dGluZ3MublRIZWFkID0gdGhlYWRbMF07CgkJCQoJCQkJdmFyIHRib2R5ID0gJHRoaXMuY2hpbGRyZW4oJ3Rib2R5Jyk7CgkJCQlpZiAoIHRib2R5Lmxlbmd0aCA9PT0gMCApIHsKCQkJCQl0Ym9keSA9ICQoJzx0Ym9keS8+JykuaW5zZXJ0QWZ0ZXIodGhlYWQpOwoJCQkJfQoJCQkJb1NldHRpbmdzLm5UQm9keSA9IHRib2R5WzBdOwoJCQkKCQkJCXZhciB0Zm9vdCA9ICR0aGlzLmNoaWxkcmVuKCd0Zm9vdCcpOwoJCQkJaWYgKCB0Zm9vdC5sZW5ndGggPT09IDAgJiYgY2FwdGlvbnMubGVuZ3RoID4gMCAmJiAob1NldHRpbmdzLm9TY3JvbGwuc1ggIT09ICIiIHx8IG9TZXR0aW5ncy5vU2Nyb2xsLnNZICE9PSAiIikgKSB7CgkJCQkJLy8gSWYgd2UgYXJlIGEgc2Nyb2xsaW5nIHRhYmxlLCBhbmQgbm8gZm9vdGVyIGhhcyBiZWVuIGdpdmVuLCB0aGVuIHdlIG5lZWQgdG8gY3JlYXRlCgkJCQkJLy8gYSB0Zm9vdCBlbGVtZW50IGZvciB0aGUgY2FwdGlvbiBlbGVtZW50IHRvIGJlIGFwcGVuZGVkIHRvCgkJCQkJdGZvb3QgPSAkKCc8dGZvb3QvPicpLmFwcGVuZFRvKCR0aGlzKTsKCQkJCX0KCQkJCgkJCQlpZiAoIHRmb290Lmxlbmd0aCA9PT0gMCB8fCB0Zm9vdC5jaGlsZHJlbigpLmxlbmd0aCA9PT0gMCApIHsKCQkJCQkkdGhpcy5hZGRDbGFzcyggb0NsYXNzZXMuc05vRm9vdGVyICk7CgkJCQl9CgkJCQllbHNlIGlmICggdGZvb3QubGVuZ3RoID4gMCApIHsKCQkJCQlvU2V0dGluZ3MublRGb290ID0gdGZvb3RbMF07CgkJCQkJX2ZuRGV0ZWN0SGVhZGVyKCBvU2V0dGluZ3MuYW9Gb290ZXIsIG9TZXR0aW5ncy5uVEZvb3QgKTsKCQkJCX0KCQkJCgkJCQkvKiBDaGVjayBpZiB0aGVyZSBpcyBkYXRhIHBhc3NpbmcgaW50byB0aGUgY29uc3RydWN0b3IgKi8KCQkJCWlmICggb0luaXQuYWFEYXRhICkgewoJCQkJCWZvciAoIGk9MCA7IGk8b0luaXQuYWFEYXRhLmxlbmd0aCA7IGkrKyApIHsKCQkJCQkJX2ZuQWRkRGF0YSggb1NldHRpbmdzLCBvSW5pdC5hYURhdGFbIGkgXSApOwoJCQkJCX0KCQkJCX0KCQkJCWVsc2UgaWYgKCBvU2V0dGluZ3MuYkRlZmVyTG9hZGluZyB8fCBfZm5EYXRhU291cmNlKCBvU2V0dGluZ3MgKSA9PSAnZG9tJyApIHsKCQkJCQkvKiBHcmFiIHRoZSBkYXRhIGZyb20gdGhlIHBhZ2UgLSBvbmx5IGRvIHRoaXMgd2hlbiBkZWZlcnJlZCBsb2FkaW5nIG9yIG5vIEFqYXgKCQkJCQkgKiBzb3VyY2Ugc2luY2UgdGhlcmUgaXMgbm8gcG9pbnQgaW4gcmVhZGluZyB0aGUgRE9NIGRhdGEgaWYgd2UgYXJlIHRoZW4gZ29pbmcKCQkJCQkgKiB0byByZXBsYWNlIGl0IHdpdGggQWpheCBkYXRhCgkJCQkJICovCgkJCQkJX2ZuQWRkVHIoIG9TZXR0aW5ncywgJChvU2V0dGluZ3MublRCb2R5KS5jaGlsZHJlbigndHInKSApOwoJCQkJfQoJCQkKCQkJCS8qIENvcHkgdGhlIGRhdGEgaW5kZXggYXJyYXkgKi8KCQkJCW9TZXR0aW5ncy5haURpc3BsYXkgPSBvU2V0dGluZ3MuYWlEaXNwbGF5TWFzdGVyLnNsaWNlKCk7CgkJCQoJCQkJLyogSW5pdGlhbGlzYXRpb24gY29tcGxldGUgLSB0YWJsZSBjYW4gYmUgZHJhd24gKi8KCQkJCW9TZXR0aW5ncy5iSW5pdGlhbGlzZWQgPSB0cnVlOwoJCQkKCQkJCS8qIENoZWNrIGlmIHdlIG5lZWQgdG8gaW5pdGlhbGlzZSB0aGUgdGFibGUgKGl0IG1pZ2h0IG5vdCBoYXZlIGJlZW4gaGFuZGVkIG9mZiB0byB0aGUKCQkJCSAqIGxhbmd1YWdlIHByb2Nlc3NvcikKCQkJCSAqLwoJCQkJaWYgKCBiSW5pdEhhbmRlZE9mZiA9PT0gZmFsc2UgKSB7CgkJCQkJX2ZuSW5pdGlhbGlzZSggb1NldHRpbmdzICk7CgkJCQl9CgkJCX07CgkJCQoJCQkvKiBNdXN0IGJlIGRvbmUgYWZ0ZXIgZXZlcnl0aGluZyB3aGljaCBjYW4gYmUgb3ZlcnJpZGRlbiBieSB0aGUgc3RhdGUgc2F2aW5nISAqLwoJCQlfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCAnYW9EcmF3Q2FsbGJhY2snLCBfZm5TYXZlU3RhdGUsICdzdGF0ZV9zYXZlJyApOwoJCQkKCQkJaWYgKCBvSW5pdC5iU3RhdGVTYXZlICkKCQkJewoJCQkJZmVhdHVyZXMuYlN0YXRlU2F2ZSA9IHRydWU7CgkJCQlfZm5Mb2FkU3RhdGUoIG9TZXR0aW5ncywgb0luaXQsIGxvYWRlZEluaXQgKTsKCQkJfQoJCQllbHNlIHsKCQkJCWxvYWRlZEluaXQoKTsKCQkJfQoJCQkKCQl9ICk7CgkJX3RoYXQgPSBudWxsOwoJCXJldHVybiB0aGlzOwoJfTsKCQoJCgkvKgoJICogSXQgaXMgdXNlZnVsIHRvIGhhdmUgdmFyaWFibGVzIHdoaWNoIGFyZSBzY29wZWQgbG9jYWxseSBzbyBvbmx5IHRoZQoJICogRGF0YVRhYmxlcyBmdW5jdGlvbnMgY2FuIGFjY2VzcyB0aGVtIGFuZCB0aGV5IGRvbid0IGxlYWsgaW50byBnbG9iYWwgc3BhY2UuCgkgKiBBdCB0aGUgc2FtZSB0aW1lIHRoZXNlIGZ1bmN0aW9ucyBhcmUgb2Z0ZW4gdXNlZnVsIG92ZXIgbXVsdGlwbGUgZmlsZXMgaW4gdGhlCgkgKiBjb3JlIGFuZCBBUEksIHNvIHdlIGxpc3QsIG9yIGF0IGxlYXN0IGRvY3VtZW50LCBhbGwgdmFyaWFibGVzIHdoaWNoIGFyZSB1c2VkCgkgKiBieSBEYXRhVGFibGVzIGFzIHByaXZhdGUgdmFyaWFibGVzIGhlcmUuIFRoaXMgYWxzbyBlbnN1cmVzIHRoYXQgdGhlcmUgaXMgbm8KCSAqIGNsYXNoaW5nIG9mIHZhcmlhYmxlIG5hbWVzIGFuZCB0aGF0IHRoZXkgY2FuIGVhc2lseSByZWZlcmVuY2VkIGZvciByZXVzZS4KCSAqLwoJCgkKCS8vIERlZmluZWQgZWxzZSB3aGVyZQoJLy8gIF9zZWxlY3Rvcl9ydW4KCS8vICBfc2VsZWN0b3Jfb3B0cwoJLy8gIF9zZWxlY3Rvcl9maXJzdAoJLy8gIF9zZWxlY3Rvcl9yb3dfaW5kZXhlcwoJCgl2YXIgX2V4dDsgLy8gRGF0YVRhYmxlLmV4dAoJdmFyIF9BcGk7IC8vIERhdGFUYWJsZS5BcGkKCXZhciBfYXBpX3JlZ2lzdGVyOyAvLyBEYXRhVGFibGUuQXBpLnJlZ2lzdGVyCgl2YXIgX2FwaV9yZWdpc3RlclBsdXJhbDsgLy8gRGF0YVRhYmxlLkFwaS5yZWdpc3RlclBsdXJhbAoJCgl2YXIgX3JlX2RpYyA9IHt9OwoJdmFyIF9yZV9uZXdfbGluZXMgPSAvW1xyXG5cdTIwMjhdL2c7Cgl2YXIgX3JlX2h0bWwgPSAvPC4qPz4vZzsKCQoJLy8gVGhpcyBpcyBub3Qgc3RyaWN0IElTTzg2MDEgLSBEYXRlLnBhcnNlKCkgaXMgcXVpdGUgbGF4LCBhbHRob3VnaAoJLy8gaW1wbGVtZW50YXRpb25zIGRpZmZlciBiZXR3ZWVuIGJyb3dzZXJzLgoJdmFyIF9yZV9kYXRlID0gL15cZHsyLDR9W1wuXC9cLV1cZHsxLDJ9W1wuXC9cLV1cZHsxLDJ9KFtUIF17MX1cZHsxLDJ9WzpcLl1cZHsyfShbXC46XVxkezJ9KT8pPyQvOwoJCgkvLyBFc2NhcGUgcmVndWxhciBleHByZXNzaW9uIHNwZWNpYWwgY2hhcmFjdGVycwoJdmFyIF9yZV9lc2NhcGVfcmVnZXggPSBuZXcgUmVnRXhwKCAnKFxcJyArIFsgJy8nLCAnLicsICcqJywgJysnLCAnPycsICd8JywgJygnLCAnKScsICdbJywgJ10nLCAneycsICd9JywgJ1xcJywgJyQnLCAnXicsICctJyBdLmpvaW4oJ3xcXCcpICsgJyknLCAnZycgKTsKCQoJLy8gaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Gb3JlaWduX2V4Y2hhbmdlX21hcmtldAoJLy8gLSBcdTIwQkQgLSBSdXNzaWFuIHJ1YmxlLgoJLy8gLSBcdTIwYTkgLSBTb3V0aCBLb3JlYW4gV29uCgkvLyAtIFx1MjBCQSAtIFR1cmtpc2ggTGlyYQoJLy8gLSBcdTIwQjkgLSBJbmRpYW4gUnVwZWUKCS8vIC0gUiAtIEJyYXppbCAoUiQpIGFuZCBTb3V0aCBBZnJpY2EKCS8vIC0gZnIgLSBTd2lzcyBGcmFuYwoJLy8gLSBrciAtIFN3ZWRpc2gga3JvbmEsIE5vcndlZ2lhbiBrcm9uZSBhbmQgRGFuaXNoIGtyb25lCgkvLyAtIFx1MjAwOSBpcyB0aGluIHNwYWNlIGFuZCBcdTIwMkYgaXMgbmFycm93IG5vLWJyZWFrIHNwYWNlLCBib3RoIHVzZWQgaW4gbWFueQoJLy8gLSDJgyAtIEJpdGNvaW4KCS8vIC0gzp4gLSBFdGhlcmV1bQoJLy8gICBzdGFuZGFyZHMgYXMgdGhvdXNhbmRzIHNlcGFyYXRvcnMuCgl2YXIgX3JlX2Zvcm1hdHRlZF9udW1lcmljID0gL1snXHUwMEEwLCTCo+KCrMKlJVx1MjAwOVx1MjAyRlx1MjBCRFx1MjBhOVx1MjBCQXJma8mDzp5dL2dpOwoJCgkKCXZhciBfZW1wdHkgPSBmdW5jdGlvbiAoIGQgKSB7CgkJcmV0dXJuICFkIHx8IGQgPT09IHRydWUgfHwgZCA9PT0gJy0nID8gdHJ1ZSA6IGZhbHNlOwoJfTsKCQoJCgl2YXIgX2ludFZhbCA9IGZ1bmN0aW9uICggcyApIHsKCQl2YXIgaW50ZWdlciA9IHBhcnNlSW50KCBzLCAxMCApOwoJCXJldHVybiAhaXNOYU4oaW50ZWdlcikgJiYgaXNGaW5pdGUocykgPyBpbnRlZ2VyIDogbnVsbDsKCX07CgkKCS8vIENvbnZlcnQgZnJvbSBhIGZvcm1hdHRlZCBudW1iZXIgd2l0aCBjaGFyYWN0ZXJzIG90aGVyIHRoYW4gYC5gIGFzIHRoZQoJLy8gZGVjaW1hbCBwbGFjZSwgdG8gYSBKYXZhc2NyaXB0IG51bWJlcgoJdmFyIF9udW1Ub0RlY2ltYWwgPSBmdW5jdGlvbiAoIG51bSwgZGVjaW1hbFBvaW50ICkgewoJCS8vIENhY2hlIGNyZWF0ZWQgcmVndWxhciBleHByZXNzaW9ucyBmb3Igc3BlZWQgYXMgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgb2Z0ZW4KCQlpZiAoICEgX3JlX2RpY1sgZGVjaW1hbFBvaW50IF0gKSB7CgkJCV9yZV9kaWNbIGRlY2ltYWxQb2ludCBdID0gbmV3IFJlZ0V4cCggX2ZuRXNjYXBlUmVnZXgoIGRlY2ltYWxQb2ludCApLCAnZycgKTsKCQl9CgkJcmV0dXJuIHR5cGVvZiBudW0gPT09ICdzdHJpbmcnICYmIGRlY2ltYWxQb2ludCAhPT0gJy4nID8KCQkJbnVtLnJlcGxhY2UoIC9cLi9nLCAnJyApLnJlcGxhY2UoIF9yZV9kaWNbIGRlY2ltYWxQb2ludCBdLCAnLicgKSA6CgkJCW51bTsKCX07CgkKCQoJdmFyIF9pc051bWJlciA9IGZ1bmN0aW9uICggZCwgZGVjaW1hbFBvaW50LCBmb3JtYXR0ZWQgKSB7CgkJdmFyIHN0clR5cGUgPSB0eXBlb2YgZCA9PT0gJ3N0cmluZyc7CgkKCQkvLyBJZiBlbXB0eSByZXR1cm4gaW1tZWRpYXRlbHkgc28gdGhlcmUgbXVzdCBiZSBhIG51bWJlciBpZiBpdCBpcyBhCgkJLy8gZm9ybWF0dGVkIHN0cmluZyAodGhpcyBzdG9wcyB0aGUgc3RyaW5nICJrIiwgb3IgImtyIiwgZXRjIGJlaW5nIGRldGVjdGVkCgkJLy8gYXMgYSBmb3JtYXR0ZWQgbnVtYmVyIGZvciBjdXJyZW5jeQoJCWlmICggX2VtcHR5KCBkICkgKSB7CgkJCXJldHVybiB0cnVlOwoJCX0KCQoJCWlmICggZGVjaW1hbFBvaW50ICYmIHN0clR5cGUgKSB7CgkJCWQgPSBfbnVtVG9EZWNpbWFsKCBkLCBkZWNpbWFsUG9pbnQgKTsKCQl9CgkKCQlpZiAoIGZvcm1hdHRlZCAmJiBzdHJUeXBlICkgewoJCQlkID0gZC5yZXBsYWNlKCBfcmVfZm9ybWF0dGVkX251bWVyaWMsICcnICk7CgkJfQoJCgkJcmV0dXJuICFpc05hTiggcGFyc2VGbG9hdChkKSApICYmIGlzRmluaXRlKCBkICk7Cgl9OwoJCgkKCS8vIEEgc3RyaW5nIHdpdGhvdXQgSFRNTCBpbiBpdCBjYW4gYmUgY29uc2lkZXJlZCB0byBiZSBIVE1MIHN0aWxsCgl2YXIgX2lzSHRtbCA9IGZ1bmN0aW9uICggZCApIHsKCQlyZXR1cm4gX2VtcHR5KCBkICkgfHwgdHlwZW9mIGQgPT09ICdzdHJpbmcnOwoJfTsKCQoJCgl2YXIgX2h0bWxOdW1lcmljID0gZnVuY3Rpb24gKCBkLCBkZWNpbWFsUG9pbnQsIGZvcm1hdHRlZCApIHsKCQlpZiAoIF9lbXB0eSggZCApICkgewoJCQlyZXR1cm4gdHJ1ZTsKCQl9CgkKCQl2YXIgaHRtbCA9IF9pc0h0bWwoIGQgKTsKCQlyZXR1cm4gISBodG1sID8KCQkJbnVsbCA6CgkJCV9pc051bWJlciggX3N0cmlwSHRtbCggZCApLCBkZWNpbWFsUG9pbnQsIGZvcm1hdHRlZCApID8KCQkJCXRydWUgOgoJCQkJbnVsbDsKCX07CgkKCQoJdmFyIF9wbHVjayA9IGZ1bmN0aW9uICggYSwgcHJvcCwgcHJvcDIgKSB7CgkJdmFyIG91dCA9IFtdOwoJCXZhciBpPTAsIGllbj1hLmxlbmd0aDsKCQoJCS8vIENvdWxkIGhhdmUgdGhlIHRlc3QgaW4gdGhlIGxvb3AgZm9yIHNsaWdodGx5IHNtYWxsZXIgY29kZSwgYnV0IHNwZWVkCgkJLy8gaXMgZXNzZW50aWFsIGhlcmUKCQlpZiAoIHByb3AyICE9PSB1bmRlZmluZWQgKSB7CgkJCWZvciAoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQlpZiAoIGFbaV0gJiYgYVtpXVsgcHJvcCBdICkgewoJCQkJCW91dC5wdXNoKCBhW2ldWyBwcm9wIF1bIHByb3AyIF0gKTsKCQkJCX0KCQkJfQoJCX0KCQllbHNlIHsKCQkJZm9yICggOyBpPGllbiA7IGkrKyApIHsKCQkJCWlmICggYVtpXSApIHsKCQkJCQlvdXQucHVzaCggYVtpXVsgcHJvcCBdICk7CgkJCQl9CgkJCX0KCQl9CgkKCQlyZXR1cm4gb3V0OwoJfTsKCQoJCgkvLyBCYXNpY2FsbHkgdGhlIHNhbWUgYXMgX3BsdWNrLCBidXQgcmF0aGVyIHRoYW4gbG9vcGluZyBvdmVyIGBhYCB3ZSB1c2UgYG9yZGVyYAoJLy8gYXMgdGhlIGluZGV4ZXMgdG8gcGljayBmcm9tIGBhYAoJdmFyIF9wbHVja19vcmRlciA9IGZ1bmN0aW9uICggYSwgb3JkZXIsIHByb3AsIHByb3AyICkKCXsKCQl2YXIgb3V0ID0gW107CgkJdmFyIGk9MCwgaWVuPW9yZGVyLmxlbmd0aDsKCQoJCS8vIENvdWxkIGhhdmUgdGhlIHRlc3QgaW4gdGhlIGxvb3AgZm9yIHNsaWdodGx5IHNtYWxsZXIgY29kZSwgYnV0IHNwZWVkCgkJLy8gaXMgZXNzZW50aWFsIGhlcmUKCQlpZiAoIHByb3AyICE9PSB1bmRlZmluZWQgKSB7CgkJCWZvciAoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQlpZiAoIGFbIG9yZGVyW2ldIF1bIHByb3AgXSApIHsKCQkJCQlvdXQucHVzaCggYVsgb3JkZXJbaV0gXVsgcHJvcCBdWyBwcm9wMiBdICk7CgkJCQl9CgkJCX0KCQl9CgkJZWxzZSB7CgkJCWZvciAoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQlvdXQucHVzaCggYVsgb3JkZXJbaV0gXVsgcHJvcCBdICk7CgkJCX0KCQl9CgkKCQlyZXR1cm4gb3V0OwoJfTsKCQoJCgl2YXIgX3JhbmdlID0gZnVuY3Rpb24gKCBsZW4sIHN0YXJ0ICkKCXsKCQl2YXIgb3V0ID0gW107CgkJdmFyIGVuZDsKCQoJCWlmICggc3RhcnQgPT09IHVuZGVmaW5lZCApIHsKCQkJc3RhcnQgPSAwOwoJCQllbmQgPSBsZW47CgkJfQoJCWVsc2UgewoJCQllbmQgPSBzdGFydDsKCQkJc3RhcnQgPSBsZW47CgkJfQoJCgkJZm9yICggdmFyIGk9c3RhcnQgOyBpPGVuZCA7IGkrKyApIHsKCQkJb3V0LnB1c2goIGkgKTsKCQl9CgkKCQlyZXR1cm4gb3V0OwoJfTsKCQoJCgl2YXIgX3JlbW92ZUVtcHR5ID0gZnVuY3Rpb24gKCBhICkKCXsKCQl2YXIgb3V0ID0gW107CgkKCQlmb3IgKCB2YXIgaT0wLCBpZW49YS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHsKCQkJaWYgKCBhW2ldICkgeyAvLyBjYXJlZnVsIC0gd2lsbCByZW1vdmUgYWxsIGZhbHN5IHZhbHVlcyEKCQkJCW91dC5wdXNoKCBhW2ldICk7CgkJCX0KCQl9CgkKCQlyZXR1cm4gb3V0OwoJfTsKCQoJCgl2YXIgX3N0cmlwSHRtbCA9IGZ1bmN0aW9uICggZCApIHsKCQlyZXR1cm4gZC5yZXBsYWNlKCBfcmVfaHRtbCwgJycgKTsKCX07CgkKCQoJLyoqCgkgKiBEZXRlcm1pbmUgaWYgYWxsIHZhbHVlcyBpbiB0aGUgYXJyYXkgYXJlIHVuaXF1ZS4gVGhpcyBtZWFucyB3ZSBjYW4gc2hvcnQKCSAqIGN1dCB0aGUgX3VuaXF1ZSBtZXRob2QgYXQgdGhlIGNvc3Qgb2YgYSBzaW5nbGUgbG9vcC4gQSBzb3J0ZWQgYXJyYXkgaXMgdXNlZAoJICogdG8gZWFzaWx5IGNoZWNrIHRoZSB2YWx1ZXMuCgkgKgoJICogQHBhcmFtICB7YXJyYXl9IHNyYyBTb3VyY2UgYXJyYXkKCSAqIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgaWYgYWxsIHVuaXF1ZSwgZmFsc2Ugb3RoZXJ3aXNlCgkgKiBAaWdub3JlCgkgKi8KCXZhciBfYXJlQWxsVW5pcXVlID0gZnVuY3Rpb24gKCBzcmMgKSB7CgkJaWYgKCBzcmMubGVuZ3RoIDwgMiApIHsKCQkJcmV0dXJuIHRydWU7CgkJfQoJCgkJdmFyIHNvcnRlZCA9IHNyYy5zbGljZSgpLnNvcnQoKTsKCQl2YXIgbGFzdCA9IHNvcnRlZFswXTsKCQoJCWZvciAoIHZhciBpPTEsIGllbj1zb3J0ZWQubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCWlmICggc29ydGVkW2ldID09PSBsYXN0ICkgewoJCQkJcmV0dXJuIGZhbHNlOwoJCQl9CgkKCQkJbGFzdCA9IHNvcnRlZFtpXTsKCQl9CgkKCQlyZXR1cm4gdHJ1ZTsKCX07CgkKCQoJLyoqCgkgKiBGaW5kIHRoZSB1bmlxdWUgZWxlbWVudHMgaW4gYSBzb3VyY2UgYXJyYXkuCgkgKgoJICogQHBhcmFtICB7YXJyYXl9IHNyYyBTb3VyY2UgYXJyYXkKCSAqIEByZXR1cm4ge2FycmF5fSBBcnJheSBvZiB1bmlxdWUgaXRlbXMKCSAqIEBpZ25vcmUKCSAqLwoJdmFyIF91bmlxdWUgPSBmdW5jdGlvbiAoIHNyYyApCgl7CgkJaWYgKCBfYXJlQWxsVW5pcXVlKCBzcmMgKSApIHsKCQkJcmV0dXJuIHNyYy5zbGljZSgpOwoJCX0KCQoJCS8vIEEgZmFzdGVyIHVuaXF1ZSBtZXRob2QgaXMgdG8gdXNlIG9iamVjdCBrZXlzIHRvIGlkZW50aWZ5IHVzZWQgdmFsdWVzLAoJCS8vIGJ1dCB0aGlzIGRvZXNuJ3Qgd29yayB3aXRoIGFycmF5cyBvciBvYmplY3RzLCB3aGljaCB3ZSBtdXN0IGFsc28KCQkvLyBjb25zaWRlci4gU2VlIGpzcGVyZi5jb20vY29tcGFyZS1hcnJheS11bmlxdWUtdmVyc2lvbnMvNCBmb3IgbW9yZQoJCS8vIGluZm9ybWF0aW9uLgoJCXZhcgoJCQlvdXQgPSBbXSwKCQkJdmFsLAoJCQlpLCBpZW49c3JjLmxlbmd0aCwKCQkJaiwgaz0wOwoJCgkJYWdhaW46IGZvciAoIGk9MCA7IGk8aWVuIDsgaSsrICkgewoJCQl2YWwgPSBzcmNbaV07CgkKCQkJZm9yICggaj0wIDsgajxrIDsgaisrICkgewoJCQkJaWYgKCBvdXRbal0gPT09IHZhbCApIHsKCQkJCQljb250aW51ZSBhZ2FpbjsKCQkJCX0KCQkJfQoJCgkJCW91dC5wdXNoKCB2YWwgKTsKCQkJaysrOwoJCX0KCQoJCXJldHVybiBvdXQ7Cgl9OwoJCgkvLyBTdXJwcmlzaW5nbHkgdGhpcyBpcyBmYXN0ZXIgdGhhbiBbXS5jb25jYXQuYXBwbHkKCS8vIGh0dHBzOi8vanNwZXJmLmNvbS9mbGF0dGVuLWFuLWFycmF5LWxvb3AtdnMtcmVkdWNlLzIKCXZhciBfZmxhdHRlbiA9IGZ1bmN0aW9uIChvdXQsIHZhbCkgewoJCWlmIChBcnJheS5pc0FycmF5KHZhbCkpIHsKCQkJZm9yICh2YXIgaT0wIDsgaTx2YWwubGVuZ3RoIDsgaSsrKSB7CgkJCQlfZmxhdHRlbihvdXQsIHZhbFtpXSk7CgkJCX0KCQl9CgkJZWxzZSB7CgkJCW91dC5wdXNoKHZhbCk7CgkJfQoJICAKCQlyZXR1cm4gb3V0OwoJfQoJCgl2YXIgX2luY2x1ZGVzID0gZnVuY3Rpb24gKHNlYXJjaCwgc3RhcnQpIHsKCQlpZiAoc3RhcnQgPT09IHVuZGVmaW5lZCkgewoJCQlzdGFydCA9IDA7CgkJfQoJCgkJcmV0dXJuIHRoaXMuaW5kZXhPZihzZWFyY2gsIHN0YXJ0KSAhPT0gLTE7CQoJfTsKCQoJLy8gQXJyYXkuaXNBcnJheSBwb2x5ZmlsbC4KCS8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2lzQXJyYXkKCWlmICghIEFycmF5LmlzQXJyYXkpIHsKCSAgICBBcnJheS5pc0FycmF5ID0gZnVuY3Rpb24oYXJnKSB7CgkgICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYXJnKSA9PT0gJ1tvYmplY3QgQXJyYXldJzsKCSAgICB9OwoJfQoJCglpZiAoISBBcnJheS5wcm90b3R5cGUuaW5jbHVkZXMpIHsKCQlBcnJheS5wcm90b3R5cGUuaW5jbHVkZXMgPSBfaW5jbHVkZXM7Cgl9CgkKCS8vIC50cmltKCkgcG9seWZpbGwKCS8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL1N0cmluZy90cmltCglpZiAoIVN0cmluZy5wcm90b3R5cGUudHJpbSkgewoJICBTdHJpbmcucHJvdG90eXBlLnRyaW0gPSBmdW5jdGlvbiAoKSB7CgkgICAgcmV0dXJuIHRoaXMucmVwbGFjZSgvXltcc1x1RkVGRlx4QTBdK3xbXHNcdUZFRkZceEEwXSskL2csICcnKTsKCSAgfTsKCX0KCQoJaWYgKCEgU3RyaW5nLnByb3RvdHlwZS5pbmNsdWRlcykgewoJCVN0cmluZy5wcm90b3R5cGUuaW5jbHVkZXMgPSBfaW5jbHVkZXM7Cgl9CgkKCS8qKgoJICogRGF0YVRhYmxlcyB1dGlsaXR5IG1ldGhvZHMKCSAqIAoJICogVGhpcyBuYW1lc3BhY2UgcHJvdmlkZXMgaGVscGVyIG1ldGhvZHMgdGhhdCBEYXRhVGFibGVzIHVzZXMgaW50ZXJuYWxseSB0bwoJICogY3JlYXRlIGEgRGF0YVRhYmxlLCBidXQgd2hpY2ggYXJlIG5vdCBleGNsdXNpdmVseSB1c2VkIG9ubHkgZm9yIERhdGFUYWJsZXMuCgkgKiBUaGVzZSBtZXRob2RzIGNhbiBiZSB1c2VkIGJ5IGV4dGVuc2lvbiBhdXRob3JzIHRvIHNhdmUgdGhlIGR1cGxpY2F0aW9uIG9mCgkgKiBjb2RlLgoJICoKCSAqICBAbmFtZXNwYWNlCgkgKi8KCURhdGFUYWJsZS51dGlsID0gewoJCS8qKgoJCSAqIFRocm90dGxlIHRoZSBjYWxscyB0byBhIGZ1bmN0aW9uLiBBcmd1bWVudHMgYW5kIGNvbnRleHQgYXJlIG1haW50YWluZWQKCQkgKiBmb3IgdGhlIHRocm90dGxlZCBmdW5jdGlvbi4KCQkgKgoJCSAqIEBwYXJhbSB7ZnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZAoJCSAqIEBwYXJhbSB7aW50ZWdlcn0gZnJlcSBDYWxsIGZyZXF1ZW5jeSBpbiBtUwoJCSAqIEByZXR1cm4ge2Z1bmN0aW9ufSBXcmFwcGVkIGZ1bmN0aW9uCgkJICovCgkJdGhyb3R0bGU6IGZ1bmN0aW9uICggZm4sIGZyZXEgKSB7CgkJCXZhcgoJCQkJZnJlcXVlbmN5ID0gZnJlcSAhPT0gdW5kZWZpbmVkID8gZnJlcSA6IDIwMCwKCQkJCWxhc3QsCgkJCQl0aW1lcjsKCQoJCQlyZXR1cm4gZnVuY3Rpb24gKCkgewoJCQkJdmFyCgkJCQkJdGhhdCA9IHRoaXMsCgkJCQkJbm93ICA9ICtuZXcgRGF0ZSgpLAoJCQkJCWFyZ3MgPSBhcmd1bWVudHM7CgkKCQkJCWlmICggbGFzdCAmJiBub3cgPCBsYXN0ICsgZnJlcXVlbmN5ICkgewoJCQkJCWNsZWFyVGltZW91dCggdGltZXIgKTsKCQoJCQkJCXRpbWVyID0gc2V0VGltZW91dCggZnVuY3Rpb24gKCkgewoJCQkJCQlsYXN0ID0gdW5kZWZpbmVkOwoJCQkJCQlmbi5hcHBseSggdGhhdCwgYXJncyApOwoJCQkJCX0sIGZyZXF1ZW5jeSApOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJbGFzdCA9IG5vdzsKCQkJCQlmbi5hcHBseSggdGhhdCwgYXJncyApOwoJCQkJfQoJCQl9OwoJCX0sCgkKCQoJCS8qKgoJCSAqIEVzY2FwZSBhIHN0cmluZyBzdWNoIHRoYXQgaXQgY2FuIGJlIHVzZWQgaW4gYSByZWd1bGFyIGV4cHJlc3Npb24KCQkgKgoJCSAqICBAcGFyYW0ge3N0cmluZ30gdmFsIHN0cmluZyB0byBlc2NhcGUKCQkgKiAgQHJldHVybnMge3N0cmluZ30gZXNjYXBlZCBzdHJpbmcKCQkgKi8KCQllc2NhcGVSZWdleDogZnVuY3Rpb24gKCB2YWwgKSB7CgkJCXJldHVybiB2YWwucmVwbGFjZSggX3JlX2VzY2FwZV9yZWdleCwgJ1xcJDEnICk7CgkJfSwKCQoJCS8qKgoJCSAqIENyZWF0ZSBhIGZ1bmN0aW9uIHRoYXQgd2lsbCB3cml0ZSB0byBhIG5lc3RlZCBvYmplY3Qgb3IgYXJyYXkKCQkgKiBAcGFyYW0geyp9IHNvdXJjZSBKU09OIG5vdGF0aW9uIHN0cmluZwoJCSAqIEByZXR1cm5zIFdyaXRlIGZ1bmN0aW9uCgkJICovCgkJc2V0OiBmdW5jdGlvbiAoIHNvdXJjZSApIHsKCQkJaWYgKCAkLmlzUGxhaW5PYmplY3QoIHNvdXJjZSApICkgewoJCQkJLyogVW5saWtlIGdldCwgb25seSB0aGUgdW5kZXJzY29yZSAoZ2xvYmFsKSBvcHRpb24gaXMgdXNlZCBmb3IgZm9yCgkJCQkgKiBzZXR0aW5nIGRhdGEgc2luY2Ugd2UgZG9uJ3Qga25vdyB0aGUgdHlwZSBoZXJlLiBUaGlzIGlzIHdoeSBhbiBvYmplY3QKCQkJCSAqIG9wdGlvbiBpcyBub3QgZG9jdW1lbnRlZCBmb3IgYG1EYXRhYCAod2hpY2ggaXMgcmVhZC93cml0ZSksIGJ1dCBpdCBpcwoJCQkJICogZm9yIGBtUmVuZGVyYCB3aGljaCBpcyByZWFkIG9ubHkuCgkJCQkgKi8KCQkJCXJldHVybiBEYXRhVGFibGUudXRpbC5zZXQoIHNvdXJjZS5fICk7CgkJCX0KCQkJZWxzZSBpZiAoIHNvdXJjZSA9PT0gbnVsbCApIHsKCQkJCS8vIE5vdGhpbmcgdG8gZG8gd2hlbiB0aGUgZGF0YSBzb3VyY2UgaXMgbnVsbAoJCQkJcmV0dXJuIGZ1bmN0aW9uICgpIHt9OwoJCQl9CgkJCWVsc2UgaWYgKCB0eXBlb2Ygc291cmNlID09PSAnZnVuY3Rpb24nICkgewoJCQkJcmV0dXJuIGZ1bmN0aW9uIChkYXRhLCB2YWwsIG1ldGEpIHsKCQkJCQlzb3VyY2UoIGRhdGEsICdzZXQnLCB2YWwsIG1ldGEgKTsKCQkJCX07CgkJCX0KCQkJZWxzZSBpZiAoIHR5cGVvZiBzb3VyY2UgPT09ICdzdHJpbmcnICYmIChzb3VyY2UuaW5kZXhPZignLicpICE9PSAtMSB8fAoJCQkJCSAgc291cmNlLmluZGV4T2YoJ1snKSAhPT0gLTEgfHwgc291cmNlLmluZGV4T2YoJygnKSAhPT0gLTEpICkKCQkJewoJCQkJLy8gTGlrZSB0aGUgZ2V0LCB3ZSBuZWVkIHRvIGdldCBkYXRhIGZyb20gYSBuZXN0ZWQgb2JqZWN0CgkJCQl2YXIgc2V0RGF0YSA9IGZ1bmN0aW9uIChkYXRhLCB2YWwsIHNyYykgewoJCQkJCXZhciBhID0gX2ZuU3BsaXRPYmpOb3RhdGlvbiggc3JjICksIGI7CgkJCQkJdmFyIGFMYXN0ID0gYVthLmxlbmd0aC0xXTsKCQkJCQl2YXIgYXJyYXlOb3RhdGlvbiwgZnVuY05vdGF0aW9uLCBvLCBpbm5lclNyYzsKCQkKCQkJCQlmb3IgKCB2YXIgaT0wLCBpTGVuPWEubGVuZ3RoLTEgOyBpPGlMZW4gOyBpKysgKSB7CgkJCQkJCS8vIFByb3RlY3QgYWdhaW5zdCBwcm90b3R5cGUgcG9sbHV0aW9uCgkJCQkJCWlmIChhW2ldID09PSAnX19wcm90b19fJyB8fCBhW2ldID09PSAnY29uc3RydWN0b3InKSB7CgkJCQkJCQl0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBzZXQgcHJvdG90eXBlIHZhbHVlcycpOwoJCQkJCQl9CgkJCgkJCQkJCS8vIENoZWNrIGlmIHdlIGFyZSBkZWFsaW5nIHdpdGggYW4gYXJyYXkgbm90YXRpb24gcmVxdWVzdAoJCQkJCQlhcnJheU5vdGF0aW9uID0gYVtpXS5tYXRjaChfX3JlQXJyYXkpOwoJCQkJCQlmdW5jTm90YXRpb24gPSBhW2ldLm1hdGNoKF9fcmVGbik7CgkJCgkJCQkJCWlmICggYXJyYXlOb3RhdGlvbiApIHsKCQkJCQkJCWFbaV0gPSBhW2ldLnJlcGxhY2UoX19yZUFycmF5LCAnJyk7CgkJCQkJCQlkYXRhWyBhW2ldIF0gPSBbXTsKCQkKCQkJCQkJCS8vIEdldCB0aGUgcmVtYWluZGVyIG9mIHRoZSBuZXN0ZWQgb2JqZWN0IHRvIHNldCBzbyB3ZSBjYW4gcmVjdXJzZQoJCQkJCQkJYiA9IGEuc2xpY2UoKTsKCQkJCQkJCWIuc3BsaWNlKCAwLCBpKzEgKTsKCQkJCQkJCWlubmVyU3JjID0gYi5qb2luKCcuJyk7CgkJCgkJCQkJCQkvLyBUcmF2ZXJzZSBlYWNoIGVudHJ5IGluIHRoZSBhcnJheSBzZXR0aW5nIHRoZSBwcm9wZXJ0aWVzIHJlcXVlc3RlZAoJCQkJCQkJaWYgKCBBcnJheS5pc0FycmF5KCB2YWwgKSApIHsKCQkJCQkJCQlmb3IgKCB2YXIgaj0wLCBqTGVuPXZhbC5sZW5ndGggOyBqPGpMZW4gOyBqKysgKSB7CgkJCQkJCQkJCW8gPSB7fTsKCQkJCQkJCQkJc2V0RGF0YSggbywgdmFsW2pdLCBpbm5lclNyYyApOwoJCQkJCQkJCQlkYXRhWyBhW2ldIF0ucHVzaCggbyApOwoJCQkJCQkJCX0KCQkJCQkJCX0KCQkJCQkJCWVsc2UgewoJCQkJCQkJCS8vIFdlJ3ZlIGJlZW4gYXNrZWQgdG8gc2F2ZSBkYXRhIHRvIGFuIGFycmF5LCBidXQgaXQKCQkJCQkJCQkvLyBpc24ndCBhcnJheSBkYXRhIHRvIGJlIHNhdmVkLiBCZXN0IHRoYXQgY2FuIGJlIGRvbmUKCQkJCQkJCQkvLyBpcyB0byBqdXN0IHNhdmUgdGhlIHZhbHVlLgoJCQkJCQkJCWRhdGFbIGFbaV0gXSA9IHZhbDsKCQkJCQkJCX0KCQkKCQkJCQkJCS8vIFRoZSBpbm5lciBjYWxsIHRvIHNldERhdGEgaGFzIGFscmVhZHkgdHJhdmVyc2VkIHRocm91Z2ggdGhlIHJlbWFpbmRlcgoJCQkJCQkJLy8gb2YgdGhlIHNvdXJjZSBhbmQgaGFzIHNldCB0aGUgZGF0YSwgdGh1cyB3ZSBjYW4gZXhpdCBoZXJlCgkJCQkJCQlyZXR1cm47CgkJCQkJCX0KCQkJCQkJZWxzZSBpZiAoIGZ1bmNOb3RhdGlvbiApIHsKCQkJCQkJCS8vIEZ1bmN0aW9uIGNhbGwKCQkJCQkJCWFbaV0gPSBhW2ldLnJlcGxhY2UoX19yZUZuLCAnJyk7CgkJCQkJCQlkYXRhID0gZGF0YVsgYVtpXSBdKCB2YWwgKTsKCQkJCQkJfQoJCQoJCQkJCQkvLyBJZiB0aGUgbmVzdGVkIG9iamVjdCBkb2Vzbid0IGN1cnJlbnRseSBleGlzdCAtIHNpbmNlIHdlIGFyZQoJCQkJCQkvLyB0cnlpbmcgdG8gc2V0IHRoZSB2YWx1ZSAtIGNyZWF0ZSBpdAoJCQkJCQlpZiAoIGRhdGFbIGFbaV0gXSA9PT0gbnVsbCB8fCBkYXRhWyBhW2ldIF0gPT09IHVuZGVmaW5lZCApIHsKCQkJCQkJCWRhdGFbIGFbaV0gXSA9IHt9OwoJCQkJCQl9CgkJCQkJCWRhdGEgPSBkYXRhWyBhW2ldIF07CgkJCQkJfQoJCQoJCQkJCS8vIExhc3QgaXRlbSBpbiB0aGUgaW5wdXQgLSBpLmUsIHRoZSBhY3R1YWwgc2V0CgkJCQkJaWYgKCBhTGFzdC5tYXRjaChfX3JlRm4gKSApIHsKCQkJCQkJLy8gRnVuY3Rpb24gY2FsbAoJCQkJCQlkYXRhID0gZGF0YVsgYUxhc3QucmVwbGFjZShfX3JlRm4sICcnKSBdKCB2YWwgKTsKCQkJCQl9CgkJCQkJZWxzZSB7CgkJCQkJCS8vIElmIGFycmF5IG5vdGF0aW9uIGlzIHVzZWQsIHdlIGp1c3Qgd2FudCB0byBzdHJpcCBpdCBhbmQgdXNlIHRoZSBwcm9wZXJ0eSBuYW1lCgkJCQkJCS8vIGFuZCBhc3NpZ24gdGhlIHZhbHVlLiBJZiBpdCBpc24ndCB1c2VkLCB0aGVuIHdlIGdldCB0aGUgcmVzdWx0IHdlIHdhbnQgYW55d2F5CgkJCQkJCWRhdGFbIGFMYXN0LnJlcGxhY2UoX19yZUFycmF5LCAnJykgXSA9IHZhbDsKCQkJCQl9CgkJCQl9OwoJCQoJCQkJcmV0dXJuIGZ1bmN0aW9uIChkYXRhLCB2YWwpIHsgLy8gbWV0YSBpcyBhbHNvIHBhc3NlZCBpbiwgYnV0IG5vdCB1c2VkCgkJCQkJcmV0dXJuIHNldERhdGEoIGRhdGEsIHZhbCwgc291cmNlICk7CgkJCQl9OwoJCQl9CgkJCWVsc2UgewoJCQkJLy8gQXJyYXkgb3IgZmxhdCBvYmplY3QgbWFwcGluZwoJCQkJcmV0dXJuIGZ1bmN0aW9uIChkYXRhLCB2YWwpIHsgLy8gbWV0YSBpcyBhbHNvIHBhc3NlZCBpbiwgYnV0IG5vdCB1c2VkCgkJCQkJZGF0YVtzb3VyY2VdID0gdmFsOwoJCQkJfTsKCQkJfQoJCX0sCgkKCQkvKioKCQkgKiBDcmVhdGUgYSBmdW5jdGlvbiB0aGF0IHdpbGwgcmVhZCBuZXN0ZWQgb2JqZWN0cyBmcm9tIGFycmF5cywgYmFzZWQgb24gSlNPTiBub3RhdGlvbgoJCSAqIEBwYXJhbSB7Kn0gc291cmNlIEpTT04gbm90YXRpb24gc3RyaW5nCgkJICogQHJldHVybnMgVmFsdWUgcmVhZAoJCSAqLwoJCWdldDogZnVuY3Rpb24gKCBzb3VyY2UgKSB7CgkJCWlmICggJC5pc1BsYWluT2JqZWN0KCBzb3VyY2UgKSApIHsKCQkJCS8vIEJ1aWxkIGFuIG9iamVjdCBvZiBnZXQgZnVuY3Rpb25zLCBhbmQgd3JhcCB0aGVtIGluIGEgc2luZ2xlIGNhbGwKCQkJCXZhciBvID0ge307CgkJCQkkLmVhY2goIHNvdXJjZSwgZnVuY3Rpb24gKGtleSwgdmFsKSB7CgkJCQkJaWYgKCB2YWwgKSB7CgkJCQkJCW9ba2V5XSA9IERhdGFUYWJsZS51dGlsLmdldCggdmFsICk7CgkJCQkJfQoJCQkJfSApOwoJCQoJCQkJcmV0dXJuIGZ1bmN0aW9uIChkYXRhLCB0eXBlLCByb3csIG1ldGEpIHsKCQkJCQl2YXIgdCA9IG9bdHlwZV0gfHwgby5fOwoJCQkJCXJldHVybiB0ICE9PSB1bmRlZmluZWQgPwoJCQkJCQl0KGRhdGEsIHR5cGUsIHJvdywgbWV0YSkgOgoJCQkJCQlkYXRhOwoJCQkJfTsKCQkJfQoJCQllbHNlIGlmICggc291cmNlID09PSBudWxsICkgewoJCQkJLy8gR2l2ZSBhbiBlbXB0eSBzdHJpbmcgZm9yIHJlbmRlcmluZyAvIHNvcnRpbmcgZXRjCgkJCQlyZXR1cm4gZnVuY3Rpb24gKGRhdGEpIHsgLy8gdHlwZSwgcm93IGFuZCBtZXRhIGFsc28gcGFzc2VkLCBidXQgbm90IHVzZWQKCQkJCQlyZXR1cm4gZGF0YTsKCQkJCX07CgkJCX0KCQkJZWxzZSBpZiAoIHR5cGVvZiBzb3VyY2UgPT09ICdmdW5jdGlvbicgKSB7CgkJCQlyZXR1cm4gZnVuY3Rpb24gKGRhdGEsIHR5cGUsIHJvdywgbWV0YSkgewoJCQkJCXJldHVybiBzb3VyY2UoIGRhdGEsIHR5cGUsIHJvdywgbWV0YSApOwoJCQkJfTsKCQkJfQoJCQllbHNlIGlmICggdHlwZW9mIHNvdXJjZSA9PT0gJ3N0cmluZycgJiYgKHNvdXJjZS5pbmRleE9mKCcuJykgIT09IC0xIHx8CgkJCQkJICBzb3VyY2UuaW5kZXhPZignWycpICE9PSAtMSB8fCBzb3VyY2UuaW5kZXhPZignKCcpICE9PSAtMSkgKQoJCQl7CgkJCQkvKiBJZiB0aGVyZSBpcyBhIC4gaW4gdGhlIHNvdXJjZSBzdHJpbmcgdGhlbiB0aGUgZGF0YSBzb3VyY2UgaXMgaW4gYQoJCQkJICogbmVzdGVkIG9iamVjdCBzbyB3ZSBsb29wIG92ZXIgdGhlIGRhdGEgZm9yIGVhY2ggbGV2ZWwgdG8gZ2V0IHRoZSBuZXh0CgkJCQkgKiBsZXZlbCBkb3duLiBPbiBlYWNoIGxvb3Agd2UgdGVzdCBmb3IgdW5kZWZpbmVkLCBhbmQgaWYgZm91bmQgaW1tZWRpYXRlbHkKCQkJCSAqIHJldHVybi4gVGhpcyBhbGxvd3MgZW50aXJlIG9iamVjdHMgdG8gYmUgbWlzc2luZyBhbmQgc0RlZmF1bHRDb250ZW50IHRvCgkJCQkgKiBiZSB1c2VkIGlmIGRlZmluZWQsIHJhdGhlciB0aGFuIHRocm93aW5nIGFuIGVycm9yCgkJCQkgKi8KCQkJCXZhciBmZXRjaERhdGEgPSBmdW5jdGlvbiAoZGF0YSwgdHlwZSwgc3JjKSB7CgkJCQkJdmFyIGFycmF5Tm90YXRpb24sIGZ1bmNOb3RhdGlvbiwgb3V0LCBpbm5lclNyYzsKCQkKCQkJCQlpZiAoIHNyYyAhPT0gIiIgKSB7CgkJCQkJCXZhciBhID0gX2ZuU3BsaXRPYmpOb3RhdGlvbiggc3JjICk7CgkJCgkJCQkJCWZvciAoIHZhciBpPTAsIGlMZW49YS5sZW5ndGggOyBpPGlMZW4gOyBpKysgKSB7CgkJCQkJCQkvLyBDaGVjayBpZiB3ZSBhcmUgZGVhbGluZyB3aXRoIHNwZWNpYWwgbm90YXRpb24KCQkJCQkJCWFycmF5Tm90YXRpb24gPSBhW2ldLm1hdGNoKF9fcmVBcnJheSk7CgkJCQkJCQlmdW5jTm90YXRpb24gPSBhW2ldLm1hdGNoKF9fcmVGbik7CgkJCgkJCQkJCQlpZiAoIGFycmF5Tm90YXRpb24gKSB7CgkJCQkJCQkJLy8gQXJyYXkgbm90YXRpb24KCQkJCQkJCQlhW2ldID0gYVtpXS5yZXBsYWNlKF9fcmVBcnJheSwgJycpOwoJCQoJCQkJCQkJCS8vIENvbmRpdGlvbiBhbGxvd3Mgc2ltcGx5IFtdIHRvIGJlIHBhc3NlZCBpbgoJCQkJCQkJCWlmICggYVtpXSAhPT0gIiIgKSB7CgkJCQkJCQkJCWRhdGEgPSBkYXRhWyBhW2ldIF07CgkJCQkJCQkJfQoJCQkJCQkJCW91dCA9IFtdOwoJCQoJCQkJCQkJCS8vIEdldCB0aGUgcmVtYWluZGVyIG9mIHRoZSBuZXN0ZWQgb2JqZWN0IHRvIGdldAoJCQkJCQkJCWEuc3BsaWNlKCAwLCBpKzEgKTsKCQkJCQkJCQlpbm5lclNyYyA9IGEuam9pbignLicpOwoJCQoJCQkJCQkJCS8vIFRyYXZlcnNlIGVhY2ggZW50cnkgaW4gdGhlIGFycmF5IGdldHRpbmcgdGhlIHByb3BlcnRpZXMgcmVxdWVzdGVkCgkJCQkJCQkJaWYgKCBBcnJheS5pc0FycmF5KCBkYXRhICkgKSB7CgkJCQkJCQkJCWZvciAoIHZhciBqPTAsIGpMZW49ZGF0YS5sZW5ndGggOyBqPGpMZW4gOyBqKysgKSB7CgkJCQkJCQkJCQlvdXQucHVzaCggZmV0Y2hEYXRhKCBkYXRhW2pdLCB0eXBlLCBpbm5lclNyYyApICk7CgkJCQkJCQkJCX0KCQkJCQkJCQl9CgkJCgkJCQkJCQkJLy8gSWYgYSBzdHJpbmcgaXMgZ2l2ZW4gaW4gYmV0d2VlbiB0aGUgYXJyYXkgbm90YXRpb24gaW5kaWNhdG9ycywgdGhhdAoJCQkJCQkJCS8vIGlzIHVzZWQgdG8gam9pbiB0aGUgc3RyaW5ncyB0b2dldGhlciwgb3RoZXJ3aXNlIGFuIGFycmF5IGlzIHJldHVybmVkCgkJCQkJCQkJdmFyIGpvaW4gPSBhcnJheU5vdGF0aW9uWzBdLnN1YnN0cmluZygxLCBhcnJheU5vdGF0aW9uWzBdLmxlbmd0aC0xKTsKCQkJCQkJCQlkYXRhID0gKGpvaW49PT0iIikgPyBvdXQgOiBvdXQuam9pbihqb2luKTsKCQkKCQkJCQkJCQkvLyBUaGUgaW5uZXIgY2FsbCB0byBmZXRjaERhdGEgaGFzIGFscmVhZHkgdHJhdmVyc2VkIHRocm91Z2ggdGhlIHJlbWFpbmRlcgoJCQkJCQkJCS8vIG9mIHRoZSBzb3VyY2UgcmVxdWVzdGVkLCBzbyB3ZSBleGl0IGZyb20gdGhlIGxvb3AKCQkJCQkJCQlicmVhazsKCQkJCQkJCX0KCQkJCQkJCWVsc2UgaWYgKCBmdW5jTm90YXRpb24gKSB7CgkJCQkJCQkJLy8gRnVuY3Rpb24gY2FsbAoJCQkJCQkJCWFbaV0gPSBhW2ldLnJlcGxhY2UoX19yZUZuLCAnJyk7CgkJCQkJCQkJZGF0YSA9IGRhdGFbIGFbaV0gXSgpOwoJCQkJCQkJCWNvbnRpbnVlOwoJCQkJCQkJfQoJCQoJCQkJCQkJaWYgKCBkYXRhID09PSBudWxsIHx8IGRhdGFbIGFbaV0gXSA9PT0gdW5kZWZpbmVkICkgewoJCQkJCQkJCXJldHVybiB1bmRlZmluZWQ7CgkJCQkJCQl9CgkKCQkJCQkJCWRhdGEgPSBkYXRhWyBhW2ldIF07CgkJCQkJCX0KCQkJCQl9CgkJCgkJCQkJcmV0dXJuIGRhdGE7CgkJCQl9OwoJCQoJCQkJcmV0dXJuIGZ1bmN0aW9uIChkYXRhLCB0eXBlKSB7IC8vIHJvdyBhbmQgbWV0YSBhbHNvIHBhc3NlZCwgYnV0IG5vdCB1c2VkCgkJCQkJcmV0dXJuIGZldGNoRGF0YSggZGF0YSwgdHlwZSwgc291cmNlICk7CgkJCQl9OwoJCQl9CgkJCWVsc2UgewoJCQkJLy8gQXJyYXkgb3IgZmxhdCBvYmplY3QgbWFwcGluZwoJCQkJcmV0dXJuIGZ1bmN0aW9uIChkYXRhLCB0eXBlKSB7IC8vIHJvdyBhbmQgbWV0YSBhbHNvIHBhc3NlZCwgYnV0IG5vdCB1c2VkCgkJCQkJcmV0dXJuIGRhdGFbc291cmNlXTsKCQkJCX07CgkJCX0KCQl9Cgl9OwoJCgkKCQoJLyoqCgkgKiBDcmVhdGUgYSBtYXBwaW5nIG9iamVjdCB0aGF0IGFsbG93cyBjYW1lbCBjYXNlIHBhcmFtZXRlcnMgdG8gYmUgbG9va2VkIHVwCgkgKiBmb3IgdGhlaXIgSHVuZ2FyaWFuIGNvdW50ZXJwYXJ0cy4gVGhlIG1hcHBpbmcgaXMgc3RvcmVkIGluIGEgcHJpdmF0ZQoJICogcGFyYW1ldGVyIGNhbGxlZCBgX2h1bmdhcmlhbk1hcGAgd2hpY2ggY2FuIGJlIGFjY2Vzc2VkIG9uIHRoZSBzb3VyY2Ugb2JqZWN0LgoJICogIEBwYXJhbSB7b2JqZWN0fSBvCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkh1bmdhcmlhbk1hcCAoIG8gKQoJewoJCXZhcgoJCQlodW5nYXJpYW4gPSAnYSBhYSBhaSBhbyBhcyBiIGZuIGkgbSBvIHMgJywKCQkJbWF0Y2gsCgkJCW5ld0tleSwKCQkJbWFwID0ge307CgkKCQkkLmVhY2goIG8sIGZ1bmN0aW9uIChrZXksIHZhbCkgewoJCQltYXRjaCA9IGtleS5tYXRjaCgvXihbXkEtWl0rPykoW0EtWl0pLyk7CgkKCQkJaWYgKCBtYXRjaCAmJiBodW5nYXJpYW4uaW5kZXhPZihtYXRjaFsxXSsnICcpICE9PSAtMSApCgkJCXsKCQkJCW5ld0tleSA9IGtleS5yZXBsYWNlKCBtYXRjaFswXSwgbWF0Y2hbMl0udG9Mb3dlckNhc2UoKSApOwoJCQkJbWFwWyBuZXdLZXkgXSA9IGtleTsKCQoJCQkJaWYgKCBtYXRjaFsxXSA9PT0gJ28nICkKCQkJCXsKCQkJCQlfZm5IdW5nYXJpYW5NYXAoIG9ba2V5XSApOwoJCQkJfQoJCQl9CgkJfSApOwoJCgkJby5faHVuZ2FyaWFuTWFwID0gbWFwOwoJfQoJCgkKCS8qKgoJICogQ29udmVydCBmcm9tIGNhbWVsIGNhc2UgcGFyYW1ldGVycyB0byBIdW5nYXJpYW4sIGJhc2VkIG9uIGEgSHVuZ2FyaWFuIG1hcAoJICogY3JlYXRlZCBieSBfZm5IdW5nYXJpYW5NYXAuCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNyYyBUaGUgbW9kZWwgb2JqZWN0IHdoaWNoIGhvbGRzIGFsbCBwYXJhbWV0ZXJzIHRoYXQgY2FuIGJlCgkgKiAgICBtYXBwZWQuCgkgKiAgQHBhcmFtIHtvYmplY3R9IHVzZXIgVGhlIG9iamVjdCB0byBjb252ZXJ0IGZyb20gY2FtZWwgY2FzZSB0byBIdW5nYXJpYW4uCgkgKiAgQHBhcmFtIHtib29sZWFufSBmb3JjZSBXaGVuIHNldCB0byBgdHJ1ZWAsIHByb3BlcnRpZXMgd2hpY2ggYWxyZWFkeSBoYXZlIGEKCSAqICAgIEh1bmdhcmlhbiB2YWx1ZSBpbiB0aGUgYHVzZXJgIG9iamVjdCB3aWxsIGJlIG92ZXJ3cml0dGVuLiBPdGhlcndpc2UgdGhleQoJICogICAgd29uJ3QgYmUuCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkNhbWVsVG9IdW5nYXJpYW4gKCBzcmMsIHVzZXIsIGZvcmNlICkKCXsKCQlpZiAoICEgc3JjLl9odW5nYXJpYW5NYXAgKSB7CgkJCV9mbkh1bmdhcmlhbk1hcCggc3JjICk7CgkJfQoJCgkJdmFyIGh1bmdhcmlhbktleTsKCQoJCSQuZWFjaCggdXNlciwgZnVuY3Rpb24gKGtleSwgdmFsKSB7CgkJCWh1bmdhcmlhbktleSA9IHNyYy5faHVuZ2FyaWFuTWFwWyBrZXkgXTsKCQoJCQlpZiAoIGh1bmdhcmlhbktleSAhPT0gdW5kZWZpbmVkICYmIChmb3JjZSB8fCB1c2VyW2h1bmdhcmlhbktleV0gPT09IHVuZGVmaW5lZCkgKQoJCQl7CgkJCQkvLyBGb3Igb2JqZWN0cywgd2UgbmVlZCB0byBidXp6IGRvd24gaW50byB0aGUgb2JqZWN0IHRvIGNvcHkgcGFyYW1ldGVycwoJCQkJaWYgKCBodW5nYXJpYW5LZXkuY2hhckF0KDApID09PSAnbycgKQoJCQkJewoJCQkJCS8vIENvcHkgdGhlIGNhbWVsQ2FzZSBvcHRpb25zIG92ZXIgdG8gdGhlIGh1bmdhcmlhbgoJCQkJCWlmICggISB1c2VyWyBodW5nYXJpYW5LZXkgXSApIHsKCQkJCQkJdXNlclsgaHVuZ2FyaWFuS2V5IF0gPSB7fTsKCQkJCQl9CgkJCQkJJC5leHRlbmQoIHRydWUsIHVzZXJbaHVuZ2FyaWFuS2V5XSwgdXNlcltrZXldICk7CgkKCQkJCQlfZm5DYW1lbFRvSHVuZ2FyaWFuKCBzcmNbaHVuZ2FyaWFuS2V5XSwgdXNlcltodW5nYXJpYW5LZXldLCBmb3JjZSApOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJdXNlcltodW5nYXJpYW5LZXldID0gdXNlclsga2V5IF07CgkJCQl9CgkJCX0KCQl9ICk7Cgl9CgkKCQoJLyoqCgkgKiBMYW5ndWFnZSBjb21wYXRpYmlsaXR5IC0gd2hlbiBjZXJ0YWluIG9wdGlvbnMgYXJlIGdpdmVuLCBhbmQgb3RoZXJzIGFyZW4ndCwgd2UKCSAqIG5lZWQgdG8gZHVwbGljYXRlIHRoZSB2YWx1ZXMgb3ZlciwgaW4gb3JkZXIgdG8gcHJvdmlkZSBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eQoJICogd2l0aCBvbGRlciBsYW5ndWFnZSBmaWxlcy4KCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkxhbmd1YWdlQ29tcGF0KCBsYW5nICkKCXsKCQkvLyBOb3RlIHRoZSB1c2Ugb2YgdGhlIEh1bmdhcmlhbiBub3RhdGlvbiBmb3IgdGhlIHBhcmFtZXRlcnMgaW4gdGhpcyBtZXRob2QgYXMKCQkvLyB0aGlzIGlzIGNhbGxlZCBhZnRlciB0aGUgbWFwcGluZyBvZiBjYW1lbENhc2UgdG8gSHVuZ2FyaWFuCgkJdmFyIGRlZmF1bHRzID0gRGF0YVRhYmxlLmRlZmF1bHRzLm9MYW5ndWFnZTsKCQoJCS8vIERlZmF1bHQgbWFwcGluZwoJCXZhciBkZWZhdWx0RGVjaW1hbCA9IGRlZmF1bHRzLnNEZWNpbWFsOwoJCWlmICggZGVmYXVsdERlY2ltYWwgKSB7CgkJCV9hZGROdW1lcmljU29ydCggZGVmYXVsdERlY2ltYWwgKTsKCQl9CgkKCQlpZiAoIGxhbmcgKSB7CgkJCXZhciB6ZXJvUmVjb3JkcyA9IGxhbmcuc1plcm9SZWNvcmRzOwoJCgkJCS8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IC0gaWYgdGhlcmUgaXMgbm8gc0VtcHR5VGFibGUgZ2l2ZW4sIHRoZW4gdXNlIHRoZSBzYW1lIGFzCgkJCS8vIHNaZXJvUmVjb3JkcyAtIGFzc3VtaW5nIHRoYXQgaXMgZ2l2ZW4uCgkJCWlmICggISBsYW5nLnNFbXB0eVRhYmxlICYmIHplcm9SZWNvcmRzICYmCgkJCQlkZWZhdWx0cy5zRW1wdHlUYWJsZSA9PT0gIk5vIGRhdGEgYXZhaWxhYmxlIGluIHRhYmxlIiApCgkJCXsKCQkJCV9mbk1hcCggbGFuZywgbGFuZywgJ3NaZXJvUmVjb3JkcycsICdzRW1wdHlUYWJsZScgKTsKCQkJfQoJCgkJCS8vIExpa2V3aXNlIHdpdGggbG9hZGluZyByZWNvcmRzCgkJCWlmICggISBsYW5nLnNMb2FkaW5nUmVjb3JkcyAmJiB6ZXJvUmVjb3JkcyAmJgoJCQkJZGVmYXVsdHMuc0xvYWRpbmdSZWNvcmRzID09PSAiTG9hZGluZy4uLiIgKQoJCQl7CgkJCQlfZm5NYXAoIGxhbmcsIGxhbmcsICdzWmVyb1JlY29yZHMnLCAnc0xvYWRpbmdSZWNvcmRzJyApOwoJCQl9CgkKCQkJLy8gT2xkIHBhcmFtZXRlciBuYW1lIG9mIHRoZSB0aG91c2FuZHMgc2VwYXJhdG9yIG1hcHBlZCBvbnRvIHRoZSBuZXcKCQkJaWYgKCBsYW5nLnNJbmZvVGhvdXNhbmRzICkgewoJCQkJbGFuZy5zVGhvdXNhbmRzID0gbGFuZy5zSW5mb1Rob3VzYW5kczsKCQkJfQoJCgkJCXZhciBkZWNpbWFsID0gbGFuZy5zRGVjaW1hbDsKCQkJaWYgKCBkZWNpbWFsICYmIGRlZmF1bHREZWNpbWFsICE9PSBkZWNpbWFsICkgewoJCQkJX2FkZE51bWVyaWNTb3J0KCBkZWNpbWFsICk7CgkJCX0KCQl9Cgl9CgkKCQoJLyoqCgkgKiBNYXAgb25lIHBhcmFtZXRlciBvbnRvIGFub3RoZXIKCSAqICBAcGFyYW0ge29iamVjdH0gbyBPYmplY3QgdG8gbWFwCgkgKiAgQHBhcmFtIHsqfSBrbmV3IFRoZSBuZXcgcGFyYW1ldGVyIG5hbWUKCSAqICBAcGFyYW0geyp9IG9sZCBUaGUgb2xkIHBhcmFtZXRlciBuYW1lCgkgKi8KCXZhciBfZm5Db21wYXRNYXAgPSBmdW5jdGlvbiAoIG8sIGtuZXcsIG9sZCApIHsKCQlpZiAoIG9bIGtuZXcgXSAhPT0gdW5kZWZpbmVkICkgewoJCQlvWyBvbGQgXSA9IG9bIGtuZXcgXTsKCQl9Cgl9OwoJCgkKCS8qKgoJICogUHJvdmlkZSBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBmb3IgdGhlIG1haW4gRFQgb3B0aW9ucy4gTm90ZSB0aGF0IHRoZSBuZXcKCSAqIG9wdGlvbnMgYXJlIG1hcHBlZCBvbnRvIHRoZSBvbGQgcGFyYW1ldGVycywgc28gdGhpcyBpcyBhbiBleHRlcm5hbCBpbnRlcmZhY2UKCSAqIGNoYW5nZSBvbmx5LgoJICogIEBwYXJhbSB7b2JqZWN0fSBpbml0IE9iamVjdCB0byBtYXAKCSAqLwoJZnVuY3Rpb24gX2ZuQ29tcGF0T3B0cyAoIGluaXQgKQoJewoJCV9mbkNvbXBhdE1hcCggaW5pdCwgJ29yZGVyaW5nJywgICAgICAnYlNvcnQnICk7CgkJX2ZuQ29tcGF0TWFwKCBpbml0LCAnb3JkZXJNdWx0aScsICAgICdiU29ydE11bHRpJyApOwoJCV9mbkNvbXBhdE1hcCggaW5pdCwgJ29yZGVyQ2xhc3NlcycsICAnYlNvcnRDbGFzc2VzJyApOwoJCV9mbkNvbXBhdE1hcCggaW5pdCwgJ29yZGVyQ2VsbHNUb3AnLCAnYlNvcnRDZWxsc1RvcCcgKTsKCQlfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlcicsICAgICAgICAgJ2FhU29ydGluZycgKTsKCQlfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlckZpeGVkJywgICAgJ2FhU29ydGluZ0ZpeGVkJyApOwoJCV9mbkNvbXBhdE1hcCggaW5pdCwgJ3BhZ2luZycsICAgICAgICAnYlBhZ2luYXRlJyApOwoJCV9mbkNvbXBhdE1hcCggaW5pdCwgJ3BhZ2luZ1R5cGUnLCAgICAnc1BhZ2luYXRpb25UeXBlJyApOwoJCV9mbkNvbXBhdE1hcCggaW5pdCwgJ3BhZ2VMZW5ndGgnLCAgICAnaURpc3BsYXlMZW5ndGgnICk7CgkJX2ZuQ29tcGF0TWFwKCBpbml0LCAnc2VhcmNoaW5nJywgICAgICdiRmlsdGVyJyApOwoJCgkJLy8gQm9vbGVhbiBpbml0aWFsaXNhdGlvbiBvZiB4LXNjcm9sbGluZwoJCWlmICggdHlwZW9mIGluaXQuc1Njcm9sbFggPT09ICdib29sZWFuJyApIHsKCQkJaW5pdC5zU2Nyb2xsWCA9IGluaXQuc1Njcm9sbFggPyAnMTAwJScgOiAnJzsKCQl9CgkJaWYgKCB0eXBlb2YgaW5pdC5zY3JvbGxYID09PSAnYm9vbGVhbicgKSB7CgkJCWluaXQuc2Nyb2xsWCA9IGluaXQuc2Nyb2xsWCA/ICcxMDAlJyA6ICcnOwoJCX0KCQoJCS8vIENvbHVtbiBzZWFyY2ggb2JqZWN0cyBhcmUgaW4gYW4gYXJyYXksIHNvIGl0IG5lZWRzIHRvIGJlIGNvbnZlcnRlZAoJCS8vIGVsZW1lbnQgYnkgZWxlbWVudAoJCXZhciBzZWFyY2hDb2xzID0gaW5pdC5hb1NlYXJjaENvbHM7CgkKCQlpZiAoIHNlYXJjaENvbHMgKSB7CgkJCWZvciAoIHZhciBpPTAsIGllbj1zZWFyY2hDb2xzLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJaWYgKCBzZWFyY2hDb2xzW2ldICkgewoJCQkJCV9mbkNhbWVsVG9IdW5nYXJpYW4oIERhdGFUYWJsZS5tb2RlbHMub1NlYXJjaCwgc2VhcmNoQ29sc1tpXSApOwoJCQkJfQoJCQl9CgkJfQoJfQoJCgkKCS8qKgoJICogUHJvdmlkZSBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBmb3IgY29sdW1uIG9wdGlvbnMuIE5vdGUgdGhhdCB0aGUgbmV3IG9wdGlvbnMKCSAqIGFyZSBtYXBwZWQgb250byB0aGUgb2xkIHBhcmFtZXRlcnMsIHNvIHRoaXMgaXMgYW4gZXh0ZXJuYWwgaW50ZXJmYWNlIGNoYW5nZQoJICogb25seS4KCSAqICBAcGFyYW0ge29iamVjdH0gaW5pdCBPYmplY3QgdG8gbWFwCgkgKi8KCWZ1bmN0aW9uIF9mbkNvbXBhdENvbHMgKCBpbml0ICkKCXsKCQlfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlcmFibGUnLCAgICAgJ2JTb3J0YWJsZScgKTsKCQlfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlckRhdGEnLCAgICAgJ2FEYXRhU29ydCcgKTsKCQlfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlclNlcXVlbmNlJywgJ2FzU29ydGluZycgKTsKCQlfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlckRhdGFUeXBlJywgJ3NvcnREYXRhVHlwZScgKTsKCQoJCS8vIG9yZGVyRGF0YSBjYW4gYmUgZ2l2ZW4gYXMgYW4gaW50ZWdlcgoJCXZhciBkYXRhU29ydCA9IGluaXQuYURhdGFTb3J0OwoJCWlmICggdHlwZW9mIGRhdGFTb3J0ID09PSAnbnVtYmVyJyAmJiAhIEFycmF5LmlzQXJyYXkoIGRhdGFTb3J0ICkgKSB7CgkJCWluaXQuYURhdGFTb3J0ID0gWyBkYXRhU29ydCBdOwoJCX0KCX0KCQoJCgkvKioKCSAqIEJyb3dzZXIgZmVhdHVyZSBkZXRlY3Rpb24gZm9yIGNhcGFiaWxpdGllcywgcXVpcmtzCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkJyb3dzZXJEZXRlY3QoIHNldHRpbmdzICkKCXsKCQkvLyBXZSBkb24ndCBuZWVkIHRvIGRvIHRoaXMgZXZlcnkgdGltZSBEYXRhVGFibGVzIGlzIGNvbnN0cnVjdGVkLCB0aGUgdmFsdWVzCgkJLy8gY2FsY3VsYXRlZCBhcmUgc3BlY2lmaWMgdG8gdGhlIGJyb3dzZXIgYW5kIE9TIGNvbmZpZ3VyYXRpb24gd2hpY2ggd2UKCQkvLyBkb24ndCBleHBlY3QgdG8gY2hhbmdlIGJldHdlZW4gaW5pdGlhbGlzYXRpb25zCgkJaWYgKCAhIERhdGFUYWJsZS5fX2Jyb3dzZXIgKSB7CgkJCXZhciBicm93c2VyID0ge307CgkJCURhdGFUYWJsZS5fX2Jyb3dzZXIgPSBicm93c2VyOwoJCgkJCS8vIFNjcm9sbGluZyBmZWF0dXJlIC8gcXVpcmtzIGRldGVjdGlvbgoJCQl2YXIgbiA9ICQoJzxkaXYvPicpCgkJCQkuY3NzKCB7CgkJCQkJcG9zaXRpb246ICdmaXhlZCcsCgkJCQkJdG9wOiAwLAoJCQkJCWxlZnQ6ICQod2luZG93KS5zY3JvbGxMZWZ0KCkqLTEsIC8vIGFsbG93IGZvciBzY3JvbGxpbmcKCQkJCQloZWlnaHQ6IDEsCgkJCQkJd2lkdGg6IDEsCgkJCQkJb3ZlcmZsb3c6ICdoaWRkZW4nCgkJCQl9ICkKCQkJCS5hcHBlbmQoCgkJCQkJJCgnPGRpdi8+JykKCQkJCQkJLmNzcyggewoJCQkJCQkJcG9zaXRpb246ICdhYnNvbHV0ZScsCgkJCQkJCQl0b3A6IDEsCgkJCQkJCQlsZWZ0OiAxLAoJCQkJCQkJd2lkdGg6IDEwMCwKCQkJCQkJCW92ZXJmbG93OiAnc2Nyb2xsJwoJCQkJCQl9ICkKCQkJCQkJLmFwcGVuZCgKCQkJCQkJCSQoJzxkaXYvPicpCgkJCQkJCQkJLmNzcyggewoJCQkJCQkJCQl3aWR0aDogJzEwMCUnLAoJCQkJCQkJCQloZWlnaHQ6IDEwCgkJCQkJCQkJfSApCgkJCQkJCSkKCQkJCSkKCQkJCS5hcHBlbmRUbyggJ2JvZHknICk7CgkKCQkJdmFyIG91dGVyID0gbi5jaGlsZHJlbigpOwoJCQl2YXIgaW5uZXIgPSBvdXRlci5jaGlsZHJlbigpOwoJCgkJCS8vIE51bWJlcnMgYmVsb3csIGluIG9yZGVyLCBhcmU6CgkJCS8vIGlubmVyLm9mZnNldFdpZHRoLCBpbm5lci5jbGllbnRXaWR0aCwgb3V0ZXIub2Zmc2V0V2lkdGgsIG91dGVyLmNsaWVudFdpZHRoCgkJCS8vCgkJCS8vIElFNiBYUDogICAgICAgICAgICAgICAgICAgICAgICAgICAxMDAgMTAwIDEwMCAgODMKCQkJLy8gSUU3IFZpc3RhOiAgICAgICAgICAgICAgICAgICAgICAgIDEwMCAxMDAgMTAwICA4MwoJCQkvLyBJRSA4KyBXaW5kb3dzOiAgICAgICAgICAgICAgICAgICAgIDgzICA4MyAxMDAgIDgzCgkJCS8vIEV2ZXJncmVlbiBXaW5kb3dzOiAgICAgICAgICAgICAgICAgODMgIDgzIDEwMCAgODMKCQkJLy8gRXZlcmdyZWVuIE1hYyB3aXRoIHNjcm9sbGJhcnM6ICAgICA4NSAgODUgMTAwICA4NQoJCQkvLyBFdmVyZ3JlZW4gTWFjIHdpdGhvdXQgc2Nyb2xsYmFyczogMTAwIDEwMCAxMDAgMTAwCgkKCQkJLy8gR2V0IHNjcm9sbGJhciB3aWR0aAoJCQlicm93c2VyLmJhcldpZHRoID0gb3V0ZXJbMF0ub2Zmc2V0V2lkdGggLSBvdXRlclswXS5jbGllbnRXaWR0aDsKCQoJCQkvLyBJRTYvNyB3aWxsIG92ZXJzaXplIGEgd2lkdGggMTAwJSBlbGVtZW50IGluc2lkZSBhIHNjcm9sbGluZyBlbGVtZW50LCB0bwoJCQkvLyBpbmNsdWRlIHRoZSB3aWR0aCBvZiB0aGUgc2Nyb2xsYmFyLCB3aGlsZSBvdGhlciBicm93c2VycyBlbnN1cmUgdGhlIGlubmVyCgkJCS8vIGVsZW1lbnQgaXMgY29udGFpbmVkIHdpdGhvdXQgZm9yY2luZyBzY3JvbGxpbmcKCQkJYnJvd3Nlci5iU2Nyb2xsT3ZlcnNpemUgPSBpbm5lclswXS5vZmZzZXRXaWR0aCA9PT0gMTAwICYmIG91dGVyWzBdLmNsaWVudFdpZHRoICE9PSAxMDA7CgkKCQkJLy8gSW4gcnRsIHRleHQgbGF5b3V0LCBzb21lIGJyb3dzZXJzIChtb3N0LCBidXQgbm90IGFsbCkgd2lsbCBwbGFjZSB0aGUKCQkJLy8gc2Nyb2xsYmFyIG9uIHRoZSBsZWZ0LCByYXRoZXIgdGhhbiB0aGUgcmlnaHQuCgkJCWJyb3dzZXIuYlNjcm9sbGJhckxlZnQgPSBNYXRoLnJvdW5kKCBpbm5lci5vZmZzZXQoKS5sZWZ0ICkgIT09IDE7CgkKCQkJLy8gSUU4LSBkb24ndCBwcm92aWRlIGhlaWdodCBhbmQgd2lkdGggZm9yIGdldEJvdW5kaW5nQ2xpZW50UmVjdAoJCQlicm93c2VyLmJCb3VuZGluZyA9IG5bMF0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGggPyB0cnVlIDogZmFsc2U7CgkKCQkJbi5yZW1vdmUoKTsKCQl9CgkKCQkkLmV4dGVuZCggc2V0dGluZ3Mub0Jyb3dzZXIsIERhdGFUYWJsZS5fX2Jyb3dzZXIgKTsKCQlzZXR0aW5ncy5vU2Nyb2xsLmlCYXJXaWR0aCA9IERhdGFUYWJsZS5fX2Jyb3dzZXIuYmFyV2lkdGg7Cgl9CgkKCQoJLyoqCgkgKiBBcnJheS5wcm90b3R5cGUgcmVkdWNlW1JpZ2h0XSBtZXRob2QsIHVzZWQgZm9yIGJyb3dzZXJzIHdoaWNoIGRvbid0IHN1cHBvcnQKCSAqIEpTIDEuNi4gRG9uZSB0aGlzIHdheSB0byByZWR1Y2UgY29kZSBzaXplLCBzaW5jZSB3ZSBpdGVyYXRlIGVpdGhlciB3YXkKCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuUmVkdWNlICggdGhhdCwgZm4sIGluaXQsIHN0YXJ0LCBlbmQsIGluYyApCgl7CgkJdmFyCgkJCWkgPSBzdGFydCwKCQkJdmFsdWUsCgkJCWlzU2V0ID0gZmFsc2U7CgkKCQlpZiAoIGluaXQgIT09IHVuZGVmaW5lZCApIHsKCQkJdmFsdWUgPSBpbml0OwoJCQlpc1NldCA9IHRydWU7CgkJfQoJCgkJd2hpbGUgKCBpICE9PSBlbmQgKSB7CgkJCWlmICggISB0aGF0Lmhhc093blByb3BlcnR5KGkpICkgewoJCQkJY29udGludWU7CgkJCX0KCQoJCQl2YWx1ZSA9IGlzU2V0ID8KCQkJCWZuKCB2YWx1ZSwgdGhhdFtpXSwgaSwgdGhhdCApIDoKCQkJCXRoYXRbaV07CgkKCQkJaXNTZXQgPSB0cnVlOwoJCQlpICs9IGluYzsKCQl9CgkKCQlyZXR1cm4gdmFsdWU7Cgl9CgkKCS8qKgoJICogQWRkIGEgY29sdW1uIHRvIHRoZSBsaXN0IHVzZWQgZm9yIHRoZSB0YWJsZSB3aXRoIGRlZmF1bHQgdmFsdWVzCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7bm9kZX0gblRoIFRoZSB0aCBlbGVtZW50IGZvciB0aGlzIGNvbHVtbgoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5BZGRDb2x1bW4oIG9TZXR0aW5ncywgblRoICkKCXsKCQkvLyBBZGQgY29sdW1uIHRvIGFvQ29sdW1ucyBhcnJheQoJCXZhciBvRGVmYXVsdHMgPSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uOwoJCXZhciBpQ29sID0gb1NldHRpbmdzLmFvQ29sdW1ucy5sZW5ndGg7CgkJdmFyIG9Db2wgPSAkLmV4dGVuZCgge30sIERhdGFUYWJsZS5tb2RlbHMub0NvbHVtbiwgb0RlZmF1bHRzLCB7CgkJCSJuVGgiOiBuVGggPyBuVGggOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0aCcpLAoJCQkic1RpdGxlIjogICAgb0RlZmF1bHRzLnNUaXRsZSAgICA/IG9EZWZhdWx0cy5zVGl0bGUgICAgOiBuVGggPyBuVGguaW5uZXJIVE1MIDogJycsCgkJCSJhRGF0YVNvcnQiOiBvRGVmYXVsdHMuYURhdGFTb3J0ID8gb0RlZmF1bHRzLmFEYXRhU29ydCA6IFtpQ29sXSwKCQkJIm1EYXRhIjogb0RlZmF1bHRzLm1EYXRhID8gb0RlZmF1bHRzLm1EYXRhIDogaUNvbCwKCQkJaWR4OiBpQ29sCgkJfSApOwoJCW9TZXR0aW5ncy5hb0NvbHVtbnMucHVzaCggb0NvbCApOwoJCgkJLy8gQWRkIHNlYXJjaCBvYmplY3QgZm9yIGNvbHVtbiBzcGVjaWZpYyBzZWFyY2guIE5vdGUgdGhhdCB0aGUgYHNlYXJjaENvbHNbIGlDb2wgXWAKCQkvLyBwYXNzZWQgaW50byBleHRlbmQgY2FuIGJlIHVuZGVmaW5lZC4gVGhpcyBhbGxvd3MgdGhlIHVzZXIgdG8gZ2l2ZSBhIGRlZmF1bHQKCQkvLyB3aXRoIG9ubHkgc29tZSBvZiB0aGUgcGFyYW1ldGVycyBkZWZpbmVkLCBhbmQgYWxzbyBub3QgZ2l2ZSBhIGRlZmF1bHQKCQl2YXIgc2VhcmNoQ29scyA9IG9TZXR0aW5ncy5hb1ByZVNlYXJjaENvbHM7CgkJc2VhcmNoQ29sc1sgaUNvbCBdID0gJC5leHRlbmQoIHt9LCBEYXRhVGFibGUubW9kZWxzLm9TZWFyY2gsIHNlYXJjaENvbHNbIGlDb2wgXSApOwoJCgkJLy8gVXNlIHRoZSBkZWZhdWx0IGNvbHVtbiBvcHRpb25zIGZ1bmN0aW9uIHRvIGluaXRpYWxpc2UgY2xhc3NlcyBldGMKCQlfZm5Db2x1bW5PcHRpb25zKCBvU2V0dGluZ3MsIGlDb2wsICQoblRoKS5kYXRhKCkgKTsKCX0KCQoJCgkvKioKCSAqIEFwcGx5IG9wdGlvbnMgZm9yIGEgY29sdW1uCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7aW50fSBpQ29sIGNvbHVtbiBpbmRleCB0byBjb25zaWRlcgoJICogIEBwYXJhbSB7b2JqZWN0fSBvT3B0aW9ucyBvYmplY3Qgd2l0aCBzVHlwZSwgYlZpc2libGUgYW5kIGJTZWFyY2hhYmxlIGV0YwoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5Db2x1bW5PcHRpb25zKCBvU2V0dGluZ3MsIGlDb2wsIG9PcHRpb25zICkKCXsKCQl2YXIgb0NvbCA9IG9TZXR0aW5ncy5hb0NvbHVtbnNbIGlDb2wgXTsKCQl2YXIgb0NsYXNzZXMgPSBvU2V0dGluZ3Mub0NsYXNzZXM7CgkJdmFyIHRoID0gJChvQ29sLm5UaCk7CgkKCQkvLyBUcnkgdG8gZ2V0IHdpZHRoIGluZm9ybWF0aW9uIGZyb20gdGhlIERPTS4gV2UgY2FuJ3QgZ2V0IGl0IGZyb20gQ1NTCgkJLy8gYXMgd2UnZCBuZWVkIHRvIHBhcnNlIHRoZSBDU1Mgc3R5bGVzaGVldC4gYHdpZHRoYCBvcHRpb24gY2FuIG92ZXJyaWRlCgkJaWYgKCAhIG9Db2wuc1dpZHRoT3JpZyApIHsKCQkJLy8gV2lkdGggYXR0cmlidXRlCgkJCW9Db2wuc1dpZHRoT3JpZyA9IHRoLmF0dHIoJ3dpZHRoJykgfHwgbnVsbDsKCQoJCQkvLyBTdHlsZSBhdHRyaWJ1dGUKCQkJdmFyIHQgPSAodGguYXR0cignc3R5bGUnKSB8fCAnJykubWF0Y2goL3dpZHRoOlxzKihcZCtbcHhlbSVdKykvKTsKCQkJaWYgKCB0ICkgewoJCQkJb0NvbC5zV2lkdGhPcmlnID0gdFsxXTsKCQkJfQoJCX0KCQoJCS8qIFVzZXIgc3BlY2lmaWVkIGNvbHVtbiBvcHRpb25zICovCgkJaWYgKCBvT3B0aW9ucyAhPT0gdW5kZWZpbmVkICYmIG9PcHRpb25zICE9PSBudWxsICkKCQl7CgkJCS8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5CgkJCV9mbkNvbXBhdENvbHMoIG9PcHRpb25zICk7CgkKCQkJLy8gTWFwIGNhbWVsIGNhc2UgcGFyYW1ldGVycyB0byB0aGVpciBIdW5nYXJpYW4gY291bnRlcnBhcnRzCgkJCV9mbkNhbWVsVG9IdW5nYXJpYW4oIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4sIG9PcHRpb25zLCB0cnVlICk7CgkKCQkJLyogQmFja3dhcmRzIGNvbXBhdGliaWxpdHkgZm9yIG1EYXRhUHJvcCAqLwoJCQlpZiAoIG9PcHRpb25zLm1EYXRhUHJvcCAhPT0gdW5kZWZpbmVkICYmICFvT3B0aW9ucy5tRGF0YSApCgkJCXsKCQkJCW9PcHRpb25zLm1EYXRhID0gb09wdGlvbnMubURhdGFQcm9wOwoJCQl9CgkKCQkJaWYgKCBvT3B0aW9ucy5zVHlwZSApCgkJCXsKCQkJCW9Db2wuX3NNYW51YWxUeXBlID0gb09wdGlvbnMuc1R5cGU7CgkJCX0KCQoJCQkvLyBgY2xhc3NgIGlzIGEgcmVzZXJ2ZWQgd29yZCBpbiBKYXZhc2NyaXB0LCBzbyB3ZSBuZWVkIHRvIHByb3ZpZGUKCQkJLy8gdGhlIGFiaWxpdHkgdG8gdXNlIGEgdmFsaWQgbmFtZSBmb3IgdGhlIGNhbWVsIGNhc2UgaW5wdXQKCQkJaWYgKCBvT3B0aW9ucy5jbGFzc05hbWUgJiYgISBvT3B0aW9ucy5zQ2xhc3MgKQoJCQl7CgkJCQlvT3B0aW9ucy5zQ2xhc3MgPSBvT3B0aW9ucy5jbGFzc05hbWU7CgkJCX0KCQkJaWYgKCBvT3B0aW9ucy5zQ2xhc3MgKSB7CgkJCQl0aC5hZGRDbGFzcyggb09wdGlvbnMuc0NsYXNzICk7CgkJCX0KCQoJCQl2YXIgb3JpZ0NsYXNzID0gb0NvbC5zQ2xhc3M7CgkKCQkJJC5leHRlbmQoIG9Db2wsIG9PcHRpb25zICk7CgkJCV9mbk1hcCggb0NvbCwgb09wdGlvbnMsICJzV2lkdGgiLCAic1dpZHRoT3JpZyIgKTsKCQoJCQkvLyBNZXJnZSBjbGFzcyBmcm9tIHByZXZpb3VzbHkgZGVmaW5lZCBjbGFzc2VzIHdpdGggdGhpcyBvbmUsIHJhdGhlciB0aGFuIGp1c3QKCQkJLy8gb3ZlcndyaXRpbmcgaXQgaW4gdGhlIGV4dGVuZCBhYm92ZQoJCQlpZiAob3JpZ0NsYXNzICE9PSBvQ29sLnNDbGFzcykgewoJCQkJb0NvbC5zQ2xhc3MgPSBvcmlnQ2xhc3MgKyAnICcgKyBvQ29sLnNDbGFzczsKCQkJfQoJCgkJCS8qIGlEYXRhU29ydCB0byBiZSBhcHBsaWVkIChiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSksIGJ1dCBhRGF0YVNvcnQgd2lsbCB0YWtlCgkJCSAqIHByaW9yaXR5IGlmIGRlZmluZWQKCQkJICovCgkJCWlmICggb09wdGlvbnMuaURhdGFTb3J0ICE9PSB1bmRlZmluZWQgKQoJCQl7CgkJCQlvQ29sLmFEYXRhU29ydCA9IFsgb09wdGlvbnMuaURhdGFTb3J0IF07CgkJCX0KCQkJX2ZuTWFwKCBvQ29sLCBvT3B0aW9ucywgImFEYXRhU29ydCIgKTsKCQl9CgkKCQkvKiBDYWNoZSB0aGUgZGF0YSBnZXQgYW5kIHNldCBmdW5jdGlvbnMgZm9yIHNwZWVkICovCgkJdmFyIG1EYXRhU3JjID0gb0NvbC5tRGF0YTsKCQl2YXIgbURhdGEgPSBfZm5HZXRPYmplY3REYXRhRm4oIG1EYXRhU3JjICk7CgkJdmFyIG1SZW5kZXIgPSBvQ29sLm1SZW5kZXIgPyBfZm5HZXRPYmplY3REYXRhRm4oIG9Db2wubVJlbmRlciApIDogbnVsbDsKCQoJCXZhciBhdHRyVGVzdCA9IGZ1bmN0aW9uKCBzcmMgKSB7CgkJCXJldHVybiB0eXBlb2Ygc3JjID09PSAnc3RyaW5nJyAmJiBzcmMuaW5kZXhPZignQCcpICE9PSAtMTsKCQl9OwoJCW9Db2wuX2JBdHRyU3JjID0gJC5pc1BsYWluT2JqZWN0KCBtRGF0YVNyYyApICYmICgKCQkJYXR0clRlc3QobURhdGFTcmMuc29ydCkgfHwgYXR0clRlc3QobURhdGFTcmMudHlwZSkgfHwgYXR0clRlc3QobURhdGFTcmMuZmlsdGVyKQoJCSk7CgkJb0NvbC5fc2V0dGVyID0gbnVsbDsKCQoJCW9Db2wuZm5HZXREYXRhID0gZnVuY3Rpb24gKHJvd0RhdGEsIHR5cGUsIG1ldGEpIHsKCQkJdmFyIGlubmVyRGF0YSA9IG1EYXRhKCByb3dEYXRhLCB0eXBlLCB1bmRlZmluZWQsIG1ldGEgKTsKCQoJCQlyZXR1cm4gbVJlbmRlciAmJiB0eXBlID8KCQkJCW1SZW5kZXIoIGlubmVyRGF0YSwgdHlwZSwgcm93RGF0YSwgbWV0YSApIDoKCQkJCWlubmVyRGF0YTsKCQl9OwoJCW9Db2wuZm5TZXREYXRhID0gZnVuY3Rpb24gKCByb3dEYXRhLCB2YWwsIG1ldGEgKSB7CgkJCXJldHVybiBfZm5TZXRPYmplY3REYXRhRm4oIG1EYXRhU3JjICkoIHJvd0RhdGEsIHZhbCwgbWV0YSApOwoJCX07CgkKCQkvLyBJbmRpY2F0ZSBpZiBEYXRhVGFibGVzIHNob3VsZCByZWFkIERPTSBkYXRhIGFzIGFuIG9iamVjdCBvciBhcnJheQoJCS8vIFVzZWQgaW4gX2ZuR2V0Um93RWxlbWVudHMKCQlpZiAoIHR5cGVvZiBtRGF0YVNyYyAhPT0gJ251bWJlcicgKSB7CgkJCW9TZXR0aW5ncy5fcm93UmVhZE9iamVjdCA9IHRydWU7CgkJfQoJCgkJLyogRmVhdHVyZSBzb3J0aW5nIG92ZXJyaWRlcyBjb2x1bW4gc3BlY2lmaWMgd2hlbiBvZmYgKi8KCQlpZiAoICFvU2V0dGluZ3Mub0ZlYXR1cmVzLmJTb3J0ICkKCQl7CgkJCW9Db2wuYlNvcnRhYmxlID0gZmFsc2U7CgkJCXRoLmFkZENsYXNzKCBvQ2xhc3Nlcy5zU29ydGFibGVOb25lICk7IC8vIEhhdmUgdG8gYWRkIGNsYXNzIGhlcmUgYXMgb3JkZXIgZXZlbnQgaXNuJ3QgY2FsbGVkCgkJfQoJCgkJLyogQ2hlY2sgdGhhdCB0aGUgY2xhc3MgYXNzaWdubWVudCBpcyBjb3JyZWN0IGZvciBzb3J0aW5nICovCgkJdmFyIGJBc2MgPSAkLmluQXJyYXkoJ2FzYycsIG9Db2wuYXNTb3J0aW5nKSAhPT0gLTE7CgkJdmFyIGJEZXNjID0gJC5pbkFycmF5KCdkZXNjJywgb0NvbC5hc1NvcnRpbmcpICE9PSAtMTsKCQlpZiAoICFvQ29sLmJTb3J0YWJsZSB8fCAoIWJBc2MgJiYgIWJEZXNjKSApCgkJewoJCQlvQ29sLnNTb3J0aW5nQ2xhc3MgPSBvQ2xhc3Nlcy5zU29ydGFibGVOb25lOwoJCQlvQ29sLnNTb3J0aW5nQ2xhc3NKVUkgPSAiIjsKCQl9CgkJZWxzZSBpZiAoIGJBc2MgJiYgIWJEZXNjICkKCQl7CgkJCW9Db2wuc1NvcnRpbmdDbGFzcyA9IG9DbGFzc2VzLnNTb3J0YWJsZUFzYzsKCQkJb0NvbC5zU29ydGluZ0NsYXNzSlVJID0gb0NsYXNzZXMuc1NvcnRKVUlBc2NBbGxvd2VkOwoJCX0KCQllbHNlIGlmICggIWJBc2MgJiYgYkRlc2MgKQoJCXsKCQkJb0NvbC5zU29ydGluZ0NsYXNzID0gb0NsYXNzZXMuc1NvcnRhYmxlRGVzYzsKCQkJb0NvbC5zU29ydGluZ0NsYXNzSlVJID0gb0NsYXNzZXMuc1NvcnRKVUlEZXNjQWxsb3dlZDsKCQl9CgkJZWxzZQoJCXsKCQkJb0NvbC5zU29ydGluZ0NsYXNzID0gb0NsYXNzZXMuc1NvcnRhYmxlOwoJCQlvQ29sLnNTb3J0aW5nQ2xhc3NKVUkgPSBvQ2xhc3Nlcy5zU29ydEpVSTsKCQl9Cgl9CgkKCQoJLyoqCgkgKiBBZGp1c3QgdGhlIHRhYmxlIGNvbHVtbiB3aWR0aHMgZm9yIG5ldyBkYXRhLiBOb3RlOiB5b3Ugd291bGQgcHJvYmFibHkgd2FudCB0bwoJICogZG8gYSByZWRyYXcgYWZ0ZXIgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIQoJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5BZGp1c3RDb2x1bW5TaXppbmcgKCBzZXR0aW5ncyApCgl7CgkJLyogTm90IGludGVyZXN0ZWQgaW4gZG9pbmcgY29sdW1uIHdpZHRoIGNhbGN1bGF0aW9uIGlmIGF1dG8td2lkdGggaXMgZGlzYWJsZWQgKi8KCQlpZiAoIHNldHRpbmdzLm9GZWF0dXJlcy5iQXV0b1dpZHRoICE9PSBmYWxzZSApCgkJewoJCQl2YXIgY29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1uczsKCQoJCQlfZm5DYWxjdWxhdGVDb2x1bW5XaWR0aHMoIHNldHRpbmdzICk7CgkJCWZvciAoIHZhciBpPTAgLCBpTGVuPWNvbHVtbnMubGVuZ3RoIDsgaTxpTGVuIDsgaSsrICkKCQkJewoJCQkJY29sdW1uc1tpXS5uVGguc3R5bGUud2lkdGggPSBjb2x1bW5zW2ldLnNXaWR0aDsKCQkJfQoJCX0KCQoJCXZhciBzY3JvbGwgPSBzZXR0aW5ncy5vU2Nyb2xsOwoJCWlmICggc2Nyb2xsLnNZICE9PSAnJyB8fCBzY3JvbGwuc1ggIT09ICcnKQoJCXsKCQkJX2ZuU2Nyb2xsRHJhdyggc2V0dGluZ3MgKTsKCQl9CgkKCQlfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCBudWxsLCAnY29sdW1uLXNpemluZycsIFtzZXR0aW5nc10gKTsKCX0KCQoJCgkvKioKCSAqIENvbnZlcnQgdGhlIGluZGV4IG9mIGEgdmlzaWJsZSBjb2x1bW4gdG8gdGhlIGluZGV4IGluIHRoZSBkYXRhIGFycmF5ICh0YWtlIGFjY291bnQKCSAqIG9mIGhpZGRlbiBjb2x1bW5zKQoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge2ludH0gaU1hdGNoIFZpc2libGUgY29sdW1uIGluZGV4IHRvIGxvb2t1cAoJICogIEByZXR1cm5zIHtpbnR9IGkgdGhlIGRhdGEgaW5kZXgKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuVmlzaWJsZVRvQ29sdW1uSW5kZXgoIG9TZXR0aW5ncywgaU1hdGNoICkKCXsKCQl2YXIgYWlWaXMgPSBfZm5HZXRDb2x1bW5zKCBvU2V0dGluZ3MsICdiVmlzaWJsZScgKTsKCQoJCXJldHVybiB0eXBlb2YgYWlWaXNbaU1hdGNoXSA9PT0gJ251bWJlcicgPwoJCQlhaVZpc1tpTWF0Y2hdIDoKCQkJbnVsbDsKCX0KCQoJCgkvKioKCSAqIENvbnZlcnQgdGhlIGluZGV4IG9mIGFuIGluZGV4IGluIHRoZSBkYXRhIGFycmF5IGFuZCBjb252ZXJ0IGl0IHRvIHRoZSB2aXNpYmxlCgkgKiAgIGNvbHVtbiBpbmRleCAodGFrZSBhY2NvdW50IG9mIGhpZGRlbiBjb2x1bW5zKQoJICogIEBwYXJhbSB7aW50fSBpTWF0Y2ggQ29sdW1uIGluZGV4IHRvIGxvb2t1cAoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcmV0dXJucyB7aW50fSBpIHRoZSBkYXRhIGluZGV4CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkNvbHVtbkluZGV4VG9WaXNpYmxlKCBvU2V0dGluZ3MsIGlNYXRjaCApCgl7CgkJdmFyIGFpVmlzID0gX2ZuR2V0Q29sdW1ucyggb1NldHRpbmdzLCAnYlZpc2libGUnICk7CgkJdmFyIGlQb3MgPSAkLmluQXJyYXkoIGlNYXRjaCwgYWlWaXMgKTsKCQoJCXJldHVybiBpUG9zICE9PSAtMSA/IGlQb3MgOiBudWxsOwoJfQoJCgkKCS8qKgoJICogR2V0IHRoZSBudW1iZXIgb2YgdmlzaWJsZSBjb2x1bW5zCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEByZXR1cm5zIHtpbnR9IGkgdGhlIG51bWJlciBvZiB2aXNpYmxlIGNvbHVtbnMKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuVmlzYmxlQ29sdW1ucyggb1NldHRpbmdzICkKCXsKCQl2YXIgdmlzID0gMDsKCQoJCS8vIE5vIHJlZHVjZSBpbiBJRTgsIHVzZSBhIGxvb3AgZm9yIG5vdwoJCSQuZWFjaCggb1NldHRpbmdzLmFvQ29sdW1ucywgZnVuY3Rpb24gKCBpLCBjb2wgKSB7CgkJCWlmICggY29sLmJWaXNpYmxlICYmICQoY29sLm5UaCkuY3NzKCdkaXNwbGF5JykgIT09ICdub25lJyApIHsKCQkJCXZpcysrOwoJCQl9CgkJfSApOwoJCgkJcmV0dXJuIHZpczsKCX0KCQoJCgkvKioKCSAqIEdldCBhbiBhcnJheSBvZiBjb2x1bW4gaW5kZXhlcyB0aGF0IG1hdGNoIGEgZ2l2ZW4gcHJvcGVydHkKCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIHtzdHJpbmd9IHNQYXJhbSBQYXJhbWV0ZXIgaW4gYW9Db2x1bW5zIHRvIGxvb2sgZm9yIC0gdHlwaWNhbGx5CgkgKiAgICBiVmlzaWJsZSBvciBiU2VhcmNoYWJsZQoJICogIEByZXR1cm5zIHthcnJheX0gQXJyYXkgb2YgaW5kZXhlcyB3aXRoIG1hdGNoZWQgcHJvcGVydGllcwoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5HZXRDb2x1bW5zKCBvU2V0dGluZ3MsIHNQYXJhbSApCgl7CgkJdmFyIGEgPSBbXTsKCQoJCSQubWFwKCBvU2V0dGluZ3MuYW9Db2x1bW5zLCBmdW5jdGlvbih2YWwsIGkpIHsKCQkJaWYgKCB2YWxbc1BhcmFtXSApIHsKCQkJCWEucHVzaCggaSApOwoJCQl9CgkJfSApOwoJCgkJcmV0dXJuIGE7Cgl9CgkKCQoJLyoqCgkgKiBDYWxjdWxhdGUgdGhlICd0eXBlJyBvZiBhIGNvbHVtbgoJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5Db2x1bW5UeXBlcyAoIHNldHRpbmdzICkKCXsKCQl2YXIgY29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1uczsKCQl2YXIgZGF0YSA9IHNldHRpbmdzLmFvRGF0YTsKCQl2YXIgdHlwZXMgPSBEYXRhVGFibGUuZXh0LnR5cGUuZGV0ZWN0OwoJCXZhciBpLCBpZW4sIGosIGplbiwgaywga2VuOwoJCXZhciBjb2wsIGNlbGwsIGRldGVjdGVkVHlwZSwgY2FjaGU7CgkKCQkvLyBGb3IgZWFjaCBjb2x1bW4sIHNwaW4gb3ZlciB0aGUgCgkJZm9yICggaT0wLCBpZW49Y29sdW1ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHsKCQkJY29sID0gY29sdW1uc1tpXTsKCQkJY2FjaGUgPSBbXTsKCQoJCQlpZiAoICEgY29sLnNUeXBlICYmIGNvbC5fc01hbnVhbFR5cGUgKSB7CgkJCQljb2wuc1R5cGUgPSBjb2wuX3NNYW51YWxUeXBlOwoJCQl9CgkJCWVsc2UgaWYgKCAhIGNvbC5zVHlwZSApIHsKCQkJCWZvciAoIGo9MCwgamVuPXR5cGVzLmxlbmd0aCA7IGo8amVuIDsgaisrICkgewoJCQkJCWZvciAoIGs9MCwga2VuPWRhdGEubGVuZ3RoIDsgazxrZW4gOyBrKysgKSB7CgkJCQkJCS8vIFVzZSBhIGNhY2hlIGFycmF5IHNvIHdlIG9ubHkgbmVlZCB0byBnZXQgdGhlIHR5cGUgZGF0YQoJCQkJCQkvLyBmcm9tIHRoZSBmb3JtYXR0ZXIgb25jZSAod2hlbiB1c2luZyBtdWx0aXBsZSBkZXRlY3RvcnMpCgkJCQkJCWlmICggY2FjaGVba10gPT09IHVuZGVmaW5lZCApIHsKCQkJCQkJCWNhY2hlW2tdID0gX2ZuR2V0Q2VsbERhdGEoIHNldHRpbmdzLCBrLCBpLCAndHlwZScgKTsKCQkJCQkJfQoJCgkJCQkJCWRldGVjdGVkVHlwZSA9IHR5cGVzW2pdKCBjYWNoZVtrXSwgc2V0dGluZ3MgKTsKCQoJCQkJCQkvLyBJZiBudWxsLCB0aGVuIHRoaXMgdHlwZSBjYW4ndCBhcHBseSB0byB0aGlzIGNvbHVtbiwgc28KCQkJCQkJLy8gcmF0aGVyIHRoYW4gdGVzdGluZyBhbGwgY2VsbHMsIGJyZWFrIG91dC4gVGhlcmUgaXMgYW4KCQkJCQkJLy8gZXhjZXB0aW9uIGZvciB0aGUgbGFzdCB0eXBlIHdoaWNoIGlzIGBodG1sYC4gV2UgbmVlZCB0bwoJCQkJCQkvLyBzY2FuIGFsbCByb3dzIHNpbmNlIGl0IGlzIHBvc3NpYmxlIHRvIG1peCBzdHJpbmcgYW5kIEhUTUwKCQkJCQkJLy8gdHlwZXMKCQkJCQkJaWYgKCAhIGRldGVjdGVkVHlwZSAmJiBqICE9PSB0eXBlcy5sZW5ndGgtMSApIHsKCQkJCQkJCWJyZWFrOwoJCQkJCQl9CgkKCQkJCQkJLy8gT25seSBhIHNpbmdsZSBtYXRjaCBpcyBuZWVkZWQgZm9yIGh0bWwgdHlwZSBzaW5jZSBpdCBpcwoJCQkJCQkvLyBib3R0b20gb2YgdGhlIHBpbGUgYW5kIHZlcnkgc2ltaWxhciB0byBzdHJpbmcgLSBidXQgaXQKCQkJCQkJLy8gbXVzdCBub3QgYmUgZW1wdHkKCQkJCQkJaWYgKCBkZXRlY3RlZFR5cGUgPT09ICdodG1sJyAmJiAhIF9lbXB0eShjYWNoZVtrXSkgKSB7CgkJCQkJCQlicmVhazsKCQkJCQkJfQoJCQkJCX0KCQoJCQkJCS8vIFR5cGUgaXMgdmFsaWQgZm9yIGFsbCBkYXRhIHBvaW50cyBpbiB0aGUgY29sdW1uIC0gdXNlIHRoaXMKCQkJCQkvLyB0eXBlCgkJCQkJaWYgKCBkZXRlY3RlZFR5cGUgKSB7CgkJCQkJCWNvbC5zVHlwZSA9IGRldGVjdGVkVHlwZTsKCQkJCQkJYnJlYWs7CgkJCQkJfQoJCQkJfQoJCgkJCQkvLyBGYWxsIGJhY2sgLSBpZiBubyB0eXBlIHdhcyBkZXRlY3RlZCwgYWx3YXlzIHVzZSBzdHJpbmcKCQkJCWlmICggISBjb2wuc1R5cGUgKSB7CgkJCQkJY29sLnNUeXBlID0gJ3N0cmluZyc7CgkJCQl9CgkJCX0KCQl9Cgl9CgkKCQoJLyoqCgkgKiBUYWtlIHRoZSBjb2x1bW4gZGVmaW5pdGlvbnMgYW5kIHN0YXRpYyBjb2x1bW5zIGFycmF5cyBhbmQgY2FsY3VsYXRlIGhvdwoJICogdGhleSByZWxhdGUgdG8gY29sdW1uIGluZGV4ZXMuIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB3aWxsIHRoZW4gYXBwbHkgdGhlCgkgKiBkZWZpbml0aW9uIGZvdW5kIGZvciBhIGNvbHVtbiB0byBhIHN1aXRhYmxlIGNvbmZpZ3VyYXRpb24gb2JqZWN0LgoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge2FycmF5fSBhb0NvbERlZnMgVGhlIGFvQ29sdW1uRGVmcyBhcnJheSB0aGF0IGlzIHRvIGJlIGFwcGxpZWQKCSAqICBAcGFyYW0ge2FycmF5fSBhb0NvbHMgVGhlIGFvQ29sdW1ucyBhcnJheSB0aGF0IGRlZmluZXMgY29sdW1ucyBpbmRpdmlkdWFsbHkKCSAqICBAcGFyYW0ge2Z1bmN0aW9ufSBmbiBDYWxsYmFjayBmdW5jdGlvbiAtIHRha2VzIHR3byBwYXJhbWV0ZXJzLCB0aGUgY2FsY3VsYXRlZAoJICogICAgY29sdW1uIGluZGV4IGFuZCB0aGUgZGVmaW5pdGlvbiBmb3IgdGhhdCBjb2x1bW4uCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkFwcGx5Q29sdW1uRGVmcyggb1NldHRpbmdzLCBhb0NvbERlZnMsIGFvQ29scywgZm4gKQoJewoJCXZhciBpLCBpTGVuLCBqLCBqTGVuLCBrLCBrTGVuLCBkZWY7CgkJdmFyIGNvbHVtbnMgPSBvU2V0dGluZ3MuYW9Db2x1bW5zOwoJCgkJLy8gQ29sdW1uIGRlZmluaXRpb25zIHdpdGggYVRhcmdldHMKCQlpZiAoIGFvQ29sRGVmcyApCgkJewoJCQkvKiBMb29wIG92ZXIgdGhlIGRlZmluaXRpb25zIGFycmF5IC0gbG9vcCBpbiByZXZlcnNlIHNvIGZpcnN0IGluc3RhbmNlIGhhcyBwcmlvcml0eSAqLwoJCQlmb3IgKCBpPWFvQ29sRGVmcy5sZW5ndGgtMSA7IGk+PTAgOyBpLS0gKQoJCQl7CgkJCQlkZWYgPSBhb0NvbERlZnNbaV07CgkKCQkJCS8qIEVhY2ggZGVmaW5pdGlvbiBjYW4gdGFyZ2V0IG11bHRpcGxlIGNvbHVtbnMsIGFzIGl0IGlzIGFuIGFycmF5ICovCgkJCQl2YXIgYVRhcmdldHMgPSBkZWYudGFyZ2V0ICE9PSB1bmRlZmluZWQKCQkJCQk/IGRlZi50YXJnZXQKCQkJCQk6IGRlZi50YXJnZXRzICE9PSB1bmRlZmluZWQKCQkJCQkJPyBkZWYudGFyZ2V0cwoJCQkJCQk6IGRlZi5hVGFyZ2V0czsKCQoJCQkJaWYgKCAhIEFycmF5LmlzQXJyYXkoIGFUYXJnZXRzICkgKQoJCQkJewoJCQkJCWFUYXJnZXRzID0gWyBhVGFyZ2V0cyBdOwoJCQkJfQoJCgkJCQlmb3IgKCBqPTAsIGpMZW49YVRhcmdldHMubGVuZ3RoIDsgajxqTGVuIDsgaisrICkKCQkJCXsKCQkJCQlpZiAoIHR5cGVvZiBhVGFyZ2V0c1tqXSA9PT0gJ251bWJlcicgJiYgYVRhcmdldHNbal0gPj0gMCApCgkJCQkJewoJCQkJCQkvKiBBZGQgY29sdW1ucyB0aGF0IHdlIGRvbid0IHlldCBrbm93IGFib3V0ICovCgkJCQkJCXdoaWxlKCBjb2x1bW5zLmxlbmd0aCA8PSBhVGFyZ2V0c1tqXSApCgkJCQkJCXsKCQkJCQkJCV9mbkFkZENvbHVtbiggb1NldHRpbmdzICk7CgkJCQkJCX0KCQoJCQkJCQkvKiBJbnRlZ2VyLCBiYXNpYyBpbmRleCAqLwoJCQkJCQlmbiggYVRhcmdldHNbal0sIGRlZiApOwoJCQkJCX0KCQkJCQllbHNlIGlmICggdHlwZW9mIGFUYXJnZXRzW2pdID09PSAnbnVtYmVyJyAmJiBhVGFyZ2V0c1tqXSA8IDAgKQoJCQkJCXsKCQkJCQkJLyogTmVnYXRpdmUgaW50ZWdlciwgcmlnaHQgdG8gbGVmdCBjb2x1bW4gY291bnRpbmcgKi8KCQkJCQkJZm4oIGNvbHVtbnMubGVuZ3RoK2FUYXJnZXRzW2pdLCBkZWYgKTsKCQkJCQl9CgkJCQkJZWxzZSBpZiAoIHR5cGVvZiBhVGFyZ2V0c1tqXSA9PT0gJ3N0cmluZycgKQoJCQkJCXsKCQkJCQkJLyogQ2xhc3MgbmFtZSBtYXRjaGluZyBvbiBUSCBlbGVtZW50ICovCgkJCQkJCWZvciAoIGs9MCwga0xlbj1jb2x1bW5zLmxlbmd0aCA7IGs8a0xlbiA7IGsrKyApCgkJCQkJCXsKCQkJCQkJCWlmICggYVRhcmdldHNbal0gPT0gIl9hbGwiIHx8CgkJCQkJCQkgICAgICQoY29sdW1uc1trXS5uVGgpLmhhc0NsYXNzKCBhVGFyZ2V0c1tqXSApICkKCQkJCQkJCXsKCQkJCQkJCQlmbiggaywgZGVmICk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgkKCQkvLyBTdGF0aWNhbGx5IGRlZmluZWQgY29sdW1ucyBhcnJheQoJCWlmICggYW9Db2xzICkKCQl7CgkJCWZvciAoIGk9MCwgaUxlbj1hb0NvbHMubGVuZ3RoIDsgaTxpTGVuIDsgaSsrICkKCQkJewoJCQkJZm4oIGksIGFvQ29sc1tpXSApOwoJCQl9CgkJfQoJfQoJCgkvKioKCSAqIEFkZCBhIGRhdGEgYXJyYXkgdG8gdGhlIHRhYmxlLCBjcmVhdGluZyBET00gbm9kZSBldGMuIFRoaXMgaXMgdGhlIHBhcmFsbGVsIHRvCgkgKiBfZm5HYXRoZXJEYXRhLCBidXQgZm9yIGFkZGluZyByb3dzIGZyb20gYSBKYXZhc2NyaXB0IHNvdXJjZSwgcmF0aGVyIHRoYW4gYQoJICogRE9NIHNvdXJjZS4KCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIHthcnJheX0gYURhdGEgZGF0YSBhcnJheSB0byBiZSBhZGRlZAoJICogIEBwYXJhbSB7bm9kZX0gW25Ucl0gVFIgZWxlbWVudCB0byBhZGQgdG8gdGhlIHRhYmxlIC0gb3B0aW9uYWwuIElmIG5vdCBnaXZlbiwKCSAqICAgIERhdGFUYWJsZXMgd2lsbCBjcmVhdGUgYSByb3cgYXV0b21hdGljYWxseQoJICogIEBwYXJhbSB7YXJyYXl9IFthblRkc10gQXJyYXkgb2YgVER8VEggZWxlbWVudHMgZm9yIHRoZSByb3cgLSBtdXN0IGJlIGdpdmVuCgkgKiAgICBpZiBuVHIgaXMuCgkgKiAgQHJldHVybnMge2ludH0gPj0wIGlmIHN1Y2Nlc3NmdWwgKGluZGV4IG9mIG5ldyBhb0RhdGEgZW50cnkpLCAtMSBpZiBmYWlsZWQKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuQWRkRGF0YSAoIG9TZXR0aW5ncywgYURhdGFJbiwgblRyLCBhblRkcyApCgl7CgkJLyogQ3JlYXRlIHRoZSBvYmplY3QgZm9yIHN0b3JpbmcgaW5mb3JtYXRpb24gYWJvdXQgdGhpcyBuZXcgcm93ICovCgkJdmFyIGlSb3cgPSBvU2V0dGluZ3MuYW9EYXRhLmxlbmd0aDsKCQl2YXIgb0RhdGEgPSAkLmV4dGVuZCggdHJ1ZSwge30sIERhdGFUYWJsZS5tb2RlbHMub1JvdywgewoJCQlzcmM6IG5UciA/ICdkb20nIDogJ2RhdGEnLAoJCQlpZHg6IGlSb3cKCQl9ICk7CgkKCQlvRGF0YS5fYURhdGEgPSBhRGF0YUluOwoJCW9TZXR0aW5ncy5hb0RhdGEucHVzaCggb0RhdGEgKTsKCQoJCS8qIENyZWF0ZSB0aGUgY2VsbHMgKi8KCQl2YXIgblRkLCBzVGhpc1R5cGU7CgkJdmFyIGNvbHVtbnMgPSBvU2V0dGluZ3MuYW9Db2x1bW5zOwoJCgkJLy8gSW52YWxpZGF0ZSB0aGUgY29sdW1uIHR5cGVzIGFzIHRoZSBuZXcgZGF0YSBuZWVkcyB0byBiZSByZXZhbGlkYXRlZAoJCWZvciAoIHZhciBpPTAsIGlMZW49Y29sdW1ucy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKQoJCXsKCQkJY29sdW1uc1tpXS5zVHlwZSA9IG51bGw7CgkJfQoJCgkJLyogQWRkIHRvIHRoZSBkaXNwbGF5IGFycmF5ICovCgkJb1NldHRpbmdzLmFpRGlzcGxheU1hc3Rlci5wdXNoKCBpUm93ICk7CgkKCQl2YXIgaWQgPSBvU2V0dGluZ3Mucm93SWRGbiggYURhdGFJbiApOwoJCWlmICggaWQgIT09IHVuZGVmaW5lZCApIHsKCQkJb1NldHRpbmdzLmFJZHNbIGlkIF0gPSBvRGF0YTsKCQl9CgkKCQkvKiBDcmVhdGUgdGhlIERPTSBpbmZvcm1hdGlvbiwgb3IgcmVnaXN0ZXIgaXQgaWYgYWxyZWFkeSBwcmVzZW50ICovCgkJaWYgKCBuVHIgfHwgISBvU2V0dGluZ3Mub0ZlYXR1cmVzLmJEZWZlclJlbmRlciApCgkJewoJCQlfZm5DcmVhdGVUciggb1NldHRpbmdzLCBpUm93LCBuVHIsIGFuVGRzICk7CgkJfQoJCgkJcmV0dXJuIGlSb3c7Cgl9CgkKCQoJLyoqCgkgKiBBZGQgb25lIG9yIG1vcmUgVFIgZWxlbWVudHMgdG8gdGhlIHRhYmxlLiBHZW5lcmFsbHkgd2UnZCBleHBlY3QgdG8KCSAqIHVzZSB0aGlzIGZvciByZWFkaW5nIGRhdGEgZnJvbSBhIERPTSBzb3VyY2VkIHRhYmxlLCBidXQgaXQgY291bGQgYmUKCSAqIHVzZWQgZm9yIGFuIFRSIGVsZW1lbnQuIE5vdGUgdGhhdCBpZiBhIFRSIGlzIGdpdmVuLCBpdCBpcyB1c2VkIChpLmUuCgkgKiBpdCBpcyBub3QgY2xvbmVkKS4KCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge2FycmF5fG5vZGV8alF1ZXJ5fSB0cnMgVGhlIFRSIGVsZW1lbnQocykgdG8gYWRkIHRvIHRoZSB0YWJsZQoJICogIEByZXR1cm5zIHthcnJheX0gQXJyYXkgb2YgaW5kZXhlcyBmb3IgdGhlIGFkZGVkIHJvd3MKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuQWRkVHIoIHNldHRpbmdzLCB0cnMgKQoJewoJCXZhciByb3c7CgkKCQkvLyBBbGxvdyBhbiBpbmRpdmlkdWFsIG5vZGUgdG8gYmUgcGFzc2VkIGluCgkJaWYgKCAhICh0cnMgaW5zdGFuY2VvZiAkKSApIHsKCQkJdHJzID0gJCh0cnMpOwoJCX0KCQoJCXJldHVybiB0cnMubWFwKCBmdW5jdGlvbiAoaSwgZWwpIHsKCQkJcm93ID0gX2ZuR2V0Um93RWxlbWVudHMoIHNldHRpbmdzLCBlbCApOwoJCQlyZXR1cm4gX2ZuQWRkRGF0YSggc2V0dGluZ3MsIHJvdy5kYXRhLCBlbCwgcm93LmNlbGxzICk7CgkJfSApOwoJfQoJCgkKCS8qKgoJICogVGFrZSBhIFRSIGVsZW1lbnQgYW5kIGNvbnZlcnQgaXQgdG8gYW4gaW5kZXggaW4gYW9EYXRhCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7bm9kZX0gbiB0aGUgVFIgZWxlbWVudCB0byBmaW5kCgkgKiAgQHJldHVybnMge2ludH0gaW5kZXggaWYgdGhlIG5vZGUgaXMgZm91bmQsIG51bGwgaWYgbm90CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbk5vZGVUb0RhdGFJbmRleCggb1NldHRpbmdzLCBuICkKCXsKCQlyZXR1cm4gKG4uX0RUX1Jvd0luZGV4IT09dW5kZWZpbmVkKSA/IG4uX0RUX1Jvd0luZGV4IDogbnVsbDsKCX0KCQoJCgkvKioKCSAqIFRha2UgYSBURCBlbGVtZW50IGFuZCBjb252ZXJ0IGl0IGludG8gYSBjb2x1bW4gZGF0YSBpbmRleCAobm90IHRoZSB2aXNpYmxlIGluZGV4KQoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge2ludH0gaVJvdyBUaGUgcm93IG51bWJlciB0aGUgVEQvVEggY2FuIGJlIGZvdW5kIGluCgkgKiAgQHBhcmFtIHtub2RlfSBuIFRoZSBURC9USCBlbGVtZW50IHRvIGZpbmQKCSAqICBAcmV0dXJucyB7aW50fSBpbmRleCBpZiB0aGUgbm9kZSBpcyBmb3VuZCwgLTEgaWYgbm90CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbk5vZGVUb0NvbHVtbkluZGV4KCBvU2V0dGluZ3MsIGlSb3csIG4gKQoJewoJCXJldHVybiAkLmluQXJyYXkoIG4sIG9TZXR0aW5ncy5hb0RhdGFbIGlSb3cgXS5hbkNlbGxzICk7Cgl9CgkKCQoJLyoqCgkgKiBHZXQgdGhlIGRhdGEgZm9yIGEgZ2l2ZW4gY2VsbCBmcm9tIHRoZSBpbnRlcm5hbCBjYWNoZSwgdGFraW5nIGludG8gYWNjb3VudCBkYXRhIG1hcHBpbmcKCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge2ludH0gcm93SWR4IGFvRGF0YSByb3cgaWQKCSAqICBAcGFyYW0ge2ludH0gY29sSWR4IENvbHVtbiBpbmRleAoJICogIEBwYXJhbSB7c3RyaW5nfSB0eXBlIGRhdGEgZ2V0IHR5cGUgKCdkaXNwbGF5JywgJ3R5cGUnICdmaWx0ZXJ8c2VhcmNoJyAnc29ydHxvcmRlcicpCgkgKiAgQHJldHVybnMgeyp9IENlbGwgZGF0YQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5HZXRDZWxsRGF0YSggc2V0dGluZ3MsIHJvd0lkeCwgY29sSWR4LCB0eXBlICkKCXsKCQlpZiAodHlwZSA9PT0gJ3NlYXJjaCcpIHsKCQkJdHlwZSA9ICdmaWx0ZXInOwoJCX0KCQllbHNlIGlmICh0eXBlID09PSAnb3JkZXInKSB7CgkJCXR5cGUgPSAnc29ydCc7CgkJfQoJCgkJdmFyIGRyYXcgICAgICAgICAgID0gc2V0dGluZ3MuaURyYXc7CgkJdmFyIGNvbCAgICAgICAgICAgID0gc2V0dGluZ3MuYW9Db2x1bW5zW2NvbElkeF07CgkJdmFyIHJvd0RhdGEgICAgICAgID0gc2V0dGluZ3MuYW9EYXRhW3Jvd0lkeF0uX2FEYXRhOwoJCXZhciBkZWZhdWx0Q29udGVudCA9IGNvbC5zRGVmYXVsdENvbnRlbnQ7CgkJdmFyIGNlbGxEYXRhICAgICAgID0gY29sLmZuR2V0RGF0YSggcm93RGF0YSwgdHlwZSwgewoJCQlzZXR0aW5nczogc2V0dGluZ3MsCgkJCXJvdzogICAgICByb3dJZHgsCgkJCWNvbDogICAgICBjb2xJZHgKCQl9ICk7CgkKCQlpZiAoIGNlbGxEYXRhID09PSB1bmRlZmluZWQgKSB7CgkJCWlmICggc2V0dGluZ3MuaURyYXdFcnJvciAhPSBkcmF3ICYmIGRlZmF1bHRDb250ZW50ID09PSBudWxsICkgewoJCQkJX2ZuTG9nKCBzZXR0aW5ncywgMCwgIlJlcXVlc3RlZCB1bmtub3duIHBhcmFtZXRlciAiKwoJCQkJCSh0eXBlb2YgY29sLm1EYXRhPT0nZnVuY3Rpb24nID8gJ3tmdW5jdGlvbn0nIDogIiciK2NvbC5tRGF0YSsiJyIpKwoJCQkJCSIgZm9yIHJvdyAiK3Jvd0lkeCsiLCBjb2x1bW4gIitjb2xJZHgsIDQgKTsKCQkJCXNldHRpbmdzLmlEcmF3RXJyb3IgPSBkcmF3OwoJCQl9CgkJCXJldHVybiBkZWZhdWx0Q29udGVudDsKCQl9CgkKCQkvLyBXaGVuIHRoZSBkYXRhIHNvdXJjZSBpcyBudWxsIGFuZCBhIHNwZWNpZmljIGRhdGEgdHlwZSBpcyByZXF1ZXN0ZWQgKGkuZS4KCQkvLyBub3QgdGhlIG9yaWdpbmFsIGRhdGEpLCB3ZSBjYW4gdXNlIGRlZmF1bHQgY29sdW1uIGRhdGEKCQlpZiAoIChjZWxsRGF0YSA9PT0gcm93RGF0YSB8fCBjZWxsRGF0YSA9PT0gbnVsbCkgJiYgZGVmYXVsdENvbnRlbnQgIT09IG51bGwgJiYgdHlwZSAhPT0gdW5kZWZpbmVkICkgewoJCQljZWxsRGF0YSA9IGRlZmF1bHRDb250ZW50OwoJCX0KCQllbHNlIGlmICggdHlwZW9mIGNlbGxEYXRhID09PSAnZnVuY3Rpb24nICkgewoJCQkvLyBJZiB0aGUgZGF0YSBzb3VyY2UgaXMgYSBmdW5jdGlvbiwgdGhlbiB3ZSBydW4gaXQgYW5kIHVzZSB0aGUgcmV0dXJuLAoJCQkvLyBleGVjdXRpbmcgaW4gdGhlIHNjb3BlIG9mIHRoZSBkYXRhIG9iamVjdCAoZm9yIGluc3RhbmNlcykKCQkJcmV0dXJuIGNlbGxEYXRhLmNhbGwoIHJvd0RhdGEgKTsKCQl9CgkKCQlpZiAoIGNlbGxEYXRhID09PSBudWxsICYmIHR5cGUgPT09ICdkaXNwbGF5JyApIHsKCQkJcmV0dXJuICcnOwoJCX0KCQoJCWlmICggdHlwZSA9PT0gJ2ZpbHRlcicgKSB7CgkJCXZhciBmb21hdHRlcnMgPSBEYXRhVGFibGUuZXh0LnR5cGUuc2VhcmNoOwoJCgkJCWlmICggZm9tYXR0ZXJzWyBjb2wuc1R5cGUgXSApIHsKCQkJCWNlbGxEYXRhID0gZm9tYXR0ZXJzWyBjb2wuc1R5cGUgXSggY2VsbERhdGEgKTsKCQkJfQoJCX0KCQoJCXJldHVybiBjZWxsRGF0YTsKCX0KCQoJCgkvKioKCSAqIFNldCB0aGUgdmFsdWUgZm9yIGEgc3BlY2lmaWMgY2VsbCwgaW50byB0aGUgaW50ZXJuYWwgZGF0YSBjYWNoZQoJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7aW50fSByb3dJZHggYW9EYXRhIHJvdyBpZAoJICogIEBwYXJhbSB7aW50fSBjb2xJZHggQ29sdW1uIGluZGV4CgkgKiAgQHBhcmFtIHsqfSB2YWwgVmFsdWUgdG8gc2V0CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mblNldENlbGxEYXRhKCBzZXR0aW5ncywgcm93SWR4LCBjb2xJZHgsIHZhbCApCgl7CgkJdmFyIGNvbCAgICAgPSBzZXR0aW5ncy5hb0NvbHVtbnNbY29sSWR4XTsKCQl2YXIgcm93RGF0YSA9IHNldHRpbmdzLmFvRGF0YVtyb3dJZHhdLl9hRGF0YTsKCQoJCWNvbC5mblNldERhdGEoIHJvd0RhdGEsIHZhbCwgewoJCQlzZXR0aW5nczogc2V0dGluZ3MsCgkJCXJvdzogICAgICByb3dJZHgsCgkJCWNvbDogICAgICBjb2xJZHgKCQl9ICApOwoJfQoJCgkKCS8vIFByaXZhdGUgdmFyaWFibGUgdGhhdCBpcyB1c2VkIHRvIG1hdGNoIGFjdGlvbiBzeW50YXggaW4gdGhlIGRhdGEgcHJvcGVydHkgb2JqZWN0Cgl2YXIgX19yZUFycmF5ID0gL1xbLio/XF0kLzsKCXZhciBfX3JlRm4gPSAvXChcKSQvOwoJCgkvKioKCSAqIFNwbGl0IHN0cmluZyBvbiBwZXJpb2RzLCB0YWtpbmcgaW50byBhY2NvdW50IGVzY2FwZWQgcGVyaW9kcwoJICogQHBhcmFtICB7c3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0CgkgKiBAcmV0dXJuIHthcnJheX0gU3BsaXQgc3RyaW5nCgkgKi8KCWZ1bmN0aW9uIF9mblNwbGl0T2JqTm90YXRpb24oIHN0ciApCgl7CgkJcmV0dXJuICQubWFwKCBzdHIubWF0Y2goLyhcXC58W15cLl0pKy9nKSB8fCBbJyddLCBmdW5jdGlvbiAoIHMgKSB7CgkJCXJldHVybiBzLnJlcGxhY2UoL1xcXC4vZywgJy4nKTsKCQl9ICk7Cgl9CgkKCQoJLyoqCgkgKiBSZXR1cm4gYSBmdW5jdGlvbiB0aGF0IGNhbiBiZSB1c2VkIHRvIGdldCBkYXRhIGZyb20gYSBzb3VyY2Ugb2JqZWN0LCB0YWtpbmcKCSAqIGludG8gYWNjb3VudCB0aGUgYWJpbGl0eSB0byB1c2UgbmVzdGVkIG9iamVjdHMgYXMgYSBzb3VyY2UKCSAqICBAcGFyYW0ge3N0cmluZ3xpbnR8ZnVuY3Rpb259IG1Tb3VyY2UgVGhlIGRhdGEgc291cmNlIGZvciB0aGUgb2JqZWN0CgkgKiAgQHJldHVybnMge2Z1bmN0aW9ufSBEYXRhIGdldCBmdW5jdGlvbgoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCgl2YXIgX2ZuR2V0T2JqZWN0RGF0YUZuID0gRGF0YVRhYmxlLnV0aWwuZ2V0OwoJCgkKCS8qKgoJICogUmV0dXJuIGEgZnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCB0byBzZXQgZGF0YSBmcm9tIGEgc291cmNlIG9iamVjdCwgdGFraW5nCgkgKiBpbnRvIGFjY291bnQgdGhlIGFiaWxpdHkgdG8gdXNlIG5lc3RlZCBvYmplY3RzIGFzIGEgc291cmNlCgkgKiAgQHBhcmFtIHtzdHJpbmd8aW50fGZ1bmN0aW9ufSBtU291cmNlIFRoZSBkYXRhIHNvdXJjZSBmb3IgdGhlIG9iamVjdAoJICogIEByZXR1cm5zIHtmdW5jdGlvbn0gRGF0YSBzZXQgZnVuY3Rpb24KCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJdmFyIF9mblNldE9iamVjdERhdGFGbiA9IERhdGFUYWJsZS51dGlsLnNldDsKCQoJCgkvKioKCSAqIFJldHVybiBhbiBhcnJheSB3aXRoIHRoZSBmdWxsIHRhYmxlIGRhdGEKCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHJldHVybnMgYXJyYXkge2FycmF5fSBhRGF0YSBNYXN0ZXIgZGF0YSBhcnJheQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5HZXREYXRhTWFzdGVyICggc2V0dGluZ3MgKQoJewoJCXJldHVybiBfcGx1Y2soIHNldHRpbmdzLmFvRGF0YSwgJ19hRGF0YScgKTsKCX0KCQoJCgkvKioKCSAqIE51a2UgdGhlIHRhYmxlCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5DbGVhclRhYmxlKCBzZXR0aW5ncyApCgl7CgkJc2V0dGluZ3MuYW9EYXRhLmxlbmd0aCA9IDA7CgkJc2V0dGluZ3MuYWlEaXNwbGF5TWFzdGVyLmxlbmd0aCA9IDA7CgkJc2V0dGluZ3MuYWlEaXNwbGF5Lmxlbmd0aCA9IDA7CgkJc2V0dGluZ3MuYUlkcyA9IHt9OwoJfQoJCgkKCSAvKioKCSAqIFRha2UgYW4gYXJyYXkgb2YgaW50ZWdlcnMgKGluZGV4IGFycmF5KSBhbmQgcmVtb3ZlIGEgdGFyZ2V0IGludGVnZXIgKHZhbHVlIC0gbm90CgkgKiB0aGUga2V5ISkKCSAqICBAcGFyYW0ge2FycmF5fSBhIEluZGV4IGFycmF5IHRvIHRhcmdldAoJICogIEBwYXJhbSB7aW50fSBpVGFyZ2V0IHZhbHVlIHRvIGZpbmQKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuRGVsZXRlSW5kZXgoIGEsIGlUYXJnZXQsIHNwbGljZSApCgl7CgkJdmFyIGlUYXJnZXRJbmRleCA9IC0xOwoJCgkJZm9yICggdmFyIGk9MCwgaUxlbj1hLmxlbmd0aCA7IGk8aUxlbiA7IGkrKyApCgkJewoJCQlpZiAoIGFbaV0gPT0gaVRhcmdldCApCgkJCXsKCQkJCWlUYXJnZXRJbmRleCA9IGk7CgkJCX0KCQkJZWxzZSBpZiAoIGFbaV0gPiBpVGFyZ2V0ICkKCQkJewoJCQkJYVtpXS0tOwoJCQl9CgkJfQoJCgkJaWYgKCBpVGFyZ2V0SW5kZXggIT0gLTEgJiYgc3BsaWNlID09PSB1bmRlZmluZWQgKQoJCXsKCQkJYS5zcGxpY2UoIGlUYXJnZXRJbmRleCwgMSApOwoJCX0KCX0KCQoJCgkvKioKCSAqIE1hcmsgY2FjaGVkIGRhdGEgYXMgaW52YWxpZCBzdWNoIHRoYXQgYSByZS1yZWFkIG9mIHRoZSBkYXRhIHdpbGwgb2NjdXIgd2hlbgoJICogdGhlIGNhY2hlZCBkYXRhIGlzIG5leHQgcmVxdWVzdGVkLiBBbHNvIHVwZGF0ZSBmcm9tIHRoZSBkYXRhIHNvdXJjZSBvYmplY3QuCgkgKgoJICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiBAcGFyYW0ge2ludH0gICAgcm93SWR4ICAgUm93IGluZGV4IHRvIGludmFsaWRhdGUKCSAqIEBwYXJhbSB7c3RyaW5nfSBbc3JjXSAgICBTb3VyY2UgdG8gaW52YWxpZGF0ZSBmcm9tOiB1bmRlZmluZWQsICdhdXRvJywgJ2RvbScKCSAqICAgICBvciAnZGF0YScKCSAqIEBwYXJhbSB7aW50fSAgICBbY29sSWR4XSBDb2x1bW4gaW5kZXggdG8gaW52YWxpZGF0ZS4gSWYgdW5kZWZpbmVkIHRoZSB3aG9sZQoJICogICAgIHJvdyB3aWxsIGJlIGludmFsaWRhdGVkCgkgKiBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqCgkgKiBAdG9kbyBGb3IgdGhlIG1vZHVsYXJpc2F0aW9uIG9mIHYxLjExIHRoaXMgd2lsbCBuZWVkIHRvIGJlY29tZSBhIGNhbGxiYWNrLCBzbwoJICogICB0aGUgc29ydCBhbmQgZmlsdGVyIG1ldGhvZHMgY2FuIHN1YnNjcmliZSB0byBpdC4gVGhhdCB3aWxsIHJlcXVpcmVkCgkgKiAgIGluaXRpYWxpc2F0aW9uIG9wdGlvbnMgZm9yIHNvcnRpbmcsIHdoaWNoIGlzIHdoeSBpdCBpcyBub3QgYWxyZWFkeSBiYWtlZCBpbgoJICovCglmdW5jdGlvbiBfZm5JbnZhbGlkYXRlKCBzZXR0aW5ncywgcm93SWR4LCBzcmMsIGNvbElkeCApCgl7CgkJdmFyIHJvdyA9IHNldHRpbmdzLmFvRGF0YVsgcm93SWR4IF07CgkJdmFyIGksIGllbjsKCQl2YXIgY2VsbFdyaXRlID0gZnVuY3Rpb24gKCBjZWxsLCBjb2wgKSB7CgkJCS8vIFRoaXMgaXMgdmVyeSBmcnVzdHJhdGluZywgYnV0IGluIElFIGlmIHlvdSBqdXN0IHdyaXRlIGRpcmVjdGx5CgkJCS8vIHRvIGlubmVySFRNTCwgYW5kIGVsZW1lbnRzIHRoYXQgYXJlIG92ZXJ3cml0dGVuIGFyZSBHQydlZCwKCQkJLy8gZXZlbiBpZiB0aGVyZSBpcyBhIHJlZmVyZW5jZSB0byB0aGVtIGVsc2V3aGVyZQoJCQl3aGlsZSAoIGNlbGwuY2hpbGROb2Rlcy5sZW5ndGggKSB7CgkJCQljZWxsLnJlbW92ZUNoaWxkKCBjZWxsLmZpcnN0Q2hpbGQgKTsKCQkJfQoJCgkJCWNlbGwuaW5uZXJIVE1MID0gX2ZuR2V0Q2VsbERhdGEoIHNldHRpbmdzLCByb3dJZHgsIGNvbCwgJ2Rpc3BsYXknICk7CgkJfTsKCQoJCS8vIEFyZSB3ZSByZWFkaW5nIGxhc3QgZGF0YSBmcm9tIERPTSBvciB0aGUgZGF0YSBvYmplY3Q/CgkJaWYgKCBzcmMgPT09ICdkb20nIHx8ICgoISBzcmMgfHwgc3JjID09PSAnYXV0bycpICYmIHJvdy5zcmMgPT09ICdkb20nKSApIHsKCQkJLy8gUmVhZCB0aGUgZGF0YSBmcm9tIHRoZSBET00KCQkJcm93Ll9hRGF0YSA9IF9mbkdldFJvd0VsZW1lbnRzKAoJCQkJCXNldHRpbmdzLCByb3csIGNvbElkeCwgY29sSWR4ID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWQgOiByb3cuX2FEYXRhCgkJCQkpCgkJCQkuZGF0YTsKCQl9CgkJZWxzZSB7CgkJCS8vIFJlYWRpbmcgZnJvbSBkYXRhIG9iamVjdCwgdXBkYXRlIHRoZSBET00KCQkJdmFyIGNlbGxzID0gcm93LmFuQ2VsbHM7CgkKCQkJaWYgKCBjZWxscyApIHsKCQkJCWlmICggY29sSWR4ICE9PSB1bmRlZmluZWQgKSB7CgkJCQkJY2VsbFdyaXRlKCBjZWxsc1tjb2xJZHhdLCBjb2xJZHggKTsKCQkJCX0KCQkJCWVsc2UgewoJCQkJCWZvciAoIGk9MCwgaWVuPWNlbGxzLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJCQljZWxsV3JpdGUoIGNlbGxzW2ldLCBpICk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCgkJLy8gRm9yIGJvdGggcm93IGFuZCBjZWxsIGludmFsaWRhdGlvbiwgdGhlIGNhY2hlZCBkYXRhIGZvciBzb3J0aW5nIGFuZAoJCS8vIGZpbHRlcmluZyBpcyBudWxsZWQgb3V0CgkJcm93Ll9hU29ydERhdGEgPSBudWxsOwoJCXJvdy5fYUZpbHRlckRhdGEgPSBudWxsOwoJCgkJLy8gSW52YWxpZGF0ZSB0aGUgdHlwZSBmb3IgYSBzcGVjaWZpYyBjb2x1bW4gKGlmIGdpdmVuKSBvciBhbGwgY29sdW1ucyBzaW5jZQoJCS8vIHRoZSBkYXRhIG1pZ2h0IGhhdmUgY2hhbmdlZAoJCXZhciBjb2xzID0gc2V0dGluZ3MuYW9Db2x1bW5zOwoJCWlmICggY29sSWR4ICE9PSB1bmRlZmluZWQgKSB7CgkJCWNvbHNbIGNvbElkeCBdLnNUeXBlID0gbnVsbDsKCQl9CgkJZWxzZSB7CgkJCWZvciAoIGk9MCwgaWVuPWNvbHMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQljb2xzW2ldLnNUeXBlID0gbnVsbDsKCQkJfQoJCgkJCS8vIFVwZGF0ZSBEYXRhVGFibGVzIHNwZWNpYWwgYERUXypgIGF0dHJpYnV0ZXMgZm9yIHRoZSByb3cKCQkJX2ZuUm93QXR0cmlidXRlcyggc2V0dGluZ3MsIHJvdyApOwoJCX0KCX0KCQoJCgkvKioKCSAqIEJ1aWxkIGEgZGF0YSBzb3VyY2Ugb2JqZWN0IGZyb20gYW4gSFRNTCByb3csIHJlYWRpbmcgdGhlIGNvbnRlbnRzIG9mIHRoZQoJICogY2VsbHMgdGhhdCBhcmUgaW4gdGhlIHJvdy4KCSAqCgkgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqIEBwYXJhbSB7bm9kZXxvYmplY3R9IFRSIGVsZW1lbnQgZnJvbSB3aGljaCB0byByZWFkIGRhdGEgb3IgZXhpc3Rpbmcgcm93CgkgKiAgIG9iamVjdCBmcm9tIHdoaWNoIHRvIHJlLXJlYWQgdGhlIGRhdGEgZnJvbSB0aGUgY2VsbHMKCSAqIEBwYXJhbSB7aW50fSBbY29sSWR4XSBPcHRpb25hbCBjb2x1bW4gaW5kZXgKCSAqIEBwYXJhbSB7YXJyYXl8b2JqZWN0fSBbZF0gRGF0YSBzb3VyY2Ugb2JqZWN0LiBJZiBgY29sSWR4YCBpcyBnaXZlbiB0aGVuIHRoaXMKCSAqICAgcGFyYW1ldGVyIHNob3VsZCBhbHNvIGJlIGdpdmVuIGFuZCB3aWxsIGJlIHVzZWQgdG8gd3JpdGUgdGhlIGRhdGEgaW50by4KCSAqICAgT25seSB0aGUgY29sdW1uIGluIHF1ZXN0aW9uIHdpbGwgYmUgd3JpdHRlbgoJICogQHJldHVybnMge29iamVjdH0gT2JqZWN0IHdpdGggdHdvIHBhcmFtZXRlcnM6IGBkYXRhYCB0aGUgZGF0YSByZWFkLCBpbgoJICogICBkb2N1bWVudCBvcmRlciwgYW5kIGBjZWxsc2AgYW5kIGFycmF5IG9mIG5vZGVzICh0aGV5IGNhbiBiZSB1c2VmdWwgdG8gdGhlCgkgKiAgIGNhbGxlciwgc28gcmF0aGVyIHRoYW4gbmVlZGluZyBhIHNlY29uZCB0cmF2ZXJzYWwgdG8gZ2V0IHRoZW0sIGp1c3QgcmV0dXJuCgkgKiAgIHRoZW0gZnJvbSBoZXJlKS4KCSAqIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5HZXRSb3dFbGVtZW50cyggc2V0dGluZ3MsIHJvdywgY29sSWR4LCBkICkKCXsKCQl2YXIKCQkJdGRzID0gW10sCgkJCXRkID0gcm93LmZpcnN0Q2hpbGQsCgkJCW5hbWUsIGNvbCwgbywgaT0wLCBjb250ZW50cywKCQkJY29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1ucywKCQkJb2JqZWN0UmVhZCA9IHNldHRpbmdzLl9yb3dSZWFkT2JqZWN0OwoJCgkJLy8gQWxsb3cgdGhlIGRhdGEgb2JqZWN0IHRvIGJlIHBhc3NlZCBpbiwgb3IgY29uc3RydWN0CgkJZCA9IGQgIT09IHVuZGVmaW5lZCA/CgkJCWQgOgoJCQlvYmplY3RSZWFkID8KCQkJCXt9IDoKCQkJCVtdOwoJCgkJdmFyIGF0dHIgPSBmdW5jdGlvbiAoIHN0ciwgdGQgICkgewoJCQlpZiAoIHR5cGVvZiBzdHIgPT09ICdzdHJpbmcnICkgewoJCQkJdmFyIGlkeCA9IHN0ci5pbmRleE9mKCdAJyk7CgkKCQkJCWlmICggaWR4ICE9PSAtMSApIHsKCQkJCQl2YXIgYXR0ciA9IHN0ci5zdWJzdHJpbmcoIGlkeCsxICk7CgkJCQkJdmFyIHNldHRlciA9IF9mblNldE9iamVjdERhdGFGbiggc3RyICk7CgkJCQkJc2V0dGVyKCBkLCB0ZC5nZXRBdHRyaWJ1dGUoIGF0dHIgKSApOwoJCQkJfQoJCQl9CgkJfTsKCQoJCS8vIFJlYWQgZGF0YSBmcm9tIGEgY2VsbCBhbmQgc3RvcmUgaW50byB0aGUgZGF0YSBvYmplY3QKCQl2YXIgY2VsbFByb2Nlc3MgPSBmdW5jdGlvbiAoIGNlbGwgKSB7CgkJCWlmICggY29sSWR4ID09PSB1bmRlZmluZWQgfHwgY29sSWR4ID09PSBpICkgewoJCQkJY29sID0gY29sdW1uc1tpXTsKCQkJCWNvbnRlbnRzID0gKGNlbGwuaW5uZXJIVE1MKS50cmltKCk7CgkKCQkJCWlmICggY29sICYmIGNvbC5fYkF0dHJTcmMgKSB7CgkJCQkJdmFyIHNldHRlciA9IF9mblNldE9iamVjdERhdGFGbiggY29sLm1EYXRhLl8gKTsKCQkJCQlzZXR0ZXIoIGQsIGNvbnRlbnRzICk7CgkKCQkJCQlhdHRyKCBjb2wubURhdGEuc29ydCwgY2VsbCApOwoJCQkJCWF0dHIoIGNvbC5tRGF0YS50eXBlLCBjZWxsICk7CgkJCQkJYXR0ciggY29sLm1EYXRhLmZpbHRlciwgY2VsbCApOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJLy8gRGVwZW5kaW5nIG9uIHRoZSBgZGF0YWAgb3B0aW9uIGZvciB0aGUgY29sdW1ucyB0aGUgZGF0YSBjYW4KCQkJCQkvLyBiZSByZWFkIHRvIGVpdGhlciBhbiBvYmplY3Qgb3IgYW4gYXJyYXkuCgkJCQkJaWYgKCBvYmplY3RSZWFkICkgewoJCQkJCQlpZiAoICEgY29sLl9zZXR0ZXIgKSB7CgkJCQkJCQkvLyBDYWNoZSB0aGUgc2V0dGVyIGZ1bmN0aW9uCgkJCQkJCQljb2wuX3NldHRlciA9IF9mblNldE9iamVjdERhdGFGbiggY29sLm1EYXRhICk7CgkJCQkJCX0KCQkJCQkJY29sLl9zZXR0ZXIoIGQsIGNvbnRlbnRzICk7CgkJCQkJfQoJCQkJCWVsc2UgewoJCQkJCQlkW2ldID0gY29udGVudHM7CgkJCQkJfQoJCQkJfQoJCQl9CgkKCQkJaSsrOwoJCX07CgkKCQlpZiAoIHRkICkgewoJCQkvLyBgdHJgIGVsZW1lbnQgd2FzIHBhc3NlZCBpbgoJCQl3aGlsZSAoIHRkICkgewoJCQkJbmFtZSA9IHRkLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCk7CgkKCQkJCWlmICggbmFtZSA9PSAiVEQiIHx8IG5hbWUgPT0gIlRIIiApIHsKCQkJCQljZWxsUHJvY2VzcyggdGQgKTsKCQkJCQl0ZHMucHVzaCggdGQgKTsKCQkJCX0KCQoJCQkJdGQgPSB0ZC5uZXh0U2libGluZzsKCQkJfQoJCX0KCQllbHNlIHsKCQkJLy8gRXhpc3Rpbmcgcm93IG9iamVjdCBwYXNzZWQgaW4KCQkJdGRzID0gcm93LmFuQ2VsbHM7CgkKCQkJZm9yICggdmFyIGo9MCwgamVuPXRkcy5sZW5ndGggOyBqPGplbiA7IGorKyApIHsKCQkJCWNlbGxQcm9jZXNzKCB0ZHNbal0gKTsKCQkJfQoJCX0KCQoJCS8vIFJlYWQgdGhlIElEIGZyb20gdGhlIERPTSBpZiBwcmVzZW50CgkJdmFyIHJvd05vZGUgPSByb3cuZmlyc3RDaGlsZCA/IHJvdyA6IHJvdy5uVHI7CgkKCQlpZiAoIHJvd05vZGUgKSB7CgkJCXZhciBpZCA9IHJvd05vZGUuZ2V0QXR0cmlidXRlKCAnaWQnICk7CgkKCQkJaWYgKCBpZCApIHsKCQkJCV9mblNldE9iamVjdERhdGFGbiggc2V0dGluZ3Mucm93SWQgKSggZCwgaWQgKTsKCQkJfQoJCX0KCQoJCXJldHVybiB7CgkJCWRhdGE6IGQsCgkJCWNlbGxzOiB0ZHMKCQl9OwoJfQoJLyoqCgkgKiBDcmVhdGUgYSBuZXcgVFIgZWxlbWVudCAoYW5kIGl0J3MgVEQgY2hpbGRyZW4pIGZvciBhIHJvdwoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge2ludH0gaVJvdyBSb3cgdG8gY29uc2lkZXIKCSAqICBAcGFyYW0ge25vZGV9IFtuVHJJbl0gVFIgZWxlbWVudCB0byBhZGQgdG8gdGhlIHRhYmxlIC0gb3B0aW9uYWwuIElmIG5vdCBnaXZlbiwKCSAqICAgIERhdGFUYWJsZXMgd2lsbCBjcmVhdGUgYSByb3cgYXV0b21hdGljYWxseQoJICogIEBwYXJhbSB7YXJyYXl9IFthblRkc10gQXJyYXkgb2YgVER8VEggZWxlbWVudHMgZm9yIHRoZSByb3cgLSBtdXN0IGJlIGdpdmVuCgkgKiAgICBpZiBuVHIgaXMuCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkNyZWF0ZVRyICggb1NldHRpbmdzLCBpUm93LCBuVHJJbiwgYW5UZHMgKQoJewoJCXZhcgoJCQlyb3cgPSBvU2V0dGluZ3MuYW9EYXRhW2lSb3ddLAoJCQlyb3dEYXRhID0gcm93Ll9hRGF0YSwKCQkJY2VsbHMgPSBbXSwKCQkJblRyLCBuVGQsIG9Db2wsCgkJCWksIGlMZW4sIGNyZWF0ZTsKCQoJCWlmICggcm93Lm5UciA9PT0gbnVsbCApCgkJewoJCQluVHIgPSBuVHJJbiB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0cicpOwoJCgkJCXJvdy5uVHIgPSBuVHI7CgkJCXJvdy5hbkNlbGxzID0gY2VsbHM7CgkKCQkJLyogVXNlIGEgcHJpdmF0ZSBwcm9wZXJ0eSBvbiB0aGUgbm9kZSB0byBhbGxvdyByZXNlcnZlIG1hcHBpbmcgZnJvbSB0aGUgbm9kZQoJCQkgKiB0byB0aGUgYW9EYXRhIGFycmF5IGZvciBmYXN0IGxvb2sgdXAKCQkJICovCgkJCW5Uci5fRFRfUm93SW5kZXggPSBpUm93OwoJCgkJCS8qIFNwZWNpYWwgcGFyYW1ldGVycyBjYW4gYmUgZ2l2ZW4gYnkgdGhlIGRhdGEgc291cmNlIHRvIGJlIHVzZWQgb24gdGhlIHJvdyAqLwoJCQlfZm5Sb3dBdHRyaWJ1dGVzKCBvU2V0dGluZ3MsIHJvdyApOwoJCgkJCS8qIFByb2Nlc3MgZWFjaCBjb2x1bW4gKi8KCQkJZm9yICggaT0wLCBpTGVuPW9TZXR0aW5ncy5hb0NvbHVtbnMubGVuZ3RoIDsgaTxpTGVuIDsgaSsrICkKCQkJewoJCQkJb0NvbCA9IG9TZXR0aW5ncy5hb0NvbHVtbnNbaV07CgkJCQljcmVhdGUgPSBuVHJJbiA/IGZhbHNlIDogdHJ1ZTsKCQoJCQkJblRkID0gY3JlYXRlID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggb0NvbC5zQ2VsbFR5cGUgKSA6IGFuVGRzW2ldOwoJCQkJblRkLl9EVF9DZWxsSW5kZXggPSB7CgkJCQkJcm93OiBpUm93LAoJCQkJCWNvbHVtbjogaQoJCQkJfTsKCQkJCQoJCQkJY2VsbHMucHVzaCggblRkICk7CgkKCQkJCS8vIE5lZWQgdG8gY3JlYXRlIHRoZSBIVE1MIGlmIG5ldywgb3IgaWYgYSByZW5kZXJpbmcgZnVuY3Rpb24gaXMgZGVmaW5lZAoJCQkJaWYgKCBjcmVhdGUgfHwgKChvQ29sLm1SZW5kZXIgfHwgb0NvbC5tRGF0YSAhPT0gaSkgJiYKCQkJCQkgKCEkLmlzUGxhaW5PYmplY3Qob0NvbC5tRGF0YSkgfHwgb0NvbC5tRGF0YS5fICE9PSBpKycuZGlzcGxheScpCgkJCQkpKSB7CgkJCQkJblRkLmlubmVySFRNTCA9IF9mbkdldENlbGxEYXRhKCBvU2V0dGluZ3MsIGlSb3csIGksICdkaXNwbGF5JyApOwoJCQkJfQoJCgkJCQkvKiBBZGQgdXNlciBkZWZpbmVkIGNsYXNzICovCgkJCQlpZiAoIG9Db2wuc0NsYXNzICkKCQkJCXsKCQkJCQluVGQuY2xhc3NOYW1lICs9ICcgJytvQ29sLnNDbGFzczsKCQkJCX0KCQoJCQkJLy8gVmlzaWJpbGl0eSAtIGFkZCBvciByZW1vdmUgYXMgcmVxdWlyZWQKCQkJCWlmICggb0NvbC5iVmlzaWJsZSAmJiAhIG5UckluICkKCQkJCXsKCQkJCQluVHIuYXBwZW5kQ2hpbGQoIG5UZCApOwoJCQkJfQoJCQkJZWxzZSBpZiAoICEgb0NvbC5iVmlzaWJsZSAmJiBuVHJJbiApCgkJCQl7CgkJCQkJblRkLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIG5UZCApOwoJCQkJfQoJCgkJCQlpZiAoIG9Db2wuZm5DcmVhdGVkQ2VsbCApCgkJCQl7CgkJCQkJb0NvbC5mbkNyZWF0ZWRDZWxsLmNhbGwoIG9TZXR0aW5ncy5vSW5zdGFuY2UsCgkJCQkJCW5UZCwgX2ZuR2V0Q2VsbERhdGEoIG9TZXR0aW5ncywgaVJvdywgaSApLCByb3dEYXRhLCBpUm93LCBpCgkJCQkJKTsKCQkJCX0KCQkJfQoJCgkJCV9mbkNhbGxiYWNrRmlyZSggb1NldHRpbmdzLCAnYW9Sb3dDcmVhdGVkQ2FsbGJhY2snLCBudWxsLCBbblRyLCByb3dEYXRhLCBpUm93LCBjZWxsc10gKTsKCQl9Cgl9CgkKCQoJLyoqCgkgKiBBZGQgYXR0cmlidXRlcyB0byBhIHJvdyBiYXNlZCBvbiB0aGUgc3BlY2lhbCBgRFRfKmAgcGFyYW1ldGVycyBpbiBhIGRhdGEKCSAqIHNvdXJjZSBvYmplY3QuCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIHtvYmplY3R9IERhdGFUYWJsZXMgcm93IG9iamVjdCBmb3IgdGhlIHJvdyB0byBiZSBtb2RpZmllZAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5Sb3dBdHRyaWJ1dGVzKCBzZXR0aW5ncywgcm93ICkKCXsKCQl2YXIgdHIgPSByb3cublRyOwoJCXZhciBkYXRhID0gcm93Ll9hRGF0YTsKCQoJCWlmICggdHIgKSB7CgkJCXZhciBpZCA9IHNldHRpbmdzLnJvd0lkRm4oIGRhdGEgKTsKCQoJCQlpZiAoIGlkICkgewoJCQkJdHIuaWQgPSBpZDsKCQkJfQoJCgkJCWlmICggZGF0YS5EVF9Sb3dDbGFzcyApIHsKCQkJCS8vIFJlbW92ZSBhbnkgY2xhc3NlcyBhZGRlZCBieSBEVF9Sb3dDbGFzcyBiZWZvcmUKCQkJCXZhciBhID0gZGF0YS5EVF9Sb3dDbGFzcy5zcGxpdCgnICcpOwoJCQkJcm93Ll9fcm93YyA9IHJvdy5fX3Jvd2MgPwoJCQkJCV91bmlxdWUoIHJvdy5fX3Jvd2MuY29uY2F0KCBhICkgKSA6CgkJCQkJYTsKCQoJCQkJJCh0cikKCQkJCQkucmVtb3ZlQ2xhc3MoIHJvdy5fX3Jvd2Muam9pbignICcpICkKCQkJCQkuYWRkQ2xhc3MoIGRhdGEuRFRfUm93Q2xhc3MgKTsKCQkJfQoJCgkJCWlmICggZGF0YS5EVF9Sb3dBdHRyICkgewoJCQkJJCh0cikuYXR0ciggZGF0YS5EVF9Sb3dBdHRyICk7CgkJCX0KCQoJCQlpZiAoIGRhdGEuRFRfUm93RGF0YSApIHsKCQkJCSQodHIpLmRhdGEoIGRhdGEuRFRfUm93RGF0YSApOwoJCQl9CgkJfQoJfQoJCgkKCS8qKgoJICogQ3JlYXRlIHRoZSBIVE1MIGhlYWRlciBmb3IgdGhlIHRhYmxlCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5CdWlsZEhlYWQoIG9TZXR0aW5ncyApCgl7CgkJdmFyIGksIGllbiwgY2VsbCwgcm93LCBjb2x1bW47CgkJdmFyIHRoZWFkID0gb1NldHRpbmdzLm5USGVhZDsKCQl2YXIgdGZvb3QgPSBvU2V0dGluZ3MublRGb290OwoJCXZhciBjcmVhdGVIZWFkZXIgPSAkKCd0aCwgdGQnLCB0aGVhZCkubGVuZ3RoID09PSAwOwoJCXZhciBjbGFzc2VzID0gb1NldHRpbmdzLm9DbGFzc2VzOwoJCXZhciBjb2x1bW5zID0gb1NldHRpbmdzLmFvQ29sdW1uczsKCQoJCWlmICggY3JlYXRlSGVhZGVyICkgewoJCQlyb3cgPSAkKCc8dHIvPicpLmFwcGVuZFRvKCB0aGVhZCApOwoJCX0KCQoJCWZvciAoIGk9MCwgaWVuPWNvbHVtbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCWNvbHVtbiA9IGNvbHVtbnNbaV07CgkJCWNlbGwgPSAkKCBjb2x1bW4ublRoICkuYWRkQ2xhc3MoIGNvbHVtbi5zQ2xhc3MgKTsKCQoJCQlpZiAoIGNyZWF0ZUhlYWRlciApIHsKCQkJCWNlbGwuYXBwZW5kVG8oIHJvdyApOwoJCQl9CgkKCQkJLy8gMS4xMSBtb3ZlIGludG8gc29ydGluZwoJCQlpZiAoIG9TZXR0aW5ncy5vRmVhdHVyZXMuYlNvcnQgKSB7CgkJCQljZWxsLmFkZENsYXNzKCBjb2x1bW4uc1NvcnRpbmdDbGFzcyApOwoJCgkJCQlpZiAoIGNvbHVtbi5iU29ydGFibGUgIT09IGZhbHNlICkgewoJCQkJCWNlbGwKCQkJCQkJLmF0dHIoICd0YWJpbmRleCcsIG9TZXR0aW5ncy5pVGFiSW5kZXggKQoJCQkJCQkuYXR0ciggJ2FyaWEtY29udHJvbHMnLCBvU2V0dGluZ3Muc1RhYmxlSWQgKTsKCQoJCQkJCV9mblNvcnRBdHRhY2hMaXN0ZW5lciggb1NldHRpbmdzLCBjb2x1bW4ublRoLCBpICk7CgkJCQl9CgkJCX0KCQoJCQlpZiAoIGNvbHVtbi5zVGl0bGUgIT0gY2VsbFswXS5pbm5lckhUTUwgKSB7CgkJCQljZWxsLmh0bWwoIGNvbHVtbi5zVGl0bGUgKTsKCQkJfQoJCgkJCV9mblJlbmRlcmVyKCBvU2V0dGluZ3MsICdoZWFkZXInICkoCgkJCQlvU2V0dGluZ3MsIGNlbGwsIGNvbHVtbiwgY2xhc3NlcwoJCQkpOwoJCX0KCQoJCWlmICggY3JlYXRlSGVhZGVyICkgewoJCQlfZm5EZXRlY3RIZWFkZXIoIG9TZXR0aW5ncy5hb0hlYWRlciwgdGhlYWQgKTsKCQl9CgkKCQkvKiBEZWFsIHdpdGggdGhlIGZvb3RlciAtIGFkZCBjbGFzc2VzIGlmIHJlcXVpcmVkICovCgkJJCh0aGVhZCkuY2hpbGRyZW4oJ3RyJykuY2hpbGRyZW4oJ3RoLCB0ZCcpLmFkZENsYXNzKCBjbGFzc2VzLnNIZWFkZXJUSCApOwoJCSQodGZvb3QpLmNoaWxkcmVuKCd0cicpLmNoaWxkcmVuKCd0aCwgdGQnKS5hZGRDbGFzcyggY2xhc3Nlcy5zRm9vdGVyVEggKTsKCQoJCS8vIENhY2hlIHRoZSBmb290ZXIgY2VsbHMuIE5vdGUgdGhhdCB3ZSBvbmx5IHRha2UgdGhlIGNlbGxzIGZyb20gdGhlIGZpcnN0CgkJLy8gcm93IGluIHRoZSBmb290ZXIuIElmIHRoZXJlIGlzIG1vcmUgdGhhbiBvbmUgcm93IHRoZSB1c2VyIHdhbnRzIHRvCgkJLy8gaW50ZXJhY3Qgd2l0aCwgdGhleSBuZWVkIHRvIHVzZSB0aGUgdGFibGUoKS5mb290KCkgbWV0aG9kLiBOb3RlIGFsc28gdGhpcwoJCS8vIGFsbG93cyBjZWxscyB0byBiZSB1c2VkIGZvciBtdWx0aXBsZSBjb2x1bW5zIHVzaW5nIGNvbHNwYW4KCQlpZiAoIHRmb290ICE9PSBudWxsICkgewoJCQl2YXIgY2VsbHMgPSBvU2V0dGluZ3MuYW9Gb290ZXJbMF07CgkKCQkJZm9yICggaT0wLCBpZW49Y2VsbHMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQljb2x1bW4gPSBjb2x1bW5zW2ldOwoJCQkJY29sdW1uLm5UZiA9IGNlbGxzW2ldLmNlbGw7CgkKCQkJCWlmICggY29sdW1uLnNDbGFzcyApIHsKCQkJCQkkKGNvbHVtbi5uVGYpLmFkZENsYXNzKCBjb2x1bW4uc0NsYXNzICk7CgkJCQl9CgkJCX0KCQl9Cgl9CgkKCQoJLyoqCgkgKiBEcmF3IHRoZSBoZWFkZXIgKG9yIGZvb3RlcikgZWxlbWVudCBiYXNlZCBvbiB0aGUgY29sdW1uIHZpc2liaWxpdHkgc3RhdGVzLiBUaGUKCSAqIG1ldGhvZG9sb2d5IGhlcmUgaXMgdG8gdXNlIHRoZSBsYXlvdXQgYXJyYXkgZnJvbSBfZm5EZXRlY3RIZWFkZXIsIG1vZGlmaWVkIGZvcgoJICogdGhlIGluc3RhbnRhbmVvdXMgY29sdW1uIHZpc2liaWxpdHksIHRvIGNvbnN0cnVjdCB0aGUgbmV3IGxheW91dC4gVGhlIGdyaWQgaXMKCSAqIHRyYXZlcnNlZCBvdmVyIGNlbGwgYXQgYSB0aW1lIGluIGEgcm93cyB4IGNvbHVtbnMgZ3JpZCBmYXNoaW9uLCBhbHRob3VnaCBlYWNoCgkgKiBjZWxsIGluc2VydCBjYW4gY292ZXIgbXVsdGlwbGUgZWxlbWVudHMgaW4gdGhlIGdyaWQgLSB3aGljaCBpcyB0cmFja3MgdXNpbmcgdGhlCgkgKiBhQXBwbGllZCBhcnJheS4gQ2VsbCBpbnNlcnRzIGluIHRoZSBncmlkIHdpbGwgb25seSBvY2N1ciB3aGVyZSB0aGVyZSBpc24ndAoJICogYWxyZWFkeSBhIGNlbGwgaW4gdGhhdCBwb3NpdGlvbi4KCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIGFycmF5IHtvYmplY3RzfSBhb1NvdXJjZSBMYXlvdXQgYXJyYXkgZnJvbSBfZm5EZXRlY3RIZWFkZXIKCSAqICBAcGFyYW0ge2Jvb2xlYW59IFtiSW5jbHVkZUhpZGRlbj1mYWxzZV0gSWYgdHJ1ZSB0aGVuIGluY2x1ZGUgdGhlIGhpZGRlbiBjb2x1bW5zIGluIHRoZSBjYWxjLAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5EcmF3SGVhZCggb1NldHRpbmdzLCBhb1NvdXJjZSwgYkluY2x1ZGVIaWRkZW4gKQoJewoJCXZhciBpLCBpTGVuLCBqLCBqTGVuLCBrLCBrTGVuLCBuLCBuTG9jYWxUcjsKCQl2YXIgYW9Mb2NhbCA9IFtdOwoJCXZhciBhQXBwbGllZCA9IFtdOwoJCXZhciBpQ29sdW1ucyA9IG9TZXR0aW5ncy5hb0NvbHVtbnMubGVuZ3RoOwoJCXZhciBpUm93c3BhbiwgaUNvbHNwYW47CgkKCQlpZiAoICEgYW9Tb3VyY2UgKQoJCXsKCQkJcmV0dXJuOwoJCX0KCQoJCWlmICggIGJJbmNsdWRlSGlkZGVuID09PSB1bmRlZmluZWQgKQoJCXsKCQkJYkluY2x1ZGVIaWRkZW4gPSBmYWxzZTsKCQl9CgkKCQkvKiBNYWtlIGEgY29weSBvZiB0aGUgbWFzdGVyIGxheW91dCBhcnJheSwgYnV0IHdpdGhvdXQgdGhlIHZpc2libGUgY29sdW1ucyBpbiBpdCAqLwoJCWZvciAoIGk9MCwgaUxlbj1hb1NvdXJjZS5sZW5ndGggOyBpPGlMZW4gOyBpKysgKQoJCXsKCQkJYW9Mb2NhbFtpXSA9IGFvU291cmNlW2ldLnNsaWNlKCk7CgkJCWFvTG9jYWxbaV0ublRyID0gYW9Tb3VyY2VbaV0ublRyOwoJCgkJCS8qIFJlbW92ZSBhbnkgY29sdW1ucyB3aGljaCBhcmUgY3VycmVudGx5IGhpZGRlbiAqLwoJCQlmb3IgKCBqPWlDb2x1bW5zLTEgOyBqPj0wIDsgai0tICkKCQkJewoJCQkJaWYgKCAhb1NldHRpbmdzLmFvQ29sdW1uc1tqXS5iVmlzaWJsZSAmJiAhYkluY2x1ZGVIaWRkZW4gKQoJCQkJewoJCQkJCWFvTG9jYWxbaV0uc3BsaWNlKCBqLCAxICk7CgkJCQl9CgkJCX0KCQoJCQkvKiBQcmVwIHRoZSBhcHBsaWVkIGFycmF5IC0gaXQgbmVlZHMgYW4gZWxlbWVudCBmb3IgZWFjaCByb3cgKi8KCQkJYUFwcGxpZWQucHVzaCggW10gKTsKCQl9CgkKCQlmb3IgKCBpPTAsIGlMZW49YW9Mb2NhbC5sZW5ndGggOyBpPGlMZW4gOyBpKysgKQoJCXsKCQkJbkxvY2FsVHIgPSBhb0xvY2FsW2ldLm5UcjsKCQoJCQkvKiBBbGwgY2VsbHMgYXJlIGdvaW5nIHRvIGJlIHJlcGxhY2VkLCBzbyBlbXB0eSBvdXQgdGhlIHJvdyAqLwoJCQlpZiAoIG5Mb2NhbFRyICkKCQkJewoJCQkJd2hpbGUoIChuID0gbkxvY2FsVHIuZmlyc3RDaGlsZCkgKQoJCQkJewoJCQkJCW5Mb2NhbFRyLnJlbW92ZUNoaWxkKCBuICk7CgkJCQl9CgkJCX0KCQoJCQlmb3IgKCBqPTAsIGpMZW49YW9Mb2NhbFtpXS5sZW5ndGggOyBqPGpMZW4gOyBqKysgKQoJCQl7CgkJCQlpUm93c3BhbiA9IDE7CgkJCQlpQ29sc3BhbiA9IDE7CgkKCQkJCS8qIENoZWNrIHRvIHNlZSBpZiB0aGVyZSBpcyBhbHJlYWR5IGEgY2VsbCAocm93L2NvbHNwYW4pIGNvdmVyaW5nIG91ciB0YXJnZXQKCQkJCSAqIGluc2VydCBwb2ludC4gSWYgdGhlcmUgaXMsIHRoZW4gdGhlcmUgaXMgbm90aGluZyB0byBkby4KCQkJCSAqLwoJCQkJaWYgKCBhQXBwbGllZFtpXVtqXSA9PT0gdW5kZWZpbmVkICkKCQkJCXsKCQkJCQluTG9jYWxUci5hcHBlbmRDaGlsZCggYW9Mb2NhbFtpXVtqXS5jZWxsICk7CgkJCQkJYUFwcGxpZWRbaV1bal0gPSAxOwoJCgkJCQkJLyogRXhwYW5kIHRoZSBjZWxsIHRvIGNvdmVyIGFzIG1hbnkgcm93cyBhcyBuZWVkZWQgKi8KCQkJCQl3aGlsZSAoIGFvTG9jYWxbaStpUm93c3Bhbl0gIT09IHVuZGVmaW5lZCAmJgoJCQkJCSAgICAgICAgYW9Mb2NhbFtpXVtqXS5jZWxsID09IGFvTG9jYWxbaStpUm93c3Bhbl1bal0uY2VsbCApCgkJCQkJewoJCQkJCQlhQXBwbGllZFtpK2lSb3dzcGFuXVtqXSA9IDE7CgkJCQkJCWlSb3dzcGFuKys7CgkJCQkJfQoJCgkJCQkJLyogRXhwYW5kIHRoZSBjZWxsIHRvIGNvdmVyIGFzIG1hbnkgY29sdW1ucyBhcyBuZWVkZWQgKi8KCQkJCQl3aGlsZSAoIGFvTG9jYWxbaV1baitpQ29sc3Bhbl0gIT09IHVuZGVmaW5lZCAmJgoJCQkJCSAgICAgICAgYW9Mb2NhbFtpXVtqXS5jZWxsID09IGFvTG9jYWxbaV1baitpQ29sc3Bhbl0uY2VsbCApCgkJCQkJewoJCQkJCQkvKiBNdXN0IHVwZGF0ZSB0aGUgYXBwbGllZCBhcnJheSBvdmVyIHRoZSByb3dzIGZvciB0aGUgY29sdW1ucyAqLwoJCQkJCQlmb3IgKCBrPTAgOyBrPGlSb3dzcGFuIDsgaysrICkKCQkJCQkJewoJCQkJCQkJYUFwcGxpZWRbaStrXVtqK2lDb2xzcGFuXSA9IDE7CgkJCQkJCX0KCQkJCQkJaUNvbHNwYW4rKzsKCQkJCQl9CgkKCQkJCQkvKiBEbyB0aGUgYWN0dWFsIGV4cGFuc2lvbiBpbiB0aGUgRE9NICovCgkJCQkJJChhb0xvY2FsW2ldW2pdLmNlbGwpCgkJCQkJCS5hdHRyKCdyb3dzcGFuJywgaVJvd3NwYW4pCgkJCQkJCS5hdHRyKCdjb2xzcGFuJywgaUNvbHNwYW4pOwoJCQkJfQoJCQl9CgkJfQoJfQoJCgkKCS8qKgoJICogSW5zZXJ0IHRoZSByZXF1aXJlZCBUUiBub2RlcyBpbnRvIHRoZSB0YWJsZSBmb3IgZGlzcGxheQoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0gYWpheENvbXBsZXRlIHRydWUgYWZ0ZXIgYWpheCBjYWxsIHRvIGNvbXBsZXRlIHJlbmRlcmluZwoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5EcmF3KCBvU2V0dGluZ3MsIGFqYXhDb21wbGV0ZSApCgl7CgkJLy8gQWxsb3cgZm9yIHN0YXRlIHNhdmluZyBhbmQgYSBjdXN0b20gc3RhcnQgcG9zaXRpb24KCQlfZm5TdGFydCggb1NldHRpbmdzICk7CgkKCQkvKiBQcm92aWRlIGEgcHJlLWNhbGxiYWNrIGZ1bmN0aW9uIHdoaWNoIGNhbiBiZSB1c2VkIHRvIGNhbmNlbCB0aGUgZHJhdyBpcyBmYWxzZSBpcyByZXR1cm5lZCAqLwoJCXZhciBhUHJlRHJhdyA9IF9mbkNhbGxiYWNrRmlyZSggb1NldHRpbmdzLCAnYW9QcmVEcmF3Q2FsbGJhY2snLCAncHJlRHJhdycsIFtvU2V0dGluZ3NdICk7CgkJaWYgKCAkLmluQXJyYXkoIGZhbHNlLCBhUHJlRHJhdyApICE9PSAtMSApCgkJewoJCQlfZm5Qcm9jZXNzaW5nRGlzcGxheSggb1NldHRpbmdzLCBmYWxzZSApOwoJCQlyZXR1cm47CgkJfQoJCgkJdmFyIGFuUm93cyA9IFtdOwoJCXZhciBpUm93Q291bnQgPSAwOwoJCXZhciBhc1N0cmlwZUNsYXNzZXMgPSBvU2V0dGluZ3MuYXNTdHJpcGVDbGFzc2VzOwoJCXZhciBpU3RyaXBlcyA9IGFzU3RyaXBlQ2xhc3Nlcy5sZW5ndGg7CgkJdmFyIG9MYW5nID0gb1NldHRpbmdzLm9MYW5ndWFnZTsKCQl2YXIgYlNlcnZlclNpZGUgPSBfZm5EYXRhU291cmNlKCBvU2V0dGluZ3MgKSA9PSAnc3NwJzsKCQl2YXIgYWlEaXNwbGF5ID0gb1NldHRpbmdzLmFpRGlzcGxheTsKCQl2YXIgaURpc3BsYXlTdGFydCA9IG9TZXR0aW5ncy5faURpc3BsYXlTdGFydDsKCQl2YXIgaURpc3BsYXlFbmQgPSBvU2V0dGluZ3MuZm5EaXNwbGF5RW5kKCk7CgkKCQlvU2V0dGluZ3MuYkRyYXdpbmcgPSB0cnVlOwoJCgkJLyogU2VydmVyLXNpZGUgcHJvY2Vzc2luZyBkcmF3IGludGVyY2VwdCAqLwoJCWlmICggb1NldHRpbmdzLmJEZWZlckxvYWRpbmcgKQoJCXsKCQkJb1NldHRpbmdzLmJEZWZlckxvYWRpbmcgPSBmYWxzZTsKCQkJb1NldHRpbmdzLmlEcmF3Kys7CgkJCV9mblByb2Nlc3NpbmdEaXNwbGF5KCBvU2V0dGluZ3MsIGZhbHNlICk7CgkJfQoJCWVsc2UgaWYgKCAhYlNlcnZlclNpZGUgKQoJCXsKCQkJb1NldHRpbmdzLmlEcmF3Kys7CgkJfQoJCWVsc2UgaWYgKCAhb1NldHRpbmdzLmJEZXN0cm95aW5nICYmICFhamF4Q29tcGxldGUpCgkJewoJCQlfZm5BamF4VXBkYXRlKCBvU2V0dGluZ3MgKTsKCQkJcmV0dXJuOwoJCX0KCQoJCWlmICggYWlEaXNwbGF5Lmxlbmd0aCAhPT0gMCApCgkJewoJCQl2YXIgaVN0YXJ0ID0gYlNlcnZlclNpZGUgPyAwIDogaURpc3BsYXlTdGFydDsKCQkJdmFyIGlFbmQgPSBiU2VydmVyU2lkZSA/IG9TZXR0aW5ncy5hb0RhdGEubGVuZ3RoIDogaURpc3BsYXlFbmQ7CgkKCQkJZm9yICggdmFyIGo9aVN0YXJ0IDsgajxpRW5kIDsgaisrICkKCQkJewoJCQkJdmFyIGlEYXRhSW5kZXggPSBhaURpc3BsYXlbal07CgkJCQl2YXIgYW9EYXRhID0gb1NldHRpbmdzLmFvRGF0YVsgaURhdGFJbmRleCBdOwoJCQkJaWYgKCBhb0RhdGEublRyID09PSBudWxsICkKCQkJCXsKCQkJCQlfZm5DcmVhdGVUciggb1NldHRpbmdzLCBpRGF0YUluZGV4ICk7CgkJCQl9CgkKCQkJCXZhciBuUm93ID0gYW9EYXRhLm5UcjsKCQoJCQkJLyogUmVtb3ZlIHRoZSBvbGQgc3RyaXBpbmcgY2xhc3NlcyBhbmQgdGhlbiBhZGQgdGhlIG5ldyBvbmUgKi8KCQkJCWlmICggaVN0cmlwZXMgIT09IDAgKQoJCQkJewoJCQkJCXZhciBzU3RyaXBlID0gYXNTdHJpcGVDbGFzc2VzWyBpUm93Q291bnQgJSBpU3RyaXBlcyBdOwoJCQkJCWlmICggYW9EYXRhLl9zUm93U3RyaXBlICE9IHNTdHJpcGUgKQoJCQkJCXsKCQkJCQkJJChuUm93KS5yZW1vdmVDbGFzcyggYW9EYXRhLl9zUm93U3RyaXBlICkuYWRkQ2xhc3MoIHNTdHJpcGUgKTsKCQkJCQkJYW9EYXRhLl9zUm93U3RyaXBlID0gc1N0cmlwZTsKCQkJCQl9CgkJCQl9CgkKCQkJCS8vIFJvdyBjYWxsYmFjayBmdW5jdGlvbnMgLSBtaWdodCB3YW50IHRvIG1hbmlwdWxhdGUgdGhlIHJvdwoJCQkJLy8gaVJvd0NvdW50IGFuZCBqIGFyZSBub3QgY3VycmVudGx5IGRvY3VtZW50ZWQuIEFyZSB0aGV5IGF0IGFsbAoJCQkJLy8gdXNlZnVsPwoJCQkJX2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsICdhb1Jvd0NhbGxiYWNrJywgbnVsbCwKCQkJCQlbblJvdywgYW9EYXRhLl9hRGF0YSwgaVJvd0NvdW50LCBqLCBpRGF0YUluZGV4XSApOwoJCgkJCQlhblJvd3MucHVzaCggblJvdyApOwoJCQkJaVJvd0NvdW50Kys7CgkJCX0KCQl9CgkJZWxzZQoJCXsKCQkJLyogVGFibGUgaXMgZW1wdHkgLSBjcmVhdGUgYSByb3cgd2l0aCBhbiBlbXB0eSBtZXNzYWdlIGluIGl0ICovCgkJCXZhciBzWmVybyA9IG9MYW5nLnNaZXJvUmVjb3JkczsKCQkJaWYgKCBvU2V0dGluZ3MuaURyYXcgPT0gMSAmJiAgX2ZuRGF0YVNvdXJjZSggb1NldHRpbmdzICkgPT0gJ2FqYXgnICkKCQkJewoJCQkJc1plcm8gPSBvTGFuZy5zTG9hZGluZ1JlY29yZHM7CgkJCX0KCQkJZWxzZSBpZiAoIG9MYW5nLnNFbXB0eVRhYmxlICYmIG9TZXR0aW5ncy5mblJlY29yZHNUb3RhbCgpID09PSAwICkKCQkJewoJCQkJc1plcm8gPSBvTGFuZy5zRW1wdHlUYWJsZTsKCQkJfQoJCgkJCWFuUm93c1sgMCBdID0gJCggJzx0ci8+JywgeyAnY2xhc3MnOiBpU3RyaXBlcyA/IGFzU3RyaXBlQ2xhc3Nlc1swXSA6ICcnIH0gKQoJCQkJLmFwcGVuZCggJCgnPHRkIC8+JywgewoJCQkJCSd2YWxpZ24nOiAgJ3RvcCcsCgkJCQkJJ2NvbFNwYW4nOiBfZm5WaXNibGVDb2x1bW5zKCBvU2V0dGluZ3MgKSwKCQkJCQknY2xhc3MnOiAgIG9TZXR0aW5ncy5vQ2xhc3Nlcy5zUm93RW1wdHkKCQkJCX0gKS5odG1sKCBzWmVybyApIClbMF07CgkJfQoJCgkJLyogSGVhZGVyIGFuZCBmb290ZXIgY2FsbGJhY2tzICovCgkJX2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsICdhb0hlYWRlckNhbGxiYWNrJywgJ2hlYWRlcicsIFsgJChvU2V0dGluZ3MublRIZWFkKS5jaGlsZHJlbigndHInKVswXSwKCQkJX2ZuR2V0RGF0YU1hc3Rlciggb1NldHRpbmdzICksIGlEaXNwbGF5U3RhcnQsIGlEaXNwbGF5RW5kLCBhaURpc3BsYXkgXSApOwoJCgkJX2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsICdhb0Zvb3RlckNhbGxiYWNrJywgJ2Zvb3RlcicsIFsgJChvU2V0dGluZ3MublRGb290KS5jaGlsZHJlbigndHInKVswXSwKCQkJX2ZuR2V0RGF0YU1hc3Rlciggb1NldHRpbmdzICksIGlEaXNwbGF5U3RhcnQsIGlEaXNwbGF5RW5kLCBhaURpc3BsYXkgXSApOwoJCgkJdmFyIGJvZHkgPSAkKG9TZXR0aW5ncy5uVEJvZHkpOwoJCgkJYm9keS5jaGlsZHJlbigpLmRldGFjaCgpOwoJCWJvZHkuYXBwZW5kKCAkKGFuUm93cykgKTsKCQoJCS8qIENhbGwgYWxsIHJlcXVpcmVkIGNhbGxiYWNrIGZ1bmN0aW9ucyBmb3IgdGhlIGVuZCBvZiBhIGRyYXcgKi8KCQlfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgJ2FvRHJhd0NhbGxiYWNrJywgJ2RyYXcnLCBbb1NldHRpbmdzXSApOwoJCgkJLyogRHJhdyBpcyBjb21wbGV0ZSwgc29ydGluZyBhbmQgZmlsdGVyaW5nIG11c3QgYmUgYXMgd2VsbCAqLwoJCW9TZXR0aW5ncy5iU29ydGVkID0gZmFsc2U7CgkJb1NldHRpbmdzLmJGaWx0ZXJlZCA9IGZhbHNlOwoJCW9TZXR0aW5ncy5iRHJhd2luZyA9IGZhbHNlOwoJfQoJCgkKCS8qKgoJICogUmVkcmF3IHRoZSB0YWJsZSAtIHRha2luZyBhY2NvdW50IG9mIHRoZSB2YXJpb3VzIGZlYXR1cmVzIHdoaWNoIGFyZSBlbmFibGVkCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7Ym9vbGVhbn0gW2hvbGRQb3NpdGlvbl0gS2VlcCB0aGUgY3VycmVudCBwYWdpbmcgcG9zaXRpb24uIEJ5IGRlZmF1bHQKCSAqICAgIHRoZSBwYWdpbmcgaXMgcmVzZXQgdG8gdGhlIGZpcnN0IHBhZ2UKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuUmVEcmF3KCBzZXR0aW5ncywgaG9sZFBvc2l0aW9uICkKCXsKCQl2YXIKCQkJZmVhdHVyZXMgPSBzZXR0aW5ncy5vRmVhdHVyZXMsCgkJCXNvcnQgICAgID0gZmVhdHVyZXMuYlNvcnQsCgkJCWZpbHRlciAgID0gZmVhdHVyZXMuYkZpbHRlcjsKCQoJCWlmICggc29ydCApIHsKCQkJX2ZuU29ydCggc2V0dGluZ3MgKTsKCQl9CgkKCQlpZiAoIGZpbHRlciApIHsKCQkJX2ZuRmlsdGVyQ29tcGxldGUoIHNldHRpbmdzLCBzZXR0aW5ncy5vUHJldmlvdXNTZWFyY2ggKTsKCQl9CgkJZWxzZSB7CgkJCS8vIE5vIGZpbHRlcmluZywgc28gd2Ugd2FudCB0byBqdXN0IHVzZSB0aGUgZGlzcGxheSBtYXN0ZXIKCQkJc2V0dGluZ3MuYWlEaXNwbGF5ID0gc2V0dGluZ3MuYWlEaXNwbGF5TWFzdGVyLnNsaWNlKCk7CgkJfQoJCgkJaWYgKCBob2xkUG9zaXRpb24gIT09IHRydWUgKSB7CgkJCXNldHRpbmdzLl9pRGlzcGxheVN0YXJ0ID0gMDsKCQl9CgkKCQkvLyBMZXQgYW55IG1vZHVsZXMga25vdyBhYm91dCB0aGUgZHJhdyBob2xkIHBvc2l0aW9uIHN0YXRlICh1c2VkIGJ5CgkJLy8gc2Nyb2xsaW5nIGludGVybmFsbHkpCgkJc2V0dGluZ3MuX2RyYXdIb2xkID0gaG9sZFBvc2l0aW9uOwoJCgkJX2ZuRHJhdyggc2V0dGluZ3MgKTsKCQoJCXNldHRpbmdzLl9kcmF3SG9sZCA9IGZhbHNlOwoJfQoJCgkKCS8qKgoJICogQWRkIHRoZSBvcHRpb25zIHRvIHRoZSBwYWdlIEhUTUwgZm9yIHRoZSB0YWJsZQoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuQWRkT3B0aW9uc0h0bWwgKCBvU2V0dGluZ3MgKQoJewoJCXZhciBjbGFzc2VzID0gb1NldHRpbmdzLm9DbGFzc2VzOwoJCXZhciB0YWJsZSA9ICQob1NldHRpbmdzLm5UYWJsZSk7CgkJdmFyIGhvbGRpbmcgPSAkKCc8ZGl2Lz4nKS5pbnNlcnRCZWZvcmUoIHRhYmxlICk7IC8vIEhvbGRpbmcgZWxlbWVudCBmb3Igc3BlZWQKCQl2YXIgZmVhdHVyZXMgPSBvU2V0dGluZ3Mub0ZlYXR1cmVzOwoJCgkJLy8gQWxsIERhdGFUYWJsZXMgYXJlIHdyYXBwZWQgaW4gYSBkaXYKCQl2YXIgaW5zZXJ0ID0gJCgnPGRpdi8+JywgewoJCQlpZDogICAgICBvU2V0dGluZ3Muc1RhYmxlSWQrJ193cmFwcGVyJywKCQkJJ2NsYXNzJzogY2xhc3Nlcy5zV3JhcHBlciArIChvU2V0dGluZ3MublRGb290ID8gJycgOiAnICcrY2xhc3Nlcy5zTm9Gb290ZXIpCgkJfSApOwoJCgkJb1NldHRpbmdzLm5Ib2xkaW5nID0gaG9sZGluZ1swXTsKCQlvU2V0dGluZ3MublRhYmxlV3JhcHBlciA9IGluc2VydFswXTsKCQlvU2V0dGluZ3MublRhYmxlUmVpbnNlcnRCZWZvcmUgPSBvU2V0dGluZ3MublRhYmxlLm5leHRTaWJsaW5nOwoJCgkJLyogTG9vcCBvdmVyIHRoZSB1c2VyIHNldCBwb3NpdGlvbmluZyBhbmQgcGxhY2UgdGhlIGVsZW1lbnRzIGFzIG5lZWRlZCAqLwoJCXZhciBhRG9tID0gb1NldHRpbmdzLnNEb20uc3BsaXQoJycpOwoJCXZhciBmZWF0dXJlTm9kZSwgY09wdGlvbiwgbk5ld05vZGUsIGNOZXh0LCBzQXR0ciwgajsKCQlmb3IgKCB2YXIgaT0wIDsgaTxhRG9tLmxlbmd0aCA7IGkrKyApCgkJewoJCQlmZWF0dXJlTm9kZSA9IG51bGw7CgkJCWNPcHRpb24gPSBhRG9tW2ldOwoJCgkJCWlmICggY09wdGlvbiA9PSAnPCcgKQoJCQl7CgkJCQkvKiBOZXcgY29udGFpbmVyIGRpdiAqLwoJCQkJbk5ld05vZGUgPSAkKCc8ZGl2Lz4nKVswXTsKCQoJCQkJLyogQ2hlY2sgdG8gc2VlIGlmIHdlIHNob3VsZCBhcHBlbmQgYW4gaWQgYW5kL29yIGEgY2xhc3MgbmFtZSB0byB0aGUgY29udGFpbmVyICovCgkJCQljTmV4dCA9IGFEb21baSsxXTsKCQkJCWlmICggY05leHQgPT0gIiciIHx8IGNOZXh0ID09ICciJyApCgkJCQl7CgkJCQkJc0F0dHIgPSAiIjsKCQkJCQlqID0gMjsKCQkJCQl3aGlsZSAoIGFEb21baStqXSAhPSBjTmV4dCApCgkJCQkJewoJCQkJCQlzQXR0ciArPSBhRG9tW2kral07CgkJCQkJCWorKzsKCQkJCQl9CgkKCQkJCQkvKiBSZXBsYWNlIGpRdWVyeSBVSSBjb25zdGFudHMgQHRvZG8gZGVwcmVjaWF0ZWQgKi8KCQkJCQlpZiAoIHNBdHRyID09ICJIIiApCgkJCQkJewoJCQkJCQlzQXR0ciA9IGNsYXNzZXMuc0pVSUhlYWRlcjsKCQkJCQl9CgkJCQkJZWxzZSBpZiAoIHNBdHRyID09ICJGIiApCgkJCQkJewoJCQkJCQlzQXR0ciA9IGNsYXNzZXMuc0pVSUZvb3RlcjsKCQkJCQl9CgkKCQkJCQkvKiBUaGUgYXR0cmlidXRlIGNhbiBiZSBpbiB0aGUgZm9ybWF0IG9mICIjaWQuY2xhc3MiLCAiI2lkIiBvciAiY2xhc3MiIFRoaXMgbG9naWMKCQkJCQkgKiBicmVha3MgdGhlIHN0cmluZyBpbnRvIHBhcnRzIGFuZCBhcHBsaWVzIHRoZW0gYXMgbmVlZGVkCgkJCQkJICovCgkJCQkJaWYgKCBzQXR0ci5pbmRleE9mKCcuJykgIT0gLTEgKQoJCQkJCXsKCQkJCQkJdmFyIGFTcGxpdCA9IHNBdHRyLnNwbGl0KCcuJyk7CgkJCQkJCW5OZXdOb2RlLmlkID0gYVNwbGl0WzBdLnN1YnN0cigxLCBhU3BsaXRbMF0ubGVuZ3RoLTEpOwoJCQkJCQluTmV3Tm9kZS5jbGFzc05hbWUgPSBhU3BsaXRbMV07CgkJCQkJfQoJCQkJCWVsc2UgaWYgKCBzQXR0ci5jaGFyQXQoMCkgPT0gIiMiICkKCQkJCQl7CgkJCQkJCW5OZXdOb2RlLmlkID0gc0F0dHIuc3Vic3RyKDEsIHNBdHRyLmxlbmd0aC0xKTsKCQkJCQl9CgkJCQkJZWxzZQoJCQkJCXsKCQkJCQkJbk5ld05vZGUuY2xhc3NOYW1lID0gc0F0dHI7CgkJCQkJfQoJCgkJCQkJaSArPSBqOyAvKiBNb3ZlIGFsb25nIHRoZSBwb3NpdGlvbiBhcnJheSAqLwoJCQkJfQoJCgkJCQlpbnNlcnQuYXBwZW5kKCBuTmV3Tm9kZSApOwoJCQkJaW5zZXJ0ID0gJChuTmV3Tm9kZSk7CgkJCX0KCQkJZWxzZSBpZiAoIGNPcHRpb24gPT0gJz4nICkKCQkJewoJCQkJLyogRW5kIGNvbnRhaW5lciBkaXYgKi8KCQkJCWluc2VydCA9IGluc2VydC5wYXJlbnQoKTsKCQkJfQoJCQkvLyBAdG9kbyBNb3ZlIG9wdGlvbnMgaW50byB0aGVpciBvd24gcGx1Z2lucz8KCQkJZWxzZSBpZiAoIGNPcHRpb24gPT0gJ2wnICYmIGZlYXR1cmVzLmJQYWdpbmF0ZSAmJiBmZWF0dXJlcy5iTGVuZ3RoQ2hhbmdlICkKCQkJewoJCQkJLyogTGVuZ3RoICovCgkJCQlmZWF0dXJlTm9kZSA9IF9mbkZlYXR1cmVIdG1sTGVuZ3RoKCBvU2V0dGluZ3MgKTsKCQkJfQoJCQllbHNlIGlmICggY09wdGlvbiA9PSAnZicgJiYgZmVhdHVyZXMuYkZpbHRlciApCgkJCXsKCQkJCS8qIEZpbHRlciAqLwoJCQkJZmVhdHVyZU5vZGUgPSBfZm5GZWF0dXJlSHRtbEZpbHRlciggb1NldHRpbmdzICk7CgkJCX0KCQkJZWxzZSBpZiAoIGNPcHRpb24gPT0gJ3InICYmIGZlYXR1cmVzLmJQcm9jZXNzaW5nICkKCQkJewoJCQkJLyogcFJvY2Vzc2luZyAqLwoJCQkJZmVhdHVyZU5vZGUgPSBfZm5GZWF0dXJlSHRtbFByb2Nlc3NpbmcoIG9TZXR0aW5ncyApOwoJCQl9CgkJCWVsc2UgaWYgKCBjT3B0aW9uID09ICd0JyApCgkJCXsKCQkJCS8qIFRhYmxlICovCgkJCQlmZWF0dXJlTm9kZSA9IF9mbkZlYXR1cmVIdG1sVGFibGUoIG9TZXR0aW5ncyApOwoJCQl9CgkJCWVsc2UgaWYgKCBjT3B0aW9uID09ICAnaScgJiYgZmVhdHVyZXMuYkluZm8gKQoJCQl7CgkJCQkvKiBJbmZvICovCgkJCQlmZWF0dXJlTm9kZSA9IF9mbkZlYXR1cmVIdG1sSW5mbyggb1NldHRpbmdzICk7CgkJCX0KCQkJZWxzZSBpZiAoIGNPcHRpb24gPT0gJ3AnICYmIGZlYXR1cmVzLmJQYWdpbmF0ZSApCgkJCXsKCQkJCS8qIFBhZ2luYXRpb24gKi8KCQkJCWZlYXR1cmVOb2RlID0gX2ZuRmVhdHVyZUh0bWxQYWdpbmF0ZSggb1NldHRpbmdzICk7CgkJCX0KCQkJZWxzZSBpZiAoIERhdGFUYWJsZS5leHQuZmVhdHVyZS5sZW5ndGggIT09IDAgKQoJCQl7CgkJCQkvKiBQbHVnLWluIGZlYXR1cmVzICovCgkJCQl2YXIgYW9GZWF0dXJlcyA9IERhdGFUYWJsZS5leHQuZmVhdHVyZTsKCQkJCWZvciAoIHZhciBrPTAsIGtMZW49YW9GZWF0dXJlcy5sZW5ndGggOyBrPGtMZW4gOyBrKysgKQoJCQkJewoJCQkJCWlmICggY09wdGlvbiA9PSBhb0ZlYXR1cmVzW2tdLmNGZWF0dXJlICkKCQkJCQl7CgkJCQkJCWZlYXR1cmVOb2RlID0gYW9GZWF0dXJlc1trXS5mbkluaXQoIG9TZXR0aW5ncyApOwoJCQkJCQlicmVhazsKCQkJCQl9CgkJCQl9CgkJCX0KCQoJCQkvKiBBZGQgdG8gdGhlIDJEIGZlYXR1cmVzIGFycmF5ICovCgkJCWlmICggZmVhdHVyZU5vZGUgKQoJCQl7CgkJCQl2YXIgYWFuRmVhdHVyZXMgPSBvU2V0dGluZ3MuYWFuRmVhdHVyZXM7CgkKCQkJCWlmICggISBhYW5GZWF0dXJlc1tjT3B0aW9uXSApCgkJCQl7CgkJCQkJYWFuRmVhdHVyZXNbY09wdGlvbl0gPSBbXTsKCQkJCX0KCQoJCQkJYWFuRmVhdHVyZXNbY09wdGlvbl0ucHVzaCggZmVhdHVyZU5vZGUgKTsKCQkJCWluc2VydC5hcHBlbmQoIGZlYXR1cmVOb2RlICk7CgkJCX0KCQl9CgkKCQkvKiBCdWlsdCBvdXIgRE9NIHN0cnVjdHVyZSAtIHJlcGxhY2UgdGhlIGhvbGRpbmcgZGl2IHdpdGggd2hhdCB3ZSB3YW50ICovCgkJaG9sZGluZy5yZXBsYWNlV2l0aCggaW5zZXJ0ICk7CgkJb1NldHRpbmdzLm5Ib2xkaW5nID0gbnVsbDsKCX0KCQoJCgkvKioKCSAqIFVzZSB0aGUgRE9NIHNvdXJjZSB0byBjcmVhdGUgdXAgYW4gYXJyYXkgb2YgaGVhZGVyIGNlbGxzLiBUaGUgaWRlYSBoZXJlIGlzIHRvCgkgKiBjcmVhdGUgYSBsYXlvdXQgZ3JpZCAoYXJyYXkpIG9mIHJvd3MgeCBjb2x1bW5zLCB3aGljaCBjb250YWlucyBhIHJlZmVyZW5jZQoJICogdG8gdGhlIGNlbGwgdGhhdCB0aGF0IHBvaW50IGluIHRoZSBncmlkIChyZWdhcmRsZXNzIG9mIGNvbC9yb3dzcGFuKSwgc3VjaCB0aGF0CgkgKiBhbnkgY29sdW1uIC8gcm93IGNvdWxkIGJlIHJlbW92ZWQgYW5kIHRoZSBuZXcgZ3JpZCBjb25zdHJ1Y3RlZAoJICogIEBwYXJhbSBhcnJheSB7b2JqZWN0fSBhTGF5b3V0IEFycmF5IHRvIHN0b3JlIHRoZSBjYWxjdWxhdGVkIGxheW91dCBpbgoJICogIEBwYXJhbSB7bm9kZX0gblRoZWFkIFRoZSBoZWFkZXIvZm9vdGVyIGVsZW1lbnQgZm9yIHRoZSB0YWJsZQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5EZXRlY3RIZWFkZXIgKCBhTGF5b3V0LCBuVGhlYWQgKQoJewoJCXZhciBuVHJzID0gJChuVGhlYWQpLmNoaWxkcmVuKCd0cicpOwoJCXZhciBuVHIsIG5DZWxsOwoJCXZhciBpLCBrLCBsLCBpTGVuLCBqTGVuLCBpQ29sU2hpZnRlZCwgaUNvbHVtbiwgaUNvbHNwYW4sIGlSb3dzcGFuOwoJCXZhciBiVW5pcXVlOwoJCXZhciBmblNoaWZ0Q29sID0gZnVuY3Rpb24gKCBhLCBpLCBqICkgewoJCQl2YXIgayA9IGFbaV07CgkgICAgICAgICAgICAgICAgd2hpbGUgKCBrW2pdICkgewoJCQkJaisrOwoJCQl9CgkJCXJldHVybiBqOwoJCX07CgkKCQlhTGF5b3V0LnNwbGljZSggMCwgYUxheW91dC5sZW5ndGggKTsKCQoJCS8qIFdlIGtub3cgaG93IG1hbnkgcm93cyB0aGVyZSBhcmUgaW4gdGhlIGxheW91dCAtIHNvIHByZXAgaXQgKi8KCQlmb3IgKCBpPTAsIGlMZW49blRycy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKQoJCXsKCQkJYUxheW91dC5wdXNoKCBbXSApOwoJCX0KCQoJCS8qIENhbGN1bGF0ZSBhIGxheW91dCBhcnJheSAqLwoJCWZvciAoIGk9MCwgaUxlbj1uVHJzLmxlbmd0aCA7IGk8aUxlbiA7IGkrKyApCgkJewoJCQluVHIgPSBuVHJzW2ldOwoJCQlpQ29sdW1uID0gMDsKCQoJCQkvKiBGb3IgZXZlcnkgY2VsbCBpbiB0aGUgcm93Li4uICovCgkJCW5DZWxsID0gblRyLmZpcnN0Q2hpbGQ7CgkJCXdoaWxlICggbkNlbGwgKSB7CgkJCQlpZiAoIG5DZWxsLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgPT0gIlREIiB8fAoJCQkJICAgICBuQ2VsbC5ub2RlTmFtZS50b1VwcGVyQ2FzZSgpID09ICJUSCIgKQoJCQkJewoJCQkJCS8qIEdldCB0aGUgY29sIGFuZCByb3dzcGFuIGF0dHJpYnV0ZXMgZnJvbSB0aGUgRE9NIGFuZCBzYW5pdGlzZSB0aGVtICovCgkJCQkJaUNvbHNwYW4gPSBuQ2VsbC5nZXRBdHRyaWJ1dGUoJ2NvbHNwYW4nKSAqIDE7CgkJCQkJaVJvd3NwYW4gPSBuQ2VsbC5nZXRBdHRyaWJ1dGUoJ3Jvd3NwYW4nKSAqIDE7CgkJCQkJaUNvbHNwYW4gPSAoIWlDb2xzcGFuIHx8IGlDb2xzcGFuPT09MCB8fCBpQ29sc3Bhbj09PTEpID8gMSA6IGlDb2xzcGFuOwoJCQkJCWlSb3dzcGFuID0gKCFpUm93c3BhbiB8fCBpUm93c3Bhbj09PTAgfHwgaVJvd3NwYW49PT0xKSA/IDEgOiBpUm93c3BhbjsKCQoJCQkJCS8qIFRoZXJlIG1pZ2h0IGJlIGNvbHNwYW4gY2VsbHMgYWxyZWFkeSBpbiB0aGlzIHJvdywgc28gc2hpZnQgb3VyIHRhcmdldAoJCQkJCSAqIGFjY29yZGluZ2x5CgkJCQkJICovCgkJCQkJaUNvbFNoaWZ0ZWQgPSBmblNoaWZ0Q29sKCBhTGF5b3V0LCBpLCBpQ29sdW1uICk7CgkKCQkJCQkvKiBDYWNoZSBjYWxjdWxhdGlvbiBmb3IgdW5pcXVlIGNvbHVtbnMgKi8KCQkJCQliVW5pcXVlID0gaUNvbHNwYW4gPT09IDEgPyB0cnVlIDogZmFsc2U7CgkKCQkJCQkvKiBJZiB0aGVyZSBpcyBjb2wgLyByb3dzcGFuLCBjb3B5IHRoZSBpbmZvcm1hdGlvbiBpbnRvIHRoZSBsYXlvdXQgZ3JpZCAqLwoJCQkJCWZvciAoIGw9MCA7IGw8aUNvbHNwYW4gOyBsKysgKQoJCQkJCXsKCQkJCQkJZm9yICggaz0wIDsgazxpUm93c3BhbiA7IGsrKyApCgkJCQkJCXsKCQkJCQkJCWFMYXlvdXRbaStrXVtpQ29sU2hpZnRlZCtsXSA9IHsKCQkJCQkJCQkiY2VsbCI6IG5DZWxsLAoJCQkJCQkJCSJ1bmlxdWUiOiBiVW5pcXVlCgkJCQkJCQl9OwoJCQkJCQkJYUxheW91dFtpK2tdLm5UciA9IG5UcjsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJCW5DZWxsID0gbkNlbGwubmV4dFNpYmxpbmc7CgkJCX0KCQl9Cgl9CgkKCQoJLyoqCgkgKiBHZXQgYW4gYXJyYXkgb2YgdW5pcXVlIHRoIGVsZW1lbnRzLCBvbmUgZm9yIGVhY2ggY29sdW1uCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7bm9kZX0gbkhlYWRlciBhdXRvbWF0aWNhbGx5IGRldGVjdCB0aGUgbGF5b3V0IGZyb20gdGhpcyBub2RlIC0gb3B0aW9uYWwKCSAqICBAcGFyYW0ge2FycmF5fSBhTGF5b3V0IHRoZWFkL3Rmb290IGxheW91dCBmcm9tIF9mbkRldGVjdEhlYWRlciAtIG9wdGlvbmFsCgkgKiAgQHJldHVybnMgYXJyYXkge25vZGV9IGFSZXR1cm4gbGlzdCBvZiB1bmlxdWUgdGgncwoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5HZXRVbmlxdWVUaHMgKCBvU2V0dGluZ3MsIG5IZWFkZXIsIGFMYXlvdXQgKQoJewoJCXZhciBhUmV0dXJuID0gW107CgkJaWYgKCAhYUxheW91dCApCgkJewoJCQlhTGF5b3V0ID0gb1NldHRpbmdzLmFvSGVhZGVyOwoJCQlpZiAoIG5IZWFkZXIgKQoJCQl7CgkJCQlhTGF5b3V0ID0gW107CgkJCQlfZm5EZXRlY3RIZWFkZXIoIGFMYXlvdXQsIG5IZWFkZXIgKTsKCQkJfQoJCX0KCQoJCWZvciAoIHZhciBpPTAsIGlMZW49YUxheW91dC5sZW5ndGggOyBpPGlMZW4gOyBpKysgKQoJCXsKCQkJZm9yICggdmFyIGo9MCwgakxlbj1hTGF5b3V0W2ldLmxlbmd0aCA7IGo8akxlbiA7IGorKyApCgkJCXsKCQkJCWlmICggYUxheW91dFtpXVtqXS51bmlxdWUgJiYKCQkJCQkgKCFhUmV0dXJuW2pdIHx8ICFvU2V0dGluZ3MuYlNvcnRDZWxsc1RvcCkgKQoJCQkJewoJCQkJCWFSZXR1cm5bal0gPSBhTGF5b3V0W2ldW2pdLmNlbGw7CgkJCQl9CgkJCX0KCQl9CgkKCQlyZXR1cm4gYVJldHVybjsKCX0KCQoJLyoqCgkgKiBTZXQgdGhlIHN0YXJ0IHBvc2l0aW9uIGZvciBkcmF3CgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICovCglmdW5jdGlvbiBfZm5TdGFydCggb1NldHRpbmdzICkKCXsKCQl2YXIgYlNlcnZlclNpZGUgPSBfZm5EYXRhU291cmNlKCBvU2V0dGluZ3MgKSA9PSAnc3NwJzsKCQl2YXIgaUluaXREaXNwbGF5U3RhcnQgPSBvU2V0dGluZ3MuaUluaXREaXNwbGF5U3RhcnQ7CgkKCQkvLyBDaGVjayBhbmQgc2VlIGlmIHdlIGhhdmUgYW4gaW5pdGlhbCBkcmF3IHBvc2l0aW9uIGZyb20gc3RhdGUgc2F2aW5nCgkJaWYgKCBpSW5pdERpc3BsYXlTdGFydCAhPT0gdW5kZWZpbmVkICYmIGlJbml0RGlzcGxheVN0YXJ0ICE9PSAtMSApCgkJewoJCQlvU2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgPSBiU2VydmVyU2lkZSA/CgkJCQlpSW5pdERpc3BsYXlTdGFydCA6CgkJCQlpSW5pdERpc3BsYXlTdGFydCA+PSBvU2V0dGluZ3MuZm5SZWNvcmRzRGlzcGxheSgpID8KCQkJCQkwIDoKCQkJCQlpSW5pdERpc3BsYXlTdGFydDsKCQoJCQlvU2V0dGluZ3MuaUluaXREaXNwbGF5U3RhcnQgPSAtMTsKCQl9Cgl9CgkKCS8qKgoJICogQ3JlYXRlIGFuIEFqYXggY2FsbCBiYXNlZCBvbiB0aGUgdGFibGUncyBzZXR0aW5ncywgdGFraW5nIGludG8gYWNjb3VudCB0aGF0CgkgKiBwYXJhbWV0ZXJzIGNhbiBoYXZlIG11bHRpcGxlIGZvcm1zLCBhbmQgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuCgkgKgoJICogQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogQHBhcmFtIHthcnJheX0gZGF0YSBEYXRhIHRvIHNlbmQgdG8gdGhlIHNlcnZlciwgcmVxdWlyZWQgYnkKCSAqICAgICBEYXRhVGFibGVzIC0gbWF5IGJlIGF1Z21lbnRlZCBieSBkZXZlbG9wZXIgY2FsbGJhY2tzCgkgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmbiBDYWxsYmFjayBmdW5jdGlvbiB0byBydW4gd2hlbiBkYXRhIGlzIG9idGFpbmVkCgkgKi8KCWZ1bmN0aW9uIF9mbkJ1aWxkQWpheCggb1NldHRpbmdzLCBkYXRhLCBmbiApCgl7CgkJLy8gQ29tcGF0aWJpbGl0eSB3aXRoIDEuOS0sIGFsbG93IGZuU2VydmVyRGF0YSBhbmQgZXZlbnQgdG8gbWFuaXB1bGF0ZQoJCV9mbkNhbGxiYWNrRmlyZSggb1NldHRpbmdzLCAnYW9TZXJ2ZXJQYXJhbXMnLCAnc2VydmVyUGFyYW1zJywgW2RhdGFdICk7CgkKCQkvLyBDb252ZXJ0IHRvIG9iamVjdCBiYXNlZCBmb3IgMS4xMCsgaWYgdXNpbmcgdGhlIG9sZCBhcnJheSBzY2hlbWUgd2hpY2ggY2FuCgkJLy8gY29tZSBmcm9tIHNlcnZlci1zaWRlIHByb2Nlc3Npbmcgb3Igc2VydmVyUGFyYW1zCgkJaWYgKCBkYXRhICYmIEFycmF5LmlzQXJyYXkoZGF0YSkgKSB7CgkJCXZhciB0bXAgPSB7fTsKCQkJdmFyIHJicmFja2V0ID0gLyguKj8pXFtcXSQvOwoJCgkJCSQuZWFjaCggZGF0YSwgZnVuY3Rpb24gKGtleSwgdmFsKSB7CgkJCQl2YXIgbWF0Y2ggPSB2YWwubmFtZS5tYXRjaChyYnJhY2tldCk7CgkKCQkJCWlmICggbWF0Y2ggKSB7CgkJCQkJLy8gU3VwcG9ydCBmb3IgYXJyYXlzCgkJCQkJdmFyIG5hbWUgPSBtYXRjaFswXTsKCQoJCQkJCWlmICggISB0bXBbIG5hbWUgXSApIHsKCQkJCQkJdG1wWyBuYW1lIF0gPSBbXTsKCQkJCQl9CgkJCQkJdG1wWyBuYW1lIF0ucHVzaCggdmFsLnZhbHVlICk7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQl0bXBbdmFsLm5hbWVdID0gdmFsLnZhbHVlOwoJCQkJfQoJCQl9ICk7CgkJCWRhdGEgPSB0bXA7CgkJfQoJCgkJdmFyIGFqYXhEYXRhOwoJCXZhciBhamF4ID0gb1NldHRpbmdzLmFqYXg7CgkJdmFyIGluc3RhbmNlID0gb1NldHRpbmdzLm9JbnN0YW5jZTsKCQl2YXIgY2FsbGJhY2sgPSBmdW5jdGlvbiAoIGpzb24gKSB7CgkJCXZhciBzdGF0dXMgPSBvU2V0dGluZ3MuanFYSFIKCQkJCT8gb1NldHRpbmdzLmpxWEhSLnN0YXR1cwoJCQkJOiBudWxsOwoJCgkJCWlmICgganNvbiA9PT0gbnVsbCB8fCAodHlwZW9mIHN0YXR1cyA9PT0gJ251bWJlcicgJiYgc3RhdHVzID09IDIwNCApICkgewoJCQkJanNvbiA9IHt9OwoJCQkJX2ZuQWpheERhdGFTcmMoIG9TZXR0aW5ncywganNvbiwgW10gKTsKCQkJfQoJCgkJCXZhciBlcnJvciA9IGpzb24uZXJyb3IgfHwganNvbi5zRXJyb3I7CgkJCWlmICggZXJyb3IgKSB7CgkJCQlfZm5Mb2coIG9TZXR0aW5ncywgMCwgZXJyb3IgKTsKCQkJfQoJCgkJCW9TZXR0aW5ncy5qc29uID0ganNvbjsKCQoJCQlfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgbnVsbCwgJ3hocicsIFtvU2V0dGluZ3MsIGpzb24sIG9TZXR0aW5ncy5qcVhIUl0gKTsKCQkJZm4oIGpzb24gKTsKCQl9OwoJCgkJaWYgKCAkLmlzUGxhaW5PYmplY3QoIGFqYXggKSAmJiBhamF4LmRhdGEgKQoJCXsKCQkJYWpheERhdGEgPSBhamF4LmRhdGE7CgkKCQkJdmFyIG5ld0RhdGEgPSB0eXBlb2YgYWpheERhdGEgPT09ICdmdW5jdGlvbicgPwoJCQkJYWpheERhdGEoIGRhdGEsIG9TZXR0aW5ncyApIDogIC8vIGZuIGNhbiBtYW5pcHVsYXRlIGRhdGEgb3IgcmV0dXJuCgkJCQlhamF4RGF0YTsgICAgICAgICAgICAgICAgICAgICAgLy8gYW4gb2JqZWN0IG9iamVjdCBvciBhcnJheSB0byBtZXJnZQoJCgkJCS8vIElmIHRoZSBmdW5jdGlvbiByZXR1cm5lZCBzb21ldGhpbmcsIHVzZSB0aGF0IGFsb25lCgkJCWRhdGEgPSB0eXBlb2YgYWpheERhdGEgPT09ICdmdW5jdGlvbicgJiYgbmV3RGF0YSA/CgkJCQluZXdEYXRhIDoKCQkJCSQuZXh0ZW5kKCB0cnVlLCBkYXRhLCBuZXdEYXRhICk7CgkKCQkJLy8gUmVtb3ZlIHRoZSBkYXRhIHByb3BlcnR5IGFzIHdlJ3ZlIHJlc29sdmVkIGl0IGFscmVhZHkgYW5kIGRvbid0IHdhbnQKCQkJLy8galF1ZXJ5IHRvIGRvIGl0IGFnYWluIChpdCBpcyByZXN0b3JlZCBhdCB0aGUgZW5kIG9mIHRoZSBmdW5jdGlvbikKCQkJZGVsZXRlIGFqYXguZGF0YTsKCQl9CgkKCQl2YXIgYmFzZUFqYXggPSB7CgkJCSJkYXRhIjogZGF0YSwKCQkJInN1Y2Nlc3MiOiBjYWxsYmFjaywKCQkJImRhdGFUeXBlIjogImpzb24iLAoJCQkiY2FjaGUiOiBmYWxzZSwKCQkJInR5cGUiOiBvU2V0dGluZ3Muc1NlcnZlck1ldGhvZCwKCQkJImVycm9yIjogZnVuY3Rpb24gKHhociwgZXJyb3IsIHRocm93bikgewoJCQkJdmFyIHJldCA9IF9mbkNhbGxiYWNrRmlyZSggb1NldHRpbmdzLCBudWxsLCAneGhyJywgW29TZXR0aW5ncywgbnVsbCwgb1NldHRpbmdzLmpxWEhSXSApOwoJCgkJCQlpZiAoICQuaW5BcnJheSggdHJ1ZSwgcmV0ICkgPT09IC0xICkgewoJCQkJCWlmICggZXJyb3IgPT0gInBhcnNlcmVycm9yIiApIHsKCQkJCQkJX2ZuTG9nKCBvU2V0dGluZ3MsIDAsICdJbnZhbGlkIEpTT04gcmVzcG9uc2UnLCAxICk7CgkJCQkJfQoJCQkJCWVsc2UgaWYgKCB4aHIucmVhZHlTdGF0ZSA9PT0gNCApIHsKCQkJCQkJX2ZuTG9nKCBvU2V0dGluZ3MsIDAsICdBamF4IGVycm9yJywgNyApOwoJCQkJCX0KCQkJCX0KCQoJCQkJX2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIG9TZXR0aW5ncywgZmFsc2UgKTsKCQkJfQoJCX07CgkKCQkvLyBTdG9yZSB0aGUgZGF0YSBzdWJtaXR0ZWQgZm9yIHRoZSBBUEkKCQlvU2V0dGluZ3Mub0FqYXhEYXRhID0gZGF0YTsKCQoJCS8vIEFsbG93IHBsdWctaW5zIGFuZCBleHRlcm5hbCBwcm9jZXNzZXMgdG8gbW9kaWZ5IHRoZSBkYXRhCgkJX2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsIG51bGwsICdwcmVYaHInLCBbb1NldHRpbmdzLCBkYXRhXSApOwoJCgkJaWYgKCBvU2V0dGluZ3MuZm5TZXJ2ZXJEYXRhICkKCQl7CgkJCS8vIERhdGFUYWJsZXMgMS45LSBjb21wYXRpYmlsaXR5CgkJCW9TZXR0aW5ncy5mblNlcnZlckRhdGEuY2FsbCggaW5zdGFuY2UsCgkJCQlvU2V0dGluZ3Muc0FqYXhTb3VyY2UsCgkJCQkkLm1hcCggZGF0YSwgZnVuY3Rpb24gKHZhbCwga2V5KSB7IC8vIE5lZWQgdG8gY29udmVydCBiYWNrIHRvIDEuOSB0cmFkIGZvcm1hdAoJCQkJCXJldHVybiB7IG5hbWU6IGtleSwgdmFsdWU6IHZhbCB9OwoJCQkJfSApLAoJCQkJY2FsbGJhY2ssCgkJCQlvU2V0dGluZ3MKCQkJKTsKCQl9CgkJZWxzZSBpZiAoIG9TZXR0aW5ncy5zQWpheFNvdXJjZSB8fCB0eXBlb2YgYWpheCA9PT0gJ3N0cmluZycgKQoJCXsKCQkJLy8gRGF0YVRhYmxlcyAxLjktIGNvbXBhdGliaWxpdHkKCQkJb1NldHRpbmdzLmpxWEhSID0gJC5hamF4KCAkLmV4dGVuZCggYmFzZUFqYXgsIHsKCQkJCXVybDogYWpheCB8fCBvU2V0dGluZ3Muc0FqYXhTb3VyY2UKCQkJfSApICk7CgkJfQoJCWVsc2UgaWYgKCB0eXBlb2YgYWpheCA9PT0gJ2Z1bmN0aW9uJyApCgkJewoJCQkvLyBJcyBhIGZ1bmN0aW9uIC0gbGV0IHRoZSBjYWxsZXIgZGVmaW5lIHdoYXQgbmVlZHMgdG8gYmUgZG9uZQoJCQlvU2V0dGluZ3MuanFYSFIgPSBhamF4LmNhbGwoIGluc3RhbmNlLCBkYXRhLCBjYWxsYmFjaywgb1NldHRpbmdzICk7CgkJfQoJCWVsc2UKCQl7CgkJCS8vIE9iamVjdCB0byBleHRlbmQgdGhlIGJhc2Ugc2V0dGluZ3MKCQkJb1NldHRpbmdzLmpxWEhSID0gJC5hamF4KCAkLmV4dGVuZCggYmFzZUFqYXgsIGFqYXggKSApOwoJCgkJCS8vIFJlc3RvcmUgZm9yIG5leHQgdGltZSBhcm91bmQKCQkJYWpheC5kYXRhID0gYWpheERhdGE7CgkJfQoJfQoJCgkKCS8qKgoJICogVXBkYXRlIHRoZSB0YWJsZSB1c2luZyBhbiBBamF4IGNhbGwKCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcmV0dXJucyB7Ym9vbGVhbn0gQmxvY2sgdGhlIHRhYmxlIGRyYXdpbmcgb3Igbm90CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkFqYXhVcGRhdGUoIHNldHRpbmdzICkKCXsKCQlzZXR0aW5ncy5pRHJhdysrOwoJCV9mblByb2Nlc3NpbmdEaXNwbGF5KCBzZXR0aW5ncywgdHJ1ZSApOwoJCgkJX2ZuQnVpbGRBamF4KAoJCQlzZXR0aW5ncywKCQkJX2ZuQWpheFBhcmFtZXRlcnMoIHNldHRpbmdzICksCgkJCWZ1bmN0aW9uKGpzb24pIHsKCQkJCV9mbkFqYXhVcGRhdGVEcmF3KCBzZXR0aW5ncywganNvbiApOwoJCQl9CgkJKTsKCX0KCQoJCgkvKioKCSAqIEJ1aWxkIHVwIHRoZSBwYXJhbWV0ZXJzIGluIGFuIG9iamVjdCBuZWVkZWQgZm9yIGEgc2VydmVyLXNpZGUgcHJvY2Vzc2luZwoJICogcmVxdWVzdC4gTm90ZSB0aGF0IHRoaXMgaXMgYmFzaWNhbGx5IGRvbmUgdHdpY2UsIGlzIGRpZmZlcmVudCB3YXlzIC0gYSBtb2Rlcm4KCSAqIG1ldGhvZCB3aGljaCBpcyB1c2VkIGJ5IGRlZmF1bHQgaW4gRGF0YVRhYmxlcyAxLjEwIHdoaWNoIHVzZXMgb2JqZWN0cyBhbmQKCSAqIGFycmF5cywgb3IgdGhlIDEuOS0gbWV0aG9kIHdpdGggaXMgbmFtZSAvIHZhbHVlIHBhaXJzLiAxLjkgbWV0aG9kIGlzIHVzZWQgaWYKCSAqIHRoZSBzQWpheFNvdXJjZSBvcHRpb24gaXMgdXNlZCBpbiB0aGUgaW5pdGlhbGlzYXRpb24sIG9yIHRoZSBsZWdhY3lBamF4CgkgKiBvcHRpb24gaXMgc2V0LgoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcmV0dXJucyB7Ym9vbH0gYmxvY2sgdGhlIHRhYmxlIGRyYXdpbmcgb3Igbm90CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkFqYXhQYXJhbWV0ZXJzKCBzZXR0aW5ncyApCgl7CgkJdmFyCgkJCWNvbHVtbnMgPSBzZXR0aW5ncy5hb0NvbHVtbnMsCgkJCWNvbHVtbkNvdW50ID0gY29sdW1ucy5sZW5ndGgsCgkJCWZlYXR1cmVzID0gc2V0dGluZ3Mub0ZlYXR1cmVzLAoJCQlwcmVTZWFyY2ggPSBzZXR0aW5ncy5vUHJldmlvdXNTZWFyY2gsCgkJCXByZUNvbFNlYXJjaCA9IHNldHRpbmdzLmFvUHJlU2VhcmNoQ29scywKCQkJaSwgZGF0YSA9IFtdLCBkYXRhUHJvcCwgY29sdW1uLCBjb2x1bW5TZWFyY2gsCgkJCXNvcnQgPSBfZm5Tb3J0RmxhdHRlbiggc2V0dGluZ3MgKSwKCQkJZGlzcGxheVN0YXJ0ID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsCgkJCWRpc3BsYXlMZW5ndGggPSBmZWF0dXJlcy5iUGFnaW5hdGUgIT09IGZhbHNlID8KCQkJCXNldHRpbmdzLl9pRGlzcGxheUxlbmd0aCA6CgkJCQktMTsKCQoJCXZhciBwYXJhbSA9IGZ1bmN0aW9uICggbmFtZSwgdmFsdWUgKSB7CgkJCWRhdGEucHVzaCggeyAnbmFtZSc6IG5hbWUsICd2YWx1ZSc6IHZhbHVlIH0gKTsKCQl9OwoJCgkJLy8gRGF0YVRhYmxlcyAxLjktIGNvbXBhdGlibGUgbWV0aG9kCgkJcGFyYW0oICdzRWNobycsICAgICAgICAgIHNldHRpbmdzLmlEcmF3ICk7CgkJcGFyYW0oICdpQ29sdW1ucycsICAgICAgIGNvbHVtbkNvdW50ICk7CgkJcGFyYW0oICdzQ29sdW1ucycsICAgICAgIF9wbHVjayggY29sdW1ucywgJ3NOYW1lJyApLmpvaW4oJywnKSApOwoJCXBhcmFtKCAnaURpc3BsYXlTdGFydCcsICBkaXNwbGF5U3RhcnQgKTsKCQlwYXJhbSggJ2lEaXNwbGF5TGVuZ3RoJywgZGlzcGxheUxlbmd0aCApOwoJCgkJLy8gRGF0YVRhYmxlcyAxLjEwKyBtZXRob2QKCQl2YXIgZCA9IHsKCQkJZHJhdzogICAgc2V0dGluZ3MuaURyYXcsCgkJCWNvbHVtbnM6IFtdLAoJCQlvcmRlcjogICBbXSwKCQkJc3RhcnQ6ICAgZGlzcGxheVN0YXJ0LAoJCQlsZW5ndGg6ICBkaXNwbGF5TGVuZ3RoLAoJCQlzZWFyY2g6ICB7CgkJCQl2YWx1ZTogcHJlU2VhcmNoLnNTZWFyY2gsCgkJCQlyZWdleDogcHJlU2VhcmNoLmJSZWdleAoJCQl9CgkJfTsKCQoJCWZvciAoIGk9MCA7IGk8Y29sdW1uQ291bnQgOyBpKysgKSB7CgkJCWNvbHVtbiA9IGNvbHVtbnNbaV07CgkJCWNvbHVtblNlYXJjaCA9IHByZUNvbFNlYXJjaFtpXTsKCQkJZGF0YVByb3AgPSB0eXBlb2YgY29sdW1uLm1EYXRhPT0iZnVuY3Rpb24iID8gJ2Z1bmN0aW9uJyA6IGNvbHVtbi5tRGF0YSA7CgkKCQkJZC5jb2x1bW5zLnB1c2goIHsKCQkJCWRhdGE6ICAgICAgIGRhdGFQcm9wLAoJCQkJbmFtZTogICAgICAgY29sdW1uLnNOYW1lLAoJCQkJc2VhcmNoYWJsZTogY29sdW1uLmJTZWFyY2hhYmxlLAoJCQkJb3JkZXJhYmxlOiAgY29sdW1uLmJTb3J0YWJsZSwKCQkJCXNlYXJjaDogICAgIHsKCQkJCQl2YWx1ZTogY29sdW1uU2VhcmNoLnNTZWFyY2gsCgkJCQkJcmVnZXg6IGNvbHVtblNlYXJjaC5iUmVnZXgKCQkJCX0KCQkJfSApOwoJCgkJCXBhcmFtKCAibURhdGFQcm9wXyIraSwgZGF0YVByb3AgKTsKCQoJCQlpZiAoIGZlYXR1cmVzLmJGaWx0ZXIgKSB7CgkJCQlwYXJhbSggJ3NTZWFyY2hfJytpLCAgICAgY29sdW1uU2VhcmNoLnNTZWFyY2ggKTsKCQkJCXBhcmFtKCAnYlJlZ2V4XycraSwgICAgICBjb2x1bW5TZWFyY2guYlJlZ2V4ICk7CgkJCQlwYXJhbSggJ2JTZWFyY2hhYmxlXycraSwgY29sdW1uLmJTZWFyY2hhYmxlICk7CgkJCX0KCQoJCQlpZiAoIGZlYXR1cmVzLmJTb3J0ICkgewoJCQkJcGFyYW0oICdiU29ydGFibGVfJytpLCBjb2x1bW4uYlNvcnRhYmxlICk7CgkJCX0KCQl9CgkKCQlpZiAoIGZlYXR1cmVzLmJGaWx0ZXIgKSB7CgkJCXBhcmFtKCAnc1NlYXJjaCcsIHByZVNlYXJjaC5zU2VhcmNoICk7CgkJCXBhcmFtKCAnYlJlZ2V4JywgcHJlU2VhcmNoLmJSZWdleCApOwoJCX0KCQoJCWlmICggZmVhdHVyZXMuYlNvcnQgKSB7CgkJCSQuZWFjaCggc29ydCwgZnVuY3Rpb24gKCBpLCB2YWwgKSB7CgkJCQlkLm9yZGVyLnB1c2goIHsgY29sdW1uOiB2YWwuY29sLCBkaXI6IHZhbC5kaXIgfSApOwoJCgkJCQlwYXJhbSggJ2lTb3J0Q29sXycraSwgdmFsLmNvbCApOwoJCQkJcGFyYW0oICdzU29ydERpcl8nK2ksIHZhbC5kaXIgKTsKCQkJfSApOwoJCgkJCXBhcmFtKCAnaVNvcnRpbmdDb2xzJywgc29ydC5sZW5ndGggKTsKCQl9CgkKCQkvLyBJZiB0aGUgbGVnYWN5LmFqYXggcGFyYW1ldGVyIGlzIG51bGwsIHRoZW4gd2UgYXV0b21hdGljYWxseSBkZWNpZGUgd2hpY2gKCQkvLyBmb3JtIHRvIHVzZSwgYmFzZWQgb24gc0FqYXhTb3VyY2UKCQl2YXIgbGVnYWN5ID0gRGF0YVRhYmxlLmV4dC5sZWdhY3kuYWpheDsKCQlpZiAoIGxlZ2FjeSA9PT0gbnVsbCApIHsKCQkJcmV0dXJuIHNldHRpbmdzLnNBamF4U291cmNlID8gZGF0YSA6IGQ7CgkJfQoJCgkJLy8gT3RoZXJ3aXNlLCBpZiBsZWdhY3kgaGFzIGJlZW4gc3BlY2lmaWVkIHRoZW4gd2UgdXNlIHRoYXQgdG8gZGVjaWRlIG9uIHRoZQoJCS8vIGZvcm0KCQlyZXR1cm4gbGVnYWN5ID8gZGF0YSA6IGQ7Cgl9CgkKCQoJLyoqCgkgKiBEYXRhIHRoZSBkYXRhIGZyb20gdGhlIHNlcnZlciAobnVraW5nIHRoZSBvbGQpIGFuZCByZWRyYXcgdGhlIHRhYmxlCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7b2JqZWN0fSBqc29uIGpzb24gZGF0YSByZXR1cm4gZnJvbSB0aGUgc2VydmVyLgoJICogIEBwYXJhbSB7c3RyaW5nfSBqc29uLnNFY2hvIFRyYWNraW5nIGZsYWcgZm9yIERhdGFUYWJsZXMgdG8gbWF0Y2ggcmVxdWVzdHMKCSAqICBAcGFyYW0ge2ludH0ganNvbi5pVG90YWxSZWNvcmRzIE51bWJlciBvZiByZWNvcmRzIGluIHRoZSBkYXRhIHNldCwgbm90IGFjY291bnRpbmcgZm9yIGZpbHRlcmluZwoJICogIEBwYXJhbSB7aW50fSBqc29uLmlUb3RhbERpc3BsYXlSZWNvcmRzIE51bWJlciBvZiByZWNvcmRzIGluIHRoZSBkYXRhIHNldCwgYWNjb3VudGluZyBmb3IgZmlsdGVyaW5nCgkgKiAgQHBhcmFtIHthcnJheX0ganNvbi5hYURhdGEgVGhlIGRhdGEgdG8gZGlzcGxheSBvbiB0aGlzIHBhZ2UKCSAqICBAcGFyYW0ge3N0cmluZ30gW2pzb24uc0NvbHVtbnNdIENvbHVtbiBvcmRlcmluZyAoc05hbWUsIGNvbW1hIHNlcGFyYXRlZCkKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuQWpheFVwZGF0ZURyYXcgKCBzZXR0aW5ncywganNvbiApCgl7CgkJLy8gdjEuMTAgdXNlcyBjYW1lbENhc2UgdmFyaWFibGVzLCB3aGlsZSAxLjkgdXNlcyBIdW5nYXJpYW4gbm90YXRpb24uCgkJLy8gU3VwcG9ydCBib3RoCgkJdmFyIGNvbXBhdCA9IGZ1bmN0aW9uICggb2xkLCBtb2Rlcm4gKSB7CgkJCXJldHVybiBqc29uW29sZF0gIT09IHVuZGVmaW5lZCA/IGpzb25bb2xkXSA6IGpzb25bbW9kZXJuXTsKCQl9OwoJCgkJdmFyIGRhdGEgPSBfZm5BamF4RGF0YVNyYyggc2V0dGluZ3MsIGpzb24gKTsKCQl2YXIgZHJhdyAgICAgICAgICAgID0gY29tcGF0KCAnc0VjaG8nLCAgICAgICAgICAgICAgICAnZHJhdycgKTsKCQl2YXIgcmVjb3Jkc1RvdGFsICAgID0gY29tcGF0KCAnaVRvdGFsUmVjb3JkcycsICAgICAgICAncmVjb3Jkc1RvdGFsJyApOwoJCXZhciByZWNvcmRzRmlsdGVyZWQgPSBjb21wYXQoICdpVG90YWxEaXNwbGF5UmVjb3JkcycsICdyZWNvcmRzRmlsdGVyZWQnICk7CgkKCQlpZiAoIGRyYXcgIT09IHVuZGVmaW5lZCApIHsKCQkJLy8gUHJvdGVjdCBhZ2FpbnN0IG91dCBvZiBzZXF1ZW5jZSByZXR1cm5zCgkJCWlmICggZHJhdyoxIDwgc2V0dGluZ3MuaURyYXcgKSB7CgkJCQlyZXR1cm47CgkJCX0KCQkJc2V0dGluZ3MuaURyYXcgPSBkcmF3ICogMTsKCQl9CgkKCQkvLyBObyBkYXRhIGluIHJldHVybmVkIG9iamVjdCwgc28gcmF0aGVyIHRoYW4gYW4gYXJyYXksIHdlIHNob3cgYW4gZW1wdHkgdGFibGUKCQlpZiAoICEgZGF0YSApIHsKCQkJZGF0YSA9IFtdOwoJCX0KCQoJCV9mbkNsZWFyVGFibGUoIHNldHRpbmdzICk7CgkJc2V0dGluZ3MuX2lSZWNvcmRzVG90YWwgICA9IHBhcnNlSW50KHJlY29yZHNUb3RhbCwgMTApOwoJCXNldHRpbmdzLl9pUmVjb3Jkc0Rpc3BsYXkgPSBwYXJzZUludChyZWNvcmRzRmlsdGVyZWQsIDEwKTsKCQoJCWZvciAoIHZhciBpPTAsIGllbj1kYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQlfZm5BZGREYXRhKCBzZXR0aW5ncywgZGF0YVtpXSApOwoJCX0KCQlzZXR0aW5ncy5haURpc3BsYXkgPSBzZXR0aW5ncy5haURpc3BsYXlNYXN0ZXIuc2xpY2UoKTsKCQoJCV9mbkRyYXcoIHNldHRpbmdzLCB0cnVlICk7CgkKCQlpZiAoICEgc2V0dGluZ3MuX2JJbml0Q29tcGxldGUgKSB7CgkJCV9mbkluaXRDb21wbGV0ZSggc2V0dGluZ3MsIGpzb24gKTsKCQl9CgkKCQlfZm5Qcm9jZXNzaW5nRGlzcGxheSggc2V0dGluZ3MsIGZhbHNlICk7Cgl9CgkKCQoJLyoqCgkgKiBHZXQgdGhlIGRhdGEgZnJvbSB0aGUgSlNPTiBkYXRhIHNvdXJjZSB0byB1c2UgZm9yIGRyYXdpbmcgYSB0YWJsZS4gVXNpbmcKCSAqIGBfZm5HZXRPYmplY3REYXRhRm5gIGFsbG93cyB0aGUgZGF0YSB0byBiZSBzb3VyY2VkIGZyb20gYSBwcm9wZXJ0eSBvZiB0aGUKCSAqIHNvdXJjZSBvYmplY3QsIG9yIGZyb20gYSBwcm9jZXNzaW5nIGZ1bmN0aW9uLgoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0gIHtvYmplY3R9IGpzb24gRGF0YSBzb3VyY2Ugb2JqZWN0IC8gYXJyYXkgZnJvbSB0aGUgc2VydmVyCgkgKiAgQHJldHVybiB7YXJyYXl9IEFycmF5IG9mIGRhdGEgdG8gdXNlCgkgKi8KCSBmdW5jdGlvbiBfZm5BamF4RGF0YVNyYyAoIG9TZXR0aW5ncywganNvbiwgd3JpdGUgKQoJIHsKCQl2YXIgZGF0YVNyYyA9ICQuaXNQbGFpbk9iamVjdCggb1NldHRpbmdzLmFqYXggKSAmJiBvU2V0dGluZ3MuYWpheC5kYXRhU3JjICE9PSB1bmRlZmluZWQgPwoJCQlvU2V0dGluZ3MuYWpheC5kYXRhU3JjIDoKCQkJb1NldHRpbmdzLnNBamF4RGF0YVByb3A7IC8vIENvbXBhdGliaWxpdHkgd2l0aCAxLjktLgoJCgkJaWYgKCAhIHdyaXRlICkgewoJCQlpZiAoIGRhdGFTcmMgPT09ICdkYXRhJyApIHsKCQkJCS8vIElmIHRoZSBkZWZhdWx0LCB0aGVuIHdlIHN0aWxsIHdhbnQgdG8gc3VwcG9ydCB0aGUgb2xkIHN0eWxlLCBhbmQgc2FmZWx5IGlnbm9yZQoJCQkJLy8gaXQgaWYgcG9zc2libGUKCQkJCXJldHVybiBqc29uLmFhRGF0YSB8fCBqc29uW2RhdGFTcmNdOwoJCQl9CgkKCQkJcmV0dXJuIGRhdGFTcmMgIT09ICIiID8KCQkJCV9mbkdldE9iamVjdERhdGFGbiggZGF0YVNyYyApKCBqc29uICkgOgoJCQkJanNvbjsKCQl9CgkKCQkvLyBzZXQKCQlfZm5TZXRPYmplY3REYXRhRm4oIGRhdGFTcmMgKSgganNvbiwgd3JpdGUgKTsKCX0KCQoJLyoqCgkgKiBHZW5lcmF0ZSB0aGUgbm9kZSByZXF1aXJlZCBmb3IgZmlsdGVyaW5nIHRleHQKCSAqICBAcmV0dXJucyB7bm9kZX0gRmlsdGVyIGNvbnRyb2wgZWxlbWVudAoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuRmVhdHVyZUh0bWxGaWx0ZXIgKCBzZXR0aW5ncyApCgl7CgkJdmFyIGNsYXNzZXMgPSBzZXR0aW5ncy5vQ2xhc3NlczsKCQl2YXIgdGFibGVJZCA9IHNldHRpbmdzLnNUYWJsZUlkOwoJCXZhciBsYW5ndWFnZSA9IHNldHRpbmdzLm9MYW5ndWFnZTsKCQl2YXIgcHJldmlvdXNTZWFyY2ggPSBzZXR0aW5ncy5vUHJldmlvdXNTZWFyY2g7CgkJdmFyIGZlYXR1cmVzID0gc2V0dGluZ3MuYWFuRmVhdHVyZXM7CgkJdmFyIGlucHV0ID0gJzxpbnB1dCB0eXBlPSJzZWFyY2giIGNsYXNzPSInK2NsYXNzZXMuc0ZpbHRlcklucHV0KyciLz4nOwoJCgkJdmFyIHN0ciA9IGxhbmd1YWdlLnNTZWFyY2g7CgkJc3RyID0gc3RyLm1hdGNoKC9fSU5QVVRfLykgPwoJCQlzdHIucmVwbGFjZSgnX0lOUFVUXycsIGlucHV0KSA6CgkJCXN0citpbnB1dDsKCQoJCXZhciBmaWx0ZXIgPSAkKCc8ZGl2Lz4nLCB7CgkJCQknaWQnOiAhIGZlYXR1cmVzLmYgPyB0YWJsZUlkKydfZmlsdGVyJyA6IG51bGwsCgkJCQknY2xhc3MnOiBjbGFzc2VzLnNGaWx0ZXIKCQkJfSApCgkJCS5hcHBlbmQoICQoJzxsYWJlbC8+JyApLmFwcGVuZCggc3RyICkgKTsKCQoJCXZhciBzZWFyY2hGbiA9IGZ1bmN0aW9uKGV2ZW50KSB7CgkJCS8qIFVwZGF0ZSBhbGwgb3RoZXIgZmlsdGVyIGlucHV0IGVsZW1lbnRzIGZvciB0aGUgbmV3IGRpc3BsYXkgKi8KCQkJdmFyIG4gPSBmZWF0dXJlcy5mOwoJCQl2YXIgdmFsID0gIXRoaXMudmFsdWUgPyAiIiA6IHRoaXMudmFsdWU7IC8vIG1lbnRhbCBJRTggZml4IDotKAoJCQlpZihwcmV2aW91c1NlYXJjaC5yZXR1cm4gJiYgZXZlbnQua2V5ICE9PSAiRW50ZXIiKSB7CgkJCQlyZXR1cm47CgkJCX0KCQkJLyogTm93IGRvIHRoZSBmaWx0ZXIgKi8KCQkJaWYgKCB2YWwgIT0gcHJldmlvdXNTZWFyY2guc1NlYXJjaCApIHsKCQkJCV9mbkZpbHRlckNvbXBsZXRlKCBzZXR0aW5ncywgewoJCQkJCSJzU2VhcmNoIjogdmFsLAoJCQkJCSJiUmVnZXgiOiBwcmV2aW91c1NlYXJjaC5iUmVnZXgsCgkJCQkJImJTbWFydCI6IHByZXZpb3VzU2VhcmNoLmJTbWFydCAsCgkJCQkJImJDYXNlSW5zZW5zaXRpdmUiOiBwcmV2aW91c1NlYXJjaC5iQ2FzZUluc2Vuc2l0aXZlLAoJCQkJCSJyZXR1cm4iOiBwcmV2aW91c1NlYXJjaC5yZXR1cm4KCQkJCX0gKTsKCQoJCQkJLy8gTmVlZCB0byByZWRyYXcsIHdpdGhvdXQgcmVzb3J0aW5nCgkJCQlzZXR0aW5ncy5faURpc3BsYXlTdGFydCA9IDA7CgkJCQlfZm5EcmF3KCBzZXR0aW5ncyApOwoJCQl9CgkJfTsKCQoJCXZhciBzZWFyY2hEZWxheSA9IHNldHRpbmdzLnNlYXJjaERlbGF5ICE9PSBudWxsID8KCQkJc2V0dGluZ3Muc2VhcmNoRGVsYXkgOgoJCQlfZm5EYXRhU291cmNlKCBzZXR0aW5ncyApID09PSAnc3NwJyA/CgkJCQk0MDAgOgoJCQkJMDsKCQoJCXZhciBqcUZpbHRlciA9ICQoJ2lucHV0JywgZmlsdGVyKQoJCQkudmFsKCBwcmV2aW91c1NlYXJjaC5zU2VhcmNoICkKCQkJLmF0dHIoICdwbGFjZWhvbGRlcicsIGxhbmd1YWdlLnNTZWFyY2hQbGFjZWhvbGRlciApCgkJCS5vbigKCQkJCSdrZXl1cC5EVCBzZWFyY2guRFQgaW5wdXQuRFQgcGFzdGUuRFQgY3V0LkRUJywKCQkJCXNlYXJjaERlbGF5ID8KCQkJCQlfZm5UaHJvdHRsZSggc2VhcmNoRm4sIHNlYXJjaERlbGF5ICkgOgoJCQkJCXNlYXJjaEZuCgkJCSkKCQkJLm9uKCAnbW91c2V1cCcsIGZ1bmN0aW9uKGUpIHsKCQkJCS8vIEVkZ2UgZml4ISBFZGdlIDE3IGRvZXMgbm90IHRyaWdnZXIgYW55dGhpbmcgb3RoZXIgdGhhbiBtb3VzZSBldmVudHMgd2hlbiBjbGlja2luZwoJCQkJLy8gb24gdGhlIGNsZWFyIGljb24gKEVkZ2UgYnVnIDE3NTg0NTE1KS4gVGhpcyBpcyBzYWZlIGluIG90aGVyIGJyb3dzZXJzIGFzIGBzZWFyY2hGbmAKCQkJCS8vIGNoZWNrcyB0aGUgdmFsdWUgdG8gc2VlIGlmIGl0IGhhcyBjaGFuZ2VkLiBJbiBvdGhlciBicm93c2VycyBpdCB3b24ndCBoYXZlLgoJCQkJc2V0VGltZW91dCggZnVuY3Rpb24gKCkgewoJCQkJCXNlYXJjaEZuLmNhbGwoanFGaWx0ZXJbMF0sIGUpOwoJCQkJfSwgMTApOwoJCQl9ICkKCQkJLm9uKCAna2V5cHJlc3MuRFQnLCBmdW5jdGlvbihlKSB7CgkJCQkvKiBQcmV2ZW50IGZvcm0gc3VibWlzc2lvbiAqLwoJCQkJaWYgKCBlLmtleUNvZGUgPT0gMTMgKSB7CgkJCQkJcmV0dXJuIGZhbHNlOwoJCQkJfQoJCQl9ICkKCQkJLmF0dHIoJ2FyaWEtY29udHJvbHMnLCB0YWJsZUlkKTsKCQoJCS8vIFVwZGF0ZSB0aGUgaW5wdXQgZWxlbWVudHMgd2hlbmV2ZXIgdGhlIHRhYmxlIGlzIGZpbHRlcmVkCgkJJChzZXR0aW5ncy5uVGFibGUpLm9uKCAnc2VhcmNoLmR0LkRUJywgZnVuY3Rpb24gKCBldiwgcyApIHsKCQkJaWYgKCBzZXR0aW5ncyA9PT0gcyApIHsKCQkJCS8vIElFOSB0aHJvd3MgYW4gJ3Vua25vd24gZXJyb3InIGlmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgaXMgdXNlZAoJCQkJLy8gaW5zaWRlIGFuIGlmcmFtZSBvciBmcmFtZS4uLgoJCQkJdHJ5IHsKCQkJCQlpZiAoIGpxRmlsdGVyWzBdICE9PSBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICkgewoJCQkJCQlqcUZpbHRlci52YWwoIHByZXZpb3VzU2VhcmNoLnNTZWFyY2ggKTsKCQkJCQl9CgkJCQl9CgkJCQljYXRjaCAoIGUgKSB7fQoJCQl9CgkJfSApOwoJCgkJcmV0dXJuIGZpbHRlclswXTsKCX0KCQoJCgkvKioKCSAqIEZpbHRlciB0aGUgdGFibGUgdXNpbmcgYm90aCB0aGUgZ2xvYmFsIGZpbHRlciBhbmQgY29sdW1uIGJhc2VkIGZpbHRlcmluZwoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge29iamVjdH0gb1NlYXJjaCBzZWFyY2ggaW5mb3JtYXRpb24KCSAqICBAcGFyYW0ge2ludH0gW2lGb3JjZV0gZm9yY2UgYSByZXNlYXJjaCBvZiB0aGUgbWFzdGVyIGFycmF5ICgxKSBvciBub3QgKHVuZGVmaW5lZCBvciAwKQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5GaWx0ZXJDb21wbGV0ZSAoIG9TZXR0aW5ncywgb0lucHV0LCBpRm9yY2UgKQoJewoJCXZhciBvUHJldlNlYXJjaCA9IG9TZXR0aW5ncy5vUHJldmlvdXNTZWFyY2g7CgkJdmFyIGFvUHJldlNlYXJjaCA9IG9TZXR0aW5ncy5hb1ByZVNlYXJjaENvbHM7CgkJdmFyIGZuU2F2ZUZpbHRlciA9IGZ1bmN0aW9uICggb0ZpbHRlciApIHsKCQkJLyogU2F2ZSB0aGUgZmlsdGVyaW5nIHZhbHVlcyAqLwoJCQlvUHJldlNlYXJjaC5zU2VhcmNoID0gb0ZpbHRlci5zU2VhcmNoOwoJCQlvUHJldlNlYXJjaC5iUmVnZXggPSBvRmlsdGVyLmJSZWdleDsKCQkJb1ByZXZTZWFyY2guYlNtYXJ0ID0gb0ZpbHRlci5iU21hcnQ7CgkJCW9QcmV2U2VhcmNoLmJDYXNlSW5zZW5zaXRpdmUgPSBvRmlsdGVyLmJDYXNlSW5zZW5zaXRpdmU7CgkJCW9QcmV2U2VhcmNoLnJldHVybiA9IG9GaWx0ZXIucmV0dXJuOwoJCX07CgkJdmFyIGZuUmVnZXggPSBmdW5jdGlvbiAoIG8gKSB7CgkJCS8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggdGhlIGJFc2NhcGVSZWdleCBvcHRpb24KCQkJcmV0dXJuIG8uYkVzY2FwZVJlZ2V4ICE9PSB1bmRlZmluZWQgPyAhby5iRXNjYXBlUmVnZXggOiBvLmJSZWdleDsKCQl9OwoJCgkJLy8gUmVzb2x2ZSBhbnkgY29sdW1uIHR5cGVzIHRoYXQgYXJlIHVua25vd24gZHVlIHRvIGFkZGl0aW9uIG9yIGludmFsaWRhdGlvbgoJCS8vIEB0b2RvIEFzIHBlciBzb3J0IC0gY2FuIHRoaXMgYmUgbW92ZWQgaW50byBhbiBldmVudCBoYW5kbGVyPwoJCV9mbkNvbHVtblR5cGVzKCBvU2V0dGluZ3MgKTsKCQoJCS8qIEluIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcgYWxsIGZpbHRlcmluZyBpcyBkb25lIGJ5IHRoZSBzZXJ2ZXIsIHNvIG5vIHBvaW50IGhhbmdpbmcgYXJvdW5kIGhlcmUgKi8KCQlpZiAoIF9mbkRhdGFTb3VyY2UoIG9TZXR0aW5ncyApICE9ICdzc3AnICkKCQl7CgkJCS8qIEdsb2JhbCBmaWx0ZXIgKi8KCQkJX2ZuRmlsdGVyKCBvU2V0dGluZ3MsIG9JbnB1dC5zU2VhcmNoLCBpRm9yY2UsIGZuUmVnZXgob0lucHV0KSwgb0lucHV0LmJTbWFydCwgb0lucHV0LmJDYXNlSW5zZW5zaXRpdmUsIG9JbnB1dC5yZXR1cm4gKTsKCQkJZm5TYXZlRmlsdGVyKCBvSW5wdXQgKTsKCQoJCQkvKiBOb3cgZG8gdGhlIGluZGl2aWR1YWwgY29sdW1uIGZpbHRlciAqLwoJCQlmb3IgKCB2YXIgaT0wIDsgaTxhb1ByZXZTZWFyY2gubGVuZ3RoIDsgaSsrICkKCQkJewoJCQkJX2ZuRmlsdGVyQ29sdW1uKCBvU2V0dGluZ3MsIGFvUHJldlNlYXJjaFtpXS5zU2VhcmNoLCBpLCBmblJlZ2V4KGFvUHJldlNlYXJjaFtpXSksCgkJCQkJYW9QcmV2U2VhcmNoW2ldLmJTbWFydCwgYW9QcmV2U2VhcmNoW2ldLmJDYXNlSW5zZW5zaXRpdmUgKTsKCQkJfQoJCgkJCS8qIEN1c3RvbSBmaWx0ZXJpbmcgKi8KCQkJX2ZuRmlsdGVyQ3VzdG9tKCBvU2V0dGluZ3MgKTsKCQl9CgkJZWxzZQoJCXsKCQkJZm5TYXZlRmlsdGVyKCBvSW5wdXQgKTsKCQl9CgkKCQkvKiBUZWxsIHRoZSBkcmF3IGZ1bmN0aW9uIHdlIGhhdmUgYmVlbiBmaWx0ZXJpbmcgKi8KCQlvU2V0dGluZ3MuYkZpbHRlcmVkID0gdHJ1ZTsKCQlfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgbnVsbCwgJ3NlYXJjaCcsIFtvU2V0dGluZ3NdICk7Cgl9CgkKCQoJLyoqCgkgKiBBcHBseSBjdXN0b20gZmlsdGVyaW5nIGZ1bmN0aW9ucwoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuRmlsdGVyQ3VzdG9tKCBzZXR0aW5ncyApCgl7CgkJdmFyIGZpbHRlcnMgPSBEYXRhVGFibGUuZXh0LnNlYXJjaDsKCQl2YXIgZGlzcGxheVJvd3MgPSBzZXR0aW5ncy5haURpc3BsYXk7CgkJdmFyIHJvdywgcm93SWR4OwoJCgkJZm9yICggdmFyIGk9MCwgaWVuPWZpbHRlcnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCXZhciByb3dzID0gW107CgkKCQkJLy8gTG9vcCBvdmVyIGVhY2ggcm93IGFuZCBzZWUgaWYgaXQgc2hvdWxkIGJlIGluY2x1ZGVkCgkJCWZvciAoIHZhciBqPTAsIGplbj1kaXNwbGF5Um93cy5sZW5ndGggOyBqPGplbiA7IGorKyApIHsKCQkJCXJvd0lkeCA9IGRpc3BsYXlSb3dzWyBqIF07CgkJCQlyb3cgPSBzZXR0aW5ncy5hb0RhdGFbIHJvd0lkeCBdOwoJCgkJCQlpZiAoIGZpbHRlcnNbaV0oIHNldHRpbmdzLCByb3cuX2FGaWx0ZXJEYXRhLCByb3dJZHgsIHJvdy5fYURhdGEsIGogKSApIHsKCQkJCQlyb3dzLnB1c2goIHJvd0lkeCApOwoJCQkJfQoJCQl9CgkKCQkJLy8gU28gdGhlIGFycmF5IHJlZmVyZW5jZSBkb2Vzbid0IGJyZWFrIHNldCB0aGUgcmVzdWx0cyBpbnRvIHRoZQoJCQkvLyBleGlzdGluZyBhcnJheQoJCQlkaXNwbGF5Um93cy5sZW5ndGggPSAwOwoJCQkkLm1lcmdlKCBkaXNwbGF5Um93cywgcm93cyApOwoJCX0KCX0KCQoJCgkvKioKCSAqIEZpbHRlciB0aGUgdGFibGUgb24gYSBwZXItY29sdW1uIGJhc2lzCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7c3RyaW5nfSBzSW5wdXQgc3RyaW5nIHRvIGZpbHRlciBvbgoJICogIEBwYXJhbSB7aW50fSBpQ29sdW1uIGNvbHVtbiB0byBmaWx0ZXIKCSAqICBAcGFyYW0ge2Jvb2x9IGJSZWdleCB0cmVhdCBzZWFyY2ggc3RyaW5nIGFzIGEgcmVndWxhciBleHByZXNzaW9uIG9yIG5vdAoJICogIEBwYXJhbSB7Ym9vbH0gYlNtYXJ0IHVzZSBzbWFydCBmaWx0ZXJpbmcgb3Igbm90CgkgKiAgQHBhcmFtIHtib29sfSBiQ2FzZUluc2Vuc2l0aXZlIERvIGNhc2UgaW5zZW5zaXRpdmUgbWF0Y2hpbmcgb3Igbm90CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkZpbHRlckNvbHVtbiAoIHNldHRpbmdzLCBzZWFyY2hTdHIsIGNvbElkeCwgcmVnZXgsIHNtYXJ0LCBjYXNlSW5zZW5zaXRpdmUgKQoJewoJCWlmICggc2VhcmNoU3RyID09PSAnJyApIHsKCQkJcmV0dXJuOwoJCX0KCQoJCXZhciBkYXRhOwoJCXZhciBvdXQgPSBbXTsKCQl2YXIgZGlzcGxheSA9IHNldHRpbmdzLmFpRGlzcGxheTsKCQl2YXIgcnBTZWFyY2ggPSBfZm5GaWx0ZXJDcmVhdGVTZWFyY2goIHNlYXJjaFN0ciwgcmVnZXgsIHNtYXJ0LCBjYXNlSW5zZW5zaXRpdmUgKTsKCQoJCWZvciAoIHZhciBpPTAgOyBpPGRpc3BsYXkubGVuZ3RoIDsgaSsrICkgewoJCQlkYXRhID0gc2V0dGluZ3MuYW9EYXRhWyBkaXNwbGF5W2ldIF0uX2FGaWx0ZXJEYXRhWyBjb2xJZHggXTsKCQoJCQlpZiAoIHJwU2VhcmNoLnRlc3QoIGRhdGEgKSApIHsKCQkJCW91dC5wdXNoKCBkaXNwbGF5W2ldICk7CgkJCX0KCQl9CgkKCQlzZXR0aW5ncy5haURpc3BsYXkgPSBvdXQ7Cgl9CgkKCQoJLyoqCgkgKiBGaWx0ZXIgdGhlIGRhdGEgdGFibGUgYmFzZWQgb24gdXNlciBpbnB1dCBhbmQgZHJhdyB0aGUgdGFibGUKCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge3N0cmluZ30gaW5wdXQgc3RyaW5nIHRvIGZpbHRlciBvbgoJICogIEBwYXJhbSB7aW50fSBmb3JjZSBvcHRpb25hbCAtIGZvcmNlIGEgcmVzZWFyY2ggb2YgdGhlIG1hc3RlciBhcnJheSAoMSkgb3Igbm90ICh1bmRlZmluZWQgb3IgMCkKCSAqICBAcGFyYW0ge2Jvb2x9IHJlZ2V4IHRyZWF0IGFzIGEgcmVndWxhciBleHByZXNzaW9uIG9yIG5vdAoJICogIEBwYXJhbSB7Ym9vbH0gc21hcnQgcGVyZm9ybSBzbWFydCBmaWx0ZXJpbmcgb3Igbm90CgkgKiAgQHBhcmFtIHtib29sfSBjYXNlSW5zZW5zaXRpdmUgRG8gY2FzZSBpbnNlbnNpdGl2ZSBtYXRjaGluZyBvciBub3QKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuRmlsdGVyKCBzZXR0aW5ncywgaW5wdXQsIGZvcmNlLCByZWdleCwgc21hcnQsIGNhc2VJbnNlbnNpdGl2ZSApCgl7CgkJdmFyIHJwU2VhcmNoID0gX2ZuRmlsdGVyQ3JlYXRlU2VhcmNoKCBpbnB1dCwgcmVnZXgsIHNtYXJ0LCBjYXNlSW5zZW5zaXRpdmUgKTsKCQl2YXIgcHJldlNlYXJjaCA9IHNldHRpbmdzLm9QcmV2aW91c1NlYXJjaC5zU2VhcmNoOwoJCXZhciBkaXNwbGF5TWFzdGVyID0gc2V0dGluZ3MuYWlEaXNwbGF5TWFzdGVyOwoJCXZhciBkaXNwbGF5LCBpbnZhbGlkYXRlZCwgaTsKCQl2YXIgZmlsdGVyZWQgPSBbXTsKCQoJCS8vIE5lZWQgdG8gdGFrZSBhY2NvdW50IG9mIGN1c3RvbSBmaWx0ZXJpbmcgZnVuY3Rpb25zIC0gYWx3YXlzIGZpbHRlcgoJCWlmICggRGF0YVRhYmxlLmV4dC5zZWFyY2gubGVuZ3RoICE9PSAwICkgewoJCQlmb3JjZSA9IHRydWU7CgkJfQoJCgkJLy8gQ2hlY2sgaWYgYW55IG9mIHRoZSByb3dzIHdlcmUgaW52YWxpZGF0ZWQKCQlpbnZhbGlkYXRlZCA9IF9mbkZpbHRlckRhdGEoIHNldHRpbmdzICk7CgkKCQkvLyBJZiB0aGUgaW5wdXQgaXMgYmxhbmsgLSB3ZSBqdXN0IHdhbnQgdGhlIGZ1bGwgZGF0YSBzZXQKCQlpZiAoIGlucHV0Lmxlbmd0aCA8PSAwICkgewoJCQlzZXR0aW5ncy5haURpc3BsYXkgPSBkaXNwbGF5TWFzdGVyLnNsaWNlKCk7CgkJfQoJCWVsc2UgewoJCQkvLyBOZXcgc2VhcmNoIC0gc3RhcnQgZnJvbSB0aGUgbWFzdGVyIGFycmF5CgkJCWlmICggaW52YWxpZGF0ZWQgfHwKCQkJCSBmb3JjZSB8fAoJCQkJIHJlZ2V4IHx8CgkJCQkgcHJldlNlYXJjaC5sZW5ndGggPiBpbnB1dC5sZW5ndGggfHwKCQkJCSBpbnB1dC5pbmRleE9mKHByZXZTZWFyY2gpICE9PSAwIHx8CgkJCQkgc2V0dGluZ3MuYlNvcnRlZCAvLyBPbiByZXNvcnQsIHRoZSBkaXNwbGF5IG1hc3RlciBuZWVkcyB0byBiZQoJCQkJICAgICAgICAgICAgICAgICAgLy8gcmUtZmlsdGVyZWQgc2luY2UgaW5kZXhlcyB3aWxsIGhhdmUgY2hhbmdlZAoJCQkpIHsKCQkJCXNldHRpbmdzLmFpRGlzcGxheSA9IGRpc3BsYXlNYXN0ZXIuc2xpY2UoKTsKCQkJfQoJCgkJCS8vIFNlYXJjaCB0aGUgZGlzcGxheSBhcnJheQoJCQlkaXNwbGF5ID0gc2V0dGluZ3MuYWlEaXNwbGF5OwoJCgkJCWZvciAoIGk9MCA7IGk8ZGlzcGxheS5sZW5ndGggOyBpKysgKSB7CgkJCQlpZiAoIHJwU2VhcmNoLnRlc3QoIHNldHRpbmdzLmFvRGF0YVsgZGlzcGxheVtpXSBdLl9zRmlsdGVyUm93ICkgKSB7CgkJCQkJZmlsdGVyZWQucHVzaCggZGlzcGxheVtpXSApOwoJCQkJfQoJCQl9CgkKCQkJc2V0dGluZ3MuYWlEaXNwbGF5ID0gZmlsdGVyZWQ7CgkJfQoJfQoJCgkKCS8qKgoJICogQnVpbGQgYSByZWd1bGFyIGV4cHJlc3Npb24gb2JqZWN0IHN1aXRhYmxlIGZvciBzZWFyY2hpbmcgYSB0YWJsZQoJICogIEBwYXJhbSB7c3RyaW5nfSBzU2VhcmNoIHN0cmluZyB0byBzZWFyY2ggZm9yCgkgKiAgQHBhcmFtIHtib29sfSBiUmVnZXggdHJlYXQgYXMgYSByZWd1bGFyIGV4cHJlc3Npb24gb3Igbm90CgkgKiAgQHBhcmFtIHtib29sfSBiU21hcnQgcGVyZm9ybSBzbWFydCBmaWx0ZXJpbmcgb3Igbm90CgkgKiAgQHBhcmFtIHtib29sfSBiQ2FzZUluc2Vuc2l0aXZlIERvIGNhc2UgaW5zZW5zaXRpdmUgbWF0Y2hpbmcgb3Igbm90CgkgKiAgQHJldHVybnMge1JlZ0V4cH0gY29uc3RydWN0ZWQgb2JqZWN0CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkZpbHRlckNyZWF0ZVNlYXJjaCggc2VhcmNoLCByZWdleCwgc21hcnQsIGNhc2VJbnNlbnNpdGl2ZSApCgl7CgkJc2VhcmNoID0gcmVnZXggPwoJCQlzZWFyY2ggOgoJCQlfZm5Fc2NhcGVSZWdleCggc2VhcmNoICk7CgkJCgkJaWYgKCBzbWFydCApIHsKCQkJLyogRm9yIHNtYXJ0IGZpbHRlcmluZyB3ZSB3YW50IHRvIGFsbG93IHRoZSBzZWFyY2ggdG8gd29yayByZWdhcmRsZXNzIG9mCgkJCSAqIHdvcmQgb3JkZXIuIFdlIGFsc28gd2FudCBkb3VibGUgcXVvdGVkIHRleHQgdG8gYmUgcHJlc2VydmVkLCBzbyB3b3JkCgkJCSAqIG9yZGVyIGlzIGltcG9ydGFudCAtIGEgbGEgZ29vZ2xlLiBTbyB0aGlzIGlzIHdoYXQgd2Ugd2FudCB0bwoJCQkgKiBnZW5lcmF0ZToKCQkJICogCgkJCSAqIF4oPz0uKj9cYm9uZVxiKSg/PS4qP1xidHdvIHRocmVlXGIpKD89Lio/XGJmb3VyXGIpLiokCgkJCSAqLwoJCQl2YXIgYSA9ICQubWFwKCBzZWFyY2gubWF0Y2goIC8iW14iXSsifFteIF0rL2cgKSB8fCBbJyddLCBmdW5jdGlvbiAoIHdvcmQgKSB7CgkJCQlpZiAoIHdvcmQuY2hhckF0KDApID09PSAnIicgKSB7CgkJCQkJdmFyIG0gPSB3b3JkLm1hdGNoKCAvXiIoLiopIiQvICk7CgkJCQkJd29yZCA9IG0gPyBtWzFdIDogd29yZDsKCQkJCX0KCQoJCQkJcmV0dXJuIHdvcmQucmVwbGFjZSgnIicsICcnKTsKCQkJfSApOwoJCgkJCXNlYXJjaCA9ICdeKD89Lio/JythLmpvaW4oICcpKD89Lio/JyApKycpLiokJzsKCQl9CgkKCQlyZXR1cm4gbmV3IFJlZ0V4cCggc2VhcmNoLCBjYXNlSW5zZW5zaXRpdmUgPyAnaScgOiAnJyApOwoJfQoJCgkKCS8qKgoJICogRXNjYXBlIGEgc3RyaW5nIHN1Y2ggdGhhdCBpdCBjYW4gYmUgdXNlZCBpbiBhIHJlZ3VsYXIgZXhwcmVzc2lvbgoJICogIEBwYXJhbSB7c3RyaW5nfSBzVmFsIHN0cmluZyB0byBlc2NhcGUKCSAqICBAcmV0dXJucyB7c3RyaW5nfSBlc2NhcGVkIHN0cmluZwoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCgl2YXIgX2ZuRXNjYXBlUmVnZXggPSBEYXRhVGFibGUudXRpbC5lc2NhcGVSZWdleDsKCQoJdmFyIF9fZmlsdGVyX2RpdiA9ICQoJzxkaXY+JylbMF07Cgl2YXIgX19maWx0ZXJfZGl2X3RleHRDb250ZW50ID0gX19maWx0ZXJfZGl2LnRleHRDb250ZW50ICE9PSB1bmRlZmluZWQ7CgkKCS8vIFVwZGF0ZSB0aGUgZmlsdGVyaW5nIGRhdGEgZm9yIGVhY2ggcm93IGlmIG5lZWRlZCAoYnkgaW52YWxpZGF0aW9uIG9yIGZpcnN0IHJ1bikKCWZ1bmN0aW9uIF9mbkZpbHRlckRhdGEgKCBzZXR0aW5ncyApCgl7CgkJdmFyIGNvbHVtbnMgPSBzZXR0aW5ncy5hb0NvbHVtbnM7CgkJdmFyIGNvbHVtbjsKCQl2YXIgaSwgaiwgaWVuLCBqZW4sIGZpbHRlckRhdGEsIGNlbGxEYXRhLCByb3c7CgkJdmFyIHdhc0ludmFsaWRhdGVkID0gZmFsc2U7CgkKCQlmb3IgKCBpPTAsIGllbj1zZXR0aW5ncy5hb0RhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCXJvdyA9IHNldHRpbmdzLmFvRGF0YVtpXTsKCQoJCQlpZiAoICEgcm93Ll9hRmlsdGVyRGF0YSApIHsKCQkJCWZpbHRlckRhdGEgPSBbXTsKCQoJCQkJZm9yICggaj0wLCBqZW49Y29sdW1ucy5sZW5ndGggOyBqPGplbiA7IGorKyApIHsKCQkJCQljb2x1bW4gPSBjb2x1bW5zW2pdOwoJCgkJCQkJaWYgKCBjb2x1bW4uYlNlYXJjaGFibGUgKSB7CgkJCQkJCWNlbGxEYXRhID0gX2ZuR2V0Q2VsbERhdGEoIHNldHRpbmdzLCBpLCBqLCAnZmlsdGVyJyApOwoJCgkJCQkJCS8vIFNlYXJjaCBpbiBEYXRhVGFibGVzIDEuMTAgaXMgc3RyaW5nIGJhc2VkLiBJbiAxLjExIHRoaXMKCQkJCQkJLy8gc2hvdWxkIGJlIGFsdGVyZWQgdG8gYWxzbyBhbGxvdyBzdHJpY3QgdHlwZSBjaGVja2luZy4KCQkJCQkJaWYgKCBjZWxsRGF0YSA9PT0gbnVsbCApIHsKCQkJCQkJCWNlbGxEYXRhID0gJyc7CgkJCQkJCX0KCQoJCQkJCQlpZiAoIHR5cGVvZiBjZWxsRGF0YSAhPT0gJ3N0cmluZycgJiYgY2VsbERhdGEudG9TdHJpbmcgKSB7CgkJCQkJCQljZWxsRGF0YSA9IGNlbGxEYXRhLnRvU3RyaW5nKCk7CgkJCQkJCX0KCQkJCQl9CgkJCQkJZWxzZSB7CgkJCQkJCWNlbGxEYXRhID0gJyc7CgkJCQkJfQoJCgkJCQkJLy8gSWYgaXQgbG9va3MgbGlrZSB0aGVyZSBpcyBhbiBIVE1MIGVudGl0eSBpbiB0aGUgc3RyaW5nLAoJCQkJCS8vIGF0dGVtcHQgdG8gZGVjb2RlIGl0IHNvIHNvcnRpbmcgd29ya3MgYXMgZXhwZWN0ZWQuIE5vdGUgdGhhdAoJCQkJCS8vIHdlIGNvdWxkIHVzZSBhIHNpbmdsZSBsaW5lIG9mIGpRdWVyeSB0byBkbyB0aGlzLCBidXQgdGhlIERPTQoJCQkJCS8vIG1ldGhvZCB1c2VkIGhlcmUgaXMgbXVjaCBmYXN0ZXIgaHR0cDovL2pzcGVyZi5jb20vaHRtbC1kZWNvZGUKCQkJCQlpZiAoIGNlbGxEYXRhLmluZGV4T2YgJiYgY2VsbERhdGEuaW5kZXhPZignJicpICE9PSAtMSApIHsKCQkJCQkJX19maWx0ZXJfZGl2LmlubmVySFRNTCA9IGNlbGxEYXRhOwoJCQkJCQljZWxsRGF0YSA9IF9fZmlsdGVyX2Rpdl90ZXh0Q29udGVudCA/CgkJCQkJCQlfX2ZpbHRlcl9kaXYudGV4dENvbnRlbnQgOgoJCQkJCQkJX19maWx0ZXJfZGl2LmlubmVyVGV4dDsKCQkJCQl9CgkKCQkJCQlpZiAoIGNlbGxEYXRhLnJlcGxhY2UgKSB7CgkJCQkJCWNlbGxEYXRhID0gY2VsbERhdGEucmVwbGFjZSgvW1xyXG5cdTIwMjhdL2csICcnKTsKCQkJCQl9CgkKCQkJCQlmaWx0ZXJEYXRhLnB1c2goIGNlbGxEYXRhICk7CgkJCQl9CgkKCQkJCXJvdy5fYUZpbHRlckRhdGEgPSBmaWx0ZXJEYXRhOwoJCQkJcm93Ll9zRmlsdGVyUm93ID0gZmlsdGVyRGF0YS5qb2luKCcgICcpOwoJCQkJd2FzSW52YWxpZGF0ZWQgPSB0cnVlOwoJCQl9CgkJfQoJCgkJcmV0dXJuIHdhc0ludmFsaWRhdGVkOwoJfQoJCgkKCS8qKgoJICogQ29udmVydCBmcm9tIHRoZSBpbnRlcm5hbCBIdW5nYXJpYW4gbm90YXRpb24gdG8gY2FtZWxDYXNlIGZvciBleHRlcm5hbAoJICogaW50ZXJhY3Rpb24KCSAqICBAcGFyYW0ge29iamVjdH0gb2JqIE9iamVjdCB0byBjb252ZXJ0CgkgKiAgQHJldHVybnMge29iamVjdH0gSW52ZXJ0ZWQgb2JqZWN0CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mblNlYXJjaFRvQ2FtZWwgKCBvYmogKQoJewoJCXJldHVybiB7CgkJCXNlYXJjaDogICAgICAgICAgb2JqLnNTZWFyY2gsCgkJCXNtYXJ0OiAgICAgICAgICAgb2JqLmJTbWFydCwKCQkJcmVnZXg6ICAgICAgICAgICBvYmouYlJlZ2V4LAoJCQljYXNlSW5zZW5zaXRpdmU6IG9iai5iQ2FzZUluc2Vuc2l0aXZlCgkJfTsKCX0KCQoJCgkKCS8qKgoJICogQ29udmVydCBmcm9tIGNhbWVsQ2FzZSBub3RhdGlvbiB0byB0aGUgaW50ZXJuYWwgSHVuZ2FyaWFuLiBXZSBjb3VsZCB1c2UgdGhlCgkgKiBIdW5nYXJpYW4gY29udmVydCBmdW5jdGlvbiBoZXJlLCBidXQgdGhpcyBpcyBjbGVhbmVyCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9iaiBPYmplY3QgdG8gY29udmVydAoJICogIEByZXR1cm5zIHtvYmplY3R9IEludmVydGVkIG9iamVjdAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5TZWFyY2hUb0h1bmcgKCBvYmogKQoJewoJCXJldHVybiB7CgkJCXNTZWFyY2g6ICAgICAgICAgIG9iai5zZWFyY2gsCgkJCWJTbWFydDogICAgICAgICAgIG9iai5zbWFydCwKCQkJYlJlZ2V4OiAgICAgICAgICAgb2JqLnJlZ2V4LAoJCQliQ2FzZUluc2Vuc2l0aXZlOiBvYmouY2FzZUluc2Vuc2l0aXZlCgkJfTsKCX0KCQoJLyoqCgkgKiBHZW5lcmF0ZSB0aGUgbm9kZSByZXF1aXJlZCBmb3IgdGhlIGluZm8gZGlzcGxheQoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcmV0dXJucyB7bm9kZX0gSW5mb3JtYXRpb24gZWxlbWVudAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5GZWF0dXJlSHRtbEluZm8gKCBzZXR0aW5ncyApCgl7CgkJdmFyCgkJCXRpZCA9IHNldHRpbmdzLnNUYWJsZUlkLAoJCQlub2RlcyA9IHNldHRpbmdzLmFhbkZlYXR1cmVzLmksCgkJCW4gPSAkKCc8ZGl2Lz4nLCB7CgkJCQknY2xhc3MnOiBzZXR0aW5ncy5vQ2xhc3Nlcy5zSW5mbywKCQkJCSdpZCc6ICEgbm9kZXMgPyB0aWQrJ19pbmZvJyA6IG51bGwKCQkJfSApOwoJCgkJaWYgKCAhIG5vZGVzICkgewoJCQkvLyBVcGRhdGUgZGlzcGxheSBvbiBlYWNoIGRyYXcKCQkJc2V0dGluZ3MuYW9EcmF3Q2FsbGJhY2sucHVzaCggewoJCQkJImZuIjogX2ZuVXBkYXRlSW5mbywKCQkJCSJzTmFtZSI6ICJpbmZvcm1hdGlvbiIKCQkJfSApOwoJCgkJCW4KCQkJCS5hdHRyKCAncm9sZScsICdzdGF0dXMnICkKCQkJCS5hdHRyKCAnYXJpYS1saXZlJywgJ3BvbGl0ZScgKTsKCQoJCQkvLyBUYWJsZSBpcyBkZXNjcmliZWQgYnkgb3VyIGluZm8gZGl2CgkJCSQoc2V0dGluZ3MublRhYmxlKS5hdHRyKCAnYXJpYS1kZXNjcmliZWRieScsIHRpZCsnX2luZm8nICk7CgkJfQoJCgkJcmV0dXJuIG5bMF07Cgl9CgkKCQoJLyoqCgkgKiBVcGRhdGUgdGhlIGluZm9ybWF0aW9uIGVsZW1lbnRzIGluIHRoZSBkaXNwbGF5CgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mblVwZGF0ZUluZm8gKCBzZXR0aW5ncyApCgl7CgkJLyogU2hvdyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdGFibGUgKi8KCQl2YXIgbm9kZXMgPSBzZXR0aW5ncy5hYW5GZWF0dXJlcy5pOwoJCWlmICggbm9kZXMubGVuZ3RoID09PSAwICkgewoJCQlyZXR1cm47CgkJfQoJCgkJdmFyCgkJCWxhbmcgID0gc2V0dGluZ3Mub0xhbmd1YWdlLAoJCQlzdGFydCA9IHNldHRpbmdzLl9pRGlzcGxheVN0YXJ0KzEsCgkJCWVuZCAgID0gc2V0dGluZ3MuZm5EaXNwbGF5RW5kKCksCgkJCW1heCAgID0gc2V0dGluZ3MuZm5SZWNvcmRzVG90YWwoKSwKCQkJdG90YWwgPSBzZXR0aW5ncy5mblJlY29yZHNEaXNwbGF5KCksCgkJCW91dCAgID0gdG90YWwgPwoJCQkJbGFuZy5zSW5mbyA6CgkJCQlsYW5nLnNJbmZvRW1wdHk7CgkKCQlpZiAoIHRvdGFsICE9PSBtYXggKSB7CgkJCS8qIFJlY29yZCBzZXQgYWZ0ZXIgZmlsdGVyaW5nICovCgkJCW91dCArPSAnICcgKyBsYW5nLnNJbmZvRmlsdGVyZWQ7CgkJfQoJCgkJLy8gQ29udmVydCB0aGUgbWFjcm9zCgkJb3V0ICs9IGxhbmcuc0luZm9Qb3N0Rml4OwoJCW91dCA9IF9mbkluZm9NYWNyb3MoIHNldHRpbmdzLCBvdXQgKTsKCQoJCXZhciBjYWxsYmFjayA9IGxhbmcuZm5JbmZvQ2FsbGJhY2s7CgkJaWYgKCBjYWxsYmFjayAhPT0gbnVsbCApIHsKCQkJb3V0ID0gY2FsbGJhY2suY2FsbCggc2V0dGluZ3Mub0luc3RhbmNlLAoJCQkJc2V0dGluZ3MsIHN0YXJ0LCBlbmQsIG1heCwgdG90YWwsIG91dAoJCQkpOwoJCX0KCQoJCSQobm9kZXMpLmh0bWwoIG91dCApOwoJfQoJCgkKCWZ1bmN0aW9uIF9mbkluZm9NYWNyb3MgKCBzZXR0aW5ncywgc3RyICkKCXsKCQkvLyBXaGVuIGluZmluaXRlIHNjcm9sbGluZywgd2UgYXJlIGFsd2F5cyBzdGFydGluZyBhdCAxLiBfaURpc3BsYXlTdGFydCBpcyB1c2VkIG9ubHkKCQkvLyBpbnRlcm5hbGx5CgkJdmFyCgkJCWZvcm1hdHRlciAgPSBzZXR0aW5ncy5mbkZvcm1hdE51bWJlciwKCQkJc3RhcnQgICAgICA9IHNldHRpbmdzLl9pRGlzcGxheVN0YXJ0KzEsCgkJCWxlbiAgICAgICAgPSBzZXR0aW5ncy5faURpc3BsYXlMZW5ndGgsCgkJCXZpcyAgICAgICAgPSBzZXR0aW5ncy5mblJlY29yZHNEaXNwbGF5KCksCgkJCWFsbCAgICAgICAgPSBsZW4gPT09IC0xOwoJCgkJcmV0dXJuIHN0ci4KCQkJcmVwbGFjZSgvX1NUQVJUXy9nLCBmb3JtYXR0ZXIuY2FsbCggc2V0dGluZ3MsIHN0YXJ0ICkgKS4KCQkJcmVwbGFjZSgvX0VORF8vZywgICBmb3JtYXR0ZXIuY2FsbCggc2V0dGluZ3MsIHNldHRpbmdzLmZuRGlzcGxheUVuZCgpICkgKS4KCQkJcmVwbGFjZSgvX01BWF8vZywgICBmb3JtYXR0ZXIuY2FsbCggc2V0dGluZ3MsIHNldHRpbmdzLmZuUmVjb3Jkc1RvdGFsKCkgKSApLgoJCQlyZXBsYWNlKC9fVE9UQUxfL2csIGZvcm1hdHRlci5jYWxsKCBzZXR0aW5ncywgdmlzICkgKS4KCQkJcmVwbGFjZSgvX1BBR0VfL2csICBmb3JtYXR0ZXIuY2FsbCggc2V0dGluZ3MsIGFsbCA/IDEgOiBNYXRoLmNlaWwoIHN0YXJ0IC8gbGVuICkgKSApLgoJCQlyZXBsYWNlKC9fUEFHRVNfL2csIGZvcm1hdHRlci5jYWxsKCBzZXR0aW5ncywgYWxsID8gMSA6IE1hdGguY2VpbCggdmlzIC8gbGVuICkgKSApOwoJfQoJCgkKCQoJLyoqCgkgKiBEcmF3IHRoZSB0YWJsZSBmb3IgdGhlIGZpcnN0IHRpbWUsIGFkZGluZyBhbGwgcmVxdWlyZWQgZmVhdHVyZXMKCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuSW5pdGlhbGlzZSAoIHNldHRpbmdzICkKCXsKCQl2YXIgaSwgaUxlbiwgaUFqYXhTdGFydD1zZXR0aW5ncy5pSW5pdERpc3BsYXlTdGFydDsKCQl2YXIgY29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1ucywgY29sdW1uOwoJCXZhciBmZWF0dXJlcyA9IHNldHRpbmdzLm9GZWF0dXJlczsKCQl2YXIgZGVmZXJMb2FkaW5nID0gc2V0dGluZ3MuYkRlZmVyTG9hZGluZzsgLy8gdmFsdWUgbW9kaWZpZWQgYnkgdGhlIGRyYXcKCQoJCS8qIEVuc3VyZSB0aGF0IHRoZSB0YWJsZSBkYXRhIGlzIGZ1bGx5IGluaXRpYWxpc2VkICovCgkJaWYgKCAhIHNldHRpbmdzLmJJbml0aWFsaXNlZCApIHsKCQkJc2V0VGltZW91dCggZnVuY3Rpb24oKXsgX2ZuSW5pdGlhbGlzZSggc2V0dGluZ3MgKTsgfSwgMjAwICk7CgkJCXJldHVybjsKCQl9CgkKCQkvKiBTaG93IHRoZSBkaXNwbGF5IEhUTUwgb3B0aW9ucyAqLwoJCV9mbkFkZE9wdGlvbnNIdG1sKCBzZXR0aW5ncyApOwoJCgkJLyogQnVpbGQgYW5kIGRyYXcgdGhlIGhlYWRlciAvIGZvb3RlciBmb3IgdGhlIHRhYmxlICovCgkJX2ZuQnVpbGRIZWFkKCBzZXR0aW5ncyApOwoJCV9mbkRyYXdIZWFkKCBzZXR0aW5ncywgc2V0dGluZ3MuYW9IZWFkZXIgKTsKCQlfZm5EcmF3SGVhZCggc2V0dGluZ3MsIHNldHRpbmdzLmFvRm9vdGVyICk7CgkKCQkvKiBPa2F5IHRvIHNob3cgdGhhdCBzb21ldGhpbmcgaXMgZ29pbmcgb24gbm93ICovCgkJX2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIHNldHRpbmdzLCB0cnVlICk7CgkKCQkvKiBDYWxjdWxhdGUgc2l6ZXMgZm9yIGNvbHVtbnMgKi8KCQlpZiAoIGZlYXR1cmVzLmJBdXRvV2lkdGggKSB7CgkJCV9mbkNhbGN1bGF0ZUNvbHVtbldpZHRocyggc2V0dGluZ3MgKTsKCQl9CgkKCQlmb3IgKCBpPTAsIGlMZW49Y29sdW1ucy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKSB7CgkJCWNvbHVtbiA9IGNvbHVtbnNbaV07CgkKCQkJaWYgKCBjb2x1bW4uc1dpZHRoICkgewoJCQkJY29sdW1uLm5UaC5zdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBjb2x1bW4uc1dpZHRoICk7CgkJCX0KCQl9CgkKCQlfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCBudWxsLCAncHJlSW5pdCcsIFtzZXR0aW5nc10gKTsKCQoJCS8vIElmIHRoZXJlIGlzIGRlZmF1bHQgc29ydGluZyByZXF1aXJlZCAtIGxldCdzIGRvIGl0LiBUaGUgc29ydCBmdW5jdGlvbgoJCS8vIHdpbGwgZG8gdGhlIGRyYXdpbmcgZm9yIHVzLiBPdGhlcndpc2Ugd2UgZHJhdyB0aGUgdGFibGUgcmVnYXJkbGVzcyBvZiB0aGUKCQkvLyBBamF4IHNvdXJjZSAtIHRoaXMgYWxsb3dzIHRoZSB0YWJsZSB0byBsb29rIGluaXRpYWxpc2VkIGZvciBBamF4IHNvdXJjaW5nCgkJLy8gZGF0YSAoc2hvdyAnbG9hZGluZycgbWVzc2FnZSBwb3NzaWJseSkKCQlfZm5SZURyYXcoIHNldHRpbmdzICk7CgkKCQkvLyBTZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIGluaXQgY29tcGxldGUgaXMgZG9uZSBieSBfZm5BamF4VXBkYXRlRHJhdwoJCXZhciBkYXRhU3JjID0gX2ZuRGF0YVNvdXJjZSggc2V0dGluZ3MgKTsKCQlpZiAoIGRhdGFTcmMgIT0gJ3NzcCcgfHwgZGVmZXJMb2FkaW5nICkgewoJCQkvLyBpZiB0aGVyZSBpcyBhbiBhamF4IHNvdXJjZSBsb2FkIHRoZSBkYXRhCgkJCWlmICggZGF0YVNyYyA9PSAnYWpheCcgKSB7CgkJCQlfZm5CdWlsZEFqYXgoIHNldHRpbmdzLCBbXSwgZnVuY3Rpb24oanNvbikgewoJCQkJCXZhciBhRGF0YSA9IF9mbkFqYXhEYXRhU3JjKCBzZXR0aW5ncywganNvbiApOwoJCgkJCQkJLy8gR290IHRoZSBkYXRhIC0gYWRkIGl0IHRvIHRoZSB0YWJsZQoJCQkJCWZvciAoIGk9MCA7IGk8YURhdGEubGVuZ3RoIDsgaSsrICkgewoJCQkJCQlfZm5BZGREYXRhKCBzZXR0aW5ncywgYURhdGFbaV0gKTsKCQkJCQl9CgkKCQkJCQkvLyBSZXNldCB0aGUgaW5pdCBkaXNwbGF5IGZvciBjb29raWUgc2F2aW5nLiBXZSd2ZSBhbHJlYWR5IGRvbmUKCQkJCQkvLyBhIGZpbHRlciwgYW5kIHRoZXJlZm9yZSBjbGVhcmVkIGl0IGJlZm9yZS4gU28gd2UgbmVlZCB0byBtYWtlCgkJCQkJLy8gaXQgYXBwZWFyICdmcmVzaCcKCQkJCQlzZXR0aW5ncy5pSW5pdERpc3BsYXlTdGFydCA9IGlBamF4U3RhcnQ7CgkKCQkJCQlfZm5SZURyYXcoIHNldHRpbmdzICk7CgkKCQkJCQlfZm5Qcm9jZXNzaW5nRGlzcGxheSggc2V0dGluZ3MsIGZhbHNlICk7CgkJCQkJX2ZuSW5pdENvbXBsZXRlKCBzZXR0aW5ncywganNvbiApOwoJCQkJfSwgc2V0dGluZ3MgKTsKCQkJfQoJCQllbHNlIHsKCQkJCV9mblByb2Nlc3NpbmdEaXNwbGF5KCBzZXR0aW5ncywgZmFsc2UgKTsKCQkJCV9mbkluaXRDb21wbGV0ZSggc2V0dGluZ3MgKTsKCQkJfQoJCX0KCX0KCQoJCgkvKioKCSAqIERyYXcgdGhlIHRhYmxlIGZvciB0aGUgZmlyc3QgdGltZSwgYWRkaW5nIGFsbCByZXF1aXJlZCBmZWF0dXJlcwoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge29iamVjdH0gW2pzb25dIEpTT04gZnJvbSB0aGUgc2VydmVyIHRoYXQgY29tcGxldGVkIHRoZSB0YWJsZSwgaWYgdXNpbmcgQWpheCBzb3VyY2UKCSAqICAgIHdpdGggY2xpZW50LXNpZGUgcHJvY2Vzc2luZyAob3B0aW9uYWwpCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkluaXRDb21wbGV0ZSAoIHNldHRpbmdzLCBqc29uICkKCXsKCQlzZXR0aW5ncy5fYkluaXRDb21wbGV0ZSA9IHRydWU7CgkKCQkvLyBXaGVuIGRhdGEgd2FzIGFkZGVkIGFmdGVyIHRoZSBpbml0aWFsaXNhdGlvbiAoZGF0YSBvciBBamF4KSB3ZSBuZWVkIHRvCgkJLy8gY2FsY3VsYXRlIHRoZSBjb2x1bW4gc2l6aW5nCgkJaWYgKCBqc29uIHx8IHNldHRpbmdzLm9Jbml0LmFhRGF0YSApIHsKCQkJX2ZuQWRqdXN0Q29sdW1uU2l6aW5nKCBzZXR0aW5ncyApOwoJCX0KCQoJCV9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsIG51bGwsICdwbHVnaW4taW5pdCcsIFtzZXR0aW5ncywganNvbl0gKTsKCQlfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCAnYW9Jbml0Q29tcGxldGUnLCAnaW5pdCcsIFtzZXR0aW5ncywganNvbl0gKTsKCX0KCQoJCglmdW5jdGlvbiBfZm5MZW5ndGhDaGFuZ2UgKCBzZXR0aW5ncywgdmFsICkKCXsKCQl2YXIgbGVuID0gcGFyc2VJbnQoIHZhbCwgMTAgKTsKCQlzZXR0aW5ncy5faURpc3BsYXlMZW5ndGggPSBsZW47CgkKCQlfZm5MZW5ndGhPdmVyZmxvdyggc2V0dGluZ3MgKTsKCQoJCS8vIEZpcmUgbGVuZ3RoIGNoYW5nZSBldmVudAoJCV9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsIG51bGwsICdsZW5ndGgnLCBbc2V0dGluZ3MsIGxlbl0gKTsKCX0KCQoJCgkvKioKCSAqIEdlbmVyYXRlIHRoZSBub2RlIHJlcXVpcmVkIGZvciB1c2VyIGRpc3BsYXkgbGVuZ3RoIGNoYW5naW5nCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHJldHVybnMge25vZGV9IERpc3BsYXkgbGVuZ3RoIGZlYXR1cmUgbm9kZQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5GZWF0dXJlSHRtbExlbmd0aCAoIHNldHRpbmdzICkKCXsKCQl2YXIKCQkJY2xhc3NlcyAgPSBzZXR0aW5ncy5vQ2xhc3NlcywKCQkJdGFibGVJZCAgPSBzZXR0aW5ncy5zVGFibGVJZCwKCQkJbWVudSAgICAgPSBzZXR0aW5ncy5hTGVuZ3RoTWVudSwKCQkJZDIgICAgICAgPSBBcnJheS5pc0FycmF5KCBtZW51WzBdICksCgkJCWxlbmd0aHMgID0gZDIgPyBtZW51WzBdIDogbWVudSwKCQkJbGFuZ3VhZ2UgPSBkMiA/IG1lbnVbMV0gOiBtZW51OwoJCgkJdmFyIHNlbGVjdCA9ICQoJzxzZWxlY3QvPicsIHsKCQkJJ25hbWUnOiAgICAgICAgICB0YWJsZUlkKydfbGVuZ3RoJywKCQkJJ2FyaWEtY29udHJvbHMnOiB0YWJsZUlkLAoJCQknY2xhc3MnOiAgICAgICAgIGNsYXNzZXMuc0xlbmd0aFNlbGVjdAoJCX0gKTsKCQoJCWZvciAoIHZhciBpPTAsIGllbj1sZW5ndGhzLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQlzZWxlY3RbMF1bIGkgXSA9IG5ldyBPcHRpb24oCgkJCQl0eXBlb2YgbGFuZ3VhZ2VbaV0gPT09ICdudW1iZXInID8KCQkJCQlzZXR0aW5ncy5mbkZvcm1hdE51bWJlciggbGFuZ3VhZ2VbaV0gKSA6CgkJCQkJbGFuZ3VhZ2VbaV0sCgkJCQlsZW5ndGhzW2ldCgkJCSk7CgkJfQoJCgkJdmFyIGRpdiA9ICQoJzxkaXY+PGxhYmVsLz48L2Rpdj4nKS5hZGRDbGFzcyggY2xhc3Nlcy5zTGVuZ3RoICk7CgkJaWYgKCAhIHNldHRpbmdzLmFhbkZlYXR1cmVzLmwgKSB7CgkJCWRpdlswXS5pZCA9IHRhYmxlSWQrJ19sZW5ndGgnOwoJCX0KCQoJCWRpdi5jaGlsZHJlbigpLmFwcGVuZCgKCQkJc2V0dGluZ3Mub0xhbmd1YWdlLnNMZW5ndGhNZW51LnJlcGxhY2UoICdfTUVOVV8nLCBzZWxlY3RbMF0ub3V0ZXJIVE1MICkKCQkpOwoJCgkJLy8gQ2FuJ3QgdXNlIGBzZWxlY3RgIHZhcmlhYmxlIGFzIHVzZXIgbWlnaHQgcHJvdmlkZSB0aGVpciBvd24gYW5kIHRoZQoJCS8vIHJlZmVyZW5jZSBpcyBicm9rZW4gYnkgdGhlIHVzZSBvZiBvdXRlckhUTUwKCQkkKCdzZWxlY3QnLCBkaXYpCgkJCS52YWwoIHNldHRpbmdzLl9pRGlzcGxheUxlbmd0aCApCgkJCS5vbiggJ2NoYW5nZS5EVCcsIGZ1bmN0aW9uKGUpIHsKCQkJCV9mbkxlbmd0aENoYW5nZSggc2V0dGluZ3MsICQodGhpcykudmFsKCkgKTsKCQkJCV9mbkRyYXcoIHNldHRpbmdzICk7CgkJCX0gKTsKCQoJCS8vIFVwZGF0ZSBub2RlIHZhbHVlIHdoZW5ldmVyIGFueXRoaW5nIGNoYW5nZXMgdGhlIHRhYmxlJ3MgbGVuZ3RoCgkJJChzZXR0aW5ncy5uVGFibGUpLm9uKCAnbGVuZ3RoLmR0LkRUJywgZnVuY3Rpb24gKGUsIHMsIGxlbikgewoJCQlpZiAoIHNldHRpbmdzID09PSBzICkgewoJCQkJJCgnc2VsZWN0JywgZGl2KS52YWwoIGxlbiApOwoJCQl9CgkJfSApOwoJCgkJcmV0dXJuIGRpdlswXTsKCX0KCQoJCgkKCS8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqCgkgKiBOb3RlIHRoYXQgbW9zdCBvZiB0aGUgcGFnaW5nIGxvZ2ljIGlzIGRvbmUgaW4KCSAqIERhdGFUYWJsZS5leHQucGFnZXIKCSAqLwoJCgkvKioKCSAqIEdlbmVyYXRlIHRoZSBub2RlIHJlcXVpcmVkIGZvciBkZWZhdWx0IHBhZ2luYXRpb24KCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHJldHVybnMge25vZGV9IFBhZ2luYXRpb24gZmVhdHVyZSBub2RlCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkZlYXR1cmVIdG1sUGFnaW5hdGUgKCBzZXR0aW5ncyApCgl7CgkJdmFyCgkJCXR5cGUgICA9IHNldHRpbmdzLnNQYWdpbmF0aW9uVHlwZSwKCQkJcGx1Z2luID0gRGF0YVRhYmxlLmV4dC5wYWdlclsgdHlwZSBdLAoJCQltb2Rlcm4gPSB0eXBlb2YgcGx1Z2luID09PSAnZnVuY3Rpb24nLAoJCQlyZWRyYXcgPSBmdW5jdGlvbiggc2V0dGluZ3MgKSB7CgkJCQlfZm5EcmF3KCBzZXR0aW5ncyApOwoJCQl9LAoJCQlub2RlID0gJCgnPGRpdi8+JykuYWRkQ2xhc3MoIHNldHRpbmdzLm9DbGFzc2VzLnNQYWdpbmcgKyB0eXBlIClbMF0sCgkJCWZlYXR1cmVzID0gc2V0dGluZ3MuYWFuRmVhdHVyZXM7CgkKCQlpZiAoICEgbW9kZXJuICkgewoJCQlwbHVnaW4uZm5Jbml0KCBzZXR0aW5ncywgbm9kZSwgcmVkcmF3ICk7CgkJfQoJCgkJLyogQWRkIGEgZHJhdyBjYWxsYmFjayBmb3IgdGhlIHBhZ2luYXRpb24gb24gZmlyc3QgaW5zdGFuY2UsIHRvIHVwZGF0ZSB0aGUgcGFnaW5nIGRpc3BsYXkgKi8KCQlpZiAoICEgZmVhdHVyZXMucCApCgkJewoJCQlub2RlLmlkID0gc2V0dGluZ3Muc1RhYmxlSWQrJ19wYWdpbmF0ZSc7CgkKCQkJc2V0dGluZ3MuYW9EcmF3Q2FsbGJhY2sucHVzaCggewoJCQkJImZuIjogZnVuY3Rpb24oIHNldHRpbmdzICkgewoJCQkJCWlmICggbW9kZXJuICkgewoJCQkJCQl2YXIKCQkJCQkJCXN0YXJ0ICAgICAgPSBzZXR0aW5ncy5faURpc3BsYXlTdGFydCwKCQkJCQkJCWxlbiAgICAgICAgPSBzZXR0aW5ncy5faURpc3BsYXlMZW5ndGgsCgkJCQkJCQl2aXNSZWNvcmRzID0gc2V0dGluZ3MuZm5SZWNvcmRzRGlzcGxheSgpLAoJCQkJCQkJYWxsICAgICAgICA9IGxlbiA9PT0gLTEsCgkJCQkJCQlwYWdlID0gYWxsID8gMCA6IE1hdGguY2VpbCggc3RhcnQgLyBsZW4gKSwKCQkJCQkJCXBhZ2VzID0gYWxsID8gMSA6IE1hdGguY2VpbCggdmlzUmVjb3JkcyAvIGxlbiApLAoJCQkJCQkJYnV0dG9ucyA9IHBsdWdpbihwYWdlLCBwYWdlcyksCgkJCQkJCQlpLCBpZW47CgkKCQkJCQkJZm9yICggaT0wLCBpZW49ZmVhdHVyZXMucC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHsKCQkJCQkJCV9mblJlbmRlcmVyKCBzZXR0aW5ncywgJ3BhZ2VCdXR0b24nICkoCgkJCQkJCQkJc2V0dGluZ3MsIGZlYXR1cmVzLnBbaV0sIGksIGJ1dHRvbnMsIHBhZ2UsIHBhZ2VzCgkJCQkJCQkpOwoJCQkJCQl9CgkJCQkJfQoJCQkJCWVsc2UgewoJCQkJCQlwbHVnaW4uZm5VcGRhdGUoIHNldHRpbmdzLCByZWRyYXcgKTsKCQkJCQl9CgkJCQl9LAoJCQkJInNOYW1lIjogInBhZ2luYXRpb24iCgkJCX0gKTsKCQl9CgkKCQlyZXR1cm4gbm9kZTsKCX0KCQoJCgkvKioKCSAqIEFsdGVyIHRoZSBkaXNwbGF5IHNldHRpbmdzIHRvIGNoYW5nZSB0aGUgcGFnZQoJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7c3RyaW5nfGludH0gYWN0aW9uIFBhZ2luZyBhY3Rpb24gdG8gdGFrZTogImZpcnN0IiwgInByZXZpb3VzIiwKCSAqICAgICJuZXh0IiBvciAibGFzdCIgb3IgcGFnZSBudW1iZXIgdG8ganVtcCB0byAoaW50ZWdlcikKCSAqICBAcGFyYW0gW2Jvb2xdIHJlZHJhdyBBdXRvbWF0aWNhbGx5IGRyYXcgdGhlIHVwZGF0ZSBvciBub3QKCSAqICBAcmV0dXJucyB7Ym9vbH0gdHJ1ZSBwYWdlIGhhcyBjaGFuZ2VkLCBmYWxzZSAtIG5vIGNoYW5nZQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5QYWdlQ2hhbmdlICggc2V0dGluZ3MsIGFjdGlvbiwgcmVkcmF3ICkKCXsKCQl2YXIKCQkJc3RhcnQgICAgID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsCgkJCWxlbiAgICAgICA9IHNldHRpbmdzLl9pRGlzcGxheUxlbmd0aCwKCQkJcmVjb3JkcyAgID0gc2V0dGluZ3MuZm5SZWNvcmRzRGlzcGxheSgpOwoJCgkJaWYgKCByZWNvcmRzID09PSAwIHx8IGxlbiA9PT0gLTEgKQoJCXsKCQkJc3RhcnQgPSAwOwoJCX0KCQllbHNlIGlmICggdHlwZW9mIGFjdGlvbiA9PT0gIm51bWJlciIgKQoJCXsKCQkJc3RhcnQgPSBhY3Rpb24gKiBsZW47CgkKCQkJaWYgKCBzdGFydCA+IHJlY29yZHMgKQoJCQl7CgkJCQlzdGFydCA9IDA7CgkJCX0KCQl9CgkJZWxzZSBpZiAoIGFjdGlvbiA9PSAiZmlyc3QiICkKCQl7CgkJCXN0YXJ0ID0gMDsKCQl9CgkJZWxzZSBpZiAoIGFjdGlvbiA9PSAicHJldmlvdXMiICkKCQl7CgkJCXN0YXJ0ID0gbGVuID49IDAgPwoJCQkJc3RhcnQgLSBsZW4gOgoJCQkJMDsKCQoJCQlpZiAoIHN0YXJ0IDwgMCApCgkJCXsKCQkJICBzdGFydCA9IDA7CgkJCX0KCQl9CgkJZWxzZSBpZiAoIGFjdGlvbiA9PSAibmV4dCIgKQoJCXsKCQkJaWYgKCBzdGFydCArIGxlbiA8IHJlY29yZHMgKQoJCQl7CgkJCQlzdGFydCArPSBsZW47CgkJCX0KCQl9CgkJZWxzZSBpZiAoIGFjdGlvbiA9PSAibGFzdCIgKQoJCXsKCQkJc3RhcnQgPSBNYXRoLmZsb29yKCAocmVjb3Jkcy0xKSAvIGxlbikgKiBsZW47CgkJfQoJCWVsc2UKCQl7CgkJCV9mbkxvZyggc2V0dGluZ3MsIDAsICJVbmtub3duIHBhZ2luZyBhY3Rpb246ICIrYWN0aW9uLCA1ICk7CgkJfQoJCgkJdmFyIGNoYW5nZWQgPSBzZXR0aW5ncy5faURpc3BsYXlTdGFydCAhPT0gc3RhcnQ7CgkJc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgPSBzdGFydDsKCQoJCWlmICggY2hhbmdlZCApIHsKCQkJX2ZuQ2FsbGJhY2tGaXJlKCBzZXR0aW5ncywgbnVsbCwgJ3BhZ2UnLCBbc2V0dGluZ3NdICk7CgkKCQkJaWYgKCByZWRyYXcgKSB7CgkJCQlfZm5EcmF3KCBzZXR0aW5ncyApOwoJCQl9CgkJfQoJCgkJcmV0dXJuIGNoYW5nZWQ7Cgl9CgkKCQoJCgkvKioKCSAqIEdlbmVyYXRlIHRoZSBub2RlIHJlcXVpcmVkIGZvciB0aGUgcHJvY2Vzc2luZyBub2RlCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHJldHVybnMge25vZGV9IFByb2Nlc3NpbmcgZWxlbWVudAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5GZWF0dXJlSHRtbFByb2Nlc3NpbmcgKCBzZXR0aW5ncyApCgl7CgkJcmV0dXJuICQoJzxkaXYvPicsIHsKCQkJCSdpZCc6ICEgc2V0dGluZ3MuYWFuRmVhdHVyZXMuciA/IHNldHRpbmdzLnNUYWJsZUlkKydfcHJvY2Vzc2luZycgOiBudWxsLAoJCQkJJ2NsYXNzJzogc2V0dGluZ3Mub0NsYXNzZXMuc1Byb2Nlc3NpbmcKCQkJfSApCgkJCS5odG1sKCBzZXR0aW5ncy5vTGFuZ3VhZ2Uuc1Byb2Nlc3NpbmcgKQoJCQkuYXBwZW5kKCc8ZGl2PjxkaXY+PC9kaXY+PGRpdj48L2Rpdj48ZGl2PjwvZGl2PjxkaXY+PC9kaXY+PC9kaXY+JykKCQkJLmluc2VydEJlZm9yZSggc2V0dGluZ3MublRhYmxlIClbMF07Cgl9CgkKCQoJLyoqCgkgKiBEaXNwbGF5IG9yIGhpZGUgdGhlIHByb2Nlc3NpbmcgaW5kaWNhdG9yCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIHtib29sfSBzaG93IFNob3cgdGhlIHByb2Nlc3NpbmcgaW5kaWNhdG9yICh0cnVlKSBvciBub3QgKGZhbHNlKQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5Qcm9jZXNzaW5nRGlzcGxheSAoIHNldHRpbmdzLCBzaG93ICkKCXsKCQlpZiAoIHNldHRpbmdzLm9GZWF0dXJlcy5iUHJvY2Vzc2luZyApIHsKCQkJJChzZXR0aW5ncy5hYW5GZWF0dXJlcy5yKS5jc3MoICdkaXNwbGF5Jywgc2hvdyA/ICdibG9jaycgOiAnbm9uZScgKTsKCQl9CgkKCQlfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCBudWxsLCAncHJvY2Vzc2luZycsIFtzZXR0aW5ncywgc2hvd10gKTsKCX0KCQoJLyoqCgkgKiBBZGQgYW55IGNvbnRyb2wgZWxlbWVudHMgZm9yIHRoZSB0YWJsZSAtIHNwZWNpZmljYWxseSBzY3JvbGxpbmcKCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcmV0dXJucyB7bm9kZX0gTm9kZSB0byBhZGQgdG8gdGhlIERPTQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5GZWF0dXJlSHRtbFRhYmxlICggc2V0dGluZ3MgKQoJewoJCXZhciB0YWJsZSA9ICQoc2V0dGluZ3MublRhYmxlKTsKCQoJCS8vIFNjcm9sbGluZyBmcm9tIGhlcmUgb24gaW4KCQl2YXIgc2Nyb2xsID0gc2V0dGluZ3Mub1Njcm9sbDsKCQoJCWlmICggc2Nyb2xsLnNYID09PSAnJyAmJiBzY3JvbGwuc1kgPT09ICcnICkgewoJCQlyZXR1cm4gc2V0dGluZ3MublRhYmxlOwoJCX0KCQoJCXZhciBzY3JvbGxYID0gc2Nyb2xsLnNYOwoJCXZhciBzY3JvbGxZID0gc2Nyb2xsLnNZOwoJCXZhciBjbGFzc2VzID0gc2V0dGluZ3Mub0NsYXNzZXM7CgkJdmFyIGNhcHRpb24gPSB0YWJsZS5jaGlsZHJlbignY2FwdGlvbicpOwoJCXZhciBjYXB0aW9uU2lkZSA9IGNhcHRpb24ubGVuZ3RoID8gY2FwdGlvblswXS5fY2FwdGlvblNpZGUgOiBudWxsOwoJCXZhciBoZWFkZXJDbG9uZSA9ICQoIHRhYmxlWzBdLmNsb25lTm9kZShmYWxzZSkgKTsKCQl2YXIgZm9vdGVyQ2xvbmUgPSAkKCB0YWJsZVswXS5jbG9uZU5vZGUoZmFsc2UpICk7CgkJdmFyIGZvb3RlciA9IHRhYmxlLmNoaWxkcmVuKCd0Zm9vdCcpOwoJCXZhciBfZGl2ID0gJzxkaXYvPic7CgkJdmFyIHNpemUgPSBmdW5jdGlvbiAoIHMgKSB7CgkJCXJldHVybiAhcyA/IG51bGwgOiBfZm5TdHJpbmdUb0NzcyggcyApOwoJCX07CgkKCQlpZiAoICEgZm9vdGVyLmxlbmd0aCApIHsKCQkJZm9vdGVyID0gbnVsbDsKCQl9CgkKCQkvKgoJCSAqIFRoZSBIVE1MIHN0cnVjdHVyZSB0aGF0IHdlIHdhbnQgdG8gZ2VuZXJhdGUgaW4gdGhpcyBmdW5jdGlvbiBpczoKCQkgKiAgZGl2IC0gc2Nyb2xsZXIKCQkgKiAgICBkaXYgLSBzY3JvbGwgaGVhZAoJCSAqICAgICAgZGl2IC0gc2Nyb2xsIGhlYWQgaW5uZXIKCQkgKiAgICAgICAgdGFibGUgLSBzY3JvbGwgaGVhZCB0YWJsZQoJCSAqICAgICAgICAgIHRoZWFkIC0gdGhlYWQKCQkgKiAgICBkaXYgLSBzY3JvbGwgYm9keQoJCSAqICAgICAgdGFibGUgLSB0YWJsZSAobWFzdGVyIHRhYmxlKQoJCSAqICAgICAgICB0aGVhZCAtIHRoZWFkIGNsb25lIGZvciBzaXppbmcKCQkgKiAgICAgICAgdGJvZHkgLSB0Ym9keQoJCSAqICAgIGRpdiAtIHNjcm9sbCBmb290CgkJICogICAgICBkaXYgLSBzY3JvbGwgZm9vdCBpbm5lcgoJCSAqICAgICAgICB0YWJsZSAtIHNjcm9sbCBmb290IHRhYmxlCgkJICogICAgICAgICAgdGZvb3QgLSB0Zm9vdAoJCSAqLwoJCXZhciBzY3JvbGxlciA9ICQoIF9kaXYsIHsgJ2NsYXNzJzogY2xhc3Nlcy5zU2Nyb2xsV3JhcHBlciB9ICkKCQkJLmFwcGVuZCgKCQkJCSQoX2RpdiwgeyAnY2xhc3MnOiBjbGFzc2VzLnNTY3JvbGxIZWFkIH0gKQoJCQkJCS5jc3MoIHsKCQkJCQkJb3ZlcmZsb3c6ICdoaWRkZW4nLAoJCQkJCQlwb3NpdGlvbjogJ3JlbGF0aXZlJywKCQkJCQkJYm9yZGVyOiAwLAoJCQkJCQl3aWR0aDogc2Nyb2xsWCA/IHNpemUoc2Nyb2xsWCkgOiAnMTAwJScKCQkJCQl9ICkKCQkJCQkuYXBwZW5kKAoJCQkJCQkkKF9kaXYsIHsgJ2NsYXNzJzogY2xhc3Nlcy5zU2Nyb2xsSGVhZElubmVyIH0gKQoJCQkJCQkJLmNzcyggewoJCQkJCQkJCSdib3gtc2l6aW5nJzogJ2NvbnRlbnQtYm94JywKCQkJCQkJCQl3aWR0aDogc2Nyb2xsLnNYSW5uZXIgfHwgJzEwMCUnCgkJCQkJCQl9ICkKCQkJCQkJCS5hcHBlbmQoCgkJCQkJCQkJaGVhZGVyQ2xvbmUKCQkJCQkJCQkJLnJlbW92ZUF0dHIoJ2lkJykKCQkJCQkJCQkJLmNzcyggJ21hcmdpbi1sZWZ0JywgMCApCgkJCQkJCQkJCS5hcHBlbmQoIGNhcHRpb25TaWRlID09PSAndG9wJyA/IGNhcHRpb24gOiBudWxsICkKCQkJCQkJCQkJLmFwcGVuZCgKCQkJCQkJCQkJCXRhYmxlLmNoaWxkcmVuKCd0aGVhZCcpCgkJCQkJCQkJCSkKCQkJCQkJCSkKCQkJCQkpCgkJCSkKCQkJLmFwcGVuZCgKCQkJCSQoX2RpdiwgeyAnY2xhc3MnOiBjbGFzc2VzLnNTY3JvbGxCb2R5IH0gKQoJCQkJCS5jc3MoIHsKCQkJCQkJcG9zaXRpb246ICdyZWxhdGl2ZScsCgkJCQkJCW92ZXJmbG93OiAnYXV0bycsCgkJCQkJCXdpZHRoOiBzaXplKCBzY3JvbGxYICkKCQkJCQl9ICkKCQkJCQkuYXBwZW5kKCB0YWJsZSApCgkJCSk7CgkKCQlpZiAoIGZvb3RlciApIHsKCQkJc2Nyb2xsZXIuYXBwZW5kKAoJCQkJJChfZGl2LCB7ICdjbGFzcyc6IGNsYXNzZXMuc1Njcm9sbEZvb3QgfSApCgkJCQkJLmNzcyggewoJCQkJCQlvdmVyZmxvdzogJ2hpZGRlbicsCgkJCQkJCWJvcmRlcjogMCwKCQkJCQkJd2lkdGg6IHNjcm9sbFggPyBzaXplKHNjcm9sbFgpIDogJzEwMCUnCgkJCQkJfSApCgkJCQkJLmFwcGVuZCgKCQkJCQkJJChfZGl2LCB7ICdjbGFzcyc6IGNsYXNzZXMuc1Njcm9sbEZvb3RJbm5lciB9ICkKCQkJCQkJCS5hcHBlbmQoCgkJCQkJCQkJZm9vdGVyQ2xvbmUKCQkJCQkJCQkJLnJlbW92ZUF0dHIoJ2lkJykKCQkJCQkJCQkJLmNzcyggJ21hcmdpbi1sZWZ0JywgMCApCgkJCQkJCQkJCS5hcHBlbmQoIGNhcHRpb25TaWRlID09PSAnYm90dG9tJyA/IGNhcHRpb24gOiBudWxsICkKCQkJCQkJCQkJLmFwcGVuZCgKCQkJCQkJCQkJCXRhYmxlLmNoaWxkcmVuKCd0Zm9vdCcpCgkJCQkJCQkJCSkKCQkJCQkJCSkKCQkJCQkpCgkJCSk7CgkJfQoJCgkJdmFyIGNoaWxkcmVuID0gc2Nyb2xsZXIuY2hpbGRyZW4oKTsKCQl2YXIgc2Nyb2xsSGVhZCA9IGNoaWxkcmVuWzBdOwoJCXZhciBzY3JvbGxCb2R5ID0gY2hpbGRyZW5bMV07CgkJdmFyIHNjcm9sbEZvb3QgPSBmb290ZXIgPyBjaGlsZHJlblsyXSA6IG51bGw7CgkKCQkvLyBXaGVuIHRoZSBib2R5IGlzIHNjcm9sbGVkLCB0aGVuIHdlIGFsc28gd2FudCB0byBzY3JvbGwgdGhlIGhlYWRlcnMKCQlpZiAoIHNjcm9sbFggKSB7CgkJCSQoc2Nyb2xsQm9keSkub24oICdzY3JvbGwuRFQnLCBmdW5jdGlvbiAoZSkgewoJCQkJdmFyIHNjcm9sbExlZnQgPSB0aGlzLnNjcm9sbExlZnQ7CgkKCQkJCXNjcm9sbEhlYWQuc2Nyb2xsTGVmdCA9IHNjcm9sbExlZnQ7CgkKCQkJCWlmICggZm9vdGVyICkgewoJCQkJCXNjcm9sbEZvb3Quc2Nyb2xsTGVmdCA9IHNjcm9sbExlZnQ7CgkJCQl9CgkJCX0gKTsKCQl9CgkKCQkkKHNjcm9sbEJvZHkpLmNzcygnbWF4LWhlaWdodCcsIHNjcm9sbFkpOwoJCWlmICghIHNjcm9sbC5iQ29sbGFwc2UpIHsKCQkJJChzY3JvbGxCb2R5KS5jc3MoJ2hlaWdodCcsIHNjcm9sbFkpOwoJCX0KCQoJCXNldHRpbmdzLm5TY3JvbGxIZWFkID0gc2Nyb2xsSGVhZDsKCQlzZXR0aW5ncy5uU2Nyb2xsQm9keSA9IHNjcm9sbEJvZHk7CgkJc2V0dGluZ3MublNjcm9sbEZvb3QgPSBzY3JvbGxGb290OwoJCgkJLy8gT24gcmVkcmF3IC0gYWxpZ24gY29sdW1ucwoJCXNldHRpbmdzLmFvRHJhd0NhbGxiYWNrLnB1c2goIHsKCQkJImZuIjogX2ZuU2Nyb2xsRHJhdywKCQkJInNOYW1lIjogInNjcm9sbGluZyIKCQl9ICk7CgkKCQlyZXR1cm4gc2Nyb2xsZXJbMF07Cgl9CgkKCQoJCgkvKioKCSAqIFVwZGF0ZSB0aGUgaGVhZGVyLCBmb290ZXIgYW5kIGJvZHkgdGFibGVzIGZvciByZXNpemluZyAtIGkuZS4gY29sdW1uCgkgKiBhbGlnbm1lbnQuCgkgKgoJICogV2VsY29tZSB0byB0aGUgbW9zdCBob3JyaWJsZSBmdW5jdGlvbiBEYXRhVGFibGVzLiBUaGUgcHJvY2VzcyB0aGF0IHRoaXMKCSAqIGZ1bmN0aW9uIGZvbGxvd3MgaXMgYmFzaWNhbGx5OgoJICogICAxLiBSZS1jcmVhdGUgdGhlIHRhYmxlIGluc2lkZSB0aGUgc2Nyb2xsaW5nIGRpdgoJICogICAyLiBUYWtlIGxpdmUgbWVhc3VyZW1lbnRzIGZyb20gdGhlIERPTQoJICogICAzLiBBcHBseSB0aGUgbWVhc3VyZW1lbnRzIHRvIGFsaWduIHRoZSBjb2x1bW5zCgkgKiAgIDQuIENsZWFuIHVwCgkgKgoJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5TY3JvbGxEcmF3ICggc2V0dGluZ3MgKQoJewoJCS8vIEdpdmVuIHRoYXQgdGhpcyBpcyBzdWNoIGEgbW9uc3RlciBmdW5jdGlvbiwgYSBsb3Qgb2YgdmFyaWFibGVzIGFyZSB1c2UKCQkvLyB0byB0cnkgYW5kIGtlZXAgdGhlIG1pbmltaXNlZCBzaXplIGFzIHNtYWxsIGFzIHBvc3NpYmxlCgkJdmFyCgkJCXNjcm9sbCAgICAgICAgID0gc2V0dGluZ3Mub1Njcm9sbCwKCQkJc2Nyb2xsWCAgICAgICAgPSBzY3JvbGwuc1gsCgkJCXNjcm9sbFhJbm5lciAgID0gc2Nyb2xsLnNYSW5uZXIsCgkJCXNjcm9sbFkgICAgICAgID0gc2Nyb2xsLnNZLAoJCQliYXJXaWR0aCAgICAgICA9IHNjcm9sbC5pQmFyV2lkdGgsCgkJCWRpdkhlYWRlciAgICAgID0gJChzZXR0aW5ncy5uU2Nyb2xsSGVhZCksCgkJCWRpdkhlYWRlclN0eWxlID0gZGl2SGVhZGVyWzBdLnN0eWxlLAoJCQlkaXZIZWFkZXJJbm5lciA9IGRpdkhlYWRlci5jaGlsZHJlbignZGl2JyksCgkJCWRpdkhlYWRlcklubmVyU3R5bGUgPSBkaXZIZWFkZXJJbm5lclswXS5zdHlsZSwKCQkJZGl2SGVhZGVyVGFibGUgPSBkaXZIZWFkZXJJbm5lci5jaGlsZHJlbigndGFibGUnKSwKCQkJZGl2Qm9keUVsICAgICAgPSBzZXR0aW5ncy5uU2Nyb2xsQm9keSwKCQkJZGl2Qm9keSAgICAgICAgPSAkKGRpdkJvZHlFbCksCgkJCWRpdkJvZHlTdHlsZSAgID0gZGl2Qm9keUVsLnN0eWxlLAoJCQlkaXZGb290ZXIgICAgICA9ICQoc2V0dGluZ3MublNjcm9sbEZvb3QpLAoJCQlkaXZGb290ZXJJbm5lciA9IGRpdkZvb3Rlci5jaGlsZHJlbignZGl2JyksCgkJCWRpdkZvb3RlclRhYmxlID0gZGl2Rm9vdGVySW5uZXIuY2hpbGRyZW4oJ3RhYmxlJyksCgkJCWhlYWRlciAgICAgICAgID0gJChzZXR0aW5ncy5uVEhlYWQpLAoJCQl0YWJsZSAgICAgICAgICA9ICQoc2V0dGluZ3MublRhYmxlKSwKCQkJdGFibGVFbCAgICAgICAgPSB0YWJsZVswXSwKCQkJdGFibGVTdHlsZSAgICAgPSB0YWJsZUVsLnN0eWxlLAoJCQlmb290ZXIgICAgICAgICA9IHNldHRpbmdzLm5URm9vdCA/ICQoc2V0dGluZ3MublRGb290KSA6IG51bGwsCgkJCWJyb3dzZXIgICAgICAgID0gc2V0dGluZ3Mub0Jyb3dzZXIsCgkJCWllNjcgICAgICAgICAgID0gYnJvd3Nlci5iU2Nyb2xsT3ZlcnNpemUsCgkJCWR0SGVhZGVyQ2VsbHMgID0gX3BsdWNrKCBzZXR0aW5ncy5hb0NvbHVtbnMsICduVGgnICksCgkJCWhlYWRlclRyZ0VscywgZm9vdGVyVHJnRWxzLAoJCQloZWFkZXJTcmNFbHMsIGZvb3RlclNyY0VscywKCQkJaGVhZGVyQ29weSwgZm9vdGVyQ29weSwKCQkJaGVhZGVyV2lkdGhzPVtdLCBmb290ZXJXaWR0aHM9W10sCgkJCWhlYWRlckNvbnRlbnQ9W10sIGZvb3RlckNvbnRlbnQ9W10sCgkJCWlkeCwgY29ycmVjdGlvbiwgc2FuaXR5V2lkdGgsCgkJCXplcm9PdXQgPSBmdW5jdGlvbihuU2l6ZXIpIHsKCQkJCXZhciBzdHlsZSA9IG5TaXplci5zdHlsZTsKCQkJCXN0eWxlLnBhZGRpbmdUb3AgPSAiMCI7CgkJCQlzdHlsZS5wYWRkaW5nQm90dG9tID0gIjAiOwoJCQkJc3R5bGUuYm9yZGVyVG9wV2lkdGggPSAiMCI7CgkJCQlzdHlsZS5ib3JkZXJCb3R0b21XaWR0aCA9ICIwIjsKCQkJCXN0eWxlLmhlaWdodCA9IDA7CgkJCX07CgkKCQkvLyBJZiB0aGUgc2Nyb2xsYmFyIHZpc2liaWxpdHkgaGFzIGNoYW5nZWQgZnJvbSB0aGUgbGFzdCBkcmF3LCB3ZSBuZWVkIHRvCgkJLy8gYWRqdXN0IHRoZSBjb2x1bW4gc2l6ZXMgYXMgdGhlIHRhYmxlIHdpZHRoIHdpbGwgaGF2ZSBjaGFuZ2VkIHRvIGFjY291bnQKCQkvLyBmb3IgdGhlIHNjcm9sbGJhcgoJCXZhciBzY3JvbGxCYXJWaXMgPSBkaXZCb2R5RWwuc2Nyb2xsSGVpZ2h0ID4gZGl2Qm9keUVsLmNsaWVudEhlaWdodDsKCQkKCQlpZiAoIHNldHRpbmdzLnNjcm9sbEJhclZpcyAhPT0gc2Nyb2xsQmFyVmlzICYmIHNldHRpbmdzLnNjcm9sbEJhclZpcyAhPT0gdW5kZWZpbmVkICkgewoJCQlzZXR0aW5ncy5zY3JvbGxCYXJWaXMgPSBzY3JvbGxCYXJWaXM7CgkJCV9mbkFkanVzdENvbHVtblNpemluZyggc2V0dGluZ3MgKTsKCQkJcmV0dXJuOyAvLyBhZGp1c3QgY29sdW1uIHNpemluZyB3aWxsIGNhbGwgdGhpcyBmdW5jdGlvbiBhZ2FpbgoJCX0KCQllbHNlIHsKCQkJc2V0dGluZ3Muc2Nyb2xsQmFyVmlzID0gc2Nyb2xsQmFyVmlzOwoJCX0KCQoJCS8qCgkJICogMS4gUmUtY3JlYXRlIHRoZSB0YWJsZSBpbnNpZGUgdGhlIHNjcm9sbGluZyBkaXYKCQkgKi8KCQoJCS8vIFJlbW92ZSB0aGUgb2xkIG1pbmltaXNlZCB0aGVhZCBhbmQgdGZvb3QgZWxlbWVudHMgaW4gdGhlIGlubmVyIHRhYmxlCgkJdGFibGUuY2hpbGRyZW4oJ3RoZWFkLCB0Zm9vdCcpLnJlbW92ZSgpOwoJCgkJaWYgKCBmb290ZXIgKSB7CgkJCWZvb3RlckNvcHkgPSBmb290ZXIuY2xvbmUoKS5wcmVwZW5kVG8oIHRhYmxlICk7CgkJCWZvb3RlclRyZ0VscyA9IGZvb3Rlci5maW5kKCd0cicpOyAvLyB0aGUgb3JpZ2luYWwgdGZvb3QgaXMgaW4gaXRzIG93biB0YWJsZSBhbmQgbXVzdCBiZSBzaXplZAoJCQlmb290ZXJTcmNFbHMgPSBmb290ZXJDb3B5LmZpbmQoJ3RyJyk7CgkJCWZvb3RlckNvcHkuZmluZCgnW2lkXScpLnJlbW92ZUF0dHIoJ2lkJyk7CgkJfQoJCgkJLy8gQ2xvbmUgdGhlIGN1cnJlbnQgaGVhZGVyIGFuZCBmb290ZXIgZWxlbWVudHMgYW5kIHRoZW4gcGxhY2UgaXQgaW50byB0aGUgaW5uZXIgdGFibGUKCQloZWFkZXJDb3B5ID0gaGVhZGVyLmNsb25lKCkucHJlcGVuZFRvKCB0YWJsZSApOwoJCWhlYWRlclRyZ0VscyA9IGhlYWRlci5maW5kKCd0cicpOyAvLyBvcmlnaW5hbCBoZWFkZXIgaXMgaW4gaXRzIG93biB0YWJsZQoJCWhlYWRlclNyY0VscyA9IGhlYWRlckNvcHkuZmluZCgndHInKTsKCQloZWFkZXJDb3B5LmZpbmQoJ3RoLCB0ZCcpLnJlbW92ZUF0dHIoJ3RhYmluZGV4Jyk7CgkJaGVhZGVyQ29weS5maW5kKCdbaWRdJykucmVtb3ZlQXR0cignaWQnKTsKCQoJCgkJLyoKCQkgKiAyLiBUYWtlIGxpdmUgbWVhc3VyZW1lbnRzIGZyb20gdGhlIERPTSAtIGRvIG5vdCBhbHRlciB0aGUgRE9NIGl0c2VsZiEKCQkgKi8KCQoJCS8vIFJlbW92ZSBvbGQgc2l6aW5nIGFuZCBhcHBseSB0aGUgY2FsY3VsYXRlZCBjb2x1bW4gd2lkdGhzCgkJLy8gR2V0IHRoZSB1bmlxdWUgY29sdW1uIGhlYWRlcnMgaW4gdGhlIG5ld2x5IGNyZWF0ZWQgKGNsb25lZCkgaGVhZGVyLiBXZSB3YW50IHRvIGFwcGx5IHRoZQoJCS8vIGNhbGN1bGF0ZWQgc2l6ZXMgdG8gdGhpcyBoZWFkZXIKCQlpZiAoICEgc2Nyb2xsWCApCgkJewoJCQlkaXZCb2R5U3R5bGUud2lkdGggPSAnMTAwJSc7CgkJCWRpdkhlYWRlclswXS5zdHlsZS53aWR0aCA9ICcxMDAlJzsKCQl9CgkKCQkkLmVhY2goIF9mbkdldFVuaXF1ZVRocyggc2V0dGluZ3MsIGhlYWRlckNvcHkgKSwgZnVuY3Rpb24gKCBpLCBlbCApIHsKCQkJaWR4ID0gX2ZuVmlzaWJsZVRvQ29sdW1uSW5kZXgoIHNldHRpbmdzLCBpICk7CgkJCWVsLnN0eWxlLndpZHRoID0gc2V0dGluZ3MuYW9Db2x1bW5zW2lkeF0uc1dpZHRoOwoJCX0gKTsKCQoJCWlmICggZm9vdGVyICkgewoJCQlfZm5BcHBseVRvQ2hpbGRyZW4oIGZ1bmN0aW9uKG4pIHsKCQkJCW4uc3R5bGUud2lkdGggPSAiIjsKCQkJfSwgZm9vdGVyU3JjRWxzICk7CgkJfQoJCgkJLy8gU2l6ZSB0aGUgdGFibGUgYXMgYSB3aG9sZQoJCXNhbml0eVdpZHRoID0gdGFibGUub3V0ZXJXaWR0aCgpOwoJCWlmICggc2Nyb2xsWCA9PT0gIiIgKSB7CgkJCS8vIE5vIHggc2Nyb2xsaW5nCgkJCXRhYmxlU3R5bGUud2lkdGggPSAiMTAwJSI7CgkKCQkJLy8gSUU3IHdpbGwgbWFrZSB0aGUgd2lkdGggb2YgdGhlIHRhYmxlIHdoZW4gMTAwJSBpbmNsdWRlIHRoZSBzY3JvbGxiYXIKCQkJLy8gLSB3aGljaCBpcyBzaG91bGRuJ3QuIFdoZW4gdGhlcmUgaXMgYSBzY3JvbGxiYXIgd2UgbmVlZCB0byB0YWtlIHRoaXMKCQkJLy8gaW50byBhY2NvdW50LgoJCQlpZiAoIGllNjcgJiYgKHRhYmxlLmZpbmQoJ3Rib2R5JykuaGVpZ2h0KCkgPiBkaXZCb2R5RWwub2Zmc2V0SGVpZ2h0IHx8CgkJCQlkaXZCb2R5LmNzcygnb3ZlcmZsb3cteScpID09ICJzY3JvbGwiKQoJCQkpIHsKCQkJCXRhYmxlU3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyggdGFibGUub3V0ZXJXaWR0aCgpIC0gYmFyV2lkdGgpOwoJCQl9CgkKCQkJLy8gUmVjYWxjdWxhdGUgdGhlIHNhbml0eSB3aWR0aAoJCQlzYW5pdHlXaWR0aCA9IHRhYmxlLm91dGVyV2lkdGgoKTsKCQl9CgkJZWxzZSBpZiAoIHNjcm9sbFhJbm5lciAhPT0gIiIgKSB7CgkJCS8vIGxlZ2FjeSB4IHNjcm9sbCBpbm5lciBoYXMgYmVlbiBnaXZlbiAtIHVzZSBpdAoJCQl0YWJsZVN0eWxlLndpZHRoID0gX2ZuU3RyaW5nVG9Dc3Moc2Nyb2xsWElubmVyKTsKCQoJCQkvLyBSZWNhbGN1bGF0ZSB0aGUgc2FuaXR5IHdpZHRoCgkJCXNhbml0eVdpZHRoID0gdGFibGUub3V0ZXJXaWR0aCgpOwoJCX0KCQoJCS8vIEhpZGRlbiBoZWFkZXIgc2hvdWxkIGhhdmUgemVybyBoZWlnaHQsIHNvIHJlbW92ZSBwYWRkaW5nIGFuZCBib3JkZXJzLiBUaGVuCgkJLy8gc2V0IHRoZSB3aWR0aCBiYXNlZCBvbiB0aGUgcmVhbCBoZWFkZXJzCgkKCQkvLyBBcHBseSBhbGwgc3R5bGVzIGluIG9uZSBwYXNzCgkJX2ZuQXBwbHlUb0NoaWxkcmVuKCB6ZXJvT3V0LCBoZWFkZXJTcmNFbHMgKTsKCQoJCS8vIFJlYWQgYWxsIHdpZHRocyBpbiBuZXh0IHBhc3MKCQlfZm5BcHBseVRvQ2hpbGRyZW4oIGZ1bmN0aW9uKG5TaXplcikgewoJCQl2YXIgc3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSA/CgkJCQl3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShuU2l6ZXIpLndpZHRoIDoKCQkJCV9mblN0cmluZ1RvQ3NzKCAkKG5TaXplcikud2lkdGgoKSApOwoJCgkJCWhlYWRlckNvbnRlbnQucHVzaCggblNpemVyLmlubmVySFRNTCApOwoJCQloZWFkZXJXaWR0aHMucHVzaCggc3R5bGUgKTsKCQl9LCBoZWFkZXJTcmNFbHMgKTsKCQoJCS8vIEFwcGx5IGFsbCB3aWR0aHMgaW4gZmluYWwgcGFzcwoJCV9mbkFwcGx5VG9DaGlsZHJlbiggZnVuY3Rpb24oblRvU2l6ZSwgaSkgewoJCQluVG9TaXplLnN0eWxlLndpZHRoID0gaGVhZGVyV2lkdGhzW2ldOwoJCX0sIGhlYWRlclRyZ0VscyApOwoJCgkJJChoZWFkZXJTcmNFbHMpLmNzcygnaGVpZ2h0JywgMCk7CgkKCQkvKiBTYW1lIGFnYWluIHdpdGggdGhlIGZvb3RlciBpZiB3ZSBoYXZlIG9uZSAqLwoJCWlmICggZm9vdGVyICkKCQl7CgkJCV9mbkFwcGx5VG9DaGlsZHJlbiggemVyb091dCwgZm9vdGVyU3JjRWxzICk7CgkKCQkJX2ZuQXBwbHlUb0NoaWxkcmVuKCBmdW5jdGlvbihuU2l6ZXIpIHsKCQkJCWZvb3RlckNvbnRlbnQucHVzaCggblNpemVyLmlubmVySFRNTCApOwoJCQkJZm9vdGVyV2lkdGhzLnB1c2goIF9mblN0cmluZ1RvQ3NzKCAkKG5TaXplcikuY3NzKCd3aWR0aCcpICkgKTsKCQkJfSwgZm9vdGVyU3JjRWxzICk7CgkKCQkJX2ZuQXBwbHlUb0NoaWxkcmVuKCBmdW5jdGlvbihuVG9TaXplLCBpKSB7CgkJCQluVG9TaXplLnN0eWxlLndpZHRoID0gZm9vdGVyV2lkdGhzW2ldOwoJCQl9LCBmb290ZXJUcmdFbHMgKTsKCQoJCQkkKGZvb3RlclNyY0VscykuaGVpZ2h0KDApOwoJCX0KCQoJCgkJLyoKCQkgKiAzLiBBcHBseSB0aGUgbWVhc3VyZW1lbnRzCgkJICovCgkKCQkvLyAiSGlkZSIgdGhlIGhlYWRlciBhbmQgZm9vdGVyIHRoYXQgd2UgdXNlZCBmb3IgdGhlIHNpemluZy4gV2UgbmVlZCB0byBrZWVwCgkJLy8gdGhlIGNvbnRlbnQgb2YgdGhlIGNlbGwgc28gdGhhdCB0aGUgd2lkdGggYXBwbGllZCB0byB0aGUgaGVhZGVyIGFuZCBib2R5CgkJLy8gYm90aCBtYXRjaCwgYnV0IHdlIHdhbnQgdG8gaGlkZSBpdCBjb21wbGV0ZWx5LiBXZSB3YW50IHRvIGFsc28gZml4IHRoZWlyCgkJLy8gd2lkdGggdG8gd2hhdCB0aGV5IGN1cnJlbnRseSBhcmUKCQlfZm5BcHBseVRvQ2hpbGRyZW4oIGZ1bmN0aW9uKG5TaXplciwgaSkgewoJCQluU2l6ZXIuaW5uZXJIVE1MID0gJzxkaXYgY2xhc3M9ImRhdGFUYWJsZXNfc2l6aW5nIj4nK2hlYWRlckNvbnRlbnRbaV0rJzwvZGl2Pic7CgkJCW5TaXplci5jaGlsZE5vZGVzWzBdLnN0eWxlLmhlaWdodCA9ICIwIjsKCQkJblNpemVyLmNoaWxkTm9kZXNbMF0uc3R5bGUub3ZlcmZsb3cgPSAiaGlkZGVuIjsKCQkJblNpemVyLnN0eWxlLndpZHRoID0gaGVhZGVyV2lkdGhzW2ldOwoJCX0sIGhlYWRlclNyY0VscyApOwoJCgkJaWYgKCBmb290ZXIgKQoJCXsKCQkJX2ZuQXBwbHlUb0NoaWxkcmVuKCBmdW5jdGlvbihuU2l6ZXIsIGkpIHsKCQkJCW5TaXplci5pbm5lckhUTUwgPSAnPGRpdiBjbGFzcz0iZGF0YVRhYmxlc19zaXppbmciPicrZm9vdGVyQ29udGVudFtpXSsnPC9kaXY+JzsKCQkJCW5TaXplci5jaGlsZE5vZGVzWzBdLnN0eWxlLmhlaWdodCA9ICIwIjsKCQkJCW5TaXplci5jaGlsZE5vZGVzWzBdLnN0eWxlLm92ZXJmbG93ID0gImhpZGRlbiI7CgkJCQluU2l6ZXIuc3R5bGUud2lkdGggPSBmb290ZXJXaWR0aHNbaV07CgkJCX0sIGZvb3RlclNyY0VscyApOwoJCX0KCQoJCS8vIFNhbml0eSBjaGVjayB0aGF0IHRoZSB0YWJsZSBpcyBvZiBhIHNlbnNpYmxlIHdpZHRoLiBJZiBub3QgdGhlbiB3ZSBhcmUgZ29pbmcgdG8gZ2V0CgkJLy8gbWlzYWxpZ25tZW50IC0gdHJ5IHRvIHByZXZlbnQgdGhpcyBieSBub3QgYWxsb3dpbmcgdGhlIHRhYmxlIHRvIHNocmluayBiZWxvdyBpdHMgbWluIHdpZHRoCgkJaWYgKCBNYXRoLnJvdW5kKHRhYmxlLm91dGVyV2lkdGgoKSkgPCBNYXRoLnJvdW5kKHNhbml0eVdpZHRoKSApCgkJewoJCQkvLyBUaGUgbWluIHdpZHRoIGRlcGVuZHMgdXBvbiBpZiB3ZSBoYXZlIGEgdmVydGljYWwgc2Nyb2xsYmFyIHZpc2libGUgb3Igbm90ICovCgkJCWNvcnJlY3Rpb24gPSAoKGRpdkJvZHlFbC5zY3JvbGxIZWlnaHQgPiBkaXZCb2R5RWwub2Zmc2V0SGVpZ2h0IHx8CgkJCQlkaXZCb2R5LmNzcygnb3ZlcmZsb3cteScpID09ICJzY3JvbGwiKSkgPwoJCQkJCXNhbml0eVdpZHRoK2JhcldpZHRoIDoKCQkJCQlzYW5pdHlXaWR0aDsKCQoJCQkvLyBJRTYvNyBhcmUgYSBsYXcgdW50byB0aGVtc2VsdmVzLi4uCgkJCWlmICggaWU2NyAmJiAoZGl2Qm9keUVsLnNjcm9sbEhlaWdodCA+CgkJCQlkaXZCb2R5RWwub2Zmc2V0SGVpZ2h0IHx8IGRpdkJvZHkuY3NzKCdvdmVyZmxvdy15JykgPT0gInNjcm9sbCIpCgkJCSkgewoJCQkJdGFibGVTdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBjb3JyZWN0aW9uLWJhcldpZHRoICk7CgkJCX0KCQoJCQkvLyBBbmQgZ2l2ZSB0aGUgdXNlciBhIHdhcm5pbmcgdGhhdCB3ZSd2ZSBzdG9wcGVkIHRoZSB0YWJsZSBnZXR0aW5nIHRvbyBzbWFsbAoJCQlpZiAoIHNjcm9sbFggPT09ICIiIHx8IHNjcm9sbFhJbm5lciAhPT0gIiIgKSB7CgkJCQlfZm5Mb2coIHNldHRpbmdzLCAxLCAnUG9zc2libGUgY29sdW1uIG1pc2FsaWdubWVudCcsIDYgKTsKCQkJfQoJCX0KCQllbHNlCgkJewoJCQljb3JyZWN0aW9uID0gJzEwMCUnOwoJCX0KCQoJCS8vIEFwcGx5IHRvIHRoZSBjb250YWluZXIgZWxlbWVudHMKCQlkaXZCb2R5U3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyggY29ycmVjdGlvbiApOwoJCWRpdkhlYWRlclN0eWxlLndpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIGNvcnJlY3Rpb24gKTsKCQoJCWlmICggZm9vdGVyICkgewoJCQlzZXR0aW5ncy5uU2Nyb2xsRm9vdC5zdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBjb3JyZWN0aW9uICk7CgkJfQoJCgkKCQkvKgoJCSAqIDQuIENsZWFuIHVwCgkJICovCgkJaWYgKCAhIHNjcm9sbFkgKSB7CgkJCS8qIElFNzwgcHV0cyBhIHZlcnRpY2FsIHNjcm9sbGJhciBpbiBwbGFjZSAod2hlbiBpdCBzaG91bGRuJ3QgYmUpIGR1ZSB0byBzdWJ0cmFjdGluZwoJCQkgKiB0aGUgc2Nyb2xsYmFyIGhlaWdodCBmcm9tIHRoZSB2aXNpYmxlIGRpc3BsYXksIHJhdGhlciB0aGFuIGFkZGluZyBpdCBvbi4gV2UgbmVlZCB0bwoJCQkgKiBzZXQgdGhlIGhlaWdodCBpbiBvcmRlciB0byBzb3J0IHRoaXMuIERvbid0IHdhbnQgdG8gZG8gaXQgaW4gYW55IG90aGVyIGJyb3dzZXJzLgoJCQkgKi8KCQkJaWYgKCBpZTY3ICkgewoJCQkJZGl2Qm9keVN0eWxlLmhlaWdodCA9IF9mblN0cmluZ1RvQ3NzKCB0YWJsZUVsLm9mZnNldEhlaWdodCtiYXJXaWR0aCApOwoJCQl9CgkJfQoJCgkJLyogRmluYWxseSBzZXQgdGhlIHdpZHRoJ3Mgb2YgdGhlIGhlYWRlciBhbmQgZm9vdGVyIHRhYmxlcyAqLwoJCXZhciBpT3V0ZXJXaWR0aCA9IHRhYmxlLm91dGVyV2lkdGgoKTsKCQlkaXZIZWFkZXJUYWJsZVswXS5zdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBpT3V0ZXJXaWR0aCApOwoJCWRpdkhlYWRlcklubmVyU3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyggaU91dGVyV2lkdGggKTsKCQoJCS8vIEZpZ3VyZSBvdXQgaWYgdGhlcmUgYXJlIHNjcm9sbGJhciBwcmVzZW50IC0gaWYgc28gdGhlbiB3ZSBuZWVkIGEgdGhlIGhlYWRlciBhbmQgZm9vdGVyIHRvCgkJLy8gcHJvdmlkZSBhIGJpdCBtb3JlIHNwYWNlIHRvIGFsbG93ICJvdmVyZmxvdyIgc2Nyb2xsaW5nIChpLmUuIHBhc3QgdGhlIHNjcm9sbGJhcikKCQl2YXIgYlNjcm9sbGluZyA9IHRhYmxlLmhlaWdodCgpID4gZGl2Qm9keUVsLmNsaWVudEhlaWdodCB8fCBkaXZCb2R5LmNzcygnb3ZlcmZsb3cteScpID09ICJzY3JvbGwiOwoJCXZhciBwYWRkaW5nID0gJ3BhZGRpbmcnICsgKGJyb3dzZXIuYlNjcm9sbGJhckxlZnQgPyAnTGVmdCcgOiAnUmlnaHQnICk7CgkJZGl2SGVhZGVySW5uZXJTdHlsZVsgcGFkZGluZyBdID0gYlNjcm9sbGluZyA/IGJhcldpZHRoKyJweCIgOiAiMHB4IjsKCQoJCWlmICggZm9vdGVyICkgewoJCQlkaXZGb290ZXJUYWJsZVswXS5zdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBpT3V0ZXJXaWR0aCApOwoJCQlkaXZGb290ZXJJbm5lclswXS5zdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBpT3V0ZXJXaWR0aCApOwoJCQlkaXZGb290ZXJJbm5lclswXS5zdHlsZVtwYWRkaW5nXSA9IGJTY3JvbGxpbmcgPyBiYXJXaWR0aCsicHgiIDogIjBweCI7CgkJfQoJCgkJLy8gQ29ycmVjdCBET00gb3JkZXJpbmcgZm9yIGNvbGdyb3VwIC0gY29tZXMgYmVmb3JlIHRoZSB0aGVhZAoJCXRhYmxlLmNoaWxkcmVuKCdjb2xncm91cCcpLmluc2VydEJlZm9yZSggdGFibGUuY2hpbGRyZW4oJ3RoZWFkJykgKTsKCQoJCS8qIEFkanVzdCB0aGUgcG9zaXRpb24gb2YgdGhlIGhlYWRlciBpbiBjYXNlIHdlIGxvb3NlIHRoZSB5LXNjcm9sbGJhciAqLwoJCWRpdkJvZHkudHJpZ2dlcignc2Nyb2xsJyk7CgkKCQkvLyBJZiBzb3J0aW5nIG9yIGZpbHRlcmluZyBoYXMgb2NjdXJyZWQsIGp1bXAgdGhlIHNjcm9sbGluZyBiYWNrIHRvIHRoZSB0b3AKCQkvLyBvbmx5IGlmIHdlIGFyZW4ndCBob2xkaW5nIHRoZSBwb3NpdGlvbgoJCWlmICggKHNldHRpbmdzLmJTb3J0ZWQgfHwgc2V0dGluZ3MuYkZpbHRlcmVkKSAmJiAhIHNldHRpbmdzLl9kcmF3SG9sZCApIHsKCQkJZGl2Qm9keUVsLnNjcm9sbFRvcCA9IDA7CgkJfQoJfQoJCgkKCQoJLyoqCgkgKiBBcHBseSBhIGdpdmVuIGZ1bmN0aW9uIHRvIHRoZSBkaXNwbGF5IGNoaWxkIG5vZGVzIG9mIGFuIGVsZW1lbnQgYXJyYXkgKHR5cGljYWxseQoJICogVEQgY2hpbGRyZW4gb2YgVFIgcm93cwoJICogIEBwYXJhbSB7ZnVuY3Rpb259IGZuIE1ldGhvZCB0byBhcHBseSB0byB0aGUgb2JqZWN0cwoJICogIEBwYXJhbSBhcnJheSB7bm9kZXN9IGFuMSBMaXN0IG9mIGVsZW1lbnRzIHRvIGxvb2sgdGhyb3VnaCBmb3IgZGlzcGxheSBjaGlsZHJlbgoJICogIEBwYXJhbSBhcnJheSB7bm9kZXN9IGFuMiBBbm90aGVyIGxpc3QgKGlkZW50aWNhbCBzdHJ1Y3R1cmUgdG8gdGhlIGZpcnN0KSAtIG9wdGlvbmFsCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkFwcGx5VG9DaGlsZHJlbiggZm4sIGFuMSwgYW4yICkKCXsKCQl2YXIgaW5kZXg9MCwgaT0wLCBpTGVuPWFuMS5sZW5ndGg7CgkJdmFyIG5Ob2RlMSwgbk5vZGUyOwoJCgkJd2hpbGUgKCBpIDwgaUxlbiApIHsKCQkJbk5vZGUxID0gYW4xW2ldLmZpcnN0Q2hpbGQ7CgkJCW5Ob2RlMiA9IGFuMiA/IGFuMltpXS5maXJzdENoaWxkIDogbnVsbDsKCQoJCQl3aGlsZSAoIG5Ob2RlMSApIHsKCQkJCWlmICggbk5vZGUxLm5vZGVUeXBlID09PSAxICkgewoJCQkJCWlmICggYW4yICkgewoJCQkJCQlmbiggbk5vZGUxLCBuTm9kZTIsIGluZGV4ICk7CgkJCQkJfQoJCQkJCWVsc2UgewoJCQkJCQlmbiggbk5vZGUxLCBpbmRleCApOwoJCQkJCX0KCQoJCQkJCWluZGV4Kys7CgkJCQl9CgkKCQkJCW5Ob2RlMSA9IG5Ob2RlMS5uZXh0U2libGluZzsKCQkJCW5Ob2RlMiA9IGFuMiA/IG5Ob2RlMi5uZXh0U2libGluZyA6IG51bGw7CgkJCX0KCQoJCQlpKys7CgkJfQoJfQoJCgkKCQoJdmFyIF9fcmVfaHRtbF9yZW1vdmUgPSAvPC4qPz4vZzsKCQoJCgkvKioKCSAqIENhbGN1bGF0ZSB0aGUgd2lkdGggb2YgY29sdW1ucyBmb3IgdGhlIHRhYmxlCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5DYWxjdWxhdGVDb2x1bW5XaWR0aHMgKCBvU2V0dGluZ3MgKQoJewoJCXZhcgoJCQl0YWJsZSA9IG9TZXR0aW5ncy5uVGFibGUsCgkJCWNvbHVtbnMgPSBvU2V0dGluZ3MuYW9Db2x1bW5zLAoJCQlzY3JvbGwgPSBvU2V0dGluZ3Mub1Njcm9sbCwKCQkJc2Nyb2xsWSA9IHNjcm9sbC5zWSwKCQkJc2Nyb2xsWCA9IHNjcm9sbC5zWCwKCQkJc2Nyb2xsWElubmVyID0gc2Nyb2xsLnNYSW5uZXIsCgkJCWNvbHVtbkNvdW50ID0gY29sdW1ucy5sZW5ndGgsCgkJCXZpc2libGVDb2x1bW5zID0gX2ZuR2V0Q29sdW1ucyggb1NldHRpbmdzLCAnYlZpc2libGUnICksCgkJCWhlYWRlckNlbGxzID0gJCgndGgnLCBvU2V0dGluZ3MublRIZWFkKSwKCQkJdGFibGVXaWR0aEF0dHIgPSB0YWJsZS5nZXRBdHRyaWJ1dGUoJ3dpZHRoJyksIC8vIGZyb20gRE9NIGVsZW1lbnQKCQkJdGFibGVDb250YWluZXIgPSB0YWJsZS5wYXJlbnROb2RlLAoJCQl1c2VySW5wdXRzID0gZmFsc2UsCgkJCWksIGNvbHVtbiwgY29sdW1uSWR4LCB3aWR0aCwgb3V0ZXJXaWR0aCwKCQkJYnJvd3NlciA9IG9TZXR0aW5ncy5vQnJvd3NlciwKCQkJaWU2NyA9IGJyb3dzZXIuYlNjcm9sbE92ZXJzaXplOwoJCgkJdmFyIHN0eWxlV2lkdGggPSB0YWJsZS5zdHlsZS53aWR0aDsKCQlpZiAoIHN0eWxlV2lkdGggJiYgc3R5bGVXaWR0aC5pbmRleE9mKCclJykgIT09IC0xICkgewoJCQl0YWJsZVdpZHRoQXR0ciA9IHN0eWxlV2lkdGg7CgkJfQoJCgkJLyogQ29udmVydCBhbnkgdXNlciBpbnB1dCBzaXplcyBpbnRvIHBpeGVsIHNpemVzICovCgkJZm9yICggaT0wIDsgaTx2aXNpYmxlQ29sdW1ucy5sZW5ndGggOyBpKysgKSB7CgkJCWNvbHVtbiA9IGNvbHVtbnNbIHZpc2libGVDb2x1bW5zW2ldIF07CgkKCQkJaWYgKCBjb2x1bW4uc1dpZHRoICE9PSBudWxsICkgewoJCQkJY29sdW1uLnNXaWR0aCA9IF9mbkNvbnZlcnRUb1dpZHRoKCBjb2x1bW4uc1dpZHRoT3JpZywgdGFibGVDb250YWluZXIgKTsKCQoJCQkJdXNlcklucHV0cyA9IHRydWU7CgkJCX0KCQl9CgkKCQkvKiBJZiB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIERPTSBlcXVhbHMgdGhlIG51bWJlciB0aGF0IHdlIGhhdmUgdG8KCQkgKiBwcm9jZXNzIGluIERhdGFUYWJsZXMsIHRoZW4gd2UgY2FuIHVzZSB0aGUgb2Zmc2V0cyB0aGF0IGFyZSBjcmVhdGVkIGJ5CgkJICogdGhlIHdlYi0gYnJvd3Nlci4gTm8gY3VzdG9tIHNpemVzIGNhbiBiZSBzZXQgaW4gb3JkZXIgZm9yIHRoaXMgdG8gaGFwcGVuLAoJCSAqIG5vciBzY3JvbGxpbmcgdXNlZAoJCSAqLwoJCWlmICggaWU2NyB8fCAhIHVzZXJJbnB1dHMgJiYgISBzY3JvbGxYICYmICEgc2Nyb2xsWSAmJgoJCSAgICAgY29sdW1uQ291bnQgPT0gX2ZuVmlzYmxlQ29sdW1ucyggb1NldHRpbmdzICkgJiYKCQkgICAgIGNvbHVtbkNvdW50ID09IGhlYWRlckNlbGxzLmxlbmd0aAoJCSkgewoJCQlmb3IgKCBpPTAgOyBpPGNvbHVtbkNvdW50IDsgaSsrICkgewoJCQkJdmFyIGNvbElkeCA9IF9mblZpc2libGVUb0NvbHVtbkluZGV4KCBvU2V0dGluZ3MsIGkgKTsKCQoJCQkJaWYgKCBjb2xJZHggIT09IG51bGwgKSB7CgkJCQkJY29sdW1uc1sgY29sSWR4IF0uc1dpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIGhlYWRlckNlbGxzLmVxKGkpLndpZHRoKCkgKTsKCQkJCX0KCQkJfQoJCX0KCQllbHNlCgkJewoJCQkvLyBPdGhlcndpc2UgY29uc3RydWN0IGEgc2luZ2xlIHJvdywgd29yc3QgY2FzZSwgdGFibGUgd2l0aCB0aGUgd2lkZXN0CgkJCS8vIG5vZGUgaW4gdGhlIGRhdGEsIGFzc2lnbiBhbnkgdXNlciBkZWZpbmVkIHdpZHRocywgdGhlbiBpbnNlcnQgaXQgaW50bwoJCQkvLyB0aGUgRE9NIGFuZCBhbGxvdyB0aGUgYnJvd3NlciB0byBkbyBhbGwgdGhlIGhhcmQgd29yayBvZiBjYWxjdWxhdGluZwoJCQkvLyB0YWJsZSB3aWR0aHMKCQkJdmFyIHRtcFRhYmxlID0gJCh0YWJsZSkuY2xvbmUoKSAvLyBkb24ndCB1c2UgY2xvbmVOb2RlIC0gSUU4IHdpbGwgcmVtb3ZlIGV2ZW50cyBvbiB0aGUgbWFpbiB0YWJsZQoJCQkJLmNzcyggJ3Zpc2liaWxpdHknLCAnaGlkZGVuJyApCgkJCQkucmVtb3ZlQXR0ciggJ2lkJyApOwoJCgkJCS8vIENsZWFuIHVwIHRoZSB0YWJsZSBib2R5CgkJCXRtcFRhYmxlLmZpbmQoJ3Rib2R5IHRyJykucmVtb3ZlKCk7CgkJCXZhciB0ciA9ICQoJzx0ci8+JykuYXBwZW5kVG8oIHRtcFRhYmxlLmZpbmQoJ3Rib2R5JykgKTsKCQoJCQkvLyBDbG9uZSB0aGUgdGFibGUgaGVhZGVyIGFuZCBmb290ZXIgLSB3ZSBjYW4ndCB1c2UgdGhlIGhlYWRlciAvIGZvb3RlcgoJCQkvLyBmcm9tIHRoZSBjbG9uZWQgdGFibGUsIHNpbmNlIGlmIHNjcm9sbGluZyBpcyBhY3RpdmUsIHRoZSB0YWJsZSdzCgkJCS8vIHJlYWwgaGVhZGVyIGFuZCBmb290ZXIgYXJlIGNvbnRhaW5lZCBpbiBkaWZmZXJlbnQgdGFibGUgdGFncwoJCQl0bXBUYWJsZS5maW5kKCd0aGVhZCwgdGZvb3QnKS5yZW1vdmUoKTsKCQkJdG1wVGFibGUKCQkJCS5hcHBlbmQoICQob1NldHRpbmdzLm5USGVhZCkuY2xvbmUoKSApCgkJCQkuYXBwZW5kKCAkKG9TZXR0aW5ncy5uVEZvb3QpLmNsb25lKCkgKTsKCQoJCQkvLyBSZW1vdmUgYW55IGFzc2lnbmVkIHdpZHRocyBmcm9tIHRoZSBmb290ZXIgKGZyb20gc2Nyb2xsaW5nKQoJCQl0bXBUYWJsZS5maW5kKCd0Zm9vdCB0aCwgdGZvb3QgdGQnKS5jc3MoJ3dpZHRoJywgJycpOwoJCgkJCS8vIEFwcGx5IGN1c3RvbSBzaXppbmcgdG8gdGhlIGNsb25lZCBoZWFkZXIKCQkJaGVhZGVyQ2VsbHMgPSBfZm5HZXRVbmlxdWVUaHMoIG9TZXR0aW5ncywgdG1wVGFibGUuZmluZCgndGhlYWQnKVswXSApOwoJCgkJCWZvciAoIGk9MCA7IGk8dmlzaWJsZUNvbHVtbnMubGVuZ3RoIDsgaSsrICkgewoJCQkJY29sdW1uID0gY29sdW1uc1sgdmlzaWJsZUNvbHVtbnNbaV0gXTsKCQoJCQkJaGVhZGVyQ2VsbHNbaV0uc3R5bGUud2lkdGggPSBjb2x1bW4uc1dpZHRoT3JpZyAhPT0gbnVsbCAmJiBjb2x1bW4uc1dpZHRoT3JpZyAhPT0gJycgPwoJCQkJCV9mblN0cmluZ1RvQ3NzKCBjb2x1bW4uc1dpZHRoT3JpZyApIDoKCQkJCQknJzsKCQoJCQkJLy8gRm9yIHNjcm9sbFggd2UgbmVlZCB0byBmb3JjZSB0aGUgY29sdW1uIHdpZHRoIG90aGVyd2lzZSB0aGUKCQkJCS8vIGJyb3dzZXIgd2lsbCBjb2xsYXBzZSBpdC4gSWYgdGhpcyB3aWR0aCBpcyBzbWFsbGVyIHRoYW4gdGhlCgkJCQkvLyB3aWR0aCB0aGUgY29sdW1uIHJlcXVpcmVzLCB0aGVuIGl0IHdpbGwgaGF2ZSBubyBlZmZlY3QKCQkJCWlmICggY29sdW1uLnNXaWR0aE9yaWcgJiYgc2Nyb2xsWCApIHsKCQkJCQkkKCBoZWFkZXJDZWxsc1tpXSApLmFwcGVuZCggJCgnPGRpdi8+JykuY3NzKCB7CgkJCQkJCXdpZHRoOiBjb2x1bW4uc1dpZHRoT3JpZywKCQkJCQkJbWFyZ2luOiAwLAoJCQkJCQlwYWRkaW5nOiAwLAoJCQkJCQlib3JkZXI6IDAsCgkJCQkJCWhlaWdodDogMQoJCQkJCX0gKSApOwoJCQkJfQoJCQl9CgkKCQkJLy8gRmluZCB0aGUgd2lkZXN0IGNlbGwgZm9yIGVhY2ggY29sdW1uIGFuZCBwdXQgaXQgaW50byB0aGUgdGFibGUKCQkJaWYgKCBvU2V0dGluZ3MuYW9EYXRhLmxlbmd0aCApIHsKCQkJCWZvciAoIGk9MCA7IGk8dmlzaWJsZUNvbHVtbnMubGVuZ3RoIDsgaSsrICkgewoJCQkJCWNvbHVtbklkeCA9IHZpc2libGVDb2x1bW5zW2ldOwoJCQkJCWNvbHVtbiA9IGNvbHVtbnNbIGNvbHVtbklkeCBdOwoJCgkJCQkJJCggX2ZuR2V0V2lkZXN0Tm9kZSggb1NldHRpbmdzLCBjb2x1bW5JZHggKSApCgkJCQkJCS5jbG9uZSggZmFsc2UgKQoJCQkJCQkuYXBwZW5kKCBjb2x1bW4uc0NvbnRlbnRQYWRkaW5nICkKCQkJCQkJLmFwcGVuZFRvKCB0ciApOwoJCQkJfQoJCQl9CgkKCQkJLy8gVGlkeSB0aGUgdGVtcG9yYXJ5IHRhYmxlIC0gcmVtb3ZlIG5hbWUgYXR0cmlidXRlcyBzbyB0aGVyZSBhcmVuJ3QKCQkJLy8gZHVwbGljYXRlZCBpbiB0aGUgZG9tIChyYWRpbyBlbGVtZW50cyBmb3IgZXhhbXBsZSkKCQkJJCgnW25hbWVdJywgdG1wVGFibGUpLnJlbW92ZUF0dHIoJ25hbWUnKTsKCQoJCQkvLyBUYWJsZSBoYXMgYmVlbiBidWlsdCwgYXR0YWNoIHRvIHRoZSBkb2N1bWVudCBzbyB3ZSBjYW4gd29yayB3aXRoIGl0LgoJCQkvLyBBIGhvbGRpbmcgZWxlbWVudCBpcyB1c2VkLCBwb3NpdGlvbmVkIGF0IHRoZSB0b3Agb2YgdGhlIGNvbnRhaW5lcgoJCQkvLyB3aXRoIG1pbmltYWwgaGVpZ2h0LCBzbyBpdCBoYXMgbm8gZWZmZWN0IG9uIGlmIHRoZSBjb250YWluZXIgc2Nyb2xscwoJCQkvLyBvciBub3QuIE90aGVyd2lzZSBpdCBtaWdodCB0cmlnZ2VyIHNjcm9sbGluZyB3aGVuIGl0IGFjdHVhbGx5IGlzbid0CgkJCS8vIG5lZWRlZAoJCQl2YXIgaG9sZGVyID0gJCgnPGRpdi8+JykuY3NzKCBzY3JvbGxYIHx8IHNjcm9sbFkgPwoJCQkJCXsKCQkJCQkJcG9zaXRpb246ICdhYnNvbHV0ZScsCgkJCQkJCXRvcDogMCwKCQkJCQkJbGVmdDogMCwKCQkJCQkJaGVpZ2h0OiAxLAoJCQkJCQlyaWdodDogMCwKCQkJCQkJb3ZlcmZsb3c6ICdoaWRkZW4nCgkJCQkJfSA6CgkJCQkJe30KCQkJCSkKCQkJCS5hcHBlbmQoIHRtcFRhYmxlICkKCQkJCS5hcHBlbmRUbyggdGFibGVDb250YWluZXIgKTsKCQoJCQkvLyBXaGVuIHNjcm9sbGluZyAoWCBvciBZKSB3ZSB3YW50IHRvIHNldCB0aGUgd2lkdGggb2YgdGhlIHRhYmxlIGFzIAoJCQkvLyBhcHByb3ByaWF0ZS4gSG93ZXZlciwgd2hlbiBub3Qgc2Nyb2xsaW5nIGxlYXZlIHRoZSB0YWJsZSB3aWR0aCBhcyBpdAoJCQkvLyBpcy4gVGhpcyByZXN1bHRzIGluIHNsaWdodGx5IGRpZmZlcmVudCwgYnV0IEkgdGhpbmsgY29ycmVjdCBiZWhhdmlvdXIKCQkJaWYgKCBzY3JvbGxYICYmIHNjcm9sbFhJbm5lciApIHsKCQkJCXRtcFRhYmxlLndpZHRoKCBzY3JvbGxYSW5uZXIgKTsKCQkJfQoJCQllbHNlIGlmICggc2Nyb2xsWCApIHsKCQkJCXRtcFRhYmxlLmNzcyggJ3dpZHRoJywgJ2F1dG8nICk7CgkJCQl0bXBUYWJsZS5yZW1vdmVBdHRyKCd3aWR0aCcpOwoJCgkJCQkvLyBJZiB0aGVyZSBpcyBubyB3aWR0aCBhdHRyaWJ1dGUgb3Igc3R5bGUsIHRoZW4gYWxsb3cgdGhlIHRhYmxlIHRvCgkJCQkvLyBjb2xsYXBzZQoJCQkJaWYgKCB0bXBUYWJsZS53aWR0aCgpIDwgdGFibGVDb250YWluZXIuY2xpZW50V2lkdGggJiYgdGFibGVXaWR0aEF0dHIgKSB7CgkJCQkJdG1wVGFibGUud2lkdGgoIHRhYmxlQ29udGFpbmVyLmNsaWVudFdpZHRoICk7CgkJCQl9CgkJCX0KCQkJZWxzZSBpZiAoIHNjcm9sbFkgKSB7CgkJCQl0bXBUYWJsZS53aWR0aCggdGFibGVDb250YWluZXIuY2xpZW50V2lkdGggKTsKCQkJfQoJCQllbHNlIGlmICggdGFibGVXaWR0aEF0dHIgKSB7CgkJCQl0bXBUYWJsZS53aWR0aCggdGFibGVXaWR0aEF0dHIgKTsKCQkJfQoJCgkJCS8vIEdldCB0aGUgd2lkdGggb2YgZWFjaCBjb2x1bW4gaW4gdGhlIGNvbnN0cnVjdGVkIHRhYmxlIC0gd2UgbmVlZCB0bwoJCQkvLyBrbm93IHRoZSBpbm5lciB3aWR0aCAoc28gaXQgY2FuIGJlIGFzc2lnbmVkIHRvIHRoZSBvdGhlciB0YWJsZSdzCgkJCS8vIGNlbGxzKSBhbmQgdGhlIG91dGVyIHdpZHRoIHNvIHdlIGNhbiBjYWxjdWxhdGUgdGhlIGZ1bGwgd2lkdGggb2YgdGhlCgkJCS8vIHRhYmxlLiBUaGlzIGlzIHNhZmUgc2luY2UgRGF0YVRhYmxlcyByZXF1aXJlcyBhIHVuaXF1ZSBjZWxsIGZvciBlYWNoCgkJCS8vIGNvbHVtbiwgYnV0IGlmIGV2ZXIgYSBoZWFkZXIgY2FuIHNwYW4gbXVsdGlwbGUgY29sdW1ucywgdGhpcyB3aWxsCgkJCS8vIG5lZWQgdG8gYmUgbW9kaWZpZWQuCgkJCXZhciB0b3RhbCA9IDA7CgkJCWZvciAoIGk9MCA7IGk8dmlzaWJsZUNvbHVtbnMubGVuZ3RoIDsgaSsrICkgewoJCQkJdmFyIGNlbGwgPSAkKGhlYWRlckNlbGxzW2ldKTsKCQkJCXZhciBib3JkZXIgPSBjZWxsLm91dGVyV2lkdGgoKSAtIGNlbGwud2lkdGgoKTsKCQoJCQkJLy8gVXNlIGdldEJvdW5kaW5nLi4uIHdoZXJlIHBvc3NpYmxlIChub3QgSUU4LSkgYmVjYXVzZSBpdCBjYW4gZ2l2ZQoJCQkJLy8gc3ViLXBpeGVsIGFjY3VyYWN5LCB3aGljaCB3ZSB0aGVuIHdhbnQgdG8gcm91bmQgdXAhCgkJCQl2YXIgYm91bmRpbmcgPSBicm93c2VyLmJCb3VuZGluZyA/CgkJCQkJTWF0aC5jZWlsKCBoZWFkZXJDZWxsc1tpXS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aCApIDoKCQkJCQljZWxsLm91dGVyV2lkdGgoKTsKCQoJCQkJLy8gVG90YWwgaXMgdHJhY2tlZCB0byByZW1vdmUgYW55IHN1Yi1waXhlbCBlcnJvcnMgYXMgdGhlIG91dGVyV2lkdGgKCQkJCS8vIG9mIHRoZSB0YWJsZSBtaWdodCBub3QgZXF1YWwgdGhlIHRvdGFsIGdpdmVuIGhlcmUgKElFISkuCgkJCQl0b3RhbCArPSBib3VuZGluZzsKCQoJCQkJLy8gV2lkdGggZm9yIGVhY2ggY29sdW1uIHRvIHVzZQoJCQkJY29sdW1uc1sgdmlzaWJsZUNvbHVtbnNbaV0gXS5zV2lkdGggPSBfZm5TdHJpbmdUb0NzcyggYm91bmRpbmcgLSBib3JkZXIgKTsKCQkJfQoJCgkJCXRhYmxlLnN0eWxlLndpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIHRvdGFsICk7CgkKCQkJLy8gRmluaXNoZWQgd2l0aCB0aGUgdGFibGUgLSBkaXRjaCBpdAoJCQlob2xkZXIucmVtb3ZlKCk7CgkJfQoJCgkJLy8gSWYgdGhlcmUgaXMgYSB3aWR0aCBhdHRyLCB3ZSB3YW50IHRvIGF0dGFjaCBhbiBldmVudCBsaXN0ZW5lciB3aGljaAoJCS8vIGFsbG93cyB0aGUgdGFibGUgc2l6aW5nIHRvIGF1dG9tYXRpY2FsbHkgYWRqdXN0IHdoZW4gdGhlIHdpbmRvdyBpcwoJCS8vIHJlc2l6ZWQuIFVzZSB0aGUgd2lkdGggYXR0ciByYXRoZXIgdGhhbiBDU1MsIHNpbmNlIHdlIGNhbid0IGtub3cgaWYgdGhlCgkJLy8gQ1NTIGlzIGEgcmVsYXRpdmUgdmFsdWUgb3IgYWJzb2x1dGUgLSBET00gcmVhZCBpcyBhbHdheXMgcHguCgkJaWYgKCB0YWJsZVdpZHRoQXR0ciApIHsKCQkJdGFibGUuc3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyggdGFibGVXaWR0aEF0dHIgKTsKCQl9CgkKCQlpZiAoICh0YWJsZVdpZHRoQXR0ciB8fCBzY3JvbGxYKSAmJiAhIG9TZXR0aW5ncy5fcmVzekV2dCApIHsKCQkJdmFyIGJpbmRSZXNpemUgPSBmdW5jdGlvbiAoKSB7CgkJCQkkKHdpbmRvdykub24oJ3Jlc2l6ZS5EVC0nK29TZXR0aW5ncy5zSW5zdGFuY2UsIF9mblRocm90dGxlKCBmdW5jdGlvbiAoKSB7CgkJCQkJX2ZuQWRqdXN0Q29sdW1uU2l6aW5nKCBvU2V0dGluZ3MgKTsKCQkJCX0gKSApOwoJCQl9OwoJCgkJCS8vIElFNi83IHdpbGwgY3Jhc2ggaWYgd2UgYmluZCBhIHJlc2l6ZSBldmVudCBoYW5kbGVyIG9uIHBhZ2UgbG9hZC4KCQkJLy8gVG8gYmUgcmVtb3ZlZCBpbiAxLjExIHdoaWNoIGRyb3BzIElFNi83IHN1cHBvcnQKCQkJaWYgKCBpZTY3ICkgewoJCQkJc2V0VGltZW91dCggYmluZFJlc2l6ZSwgMTAwMCApOwoJCQl9CgkJCWVsc2UgewoJCQkJYmluZFJlc2l6ZSgpOwoJCQl9CgkKCQkJb1NldHRpbmdzLl9yZXN6RXZ0ID0gdHJ1ZTsKCQl9Cgl9CgkKCQoJLyoqCgkgKiBUaHJvdHRsZSB0aGUgY2FsbHMgdG8gYSBmdW5jdGlvbi4gQXJndW1lbnRzIGFuZCBjb250ZXh0IGFyZSBtYWludGFpbmVkIGZvcgoJICogdGhlIHRocm90dGxlZCBmdW5jdGlvbgoJICogIEBwYXJhbSB7ZnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZAoJICogIEBwYXJhbSB7aW50fSBbZnJlcT0yMDBdIGNhbGwgZnJlcXVlbmN5IGluIG1TCgkgKiAgQHJldHVybnMge2Z1bmN0aW9ufSB3cmFwcGVkIGZ1bmN0aW9uCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCXZhciBfZm5UaHJvdHRsZSA9IERhdGFUYWJsZS51dGlsLnRocm90dGxlOwoJCgkKCS8qKgoJICogQ29udmVydCBhIENTUyB1bml0IHdpZHRoIHRvIHBpeGVscyAoZS5nLiAyZW0pCgkgKiAgQHBhcmFtIHtzdHJpbmd9IHdpZHRoIHdpZHRoIHRvIGJlIGNvbnZlcnRlZAoJICogIEBwYXJhbSB7bm9kZX0gcGFyZW50IHBhcmVudCB0byBnZXQgdGhlIHdpdGggZm9yIChyZXF1aXJlZCBmb3IgcmVsYXRpdmUgd2lkdGhzKSAtIG9wdGlvbmFsCgkgKiAgQHJldHVybnMge2ludH0gd2lkdGggaW4gcGl4ZWxzCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkNvbnZlcnRUb1dpZHRoICggd2lkdGgsIHBhcmVudCApCgl7CgkJaWYgKCAhIHdpZHRoICkgewoJCQlyZXR1cm4gMDsKCQl9CgkKCQl2YXIgbiA9ICQoJzxkaXYvPicpCgkJCS5jc3MoICd3aWR0aCcsIF9mblN0cmluZ1RvQ3NzKCB3aWR0aCApICkKCQkJLmFwcGVuZFRvKCBwYXJlbnQgfHwgZG9jdW1lbnQuYm9keSApOwoJCgkJdmFyIHZhbCA9IG5bMF0ub2Zmc2V0V2lkdGg7CgkJbi5yZW1vdmUoKTsKCQoJCXJldHVybiB2YWw7Cgl9CgkKCQoJLyoqCgkgKiBHZXQgdGhlIHdpZGVzdCBub2RlCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIHtpbnR9IGNvbElkeCBjb2x1bW4gb2YgaW50ZXJlc3QKCSAqICBAcmV0dXJucyB7bm9kZX0gd2lkZXN0IHRhYmxlIG5vZGUKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuR2V0V2lkZXN0Tm9kZSggc2V0dGluZ3MsIGNvbElkeCApCgl7CgkJdmFyIGlkeCA9IF9mbkdldE1heExlblN0cmluZyggc2V0dGluZ3MsIGNvbElkeCApOwoJCWlmICggaWR4IDwgMCApIHsKCQkJcmV0dXJuIG51bGw7CgkJfQoJCgkJdmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGFbIGlkeCBdOwoJCXJldHVybiAhIGRhdGEublRyID8gLy8gTWlnaHQgbm90IGhhdmUgYmVlbiBjcmVhdGVkIHdoZW4gZGVmZXJyZWQgcmVuZGVyaW5nCgkJCSQoJzx0ZC8+JykuaHRtbCggX2ZuR2V0Q2VsbERhdGEoIHNldHRpbmdzLCBpZHgsIGNvbElkeCwgJ2Rpc3BsYXknICkgKVswXSA6CgkJCWRhdGEuYW5DZWxsc1sgY29sSWR4IF07Cgl9CgkKCQoJLyoqCgkgKiBHZXQgdGhlIG1heGltdW0gc3RybGVuIGZvciBlYWNoIGRhdGEgY29sdW1uCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIHtpbnR9IGNvbElkeCBjb2x1bW4gb2YgaW50ZXJlc3QKCSAqICBAcmV0dXJucyB7c3RyaW5nfSBtYXggc3RyaW5nIGxlbmd0aCBmb3IgZWFjaCBjb2x1bW4KCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuR2V0TWF4TGVuU3RyaW5nKCBzZXR0aW5ncywgY29sSWR4ICkKCXsKCQl2YXIgcywgbWF4PS0xLCBtYXhJZHggPSAtMTsKCQoJCWZvciAoIHZhciBpPTAsIGllbj1zZXR0aW5ncy5hb0RhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCXMgPSBfZm5HZXRDZWxsRGF0YSggc2V0dGluZ3MsIGksIGNvbElkeCwgJ2Rpc3BsYXknICkrJyc7CgkJCXMgPSBzLnJlcGxhY2UoIF9fcmVfaHRtbF9yZW1vdmUsICcnICk7CgkJCXMgPSBzLnJlcGxhY2UoIC8mbmJzcDsvZywgJyAnICk7CgkKCQkJaWYgKCBzLmxlbmd0aCA+IG1heCApIHsKCQkJCW1heCA9IHMubGVuZ3RoOwoJCQkJbWF4SWR4ID0gaTsKCQkJfQoJCX0KCQoJCXJldHVybiBtYXhJZHg7Cgl9CgkKCQoJLyoqCgkgKiBBcHBlbmQgYSBDU1MgdW5pdCAob25seSBpZiByZXF1aXJlZCkgdG8gYSBzdHJpbmcKCSAqICBAcGFyYW0ge3N0cmluZ30gdmFsdWUgdG8gY3NzLWlmeQoJICogIEByZXR1cm5zIHtzdHJpbmd9IHZhbHVlIHdpdGggY3NzIHVuaXQKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuU3RyaW5nVG9Dc3MoIHMgKQoJewoJCWlmICggcyA9PT0gbnVsbCApIHsKCQkJcmV0dXJuICcwcHgnOwoJCX0KCQoJCWlmICggdHlwZW9mIHMgPT0gJ251bWJlcicgKSB7CgkJCXJldHVybiBzIDwgMCA/CgkJCQknMHB4JyA6CgkJCQlzKydweCc7CgkJfQoJCgkJLy8gQ2hlY2sgaXQgaGFzIGEgdW5pdCBjaGFyYWN0ZXIgYWxyZWFkeQoJCXJldHVybiBzLm1hdGNoKC9cZCQvKSA/CgkJCXMrJ3B4JyA6CgkJCXM7Cgl9CgkKCQoJCglmdW5jdGlvbiBfZm5Tb3J0RmxhdHRlbiAoIHNldHRpbmdzICkKCXsKCQl2YXIKCQkJaSwgaUxlbiwgaywga0xlbiwKCQkJYVNvcnQgPSBbXSwKCQkJYWlPcmlnID0gW10sCgkJCWFvQ29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1ucywKCQkJYURhdGFTb3J0LCBpQ29sLCBzVHlwZSwgc3JjQ29sLAoJCQlmaXhlZCA9IHNldHRpbmdzLmFhU29ydGluZ0ZpeGVkLAoJCQlmaXhlZE9iaiA9ICQuaXNQbGFpbk9iamVjdCggZml4ZWQgKSwKCQkJbmVzdGVkU29ydCA9IFtdLAoJCQlhZGQgPSBmdW5jdGlvbiAoIGEgKSB7CgkJCQlpZiAoIGEubGVuZ3RoICYmICEgQXJyYXkuaXNBcnJheSggYVswXSApICkgewoJCQkJCS8vIDFEIGFycmF5CgkJCQkJbmVzdGVkU29ydC5wdXNoKCBhICk7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQkvLyAyRCBhcnJheQoJCQkJCSQubWVyZ2UoIG5lc3RlZFNvcnQsIGEgKTsKCQkJCX0KCQkJfTsKCQoJCS8vIEJ1aWxkIHRoZSBzb3J0IGFycmF5LCB3aXRoIHByZS1maXggYW5kIHBvc3QtZml4IG9wdGlvbnMgaWYgdGhleSBoYXZlIGJlZW4KCQkvLyBzcGVjaWZpZWQKCQlpZiAoIEFycmF5LmlzQXJyYXkoIGZpeGVkICkgKSB7CgkJCWFkZCggZml4ZWQgKTsKCQl9CgkKCQlpZiAoIGZpeGVkT2JqICYmIGZpeGVkLnByZSApIHsKCQkJYWRkKCBmaXhlZC5wcmUgKTsKCQl9CgkKCQlhZGQoIHNldHRpbmdzLmFhU29ydGluZyApOwoJCgkJaWYgKGZpeGVkT2JqICYmIGZpeGVkLnBvc3QgKSB7CgkJCWFkZCggZml4ZWQucG9zdCApOwoJCX0KCQoJCWZvciAoIGk9MCA7IGk8bmVzdGVkU29ydC5sZW5ndGggOyBpKysgKQoJCXsKCQkJc3JjQ29sID0gbmVzdGVkU29ydFtpXVswXTsKCQkJYURhdGFTb3J0ID0gYW9Db2x1bW5zWyBzcmNDb2wgXS5hRGF0YVNvcnQ7CgkKCQkJZm9yICggaz0wLCBrTGVuPWFEYXRhU29ydC5sZW5ndGggOyBrPGtMZW4gOyBrKysgKQoJCQl7CgkJCQlpQ29sID0gYURhdGFTb3J0W2tdOwoJCQkJc1R5cGUgPSBhb0NvbHVtbnNbIGlDb2wgXS5zVHlwZSB8fCAnc3RyaW5nJzsKCQoJCQkJaWYgKCBuZXN0ZWRTb3J0W2ldLl9pZHggPT09IHVuZGVmaW5lZCApIHsKCQkJCQluZXN0ZWRTb3J0W2ldLl9pZHggPSAkLmluQXJyYXkoIG5lc3RlZFNvcnRbaV1bMV0sIGFvQ29sdW1uc1tpQ29sXS5hc1NvcnRpbmcgKTsKCQkJCX0KCQoJCQkJYVNvcnQucHVzaCggewoJCQkJCXNyYzogICAgICAgc3JjQ29sLAoJCQkJCWNvbDogICAgICAgaUNvbCwKCQkJCQlkaXI6ICAgICAgIG5lc3RlZFNvcnRbaV1bMV0sCgkJCQkJaW5kZXg6ICAgICBuZXN0ZWRTb3J0W2ldLl9pZHgsCgkJCQkJdHlwZTogICAgICBzVHlwZSwKCQkJCQlmb3JtYXR0ZXI6IERhdGFUYWJsZS5leHQudHlwZS5vcmRlclsgc1R5cGUrIi1wcmUiIF0KCQkJCX0gKTsKCQkJfQoJCX0KCQoJCXJldHVybiBhU29ydDsKCX0KCQoJLyoqCgkgKiBDaGFuZ2UgdGhlIG9yZGVyIG9mIHRoZSB0YWJsZQoJICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqICBAdG9kbyBUaGlzIHJlYWxseSBuZWVkcyBzcGxpdCB1cCEKCSAqLwoJZnVuY3Rpb24gX2ZuU29ydCAoIG9TZXR0aW5ncyApCgl7CgkJdmFyCgkJCWksIGllbiwgaUxlbiwgaiwgakxlbiwgaywga0xlbiwKCQkJc0RhdGFUeXBlLCBuVGgsCgkJCWFpT3JpZyA9IFtdLAoJCQlvRXh0U29ydCA9IERhdGFUYWJsZS5leHQudHlwZS5vcmRlciwKCQkJYW9EYXRhID0gb1NldHRpbmdzLmFvRGF0YSwKCQkJYW9Db2x1bW5zID0gb1NldHRpbmdzLmFvQ29sdW1ucywKCQkJYURhdGFTb3J0LCBkYXRhLCBpQ29sLCBzVHlwZSwgb1NvcnQsCgkJCWZvcm1hdHRlcnMgPSAwLAoJCQlzb3J0Q29sLAoJCQlkaXNwbGF5TWFzdGVyID0gb1NldHRpbmdzLmFpRGlzcGxheU1hc3RlciwKCQkJYVNvcnQ7CgkKCQkvLyBSZXNvbHZlIGFueSBjb2x1bW4gdHlwZXMgdGhhdCBhcmUgdW5rbm93biBkdWUgdG8gYWRkaXRpb24gb3IgaW52YWxpZGF0aW9uCgkJLy8gQHRvZG8gQ2FuIHRoaXMgYmUgbW92ZWQgaW50byBhICdkYXRhLXJlYWR5JyBoYW5kbGVyIHdoaWNoIGlzIGNhbGxlZCB3aGVuCgkJLy8gICBkYXRhIGlzIGdvaW5nIHRvIGJlIHVzZWQgaW4gdGhlIHRhYmxlPwoJCV9mbkNvbHVtblR5cGVzKCBvU2V0dGluZ3MgKTsKCQoJCWFTb3J0ID0gX2ZuU29ydEZsYXR0ZW4oIG9TZXR0aW5ncyApOwoJCgkJZm9yICggaT0wLCBpZW49YVNvcnQubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCXNvcnRDb2wgPSBhU29ydFtpXTsKCQoJCQkvLyBUcmFjayBpZiB3ZSBjYW4gdXNlIHRoZSBmYXN0IHNvcnQgYWxnb3JpdGhtCgkJCWlmICggc29ydENvbC5mb3JtYXR0ZXIgKSB7CgkJCQlmb3JtYXR0ZXJzKys7CgkJCX0KCQoJCQkvLyBMb2FkIHRoZSBkYXRhIG5lZWRlZCBmb3IgdGhlIHNvcnQsIGZvciBlYWNoIGNlbGwKCQkJX2ZuU29ydERhdGEoIG9TZXR0aW5ncywgc29ydENvbC5jb2wgKTsKCQl9CgkKCQkvKiBObyBzb3J0aW5nIHJlcXVpcmVkIGlmIHNlcnZlci1zaWRlIG9yIG5vIHNvcnRpbmcgYXJyYXkgKi8KCQlpZiAoIF9mbkRhdGFTb3VyY2UoIG9TZXR0aW5ncyApICE9ICdzc3AnICYmIGFTb3J0Lmxlbmd0aCAhPT0gMCApCgkJewoJCQkvLyBDcmVhdGUgYSB2YWx1ZSAtIGtleSBhcnJheSBvZiB0aGUgY3VycmVudCByb3cgcG9zaXRpb25zIHN1Y2ggdGhhdCB3ZSBjYW4gdXNlIHRoZWlyCgkJCS8vIGN1cnJlbnQgcG9zaXRpb24gZHVyaW5nIHRoZSBzb3J0LCBpZiB2YWx1ZXMgbWF0Y2gsIGluIG9yZGVyIHRvIHBlcmZvcm0gc3RhYmxlIHNvcnRpbmcKCQkJZm9yICggaT0wLCBpTGVuPWRpc3BsYXlNYXN0ZXIubGVuZ3RoIDsgaTxpTGVuIDsgaSsrICkgewoJCQkJYWlPcmlnWyBkaXNwbGF5TWFzdGVyW2ldIF0gPSBpOwoJCQl9CgkKCQkJLyogRG8gdGhlIHNvcnQgLSBoZXJlIHdlIHdhbnQgbXVsdGktY29sdW1uIHNvcnRpbmcgYmFzZWQgb24gYSBnaXZlbiBkYXRhIHNvdXJjZSAoY29sdW1uKQoJCQkgKiBhbmQgc29ydGluZyBmdW5jdGlvbiAoZnJvbSBvU29ydCkgaW4gYSBjZXJ0YWluIGRpcmVjdGlvbi4gSXQncyByZWFzb25hYmx5IGNvbXBsZXggdG8KCQkJICogZm9sbG93IG9uIGl0J3Mgb3duLCBidXQgdGhpcyBpcyB3aGF0IHdlIHdhbnQgKGV4YW1wbGUgdHdvIGNvbHVtbiBzb3J0aW5nKToKCQkJICogIGZuTG9jYWxTb3J0aW5nID0gZnVuY3Rpb24oYSxiKXsKCQkJICogICAgdmFyIGlUZXN0OwoJCQkgKiAgICBpVGVzdCA9IG9Tb3J0WydzdHJpbmctYXNjJ10oJ2RhdGExMScsICdkYXRhMTInKTsKCQkJICogICAgICBpZiAoaVRlc3QgIT09IDApCgkJCSAqICAgICAgICByZXR1cm4gaVRlc3Q7CgkJCSAqICAgIGlUZXN0ID0gb1NvcnRbJ251bWVyaWMtZGVzYyddKCdkYXRhMjEnLCAnZGF0YTIyJyk7CgkJCSAqICAgIGlmIChpVGVzdCAhPT0gMCkKCQkJICogICAgICByZXR1cm4gaVRlc3Q7CgkJCSAqICAgIHJldHVybiBvU29ydFsnbnVtZXJpYy1hc2MnXSggYWlPcmlnW2FdLCBhaU9yaWdbYl0gKTsKCQkJICogIH0KCQkJICogQmFzaWNhbGx5IHdlIGhhdmUgYSB0ZXN0IGZvciBlYWNoIHNvcnRpbmcgY29sdW1uLCBpZiB0aGUgZGF0YSBpbiB0aGF0IGNvbHVtbiBpcyBlcXVhbCwKCQkJICogdGVzdCB0aGUgbmV4dCBjb2x1bW4uIElmIGFsbCBjb2x1bW5zIG1hdGNoLCB0aGVuIHdlIHVzZSBhIG51bWVyaWMgc29ydCBvbiB0aGUgcm93CgkJCSAqIHBvc2l0aW9ucyBpbiB0aGUgb3JpZ2luYWwgZGF0YSBhcnJheSB0byBwcm92aWRlIGEgc3RhYmxlIHNvcnQuCgkJCSAqCgkJCSAqIE5vdGUgLSBJIGtub3cgaXQgc2VlbXMgZXhjZXNzaXZlIHRvIGhhdmUgdHdvIHNvcnRpbmcgbWV0aG9kcywgYnV0IHRoZSBmaXJzdCBpcyBhcm91bmQKCQkJICogMTUlIGZhc3Rlciwgc28gdGhlIHNlY29uZCBpcyBvbmx5IG1haW50YWluZWQgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggc29ydGluZwoJCQkgKiBtZXRob2RzIHdoaWNoIGRvIG5vdCBoYXZlIGEgcHJlLXNvcnQgZm9ybWF0dGluZyBmdW5jdGlvbi4KCQkJICovCgkJCWlmICggZm9ybWF0dGVycyA9PT0gYVNvcnQubGVuZ3RoICkgewoJCQkJLy8gQWxsIHNvcnQgdHlwZXMgaGF2ZSBmb3JtYXR0aW5nIGZ1bmN0aW9ucwoJCQkJZGlzcGxheU1hc3Rlci5zb3J0KCBmdW5jdGlvbiAoIGEsIGIgKSB7CgkJCQkJdmFyCgkJCQkJCXgsIHksIGssIHRlc3QsIHNvcnQsCgkJCQkJCWxlbj1hU29ydC5sZW5ndGgsCgkJCQkJCWRhdGFBID0gYW9EYXRhW2FdLl9hU29ydERhdGEsCgkJCQkJCWRhdGFCID0gYW9EYXRhW2JdLl9hU29ydERhdGE7CgkKCQkJCQlmb3IgKCBrPTAgOyBrPGxlbiA7IGsrKyApIHsKCQkJCQkJc29ydCA9IGFTb3J0W2tdOwoJCgkJCQkJCXggPSBkYXRhQVsgc29ydC5jb2wgXTsKCQkJCQkJeSA9IGRhdGFCWyBzb3J0LmNvbCBdOwoJCgkJCQkJCXRlc3QgPSB4PHkgPyAtMSA6IHg+eSA/IDEgOiAwOwoJCQkJCQlpZiAoIHRlc3QgIT09IDAgKSB7CgkJCQkJCQlyZXR1cm4gc29ydC5kaXIgPT09ICdhc2MnID8gdGVzdCA6IC10ZXN0OwoJCQkJCQl9CgkJCQkJfQoJCgkJCQkJeCA9IGFpT3JpZ1thXTsKCQkJCQl5ID0gYWlPcmlnW2JdOwoJCQkJCXJldHVybiB4PHkgPyAtMSA6IHg+eSA/IDEgOiAwOwoJCQkJfSApOwoJCQl9CgkJCWVsc2UgewoJCQkJLy8gRGVwcmVjaWF0ZWQgLSByZW1vdmUgaW4gMS4xMSAocHJvdmlkaW5nIGEgcGx1Zy1pbiBvcHRpb24pCgkJCQkvLyBOb3QgYWxsIHNvcnQgdHlwZXMgaGF2ZSBmb3JtYXR0aW5nIG1ldGhvZHMsIHNvIHdlIGhhdmUgdG8gY2FsbCB0aGVpciBzb3J0aW5nCgkJCQkvLyBtZXRob2RzLgoJCQkJZGlzcGxheU1hc3Rlci5zb3J0KCBmdW5jdGlvbiAoIGEsIGIgKSB7CgkJCQkJdmFyCgkJCQkJCXgsIHksIGssIGwsIHRlc3QsIHNvcnQsIGZuLAoJCQkJCQlsZW49YVNvcnQubGVuZ3RoLAoJCQkJCQlkYXRhQSA9IGFvRGF0YVthXS5fYVNvcnREYXRhLAoJCQkJCQlkYXRhQiA9IGFvRGF0YVtiXS5fYVNvcnREYXRhOwoJCgkJCQkJZm9yICggaz0wIDsgazxsZW4gOyBrKysgKSB7CgkJCQkJCXNvcnQgPSBhU29ydFtrXTsKCQoJCQkJCQl4ID0gZGF0YUFbIHNvcnQuY29sIF07CgkJCQkJCXkgPSBkYXRhQlsgc29ydC5jb2wgXTsKCQoJCQkJCQlmbiA9IG9FeHRTb3J0WyBzb3J0LnR5cGUrIi0iK3NvcnQuZGlyIF0gfHwgb0V4dFNvcnRbICJzdHJpbmctIitzb3J0LmRpciBdOwoJCQkJCQl0ZXN0ID0gZm4oIHgsIHkgKTsKCQkJCQkJaWYgKCB0ZXN0ICE9PSAwICkgewoJCQkJCQkJcmV0dXJuIHRlc3Q7CgkJCQkJCX0KCQkJCQl9CgkKCQkJCQl4ID0gYWlPcmlnW2FdOwoJCQkJCXkgPSBhaU9yaWdbYl07CgkJCQkJcmV0dXJuIHg8eSA/IC0xIDogeD55ID8gMSA6IDA7CgkJCQl9ICk7CgkJCX0KCQl9CgkKCQkvKiBUZWxsIHRoZSBkcmF3IGZ1bmN0aW9uIHRoYXQgd2UgaGF2ZSBzb3J0ZWQgdGhlIGRhdGEgKi8KCQlvU2V0dGluZ3MuYlNvcnRlZCA9IHRydWU7Cgl9CgkKCQoJZnVuY3Rpb24gX2ZuU29ydEFyaWEgKCBzZXR0aW5ncyApCgl7CgkJdmFyIGxhYmVsOwoJCXZhciBuZXh0U29ydDsKCQl2YXIgY29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1uczsKCQl2YXIgYVNvcnQgPSBfZm5Tb3J0RmxhdHRlbiggc2V0dGluZ3MgKTsKCQl2YXIgb0FyaWEgPSBzZXR0aW5ncy5vTGFuZ3VhZ2Uub0FyaWE7CgkKCQkvLyBBUklBIGF0dHJpYnV0ZXMgLSBuZWVkIHRvIGxvb3AgYWxsIGNvbHVtbnMsIHRvIHVwZGF0ZSBhbGwgKHJlbW92aW5nIG9sZAoJCS8vIGF0dHJpYnV0ZXMgYXMgbmVlZGVkKQoJCWZvciAoIHZhciBpPTAsIGlMZW49Y29sdW1ucy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKQoJCXsKCQkJdmFyIGNvbCA9IGNvbHVtbnNbaV07CgkJCXZhciBhc1NvcnRpbmcgPSBjb2wuYXNTb3J0aW5nOwoJCQl2YXIgc1RpdGxlID0gY29sLmFyaWFUaXRsZSB8fCBjb2wuc1RpdGxlLnJlcGxhY2UoIC88Lio/Pi9nLCAiIiApOwoJCQl2YXIgdGggPSBjb2wublRoOwoJCgkJCS8vIElFNyBpcyB0aHJvd2luZyBhbiBlcnJvciB3aGVuIHNldHRpbmcgdGhlc2UgcHJvcGVydGllcyB3aXRoIGpRdWVyeSdzCgkJCS8vIGF0dHIoKSBhbmQgcmVtb3ZlQXR0cigpIG1ldGhvZHMuLi4KCQkJdGgucmVtb3ZlQXR0cmlidXRlKCdhcmlhLXNvcnQnKTsKCQoJCQkvKiBJbiBBUklBIG9ubHkgdGhlIGZpcnN0IHNvcnRpbmcgY29sdW1uIGNhbiBiZSBtYXJrZWQgYXMgc29ydGluZyAtIG5vIG11bHRpLXNvcnQgb3B0aW9uICovCgkJCWlmICggY29sLmJTb3J0YWJsZSApIHsKCQkJCWlmICggYVNvcnQubGVuZ3RoID4gMCAmJiBhU29ydFswXS5jb2wgPT0gaSApIHsKCQkJCQl0aC5zZXRBdHRyaWJ1dGUoJ2FyaWEtc29ydCcsIGFTb3J0WzBdLmRpcj09ImFzYyIgPyAiYXNjZW5kaW5nIiA6ICJkZXNjZW5kaW5nIiApOwoJCQkJCW5leHRTb3J0ID0gYXNTb3J0aW5nWyBhU29ydFswXS5pbmRleCsxIF0gfHwgYXNTb3J0aW5nWzBdOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJbmV4dFNvcnQgPSBhc1NvcnRpbmdbMF07CgkJCQl9CgkKCQkJCWxhYmVsID0gc1RpdGxlICsgKCBuZXh0U29ydCA9PT0gImFzYyIgPwoJCQkJCW9BcmlhLnNTb3J0QXNjZW5kaW5nIDoKCQkJCQlvQXJpYS5zU29ydERlc2NlbmRpbmcKCQkJCSk7CgkJCX0KCQkJZWxzZSB7CgkJCQlsYWJlbCA9IHNUaXRsZTsKCQkJfQoJCgkJCXRoLnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcsIGxhYmVsKTsKCQl9Cgl9CgkKCQoJLyoqCgkgKiBGdW5jdGlvbiB0byBydW4gb24gdXNlciBzb3J0IHJlcXVlc3QKCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICBAcGFyYW0ge25vZGV9IGF0dGFjaFRvIG5vZGUgdG8gYXR0YWNoIHRoZSBoYW5kbGVyIHRvCgkgKiAgQHBhcmFtIHtpbnR9IGNvbElkeCBjb2x1bW4gc29ydGluZyBpbmRleAoJICogIEBwYXJhbSB7Ym9vbGVhbn0gW2FwcGVuZD1mYWxzZV0gQXBwZW5kIHRoZSByZXF1ZXN0ZWQgc29ydCB0byB0aGUgZXhpc3RpbmcKCSAqICAgIHNvcnQgaWYgdHJ1ZSAoaS5lLiBtdWx0aS1jb2x1bW4gc29ydCkKCSAqICBAcGFyYW0ge2Z1bmN0aW9ufSBbY2FsbGJhY2tdIGNhbGxiYWNrIGZ1bmN0aW9uCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mblNvcnRMaXN0ZW5lciAoIHNldHRpbmdzLCBjb2xJZHgsIGFwcGVuZCwgY2FsbGJhY2sgKQoJewoJCXZhciBjb2wgPSBzZXR0aW5ncy5hb0NvbHVtbnNbIGNvbElkeCBdOwoJCXZhciBzb3J0aW5nID0gc2V0dGluZ3MuYWFTb3J0aW5nOwoJCXZhciBhc1NvcnRpbmcgPSBjb2wuYXNTb3J0aW5nOwoJCXZhciBuZXh0U29ydElkeDsKCQl2YXIgbmV4dCA9IGZ1bmN0aW9uICggYSwgb3ZlcmZsb3cgKSB7CgkJCXZhciBpZHggPSBhLl9pZHg7CgkJCWlmICggaWR4ID09PSB1bmRlZmluZWQgKSB7CgkJCQlpZHggPSAkLmluQXJyYXkoIGFbMV0sIGFzU29ydGluZyApOwoJCQl9CgkKCQkJcmV0dXJuIGlkeCsxIDwgYXNTb3J0aW5nLmxlbmd0aCA/CgkJCQlpZHgrMSA6CgkJCQlvdmVyZmxvdyA/CgkJCQkJbnVsbCA6CgkJCQkJMDsKCQl9OwoJCgkJLy8gQ29udmVydCB0byAyRCBhcnJheSBpZiBuZWVkZWQKCQlpZiAoIHR5cGVvZiBzb3J0aW5nWzBdID09PSAnbnVtYmVyJyApIHsKCQkJc29ydGluZyA9IHNldHRpbmdzLmFhU29ydGluZyA9IFsgc29ydGluZyBdOwoJCX0KCQoJCS8vIElmIGFwcGVuZGluZyB0aGUgc29ydCB0aGVuIHdlIGFyZSBtdWx0aS1jb2x1bW4gc29ydGluZwoJCWlmICggYXBwZW5kICYmIHNldHRpbmdzLm9GZWF0dXJlcy5iU29ydE11bHRpICkgewoJCQkvLyBBcmUgd2UgYWxyZWFkeSBkb2luZyBzb21lIGtpbmQgb2Ygc29ydCBvbiB0aGlzIGNvbHVtbj8KCQkJdmFyIHNvcnRJZHggPSAkLmluQXJyYXkoIGNvbElkeCwgX3BsdWNrKHNvcnRpbmcsICcwJykgKTsKCQoJCQlpZiAoIHNvcnRJZHggIT09IC0xICkgewoJCQkJLy8gWWVzLCBtb2RpZnkgdGhlIHNvcnQKCQkJCW5leHRTb3J0SWR4ID0gbmV4dCggc29ydGluZ1tzb3J0SWR4XSwgdHJ1ZSApOwoJCgkJCQlpZiAoIG5leHRTb3J0SWR4ID09PSBudWxsICYmIHNvcnRpbmcubGVuZ3RoID09PSAxICkgewoJCQkJCW5leHRTb3J0SWR4ID0gMDsgLy8gY2FuJ3QgcmVtb3ZlIHNvcnRpbmcgY29tcGxldGVseQoJCQkJfQoJCgkJCQlpZiAoIG5leHRTb3J0SWR4ID09PSBudWxsICkgewoJCQkJCXNvcnRpbmcuc3BsaWNlKCBzb3J0SWR4LCAxICk7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlzb3J0aW5nW3NvcnRJZHhdWzFdID0gYXNTb3J0aW5nWyBuZXh0U29ydElkeCBdOwoJCQkJCXNvcnRpbmdbc29ydElkeF0uX2lkeCA9IG5leHRTb3J0SWR4OwoJCQkJfQoJCQl9CgkJCWVsc2UgewoJCQkJLy8gTm8gc29ydCBvbiB0aGlzIGNvbHVtbiB5ZXQKCQkJCXNvcnRpbmcucHVzaCggWyBjb2xJZHgsIGFzU29ydGluZ1swXSwgMCBdICk7CgkJCQlzb3J0aW5nW3NvcnRpbmcubGVuZ3RoLTFdLl9pZHggPSAwOwoJCQl9CgkJfQoJCWVsc2UgaWYgKCBzb3J0aW5nLmxlbmd0aCAmJiBzb3J0aW5nWzBdWzBdID09IGNvbElkeCApIHsKCQkJLy8gU2luZ2xlIGNvbHVtbiAtIGFscmVhZHkgc29ydGluZyBvbiB0aGlzIGNvbHVtbiwgbW9kaWZ5IHRoZSBzb3J0CgkJCW5leHRTb3J0SWR4ID0gbmV4dCggc29ydGluZ1swXSApOwoJCgkJCXNvcnRpbmcubGVuZ3RoID0gMTsKCQkJc29ydGluZ1swXVsxXSA9IGFzU29ydGluZ1sgbmV4dFNvcnRJZHggXTsKCQkJc29ydGluZ1swXS5faWR4ID0gbmV4dFNvcnRJZHg7CgkJfQoJCWVsc2UgewoJCQkvLyBTaW5nbGUgY29sdW1uIC0gc29ydCBvbmx5IG9uIHRoaXMgY29sdW1uCgkJCXNvcnRpbmcubGVuZ3RoID0gMDsKCQkJc29ydGluZy5wdXNoKCBbIGNvbElkeCwgYXNTb3J0aW5nWzBdIF0gKTsKCQkJc29ydGluZ1swXS5faWR4ID0gMDsKCQl9CgkKCQkvLyBSdW4gdGhlIHNvcnQgYnkgY2FsbGluZyBhIGZ1bGwgcmVkcmF3CgkJX2ZuUmVEcmF3KCBzZXR0aW5ncyApOwoJCgkJLy8gY2FsbGJhY2sgdXNlZCBmb3IgYXN5bmMgdXNlciBpbnRlcmFjdGlvbgoJCWlmICggdHlwZW9mIGNhbGxiYWNrID09ICdmdW5jdGlvbicgKSB7CgkJCWNhbGxiYWNrKCBzZXR0aW5ncyApOwoJCX0KCX0KCQoJCgkvKioKCSAqIEF0dGFjaCBhIHNvcnQgaGFuZGxlciAoY2xpY2spIHRvIGEgbm9kZQoJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7bm9kZX0gYXR0YWNoVG8gbm9kZSB0byBhdHRhY2ggdGhlIGhhbmRsZXIgdG8KCSAqICBAcGFyYW0ge2ludH0gY29sSWR4IGNvbHVtbiBzb3J0aW5nIGluZGV4CgkgKiAgQHBhcmFtIHtmdW5jdGlvbn0gW2NhbGxiYWNrXSBjYWxsYmFjayBmdW5jdGlvbgoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5Tb3J0QXR0YWNoTGlzdGVuZXIgKCBzZXR0aW5ncywgYXR0YWNoVG8sIGNvbElkeCwgY2FsbGJhY2sgKQoJewoJCXZhciBjb2wgPSBzZXR0aW5ncy5hb0NvbHVtbnNbIGNvbElkeCBdOwoJCgkJX2ZuQmluZEFjdGlvbiggYXR0YWNoVG8sIHt9LCBmdW5jdGlvbiAoZSkgewoJCQkvKiBJZiB0aGUgY29sdW1uIGlzIG5vdCBzb3J0YWJsZSAtIGRvbid0IHRvIGFueXRoaW5nICovCgkJCWlmICggY29sLmJTb3J0YWJsZSA9PT0gZmFsc2UgKSB7CgkJCQlyZXR1cm47CgkJCX0KCQoJCQkvLyBJZiBwcm9jZXNzaW5nIGlzIGVuYWJsZWQgdXNlIGEgdGltZW91dCB0byBhbGxvdyB0aGUgcHJvY2Vzc2luZwoJCQkvLyBkaXNwbGF5IHRvIGJlIHNob3duIC0gb3RoZXJ3aXNlIHRvIGl0IHN5bmNocm9ub3VzbHkKCQkJaWYgKCBzZXR0aW5ncy5vRmVhdHVyZXMuYlByb2Nlc3NpbmcgKSB7CgkJCQlfZm5Qcm9jZXNzaW5nRGlzcGxheSggc2V0dGluZ3MsIHRydWUgKTsKCQoJCQkJc2V0VGltZW91dCggZnVuY3Rpb24oKSB7CgkJCQkJX2ZuU29ydExpc3RlbmVyKCBzZXR0aW5ncywgY29sSWR4LCBlLnNoaWZ0S2V5LCBjYWxsYmFjayApOwoJCgkJCQkJLy8gSW4gc2VydmVyLXNpZGUgcHJvY2Vzc2luZywgdGhlIGRyYXcgY2FsbGJhY2sgd2lsbCByZW1vdmUgdGhlCgkJCQkJLy8gcHJvY2Vzc2luZyBkaXNwbGF5CgkJCQkJaWYgKCBfZm5EYXRhU291cmNlKCBzZXR0aW5ncyApICE9PSAnc3NwJyApIHsKCQkJCQkJX2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIHNldHRpbmdzLCBmYWxzZSApOwoJCQkJCX0KCQkJCX0sIDAgKTsKCQkJfQoJCQllbHNlIHsKCQkJCV9mblNvcnRMaXN0ZW5lciggc2V0dGluZ3MsIGNvbElkeCwgZS5zaGlmdEtleSwgY2FsbGJhY2sgKTsKCQkJfQoJCX0gKTsKCX0KCQoJCgkvKioKCSAqIFNldCB0aGUgc29ydGluZyBjbGFzc2VzIG9uIHRhYmxlJ3MgYm9keSwgTm90ZTogaXQgaXMgc2FmZSB0byBjYWxsIHRoaXMgZnVuY3Rpb24KCSAqIHdoZW4gYlNvcnQgYW5kIGJTb3J0Q2xhc3NlcyBhcmUgZmFsc2UKCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mblNvcnRpbmdDbGFzc2VzKCBzZXR0aW5ncyApCgl7CgkJdmFyIG9sZFNvcnQgPSBzZXR0aW5ncy5hTGFzdFNvcnQ7CgkJdmFyIHNvcnRDbGFzcyA9IHNldHRpbmdzLm9DbGFzc2VzLnNTb3J0Q29sdW1uOwoJCXZhciBzb3J0ID0gX2ZuU29ydEZsYXR0ZW4oIHNldHRpbmdzICk7CgkJdmFyIGZlYXR1cmVzID0gc2V0dGluZ3Mub0ZlYXR1cmVzOwoJCXZhciBpLCBpZW4sIGNvbElkeDsKCQoJCWlmICggZmVhdHVyZXMuYlNvcnQgJiYgZmVhdHVyZXMuYlNvcnRDbGFzc2VzICkgewoJCQkvLyBSZW1vdmUgb2xkIHNvcnRpbmcgY2xhc3NlcwoJCQlmb3IgKCBpPTAsIGllbj1vbGRTb3J0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJY29sSWR4ID0gb2xkU29ydFtpXS5zcmM7CgkKCQkJCS8vIFJlbW92ZSBjb2x1bW4gc29ydGluZwoJCQkJJCggX3BsdWNrKCBzZXR0aW5ncy5hb0RhdGEsICdhbkNlbGxzJywgY29sSWR4ICkgKQoJCQkJCS5yZW1vdmVDbGFzcyggc29ydENsYXNzICsgKGk8MiA/IGkrMSA6IDMpICk7CgkJCX0KCQoJCQkvLyBBZGQgbmV3IGNvbHVtbiBzb3J0aW5nCgkJCWZvciAoIGk9MCwgaWVuPXNvcnQubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQljb2xJZHggPSBzb3J0W2ldLnNyYzsKCQoJCQkJJCggX3BsdWNrKCBzZXR0aW5ncy5hb0RhdGEsICdhbkNlbGxzJywgY29sSWR4ICkgKQoJCQkJCS5hZGRDbGFzcyggc29ydENsYXNzICsgKGk8MiA/IGkrMSA6IDMpICk7CgkJCX0KCQl9CgkKCQlzZXR0aW5ncy5hTGFzdFNvcnQgPSBzb3J0OwoJfQoJCgkKCS8vIEdldCB0aGUgZGF0YSB0byBzb3J0IGEgY29sdW1uLCBiZSBpdCBmcm9tIGNhY2hlLCBmcmVzaCAocG9wdWxhdGluZyB0aGUKCS8vIGNhY2hlKSwgb3IgZnJvbSBhIHNvcnQgZm9ybWF0dGVyCglmdW5jdGlvbiBfZm5Tb3J0RGF0YSggc2V0dGluZ3MsIGlkeCApCgl7CgkJLy8gQ3VzdG9tIHNvcnRpbmcgZnVuY3Rpb24gLSBwcm92aWRlZCBieSB0aGUgc29ydCBkYXRhIHR5cGUKCQl2YXIgY29sdW1uID0gc2V0dGluZ3MuYW9Db2x1bW5zWyBpZHggXTsKCQl2YXIgY3VzdG9tU29ydCA9IERhdGFUYWJsZS5leHQub3JkZXJbIGNvbHVtbi5zU29ydERhdGFUeXBlIF07CgkJdmFyIGN1c3RvbURhdGE7CgkKCQlpZiAoIGN1c3RvbVNvcnQgKSB7CgkJCWN1c3RvbURhdGEgPSBjdXN0b21Tb3J0LmNhbGwoIHNldHRpbmdzLm9JbnN0YW5jZSwgc2V0dGluZ3MsIGlkeCwKCQkJCV9mbkNvbHVtbkluZGV4VG9WaXNpYmxlKCBzZXR0aW5ncywgaWR4ICkKCQkJKTsKCQl9CgkKCQkvLyBVc2UgLyBwb3B1bGF0ZSBjYWNoZQoJCXZhciByb3csIGNlbGxEYXRhOwoJCXZhciBmb3JtYXR0ZXIgPSBEYXRhVGFibGUuZXh0LnR5cGUub3JkZXJbIGNvbHVtbi5zVHlwZSsiLXByZSIgXTsKCQoJCWZvciAoIHZhciBpPTAsIGllbj1zZXR0aW5ncy5hb0RhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCXJvdyA9IHNldHRpbmdzLmFvRGF0YVtpXTsKCQoJCQlpZiAoICEgcm93Ll9hU29ydERhdGEgKSB7CgkJCQlyb3cuX2FTb3J0RGF0YSA9IFtdOwoJCQl9CgkKCQkJaWYgKCAhIHJvdy5fYVNvcnREYXRhW2lkeF0gfHwgY3VzdG9tU29ydCApIHsKCQkJCWNlbGxEYXRhID0gY3VzdG9tU29ydCA/CgkJCQkJY3VzdG9tRGF0YVtpXSA6IC8vIElmIHRoZXJlIHdhcyBhIGN1c3RvbSBzb3J0IGZ1bmN0aW9uLCB1c2UgZGF0YSBmcm9tIHRoZXJlCgkJCQkJX2ZuR2V0Q2VsbERhdGEoIHNldHRpbmdzLCBpLCBpZHgsICdzb3J0JyApOwoJCgkJCQlyb3cuX2FTb3J0RGF0YVsgaWR4IF0gPSBmb3JtYXR0ZXIgPwoJCQkJCWZvcm1hdHRlciggY2VsbERhdGEgKSA6CgkJCQkJY2VsbERhdGE7CgkJCX0KCQl9Cgl9CgkKCQoJCgkvKioKCSAqIFNhdmUgdGhlIHN0YXRlIG9mIGEgdGFibGUKCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mblNhdmVTdGF0ZSAoIHNldHRpbmdzICkKCXsKCQlpZiAoc2V0dGluZ3MuX2JMb2FkaW5nU3RhdGUpIHsKCQkJcmV0dXJuOwoJCX0KCQoJCS8qIFN0b3JlIHRoZSBpbnRlcmVzdGluZyB2YXJpYWJsZXMgKi8KCQl2YXIgc3RhdGUgPSB7CgkJCXRpbWU6ICAgICtuZXcgRGF0ZSgpLAoJCQlzdGFydDogICBzZXR0aW5ncy5faURpc3BsYXlTdGFydCwKCQkJbGVuZ3RoOiAgc2V0dGluZ3MuX2lEaXNwbGF5TGVuZ3RoLAoJCQlvcmRlcjogICAkLmV4dGVuZCggdHJ1ZSwgW10sIHNldHRpbmdzLmFhU29ydGluZyApLAoJCQlzZWFyY2g6ICBfZm5TZWFyY2hUb0NhbWVsKCBzZXR0aW5ncy5vUHJldmlvdXNTZWFyY2ggKSwKCQkJY29sdW1uczogJC5tYXAoIHNldHRpbmdzLmFvQ29sdW1ucywgZnVuY3Rpb24gKCBjb2wsIGkgKSB7CgkJCQlyZXR1cm4gewoJCQkJCXZpc2libGU6IGNvbC5iVmlzaWJsZSwKCQkJCQlzZWFyY2g6IF9mblNlYXJjaFRvQ2FtZWwoIHNldHRpbmdzLmFvUHJlU2VhcmNoQ29sc1tpXSApCgkJCQl9OwoJCQl9ICkKCQl9OwoJCgkJc2V0dGluZ3Mub1NhdmVkU3RhdGUgPSBzdGF0ZTsKCQlfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCAiYW9TdGF0ZVNhdmVQYXJhbXMiLCAnc3RhdGVTYXZlUGFyYW1zJywgW3NldHRpbmdzLCBzdGF0ZV0gKTsKCQkKCQlpZiAoIHNldHRpbmdzLm9GZWF0dXJlcy5iU3RhdGVTYXZlICYmICFzZXR0aW5ncy5iRGVzdHJveWluZyApCgkJewoJCQlzZXR0aW5ncy5mblN0YXRlU2F2ZUNhbGxiYWNrLmNhbGwoIHNldHRpbmdzLm9JbnN0YW5jZSwgc2V0dGluZ3MsIHN0YXRlICk7CgkJfQkKCX0KCQoJCgkvKioKCSAqIEF0dGVtcHQgdG8gbG9hZCBhIHNhdmVkIHRhYmxlIHN0YXRlCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7b2JqZWN0fSBvSW5pdCBEYXRhVGFibGVzIGluaXQgb2JqZWN0IHNvIHdlIGNhbiBvdmVycmlkZSBzZXR0aW5ncwoJICogIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIENhbGxiYWNrIHRvIGV4ZWN1dGUgd2hlbiB0aGUgc3RhdGUgaGFzIGJlZW4gbG9hZGVkCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkxvYWRTdGF0ZSAoIHNldHRpbmdzLCBvSW5pdCwgY2FsbGJhY2sgKQoJewoJCWlmICggISBzZXR0aW5ncy5vRmVhdHVyZXMuYlN0YXRlU2F2ZSApIHsKCQkJY2FsbGJhY2soKTsKCQkJcmV0dXJuOwoJCX0KCQoJCXZhciBsb2FkZWQgPSBmdW5jdGlvbihzdGF0ZSkgewoJCQlfZm5JbXBsZW1lbnRTdGF0ZShzZXR0aW5ncywgc3RhdGUsIGNhbGxiYWNrKTsKCQl9CgkKCQl2YXIgc3RhdGUgPSBzZXR0aW5ncy5mblN0YXRlTG9hZENhbGxiYWNrLmNhbGwoIHNldHRpbmdzLm9JbnN0YW5jZSwgc2V0dGluZ3MsIGxvYWRlZCApOwoJCgkJaWYgKCBzdGF0ZSAhPT0gdW5kZWZpbmVkICkgewoJCQlfZm5JbXBsZW1lbnRTdGF0ZSggc2V0dGluZ3MsIHN0YXRlLCBjYWxsYmFjayApOwoJCX0KCQkvLyBvdGhlcndpc2UsIHdhaXQgZm9yIHRoZSBsb2FkZWQgY2FsbGJhY2sgdG8gYmUgZXhlY3V0ZWQKCQoJCXJldHVybiB0cnVlOwoJfQoJCglmdW5jdGlvbiBfZm5JbXBsZW1lbnRTdGF0ZSAoIHNldHRpbmdzLCBzLCBjYWxsYmFjaykgewoJCXZhciBpLCBpZW47CgkJdmFyIGNvbHVtbnMgPSBzZXR0aW5ncy5hb0NvbHVtbnM7CgkJc2V0dGluZ3MuX2JMb2FkaW5nU3RhdGUgPSB0cnVlOwoJCgkJLy8gV2hlbiBTdGF0ZVJlc3RvcmUgd2FzIGludHJvZHVjZWQgdGhlIHN0YXRlIGNvdWxkIG5vdyBiZSBpbXBsZW1lbnRlZCBhdCBhbnkgdGltZQoJCS8vIE5vdCBqdXN0IGluaXRpYWxpc2F0aW9uLiBUbyBkbyB0aGlzIGFuIGFwaSBpbnN0YW5jZSBpcyByZXF1aXJlZCBpbiBzb21lIHBsYWNlcwoJCXZhciBhcGkgPSBzZXR0aW5ncy5fYkluaXRDb21wbGV0ZSA/IG5ldyBEYXRhVGFibGUuQXBpKHNldHRpbmdzKSA6IG51bGw7CgkKCQlpZiAoICEgcyB8fCAhIHMudGltZSApIHsKCQkJc2V0dGluZ3MuX2JMb2FkaW5nU3RhdGUgPSBmYWxzZTsKCQkJY2FsbGJhY2soKTsKCQkJcmV0dXJuOwoJCX0KCQoJCS8vIEFsbG93IGN1c3RvbSBhbmQgcGx1Zy1pbiBtYW5pcHVsYXRpb24gZnVuY3Rpb25zIHRvIGFsdGVyIHRoZSBzYXZlZCBkYXRhIHNldCBhbmQKCQkvLyBjYW5jZWxsaW5nIG9mIGxvYWRpbmcgYnkgcmV0dXJuaW5nIGZhbHNlCgkJdmFyIGFiU3RhdGVMb2FkID0gX2ZuQ2FsbGJhY2tGaXJlKCBzZXR0aW5ncywgJ2FvU3RhdGVMb2FkUGFyYW1zJywgJ3N0YXRlTG9hZFBhcmFtcycsIFtzZXR0aW5ncywgc10gKTsKCQlpZiAoICQuaW5BcnJheSggZmFsc2UsIGFiU3RhdGVMb2FkICkgIT09IC0xICkgewoJCQlzZXR0aW5ncy5fYkxvYWRpbmdTdGF0ZSA9IGZhbHNlOwoJCQljYWxsYmFjaygpOwoJCQlyZXR1cm47CgkJfQoJCgkJLy8gUmVqZWN0IG9sZCBkYXRhCgkJdmFyIGR1cmF0aW9uID0gc2V0dGluZ3MuaVN0YXRlRHVyYXRpb247CgkJaWYgKCBkdXJhdGlvbiA+IDAgJiYgcy50aW1lIDwgK25ldyBEYXRlKCkgLSAoZHVyYXRpb24qMTAwMCkgKSB7CgkJCXNldHRpbmdzLl9iTG9hZGluZ1N0YXRlID0gZmFsc2U7CgkJCWNhbGxiYWNrKCk7CgkJCXJldHVybjsKCQl9CgkKCQkvLyBOdW1iZXIgb2YgY29sdW1ucyBoYXZlIGNoYW5nZWQgLSBhbGwgYmV0cyBhcmUgb2ZmLCBubyByZXN0b3JlIG9mIHNldHRpbmdzCgkJaWYgKCBzLmNvbHVtbnMgJiYgY29sdW1ucy5sZW5ndGggIT09IHMuY29sdW1ucy5sZW5ndGggKSB7CgkJCXNldHRpbmdzLl9iTG9hZGluZ1N0YXRlID0gZmFsc2U7CgkJCWNhbGxiYWNrKCk7CgkJCXJldHVybjsKCQl9CgkKCQkvLyBTdG9yZSB0aGUgc2F2ZWQgc3RhdGUgc28gaXQgbWlnaHQgYmUgYWNjZXNzZWQgYXQgYW55IHRpbWUKCQlzZXR0aW5ncy5vTG9hZGVkU3RhdGUgPSAkLmV4dGVuZCggdHJ1ZSwge30sIHMgKTsKCQoJCS8vIFBhZ2UgTGVuZ3RoCgkJaWYgKCBzLmxlbmd0aCAhPT0gdW5kZWZpbmVkICkgewoJCQkvLyBJZiBhbHJlYWR5IGluaXRpYWxpc2VkIGp1c3Qgc2V0IHRoZSB2YWx1ZSBkaXJlY3RseSBzbyB0aGF0IHRoZSBzZWxlY3QgZWxlbWVudCBpcyBhbHNvIHVwZGF0ZWQKCQkJaWYgKGFwaSkgewoJCQkJYXBpLnBhZ2UubGVuKHMubGVuZ3RoKQoJCQl9CgkJCWVsc2UgewoJCQkJc2V0dGluZ3MuX2lEaXNwbGF5TGVuZ3RoICAgPSBzLmxlbmd0aDsKCQkJfQoJCX0KCQoJCS8vIFJlc3RvcmUga2V5IGZlYXR1cmVzIC0gdG9kbyAtIGZvciAxLjExIHRoaXMgbmVlZHMgdG8gYmUgZG9uZSBieQoJCS8vIHN1YnNjcmliZWQgZXZlbnRzCgkJaWYgKCBzLnN0YXJ0ICE9PSB1bmRlZmluZWQgKSB7CgkJCWlmKGFwaSA9PT0gbnVsbCkgewoJCQkJc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgICAgPSBzLnN0YXJ0OwoJCQkJc2V0dGluZ3MuaUluaXREaXNwbGF5U3RhcnQgPSBzLnN0YXJ0OwoJCQl9CgkJCWVsc2UgewoJCQkJX2ZuUGFnZUNoYW5nZShzZXR0aW5ncywgcy5zdGFydC9zZXR0aW5ncy5faURpc3BsYXlMZW5ndGgpOwoJCQl9CgkJfQoJCgkJLy8gT3JkZXIKCQlpZiAoIHMub3JkZXIgIT09IHVuZGVmaW5lZCApIHsKCQkJc2V0dGluZ3MuYWFTb3J0aW5nID0gW107CgkJCSQuZWFjaCggcy5vcmRlciwgZnVuY3Rpb24gKCBpLCBjb2wgKSB7CgkJCQlzZXR0aW5ncy5hYVNvcnRpbmcucHVzaCggY29sWzBdID49IGNvbHVtbnMubGVuZ3RoID8KCQkJCQlbIDAsIGNvbFsxXSBdIDoKCQkJCQljb2wKCQkJCSk7CgkJCX0gKTsKCQl9CgkKCQkvLyBTZWFyY2gKCQlpZiAoIHMuc2VhcmNoICE9PSB1bmRlZmluZWQgKSB7CgkJCSQuZXh0ZW5kKCBzZXR0aW5ncy5vUHJldmlvdXNTZWFyY2gsIF9mblNlYXJjaFRvSHVuZyggcy5zZWFyY2ggKSApOwoJCX0KCQoJCS8vIENvbHVtbnMKCQlpZiAoIHMuY29sdW1ucyApIHsKCQkJZm9yICggaT0wLCBpZW49cy5jb2x1bW5zLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJdmFyIGNvbCA9IHMuY29sdW1uc1tpXTsKCQoJCQkJLy8gVmlzaWJpbGl0eQoJCQkJaWYgKCBjb2wudmlzaWJsZSAhPT0gdW5kZWZpbmVkICkgewoJCQkJCS8vIElmIHRoZSBhcGkgaXMgZGVmaW5lZCwgdGhlIHRhYmxlIGhhcyBiZWVuIGluaXRpYWxpc2VkIHNvIHdlIG5lZWQgdG8gdXNlIGl0IHJhdGhlciB0aGFuIGludGVybmFsIHNldHRpbmdzCgkJCQkJaWYgKGFwaSkgewoJCQkJCQkvLyBEb24ndCByZWRyYXcgdGhlIGNvbHVtbnMgb24gZXZlcnkgaXRlcmF0aW9uIG9mIHRoaXMgbG9vcCwgd2Ugd2lsbCBkbyB0aGlzIGF0IHRoZSBlbmQgaW5zdGVhZAoJCQkJCQlhcGkuY29sdW1uKGkpLnZpc2libGUoY29sLnZpc2libGUsIGZhbHNlKTsKCQkJCQl9CgkJCQkJZWxzZSB7CgkJCQkJCWNvbHVtbnNbaV0uYlZpc2libGUgPSBjb2wudmlzaWJsZTsKCQkJCQl9CgkJCQl9CgkKCQkJCS8vIFNlYXJjaAoJCQkJaWYgKCBjb2wuc2VhcmNoICE9PSB1bmRlZmluZWQgKSB7CgkJCQkJJC5leHRlbmQoIHNldHRpbmdzLmFvUHJlU2VhcmNoQ29sc1tpXSwgX2ZuU2VhcmNoVG9IdW5nKCBjb2wuc2VhcmNoICkgKTsKCQkJCX0KCQkJfQoJCQkKCQkJLy8gSWYgdGhlIGFwaSBpcyBkZWZpbmVkIHRoZW4gd2UgbmVlZCB0byBhZGp1c3QgdGhlIGNvbHVtbnMgb25jZSB0aGUgdmlzaWJpbGl0eSBoYXMgYmVlbiBjaGFuZ2VkCgkJCWlmIChhcGkpIHsKCQkJCWFwaS5jb2x1bW5zLmFkanVzdCgpOwoJCQl9CgkJfQoJCgkJc2V0dGluZ3MuX2JMb2FkaW5nU3RhdGUgPSBmYWxzZTsKCQlfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCAnYW9TdGF0ZUxvYWRlZCcsICdzdGF0ZUxvYWRlZCcsIFtzZXR0aW5ncywgc10gKTsKCQljYWxsYmFjaygpOwoJfTsKCQoJCgkvKioKCSAqIFJldHVybiB0aGUgc2V0dGluZ3Mgb2JqZWN0IGZvciBhIHBhcnRpY3VsYXIgdGFibGUKCSAqICBAcGFyYW0ge25vZGV9IHRhYmxlIHRhYmxlIHdlIGFyZSB1c2luZyBhcyBhIGRhdGFUYWJsZQoJICogIEByZXR1cm5zIHtvYmplY3R9IFNldHRpbmdzIG9iamVjdCAtIG9yIG51bGwgaWYgbm90IGZvdW5kCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mblNldHRpbmdzRnJvbU5vZGUgKCB0YWJsZSApCgl7CgkJdmFyIHNldHRpbmdzID0gRGF0YVRhYmxlLnNldHRpbmdzOwoJCXZhciBpZHggPSAkLmluQXJyYXkoIHRhYmxlLCBfcGx1Y2soIHNldHRpbmdzLCAnblRhYmxlJyApICk7CgkKCQlyZXR1cm4gaWR4ICE9PSAtMSA/CgkJCXNldHRpbmdzWyBpZHggXSA6CgkJCW51bGw7Cgl9CgkKCQoJLyoqCgkgKiBMb2cgYW4gZXJyb3IgbWVzc2FnZQoJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogIEBwYXJhbSB7aW50fSBsZXZlbCBsb2cgZXJyb3IgbWVzc2FnZXMsIG9yIGRpc3BsYXkgdGhlbSB0byB0aGUgdXNlcgoJICogIEBwYXJhbSB7c3RyaW5nfSBtc2cgZXJyb3IgbWVzc2FnZQoJICogIEBwYXJhbSB7aW50fSB0biBUZWNobmljYWwgbm90ZSBpZCB0byBnZXQgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZXJyb3IuCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKi8KCWZ1bmN0aW9uIF9mbkxvZyggc2V0dGluZ3MsIGxldmVsLCBtc2csIHRuICkKCXsKCQltc2cgPSAnRGF0YVRhYmxlcyB3YXJuaW5nOiAnKwoJCQkoc2V0dGluZ3MgPyAndGFibGUgaWQ9JytzZXR0aW5ncy5zVGFibGVJZCsnIC0gJyA6ICcnKSttc2c7CgkKCQlpZiAoIHRuICkgewoJCQltc2cgKz0gJy4gRm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhpcyBlcnJvciwgcGxlYXNlIHNlZSAnKwoJCQknaHR0cDovL2RhdGF0YWJsZXMubmV0L3RuLycrdG47CgkJfQoJCgkJaWYgKCAhIGxldmVsICApIHsKCQkJLy8gQmFja3dhcmRzIGNvbXBhdGliaWxpdHkgcHJlIDEuMTAKCQkJdmFyIGV4dCA9IERhdGFUYWJsZS5leHQ7CgkJCXZhciB0eXBlID0gZXh0LnNFcnJNb2RlIHx8IGV4dC5lcnJNb2RlOwoJCgkJCWlmICggc2V0dGluZ3MgKSB7CgkJCQlfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCBudWxsLCAnZXJyb3InLCBbIHNldHRpbmdzLCB0biwgbXNnIF0gKTsKCQkJfQoJCgkJCWlmICggdHlwZSA9PSAnYWxlcnQnICkgewoJCQkJYWxlcnQoIG1zZyApOwoJCQl9CgkJCWVsc2UgaWYgKCB0eXBlID09ICd0aHJvdycgKSB7CgkJCQl0aHJvdyBuZXcgRXJyb3IobXNnKTsKCQkJfQoJCQllbHNlIGlmICggdHlwZW9mIHR5cGUgPT0gJ2Z1bmN0aW9uJyApIHsKCQkJCXR5cGUoIHNldHRpbmdzLCB0biwgbXNnICk7CgkJCX0KCQl9CgkJZWxzZSBpZiAoIHdpbmRvdy5jb25zb2xlICYmIGNvbnNvbGUubG9nICkgewoJCQljb25zb2xlLmxvZyggbXNnICk7CgkJfQoJfQoJCgkKCS8qKgoJICogU2VlIGlmIGEgcHJvcGVydHkgaXMgZGVmaW5lZCBvbiBvbmUgb2JqZWN0LCBpZiBzbyBhc3NpZ24gaXQgdG8gdGhlIG90aGVyIG9iamVjdAoJICogIEBwYXJhbSB7b2JqZWN0fSByZXQgdGFyZ2V0IG9iamVjdAoJICogIEBwYXJhbSB7b2JqZWN0fSBzcmMgc291cmNlIG9iamVjdAoJICogIEBwYXJhbSB7c3RyaW5nfSBuYW1lIHByb3BlcnR5CgkgKiAgQHBhcmFtIHtzdHJpbmd9IFttYXBwZWROYW1lXSBuYW1lIHRvIG1hcCB0b28gLSBvcHRpb25hbCwgbmFtZSB1c2VkIGlmIG5vdCBnaXZlbgoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5NYXAoIHJldCwgc3JjLCBuYW1lLCBtYXBwZWROYW1lICkKCXsKCQlpZiAoIEFycmF5LmlzQXJyYXkoIG5hbWUgKSApIHsKCQkJJC5lYWNoKCBuYW1lLCBmdW5jdGlvbiAoaSwgdmFsKSB7CgkJCQlpZiAoIEFycmF5LmlzQXJyYXkoIHZhbCApICkgewoJCQkJCV9mbk1hcCggcmV0LCBzcmMsIHZhbFswXSwgdmFsWzFdICk7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlfZm5NYXAoIHJldCwgc3JjLCB2YWwgKTsKCQkJCX0KCQkJfSApOwoJCgkJCXJldHVybjsKCQl9CgkKCQlpZiAoIG1hcHBlZE5hbWUgPT09IHVuZGVmaW5lZCApIHsKCQkJbWFwcGVkTmFtZSA9IG5hbWU7CgkJfQoJCgkJaWYgKCBzcmNbbmFtZV0gIT09IHVuZGVmaW5lZCApIHsKCQkJcmV0W21hcHBlZE5hbWVdID0gc3JjW25hbWVdOwoJCX0KCX0KCQoJCgkvKioKCSAqIEV4dGVuZCBvYmplY3RzIC0gdmVyeSBzaW1pbGFyIHRvIGpRdWVyeS5leHRlbmQsIGJ1dCBkZWVwIGNvcHkgb2JqZWN0cywgYW5kCgkgKiBzaGFsbG93IGNvcHkgYXJyYXlzLiBUaGUgcmVhc29uIHdlIG5lZWQgdG8gZG8gdGhpcywgaXMgdGhhdCB3ZSBkb24ndCB3YW50IHRvCgkgKiBkZWVwIGNvcHkgYXJyYXkgaW5pdCB2YWx1ZXMgKHN1Y2ggYXMgYWFTb3J0aW5nKSBzaW5jZSB0aGUgZGV2IHdvdWxkbid0IGJlCgkgKiBhYmxlIHRvIG92ZXJyaWRlIHRoZW0sIGJ1dCB3ZSBkbyB3YW50IHRvIGRlZXAgY29weSBhcnJheXMuCgkgKiAgQHBhcmFtIHtvYmplY3R9IG91dCBPYmplY3QgdG8gZXh0ZW5kCgkgKiAgQHBhcmFtIHtvYmplY3R9IGV4dGVuZGVyIE9iamVjdCBmcm9tIHdoaWNoIHRoZSBwcm9wZXJ0aWVzIHdpbGwgYmUgYXBwbGllZCB0bwoJICogICAgICBvdXQKCSAqICBAcGFyYW0ge2Jvb2xlYW59IGJyZWFrUmVmcyBJZiB0cnVlLCB0aGVuIGFycmF5cyB3aWxsIGJlIHNsaWNlZCB0byB0YWtlIGFuCgkgKiAgICAgIGluZGVwZW5kZW50IGNvcHkgd2l0aCB0aGUgZXhjZXB0aW9uIG9mIHRoZSBgZGF0YWAgb3IgYGFhRGF0YWAgcGFyYW1ldGVycwoJICogICAgICBpZiB0aGV5IGFyZSBwcmVzZW50LiBUaGlzIGlzIHNvIHlvdSBjYW4gcGFzcyBpbiBhIGNvbGxlY3Rpb24gdG8KCSAqICAgICAgRGF0YVRhYmxlcyBhbmQgaGF2ZSB0aGF0IHVzZWQgYXMgeW91ciBkYXRhIHNvdXJjZSB3aXRob3V0IGJyZWFraW5nIHRoZQoJICogICAgICByZWZlcmVuY2VzCgkgKiAgQHJldHVybnMge29iamVjdH0gb3V0IFJlZmVyZW5jZSwganVzdCBmb3IgY29udmVuaWVuY2UgLSBvdXQgPT09IHRoZSByZXR1cm4uCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpCgkgKiAgQHRvZG8gVGhpcyBkb2Vzbid0IHRha2UgYWNjb3VudCBvZiBhcnJheXMgaW5zaWRlIHRoZSBkZWVwIGNvcGllZCBvYmplY3RzLgoJICovCglmdW5jdGlvbiBfZm5FeHRlbmQoIG91dCwgZXh0ZW5kZXIsIGJyZWFrUmVmcyApCgl7CgkJdmFyIHZhbDsKCQoJCWZvciAoIHZhciBwcm9wIGluIGV4dGVuZGVyICkgewoJCQlpZiAoIGV4dGVuZGVyLmhhc093blByb3BlcnR5KHByb3ApICkgewoJCQkJdmFsID0gZXh0ZW5kZXJbcHJvcF07CgkKCQkJCWlmICggJC5pc1BsYWluT2JqZWN0KCB2YWwgKSApIHsKCQkJCQlpZiAoICEgJC5pc1BsYWluT2JqZWN0KCBvdXRbcHJvcF0gKSApIHsKCQkJCQkJb3V0W3Byb3BdID0ge307CgkJCQkJfQoJCQkJCSQuZXh0ZW5kKCB0cnVlLCBvdXRbcHJvcF0sIHZhbCApOwoJCQkJfQoJCQkJZWxzZSBpZiAoIGJyZWFrUmVmcyAmJiBwcm9wICE9PSAnZGF0YScgJiYgcHJvcCAhPT0gJ2FhRGF0YScgJiYgQXJyYXkuaXNBcnJheSh2YWwpICkgewoJCQkJCW91dFtwcm9wXSA9IHZhbC5zbGljZSgpOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJb3V0W3Byb3BdID0gdmFsOwoJCQkJfQoJCQl9CgkJfQoJCgkJcmV0dXJuIG91dDsKCX0KCQoJCgkvKioKCSAqIEJpbmQgYW4gZXZlbnQgaGFuZGVycyB0byBhbGxvdyBhIGNsaWNrIG9yIHJldHVybiBrZXkgdG8gYWN0aXZhdGUgdGhlIGNhbGxiYWNrLgoJICogVGhpcyBpcyBnb29kIGZvciBhY2Nlc3NpYmlsaXR5IHNpbmNlIGEgcmV0dXJuIG9uIHRoZSBrZXlib2FyZCB3aWxsIGhhdmUgdGhlCgkgKiBzYW1lIGVmZmVjdCBhcyBhIGNsaWNrLCBpZiB0aGUgZWxlbWVudCBoYXMgZm9jdXMuCgkgKiAgQHBhcmFtIHtlbGVtZW50fSBuIEVsZW1lbnQgdG8gYmluZCB0aGUgYWN0aW9uIHRvCgkgKiAgQHBhcmFtIHtvYmplY3R9IG9EYXRhIERhdGEgb2JqZWN0IHRvIHBhc3MgdG8gdGhlIHRyaWdnZXJlZCBmdW5jdGlvbgoJICogIEBwYXJhbSB7ZnVuY3Rpb259IGZuIENhbGxiYWNrIGZ1bmN0aW9uIGZvciB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuQmluZEFjdGlvbiggbiwgb0RhdGEsIGZuICkKCXsKCQkkKG4pCgkJCS5vbiggJ2NsaWNrLkRUJywgb0RhdGEsIGZ1bmN0aW9uIChlKSB7CgkJCQkJJChuKS50cmlnZ2VyKCdibHVyJyk7IC8vIFJlbW92ZSBmb2N1cyBvdXRsaW5lIGZvciBtb3VzZSB1c2VycwoJCQkJCWZuKGUpOwoJCQkJfSApCgkJCS5vbiggJ2tleXByZXNzLkRUJywgb0RhdGEsIGZ1bmN0aW9uIChlKXsKCQkJCQlpZiAoIGUud2hpY2ggPT09IDEzICkgewoJCQkJCQllLnByZXZlbnREZWZhdWx0KCk7CgkJCQkJCWZuKGUpOwoJCQkJCX0KCQkJCX0gKQoJCQkub24oICdzZWxlY3RzdGFydC5EVCcsIGZ1bmN0aW9uICgpIHsKCQkJCQkvKiBUYWtlIHRoZSBicnV0YWwgYXBwcm9hY2ggdG8gY2FuY2VsbGluZyB0ZXh0IHNlbGVjdGlvbiAqLwoJCQkJCXJldHVybiBmYWxzZTsKCQkJCX0gKTsKCX0KCQoJCgkvKioKCSAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24uIEVhc2lseSBhbGxvd3MgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBhZGRlZCB0bwoJICogYW4gYXJyYXkgc3RvcmUgb2YgY2FsbGJhY2sgZnVuY3Rpb25zIHRoYXQgY2FuIHRoZW4gYWxsIGJlIGNhbGxlZCB0b2dldGhlci4KCSAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIHtzdHJpbmd9IHNTdG9yZSBOYW1lIG9mIHRoZSBhcnJheSBzdG9yYWdlIGZvciB0aGUgY2FsbGJhY2tzIGluIG9TZXR0aW5ncwoJICogIEBwYXJhbSB7ZnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBiYWNrCgkgKiAgQHBhcmFtIHtzdHJpbmd9IHNOYW1lIElkZW50aWZ5aW5nIG5hbWUgZm9yIHRoZSBjYWxsYmFjayAoaS5lLiBhIGxhYmVsKQoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCBzU3RvcmUsIGZuLCBzTmFtZSApCgl7CgkJaWYgKCBmbiApCgkJewoJCQlvU2V0dGluZ3Nbc1N0b3JlXS5wdXNoKCB7CgkJCQkiZm4iOiBmbiwKCQkJCSJzTmFtZSI6IHNOYW1lCgkJCX0gKTsKCQl9Cgl9CgkKCQoJLyoqCgkgKiBGaXJlIGNhbGxiYWNrIGZ1bmN0aW9ucyBhbmQgdHJpZ2dlciBldmVudHMuIE5vdGUgdGhhdCB0aGUgbG9vcCBvdmVyIHRoZQoJICogY2FsbGJhY2sgYXJyYXkgc3RvcmUgaXMgZG9uZSBiYWNrd2FyZHMhIEZ1cnRoZXIgbm90ZSB0aGF0IHlvdSBkbyBub3Qgd2FudCB0bwoJICogZmlyZSBvZmYgdHJpZ2dlcnMgaW4gdGltZSBzZW5zaXRpdmUgYXBwbGljYXRpb25zIChmb3IgZXhhbXBsZSBjZWxsIGNyZWF0aW9uKQoJICogYXMgaXRzIHNsb3cuCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHBhcmFtIHtzdHJpbmd9IGNhbGxiYWNrQXJyIE5hbWUgb2YgdGhlIGFycmF5IHN0b3JhZ2UgZm9yIHRoZSBjYWxsYmFja3MgaW4KCSAqICAgICAgb1NldHRpbmdzCgkgKiAgQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSBOYW1lIG9mIHRoZSBqUXVlcnkgY3VzdG9tIGV2ZW50IHRvIHRyaWdnZXIuIElmCgkgKiAgICAgIG51bGwgbm8gdHJpZ2dlciBpcyBmaXJlZAoJICogIEBwYXJhbSB7YXJyYXl9IGFyZ3MgQXJyYXkgb2YgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIC8KCSAqICAgICAgdHJpZ2dlcgoJICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaQoJICovCglmdW5jdGlvbiBfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCBjYWxsYmFja0FyciwgZXZlbnROYW1lLCBhcmdzICkKCXsKCQl2YXIgcmV0ID0gW107CgkKCQlpZiAoIGNhbGxiYWNrQXJyICkgewoJCQlyZXQgPSAkLm1hcCggc2V0dGluZ3NbY2FsbGJhY2tBcnJdLnNsaWNlKCkucmV2ZXJzZSgpLCBmdW5jdGlvbiAodmFsLCBpKSB7CgkJCQlyZXR1cm4gdmFsLmZuLmFwcGx5KCBzZXR0aW5ncy5vSW5zdGFuY2UsIGFyZ3MgKTsKCQkJfSApOwoJCX0KCQoJCWlmICggZXZlbnROYW1lICE9PSBudWxsICkgewoJCQl2YXIgZSA9ICQuRXZlbnQoIGV2ZW50TmFtZSsnLmR0JyApOwoJCgkJCSQoc2V0dGluZ3MublRhYmxlKS50cmlnZ2VyKCBlLCBhcmdzICk7CgkKCQkJcmV0LnB1c2goIGUucmVzdWx0ICk7CgkJfQoJCgkJcmV0dXJuIHJldDsKCX0KCQoJCglmdW5jdGlvbiBfZm5MZW5ndGhPdmVyZmxvdyAoIHNldHRpbmdzICkKCXsKCQl2YXIKCQkJc3RhcnQgPSBzZXR0aW5ncy5faURpc3BsYXlTdGFydCwKCQkJZW5kID0gc2V0dGluZ3MuZm5EaXNwbGF5RW5kKCksCgkJCWxlbiA9IHNldHRpbmdzLl9pRGlzcGxheUxlbmd0aDsKCQoJCS8qIElmIHdlIGhhdmUgc3BhY2UgdG8gc2hvdyBleHRyYSByb3dzIChiYWNraW5nIHVwIGZyb20gdGhlIGVuZCBwb2ludCAtIHRoZW4gZG8gc28gKi8KCQlpZiAoIHN0YXJ0ID49IGVuZCApCgkJewoJCQlzdGFydCA9IGVuZCAtIGxlbjsKCQl9CgkKCQkvLyBLZWVwIHRoZSBzdGFydCByZWNvcmQgb24gdGhlIGN1cnJlbnQgcGFnZQoJCXN0YXJ0IC09IChzdGFydCAlIGxlbik7CgkKCQlpZiAoIGxlbiA9PT0gLTEgfHwgc3RhcnQgPCAwICkKCQl7CgkJCXN0YXJ0ID0gMDsKCQl9CgkKCQlzZXR0aW5ncy5faURpc3BsYXlTdGFydCA9IHN0YXJ0OwoJfQoJCgkKCWZ1bmN0aW9uIF9mblJlbmRlcmVyKCBzZXR0aW5ncywgdHlwZSApCgl7CgkJdmFyIHJlbmRlcmVyID0gc2V0dGluZ3MucmVuZGVyZXI7CgkJdmFyIGhvc3QgPSBEYXRhVGFibGUuZXh0LnJlbmRlcmVyW3R5cGVdOwoJCgkJaWYgKCAkLmlzUGxhaW5PYmplY3QoIHJlbmRlcmVyICkgJiYgcmVuZGVyZXJbdHlwZV0gKSB7CgkJCS8vIFNwZWNpZmljIHJlbmRlcmVyIGZvciB0aGlzIHR5cGUuIElmIGF2YWlsYWJsZSB1c2UgaXQsIG90aGVyd2lzZSB1c2UKCQkJLy8gdGhlIGRlZmF1bHQuCgkJCXJldHVybiBob3N0W3JlbmRlcmVyW3R5cGVdXSB8fCBob3N0Ll87CgkJfQoJCWVsc2UgaWYgKCB0eXBlb2YgcmVuZGVyZXIgPT09ICdzdHJpbmcnICkgewoJCQkvLyBDb21tb24gcmVuZGVyZXIgLSBpZiB0aGVyZSBpcyBvbmUgYXZhaWxhYmxlIGZvciB0aGlzIHR5cGUgdXNlIGl0LAoJCQkvLyBvdGhlcndpc2UgdXNlIHRoZSBkZWZhdWx0CgkJCXJldHVybiBob3N0W3JlbmRlcmVyXSB8fCBob3N0Ll87CgkJfQoJCgkJLy8gVXNlIHRoZSBkZWZhdWx0CgkJcmV0dXJuIGhvc3QuXzsKCX0KCQoJCgkvKioKCSAqIERldGVjdCB0aGUgZGF0YSBzb3VyY2UgYmVpbmcgdXNlZCBmb3IgdGhlIHRhYmxlLiBVc2VkIHRvIHNpbXBsaWZ5IHRoZSBjb2RlCgkgKiBhIGxpdHRsZSAoYWpheCkgYW5kIHRvIG1ha2UgaXQgY29tcHJlc3MgYSBsaXR0bGUgc21hbGxlci4KCSAqCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkgKiAgQHJldHVybnMge3N0cmluZ30gRGF0YSBzb3VyY2UKCSAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGkKCSAqLwoJZnVuY3Rpb24gX2ZuRGF0YVNvdXJjZSAoIHNldHRpbmdzICkKCXsKCQlpZiAoIHNldHRpbmdzLm9GZWF0dXJlcy5iU2VydmVyU2lkZSApIHsKCQkJcmV0dXJuICdzc3AnOwoJCX0KCQllbHNlIGlmICggc2V0dGluZ3MuYWpheCB8fCBzZXR0aW5ncy5zQWpheFNvdXJjZSApIHsKCQkJcmV0dXJuICdhamF4JzsKCQl9CgkJcmV0dXJuICdkb20nOwoJfQoJCgkKCQoJCgkvKioKCSAqIENvbXB1dGVkIHN0cnVjdHVyZSBvZiB0aGUgRGF0YVRhYmxlcyBBUEksIGRlZmluZWQgYnkgdGhlIG9wdGlvbnMgcGFzc2VkIHRvCgkgKiBgRGF0YVRhYmxlLkFwaS5yZWdpc3RlcigpYCB3aGVuIGJ1aWxkaW5nIHRoZSBBUEkuCgkgKgoJICogVGhlIHN0cnVjdHVyZSBpcyBidWlsdCBpbiBvcmRlciB0byBzcGVlZCBjcmVhdGlvbiBhbmQgZXh0ZW5zaW9uIG9mIHRoZSBBcGkKCSAqIG9iamVjdHMgc2luY2UgdGhlIGV4dGVuc2lvbnMgYXJlIGVmZmVjdGl2ZWx5IHByZS1wYXJzZWQuCgkgKgoJICogVGhlIGFycmF5IGlzIGFuIGFycmF5IG9mIG9iamVjdHMgd2l0aCB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZSwgd2hlcmUgdGhpcwoJICogYmFzZSBhcnJheSByZXByZXNlbnRzIHRoZSBBcGkgcHJvdG90eXBlIGJhc2U6CgkgKgoJICogICAgIFsKCSAqICAgICAgIHsKCSAqICAgICAgICAgbmFtZTogICAgICAnZGF0YScgICAgICAgICAgICAgICAgLS0gc3RyaW5nICAgLSBQcm9wZXJ0eSBuYW1lCgkgKiAgICAgICAgIHZhbDogICAgICAgZnVuY3Rpb24gKCkge30sICAgICAgIC0tIGZ1bmN0aW9uIC0gQXBpIG1ldGhvZCAob3IgdW5kZWZpbmVkIGlmIGp1c3QgYW4gb2JqZWN0CgkgKiAgICAgICAgIG1ldGhvZEV4dDogWyAuLi4gXSwgICAgICAgICAgICAgIC0tIGFycmF5ICAgIC0gQXJyYXkgb2YgQXBpIG9iamVjdCBkZWZpbml0aW9ucyB0byBleHRlbmQgdGhlIG1ldGhvZCByZXN1bHQKCSAqICAgICAgICAgcHJvcEV4dDogICBbIC4uLiBdICAgICAgICAgICAgICAgLS0gYXJyYXkgICAgLSBBcnJheSBvZiBBcGkgb2JqZWN0IGRlZmluaXRpb25zIHRvIGV4dGVuZCB0aGUgcHJvcGVydHkKCSAqICAgICAgIH0sCgkgKiAgICAgICB7CgkgKiAgICAgICAgIG5hbWU6ICAgICAncm93JwoJICogICAgICAgICB2YWw6ICAgICAgIHt9LAoJICogICAgICAgICBtZXRob2RFeHQ6IFsgLi4uIF0sCgkgKiAgICAgICAgIHByb3BFeHQ6ICAgWwoJICogICAgICAgICAgIHsKCSAqICAgICAgICAgICAgIG5hbWU6ICAgICAgJ2RhdGEnCgkgKiAgICAgICAgICAgICB2YWw6ICAgICAgIGZ1bmN0aW9uICgpIHt9LAoJICogICAgICAgICAgICAgbWV0aG9kRXh0OiBbIC4uLiBdLAoJICogICAgICAgICAgICAgcHJvcEV4dDogICBbIC4uLiBdCgkgKiAgICAgICAgICAgfSwKCSAqICAgICAgICAgICAuLi4KCSAqICAgICAgICAgXQoJICogICAgICAgfQoJICogICAgIF0KCSAqCgkgKiBAdHlwZSB7QXJyYXl9CgkgKiBAaWdub3JlCgkgKi8KCXZhciBfX2FwaVN0cnVjdCA9IFtdOwoJCgkKCS8qKgoJICogYEFycmF5LnByb3RvdHlwZWAgcmVmZXJlbmNlLgoJICoKCSAqIEB0eXBlIG9iamVjdAoJICogQGlnbm9yZQoJICovCgl2YXIgX19hcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlOwoJCgkKCS8qKgoJICogQWJzdHJhY3Rpb24gZm9yIGBjb250ZXh0YCBwYXJhbWV0ZXIgb2YgdGhlIGBBcGlgIGNvbnN0cnVjdG9yIHRvIGFsbG93IGl0IHRvCgkgKiB0YWtlIHNldmVyYWwgZGlmZmVyZW50IGZvcm1zIGZvciBlYXNlIG9mIHVzZS4KCSAqCgkgKiBFYWNoIG9mIHRoZSBpbnB1dCBwYXJhbWV0ZXIgdHlwZXMgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gYSBEYXRhVGFibGVzIHNldHRpbmdzCgkgKiBvYmplY3Qgd2hlcmUgcG9zc2libGUuCgkgKgoJICogQHBhcmFtICB7c3RyaW5nfG5vZGV8alF1ZXJ5fG9iamVjdH0gbWl4ZWQgRGF0YVRhYmxlIGlkZW50aWZpZXIuIENhbiBiZSBvbmUKCSAqICAgb2Y6CgkgKgoJICogICAqIGBzdHJpbmdgIC0galF1ZXJ5IHNlbGVjdG9yLiBBbnkgRGF0YVRhYmxlcycgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yCgkgKiAgICAgd2l0aCBiZSBmb3VuZCBhbmQgdXNlZC4KCSAqICAgKiBgbm9kZWAgLSBgVEFCTEVgIG5vZGUgd2hpY2ggaGFzIGFscmVhZHkgYmVlbiBmb3JtZWQgaW50byBhIERhdGFUYWJsZS4KCSAqICAgKiBgalF1ZXJ5YCAtIEEgalF1ZXJ5IG9iamVjdCBvZiBgVEFCTEVgIG5vZGVzLgoJICogICAqIGBvYmplY3RgIC0gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCSAqICAgKiBgRGF0YVRhYmxlcy5BcGlgIC0gQVBJIGluc3RhbmNlCgkgKiBAcmV0dXJuIHthcnJheXxudWxsfSBNYXRjaGluZyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdHMuIGBudWxsYCBvcgoJICogICBgdW5kZWZpbmVkYCBpcyByZXR1cm5lZCBpZiBubyBtYXRjaGluZyBEYXRhVGFibGUgaXMgZm91bmQuCgkgKiBAaWdub3JlCgkgKi8KCXZhciBfdG9TZXR0aW5ncyA9IGZ1bmN0aW9uICggbWl4ZWQgKQoJewoJCXZhciBpZHgsIGpxOwoJCXZhciBzZXR0aW5ncyA9IERhdGFUYWJsZS5zZXR0aW5nczsKCQl2YXIgdGFibGVzID0gJC5tYXAoIHNldHRpbmdzLCBmdW5jdGlvbiAoZWwsIGkpIHsKCQkJcmV0dXJuIGVsLm5UYWJsZTsKCQl9ICk7CgkKCQlpZiAoICEgbWl4ZWQgKSB7CgkJCXJldHVybiBbXTsKCQl9CgkJZWxzZSBpZiAoIG1peGVkLm5UYWJsZSAmJiBtaXhlZC5vQXBpICkgewoJCQkvLyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJCQlyZXR1cm4gWyBtaXhlZCBdOwoJCX0KCQllbHNlIGlmICggbWl4ZWQubm9kZU5hbWUgJiYgbWl4ZWQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3RhYmxlJyApIHsKCQkJLy8gVGFibGUgbm9kZQoJCQlpZHggPSAkLmluQXJyYXkoIG1peGVkLCB0YWJsZXMgKTsKCQkJcmV0dXJuIGlkeCAhPT0gLTEgPyBbIHNldHRpbmdzW2lkeF0gXSA6IG51bGw7CgkJfQoJCWVsc2UgaWYgKCBtaXhlZCAmJiB0eXBlb2YgbWl4ZWQuc2V0dGluZ3MgPT09ICdmdW5jdGlvbicgKSB7CgkJCXJldHVybiBtaXhlZC5zZXR0aW5ncygpLnRvQXJyYXkoKTsKCQl9CgkJZWxzZSBpZiAoIHR5cGVvZiBtaXhlZCA9PT0gJ3N0cmluZycgKSB7CgkJCS8vIGpRdWVyeSBzZWxlY3RvcgoJCQlqcSA9ICQobWl4ZWQpOwoJCX0KCQllbHNlIGlmICggbWl4ZWQgaW5zdGFuY2VvZiAkICkgewoJCQkvLyBqUXVlcnkgb2JqZWN0IChhbHNvIERhdGFUYWJsZXMgaW5zdGFuY2UpCgkJCWpxID0gbWl4ZWQ7CgkJfQoJCgkJaWYgKCBqcSApIHsKCQkJcmV0dXJuIGpxLm1hcCggZnVuY3Rpb24oaSkgewoJCQkJaWR4ID0gJC5pbkFycmF5KCB0aGlzLCB0YWJsZXMgKTsKCQkJCXJldHVybiBpZHggIT09IC0xID8gc2V0dGluZ3NbaWR4XSA6IG51bGw7CgkJCX0gKS50b0FycmF5KCk7CgkJfQoJfTsKCQoJCgkvKioKCSAqIERhdGFUYWJsZXMgQVBJIGNsYXNzIC0gdXNlZCB0byBjb250cm9sIGFuZCBpbnRlcmZhY2Ugd2l0aCAgb25lIG9yIG1vcmUKCSAqIERhdGFUYWJsZXMgZW5oYW5jZWQgdGFibGVzLgoJICoKCSAqIFRoZSBBUEkgY2xhc3MgaXMgaGVhdmlseSBiYXNlZCBvbiBqUXVlcnksIHByZXNlbnRpbmcgYSBjaGFpbmFibGUgaW50ZXJmYWNlCgkgKiB0aGF0IHlvdSBjYW4gdXNlIHRvIGludGVyYWN0IHdpdGggdGFibGVzLiBFYWNoIGluc3RhbmNlIG9mIHRoZSBBUEkgY2xhc3MgaGFzCgkgKiBhICJjb250ZXh0IiAtIGkuZS4gdGhlIHRhYmxlcyB0aGF0IGl0IHdpbGwgb3BlcmF0ZSBvbi4gVGhpcyBjb3VsZCBiZSBhIHNpbmdsZQoJICogdGFibGUsIGFsbCB0YWJsZXMgb24gYSBwYWdlIG9yIGEgc3ViLXNldCB0aGVyZW9mLgoJICoKCSAqIEFkZGl0aW9uYWxseSB0aGUgQVBJIGlzIGRlc2lnbmVkIHRvIGFsbG93IHlvdSB0byBlYXNpbHkgd29yayB3aXRoIHRoZSBkYXRhIGluCgkgKiB0aGUgdGFibGVzLCByZXRyaWV2aW5nIGFuZCBtYW5pcHVsYXRpbmcgaXQgYXMgcmVxdWlyZWQuIFRoaXMgaXMgZG9uZSBieQoJICogcHJlc2VudGluZyB0aGUgQVBJIGNsYXNzIGFzIGFuIGFycmF5IGxpa2UgaW50ZXJmYWNlLiBUaGUgY29udGVudHMgb2YgdGhlCgkgKiBhcnJheSBkZXBlbmQgdXBvbiB0aGUgYWN0aW9ucyByZXF1ZXN0ZWQgYnkgZWFjaCBtZXRob2QgKGZvciBleGFtcGxlCgkgKiBgcm93cygpLm5vZGVzKClgIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIG5vZGVzLCB3aGlsZSBgcm93cygpLmRhdGEoKWAgd2lsbAoJICogcmV0dXJuIGFuIGFycmF5IG9mIG9iamVjdHMgb3IgYXJyYXlzIGRlcGVuZGluZyB1cG9uIHlvdXIgdGFibGUncwoJICogY29uZmlndXJhdGlvbikuIFRoZSBBUEkgb2JqZWN0IGhhcyBhIG51bWJlciBvZiBhcnJheSBsaWtlIG1ldGhvZHMgKGBwdXNoYCwKCSAqIGBwb3BgLCBgcmV2ZXJzZWAgZXRjKSBhcyB3ZWxsIGFzIGFkZGl0aW9uYWwgaGVscGVyIG1ldGhvZHMgKGBlYWNoYCwgYHBsdWNrYCwKCSAqIGB1bmlxdWVgIGV0YykgdG8gYXNzaXN0IHlvdXIgd29ya2luZyB3aXRoIHRoZSBkYXRhIGhlbGQgaW4gYSB0YWJsZS4KCSAqCgkgKiBNb3N0IG1ldGhvZHMgKHRob3NlIHdoaWNoIHJldHVybiBhbiBBcGkgaW5zdGFuY2UpIGFyZSBjaGFpbmFibGUsIHdoaWNoIG1lYW5zCgkgKiB0aGUgcmV0dXJuIGZyb20gYSBtZXRob2QgY2FsbCBhbHNvIGhhcyBhbGwgb2YgdGhlIG1ldGhvZHMgYXZhaWxhYmxlIHRoYXQgdGhlCgkgKiB0b3AgbGV2ZWwgb2JqZWN0IGhhZC4gRm9yIGV4YW1wbGUsIHRoZXNlIHR3byBjYWxscyBhcmUgZXF1aXZhbGVudDoKCSAqCgkgKiAgICAgLy8gTm90IGNoYWluZWQKCSAqICAgICBhcGkucm93LmFkZCggey4uLn0gKTsKCSAqICAgICBhcGkuZHJhdygpOwoJICoKCSAqICAgICAvLyBDaGFpbmVkCgkgKiAgICAgYXBpLnJvdy5hZGQoIHsuLi59ICkuZHJhdygpOwoJICoKCSAqIEBjbGFzcyBEYXRhVGFibGUuQXBpCgkgKiBAcGFyYW0ge2FycmF5fG9iamVjdHxzdHJpbmd8alF1ZXJ5fSBjb250ZXh0IERhdGFUYWJsZSBpZGVudGlmaWVyLiBUaGlzIGlzCgkgKiAgIHVzZWQgdG8gZGVmaW5lIHdoaWNoIERhdGFUYWJsZXMgZW5oYW5jZWQgdGFibGVzIHRoaXMgQVBJIHdpbGwgb3BlcmF0ZSBvbi4KCSAqICAgQ2FuIGJlIG9uZSBvZjoKCSAqCgkgKiAgICogYHN0cmluZ2AgLSBqUXVlcnkgc2VsZWN0b3IuIEFueSBEYXRhVGFibGVzJyBtYXRjaGluZyB0aGUgZ2l2ZW4gc2VsZWN0b3IKCSAqICAgICB3aXRoIGJlIGZvdW5kIGFuZCB1c2VkLgoJICogICAqIGBub2RlYCAtIGBUQUJMRWAgbm9kZSB3aGljaCBoYXMgYWxyZWFkeSBiZWVuIGZvcm1lZCBpbnRvIGEgRGF0YVRhYmxlLgoJICogICAqIGBqUXVlcnlgIC0gQSBqUXVlcnkgb2JqZWN0IG9mIGBUQUJMRWAgbm9kZXMuCgkgKiAgICogYG9iamVjdGAgLSBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJICogQHBhcmFtIHthcnJheX0gW2RhdGFdIERhdGEgdG8gaW5pdGlhbGlzZSB0aGUgQXBpIGluc3RhbmNlIHdpdGguCgkgKgoJICogQGV4YW1wbGUKCSAqICAgLy8gRGlyZWN0IGluaXRpYWxpc2F0aW9uIGR1cmluZyBEYXRhVGFibGVzIGNvbnN0cnVjdGlvbgoJICogICB2YXIgYXBpID0gJCgnI2V4YW1wbGUnKS5EYXRhVGFibGUoKTsKCSAqCgkgKiBAZXhhbXBsZQoJICogICAvLyBJbml0aWFsaXNhdGlvbiB1c2luZyBhIERhdGFUYWJsZXMgalF1ZXJ5IG9iamVjdAoJICogICB2YXIgYXBpID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKS5hcGkoKTsKCSAqCgkgKiBAZXhhbXBsZQoJICogICAvLyBJbml0aWFsaXNhdGlvbiBhcyBhIGNvbnN0cnVjdG9yCgkgKiAgIHZhciBhcGkgPSBuZXcgJC5mbi5EYXRhVGFibGUuQXBpKCAndGFibGUuZGF0YVRhYmxlJyApOwoJICovCglfQXBpID0gZnVuY3Rpb24gKCBjb250ZXh0LCBkYXRhICkKCXsKCQlpZiAoICEgKHRoaXMgaW5zdGFuY2VvZiBfQXBpKSApIHsKCQkJcmV0dXJuIG5ldyBfQXBpKCBjb250ZXh0LCBkYXRhICk7CgkJfQoJCgkJdmFyIHNldHRpbmdzID0gW107CgkJdmFyIGN0eFNldHRpbmdzID0gZnVuY3Rpb24gKCBvICkgewoJCQl2YXIgYSA9IF90b1NldHRpbmdzKCBvICk7CgkJCWlmICggYSApIHsKCQkJCXNldHRpbmdzLnB1c2guYXBwbHkoIHNldHRpbmdzLCBhICk7CgkJCX0KCQl9OwoJCgkJaWYgKCBBcnJheS5pc0FycmF5KCBjb250ZXh0ICkgKSB7CgkJCWZvciAoIHZhciBpPTAsIGllbj1jb250ZXh0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJY3R4U2V0dGluZ3MoIGNvbnRleHRbaV0gKTsKCQkJfQoJCX0KCQllbHNlIHsKCQkJY3R4U2V0dGluZ3MoIGNvbnRleHQgKTsKCQl9CgkKCQkvLyBSZW1vdmUgZHVwbGljYXRlcwoJCXRoaXMuY29udGV4dCA9IF91bmlxdWUoIHNldHRpbmdzICk7CgkKCQkvLyBJbml0aWFsIGRhdGEKCQlpZiAoIGRhdGEgKSB7CgkJCSQubWVyZ2UoIHRoaXMsIGRhdGEgKTsKCQl9CgkKCQkvLyBzZWxlY3RvcgoJCXRoaXMuc2VsZWN0b3IgPSB7CgkJCXJvd3M6IG51bGwsCgkJCWNvbHM6IG51bGwsCgkJCW9wdHM6IG51bGwKCQl9OwoJCgkJX0FwaS5leHRlbmQoIHRoaXMsIHRoaXMsIF9fYXBpU3RydWN0ICk7Cgl9OwoJCglEYXRhVGFibGUuQXBpID0gX0FwaTsKCQoJLy8gRG9uJ3QgZGVzdHJveSB0aGUgZXhpc3RpbmcgcHJvdG90eXBlLCBqdXN0IGV4dGVuZCBpdC4gUmVxdWlyZWQgZm9yIGpRdWVyeSAyJ3MKCS8vIGlzUGxhaW5PYmplY3QuCgkkLmV4dGVuZCggX0FwaS5wcm90b3R5cGUsIHsKCQlhbnk6IGZ1bmN0aW9uICgpCgkJewoJCQlyZXR1cm4gdGhpcy5jb3VudCgpICE9PSAwOwoJCX0sCgkKCQoJCWNvbmNhdDogIF9fYXJyYXlQcm90by5jb25jYXQsCgkKCQoJCWNvbnRleHQ6IFtdLCAvLyBhcnJheSBvZiB0YWJsZSBzZXR0aW5ncyBvYmplY3RzCgkKCQoJCWNvdW50OiBmdW5jdGlvbiAoKQoJCXsKCQkJcmV0dXJuIHRoaXMuZmxhdHRlbigpLmxlbmd0aDsKCQl9LAoJCgkKCQllYWNoOiBmdW5jdGlvbiAoIGZuICkKCQl7CgkJCWZvciAoIHZhciBpPTAsIGllbj10aGlzLmxlbmd0aCA7IGk8aWVuOyBpKysgKSB7CgkJCQlmbi5jYWxsKCB0aGlzLCB0aGlzW2ldLCBpLCB0aGlzICk7CgkJCX0KCQoJCQlyZXR1cm4gdGhpczsKCQl9LAoJCgkKCQllcTogZnVuY3Rpb24gKCBpZHggKQoJCXsKCQkJdmFyIGN0eCA9IHRoaXMuY29udGV4dDsKCQoJCQlyZXR1cm4gY3R4Lmxlbmd0aCA+IGlkeCA/CgkJCQluZXcgX0FwaSggY3R4W2lkeF0sIHRoaXNbaWR4XSApIDoKCQkJCW51bGw7CgkJfSwKCQoJCgkJZmlsdGVyOiBmdW5jdGlvbiAoIGZuICkKCQl7CgkJCXZhciBhID0gW107CgkKCQkJaWYgKCBfX2FycmF5UHJvdG8uZmlsdGVyICkgewoJCQkJYSA9IF9fYXJyYXlQcm90by5maWx0ZXIuY2FsbCggdGhpcywgZm4sIHRoaXMgKTsKCQkJfQoJCQllbHNlIHsKCQkJCS8vIENvbXBhdGliaWxpdHkgZm9yIGJyb3dzZXJzIHdpdGhvdXQgRU1DQS0yNTItNSAoSlMgMS42KQoJCQkJZm9yICggdmFyIGk9MCwgaWVuPXRoaXMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQkJaWYgKCBmbi5jYWxsKCB0aGlzLCB0aGlzW2ldLCBpLCB0aGlzICkgKSB7CgkJCQkJCWEucHVzaCggdGhpc1tpXSApOwoJCQkJCX0KCQkJCX0KCQkJfQoJCgkJCXJldHVybiBuZXcgX0FwaSggdGhpcy5jb250ZXh0LCBhICk7CgkJfSwKCQoJCgkJZmxhdHRlbjogZnVuY3Rpb24gKCkKCQl7CgkJCXZhciBhID0gW107CgkJCXJldHVybiBuZXcgX0FwaSggdGhpcy5jb250ZXh0LCBhLmNvbmNhdC5hcHBseSggYSwgdGhpcy50b0FycmF5KCkgKSApOwoJCX0sCgkKCQoJCWpvaW46ICAgIF9fYXJyYXlQcm90by5qb2luLAoJCgkKCQlpbmRleE9mOiBfX2FycmF5UHJvdG8uaW5kZXhPZiB8fCBmdW5jdGlvbiAob2JqLCBzdGFydCkKCQl7CgkJCWZvciAoIHZhciBpPShzdGFydCB8fCAwKSwgaWVuPXRoaXMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQlpZiAoIHRoaXNbaV0gPT09IG9iaiApIHsKCQkJCQlyZXR1cm4gaTsKCQkJCX0KCQkJfQoJCQlyZXR1cm4gLTE7CgkJfSwKCQoJCWl0ZXJhdG9yOiBmdW5jdGlvbiAoIGZsYXR0ZW4sIHR5cGUsIGZuLCBhbHdheXNOZXcgKSB7CgkJCXZhcgoJCQkJYSA9IFtdLCByZXQsCgkJCQlpLCBpZW4sIGosIGplbiwKCQkJCWNvbnRleHQgPSB0aGlzLmNvbnRleHQsCgkJCQlyb3dzLCBpdGVtcywgaXRlbSwKCQkJCXNlbGVjdG9yID0gdGhpcy5zZWxlY3RvcjsKCQoJCQkvLyBBcmd1bWVudCBzaGlmdGluZwoJCQlpZiAoIHR5cGVvZiBmbGF0dGVuID09PSAnc3RyaW5nJyApIHsKCQkJCWFsd2F5c05ldyA9IGZuOwoJCQkJZm4gPSB0eXBlOwoJCQkJdHlwZSA9IGZsYXR0ZW47CgkJCQlmbGF0dGVuID0gZmFsc2U7CgkJCX0KCQoJCQlmb3IgKCBpPTAsIGllbj1jb250ZXh0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJdmFyIGFwaUluc3QgPSBuZXcgX0FwaSggY29udGV4dFtpXSApOwoJCgkJCQlpZiAoIHR5cGUgPT09ICd0YWJsZScgKSB7CgkJCQkJcmV0ID0gZm4uY2FsbCggYXBpSW5zdCwgY29udGV4dFtpXSwgaSApOwoJCgkJCQkJaWYgKCByZXQgIT09IHVuZGVmaW5lZCApIHsKCQkJCQkJYS5wdXNoKCByZXQgKTsKCQkJCQl9CgkJCQl9CgkJCQllbHNlIGlmICggdHlwZSA9PT0gJ2NvbHVtbnMnIHx8IHR5cGUgPT09ICdyb3dzJyApIHsKCQkJCQkvLyB0aGlzIGhhcyBzYW1lIGxlbmd0aCBhcyBjb250ZXh0IC0gb25lIGVudHJ5IGZvciBlYWNoIHRhYmxlCgkJCQkJcmV0ID0gZm4uY2FsbCggYXBpSW5zdCwgY29udGV4dFtpXSwgdGhpc1tpXSwgaSApOwoJCgkJCQkJaWYgKCByZXQgIT09IHVuZGVmaW5lZCApIHsKCQkJCQkJYS5wdXNoKCByZXQgKTsKCQkJCQl9CgkJCQl9CgkJCQllbHNlIGlmICggdHlwZSA9PT0gJ2NvbHVtbicgfHwgdHlwZSA9PT0gJ2NvbHVtbi1yb3dzJyB8fCB0eXBlID09PSAncm93JyB8fCB0eXBlID09PSAnY2VsbCcgKSB7CgkJCQkJLy8gY29sdW1ucyBhbmQgcm93cyBzaGFyZSB0aGUgc2FtZSBzdHJ1Y3R1cmUuCgkJCQkJLy8gJ3RoaXMnIGlzIGFuIGFycmF5IG9mIGNvbHVtbiBpbmRleGVzIGZvciBlYWNoIGNvbnRleHQKCQkJCQlpdGVtcyA9IHRoaXNbaV07CgkKCQkJCQlpZiAoIHR5cGUgPT09ICdjb2x1bW4tcm93cycgKSB7CgkJCQkJCXJvd3MgPSBfc2VsZWN0b3Jfcm93X2luZGV4ZXMoIGNvbnRleHRbaV0sIHNlbGVjdG9yLm9wdHMgKTsKCQkJCQl9CgkKCQkJCQlmb3IgKCBqPTAsIGplbj1pdGVtcy5sZW5ndGggOyBqPGplbiA7IGorKyApIHsKCQkJCQkJaXRlbSA9IGl0ZW1zW2pdOwoJCgkJCQkJCWlmICggdHlwZSA9PT0gJ2NlbGwnICkgewoJCQkJCQkJcmV0ID0gZm4uY2FsbCggYXBpSW5zdCwgY29udGV4dFtpXSwgaXRlbS5yb3csIGl0ZW0uY29sdW1uLCBpLCBqICk7CgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQlyZXQgPSBmbi5jYWxsKCBhcGlJbnN0LCBjb250ZXh0W2ldLCBpdGVtLCBpLCBqLCByb3dzICk7CgkJCQkJCX0KCQoJCQkJCQlpZiAoIHJldCAhPT0gdW5kZWZpbmVkICkgewoJCQkJCQkJYS5wdXNoKCByZXQgKTsKCQkJCQkJfQoJCQkJCX0KCQkJCX0KCQkJfQoJCgkJCWlmICggYS5sZW5ndGggfHwgYWx3YXlzTmV3ICkgewoJCQkJdmFyIGFwaSA9IG5ldyBfQXBpKCBjb250ZXh0LCBmbGF0dGVuID8gYS5jb25jYXQuYXBwbHkoIFtdLCBhICkgOiBhICk7CgkJCQl2YXIgYXBpU2VsZWN0b3IgPSBhcGkuc2VsZWN0b3I7CgkJCQlhcGlTZWxlY3Rvci5yb3dzID0gc2VsZWN0b3Iucm93czsKCQkJCWFwaVNlbGVjdG9yLmNvbHMgPSBzZWxlY3Rvci5jb2xzOwoJCQkJYXBpU2VsZWN0b3Iub3B0cyA9IHNlbGVjdG9yLm9wdHM7CgkJCQlyZXR1cm4gYXBpOwoJCQl9CgkJCXJldHVybiB0aGlzOwoJCX0sCgkKCQoJCWxhc3RJbmRleE9mOiBfX2FycmF5UHJvdG8ubGFzdEluZGV4T2YgfHwgZnVuY3Rpb24gKG9iaiwgc3RhcnQpCgkJewoJCQkvLyBCaXQgY2hlZWt5Li4uCgkJCXJldHVybiB0aGlzLmluZGV4T2YuYXBwbHkoIHRoaXMudG9BcnJheS5yZXZlcnNlKCksIGFyZ3VtZW50cyApOwoJCX0sCgkKCQoJCWxlbmd0aDogIDAsCgkKCQoJCW1hcDogZnVuY3Rpb24gKCBmbiApCgkJewoJCQl2YXIgYSA9IFtdOwoJCgkJCWlmICggX19hcnJheVByb3RvLm1hcCApIHsKCQkJCWEgPSBfX2FycmF5UHJvdG8ubWFwLmNhbGwoIHRoaXMsIGZuLCB0aGlzICk7CgkJCX0KCQkJZWxzZSB7CgkJCQkvLyBDb21wYXRpYmlsaXR5IGZvciBicm93c2VycyB3aXRob3V0IEVNQ0EtMjUyLTUgKEpTIDEuNikKCQkJCWZvciAoIHZhciBpPTAsIGllbj10aGlzLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJCWEucHVzaCggZm4uY2FsbCggdGhpcywgdGhpc1tpXSwgaSApICk7CgkJCQl9CgkJCX0KCQoJCQlyZXR1cm4gbmV3IF9BcGkoIHRoaXMuY29udGV4dCwgYSApOwoJCX0sCgkKCQoJCXBsdWNrOiBmdW5jdGlvbiAoIHByb3AgKQoJCXsKCQkJbGV0IGZuID0gRGF0YVRhYmxlLnV0aWwuZ2V0KHByb3ApOwoJCgkJCXJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24gKCBlbCApIHsKCQkJCXJldHVybiBmbihlbCk7CgkJCX0gKTsKCQl9LAoJCgkJcG9wOiAgICAgX19hcnJheVByb3RvLnBvcCwKCQoJCgkJcHVzaDogICAgX19hcnJheVByb3RvLnB1c2gsCgkKCQoJCS8vIERvZXMgbm90IHJldHVybiBhbiBBUEkgaW5zdGFuY2UKCQlyZWR1Y2U6IF9fYXJyYXlQcm90by5yZWR1Y2UgfHwgZnVuY3Rpb24gKCBmbiwgaW5pdCApCgkJewoJCQlyZXR1cm4gX2ZuUmVkdWNlKCB0aGlzLCBmbiwgaW5pdCwgMCwgdGhpcy5sZW5ndGgsIDEgKTsKCQl9LAoJCgkKCQlyZWR1Y2VSaWdodDogX19hcnJheVByb3RvLnJlZHVjZVJpZ2h0IHx8IGZ1bmN0aW9uICggZm4sIGluaXQgKQoJCXsKCQkJcmV0dXJuIF9mblJlZHVjZSggdGhpcywgZm4sIGluaXQsIHRoaXMubGVuZ3RoLTEsIC0xLCAtMSApOwoJCX0sCgkKCQoJCXJldmVyc2U6IF9fYXJyYXlQcm90by5yZXZlcnNlLAoJCgkKCQkvLyBPYmplY3Qgd2l0aCByb3dzLCBjb2x1bW5zIGFuZCBvcHRzCgkJc2VsZWN0b3I6IG51bGwsCgkKCQoJCXNoaWZ0OiAgIF9fYXJyYXlQcm90by5zaGlmdCwKCQoJCgkJc2xpY2U6IGZ1bmN0aW9uICgpIHsKCQkJcmV0dXJuIG5ldyBfQXBpKCB0aGlzLmNvbnRleHQsIHRoaXMgKTsKCQl9LAoJCgkKCQlzb3J0OiAgICBfX2FycmF5UHJvdG8uc29ydCwgLy8gPyBuYW1lIC0gb3JkZXI/CgkKCQoJCXNwbGljZTogIF9fYXJyYXlQcm90by5zcGxpY2UsCgkKCQoJCXRvQXJyYXk6IGZ1bmN0aW9uICgpCgkJewoJCQlyZXR1cm4gX19hcnJheVByb3RvLnNsaWNlLmNhbGwoIHRoaXMgKTsKCQl9LAoJCgkKCQl0byQ6IGZ1bmN0aW9uICgpCgkJewoJCQlyZXR1cm4gJCggdGhpcyApOwoJCX0sCgkKCQoJCXRvSlF1ZXJ5OiBmdW5jdGlvbiAoKQoJCXsKCQkJcmV0dXJuICQoIHRoaXMgKTsKCQl9LAoJCgkKCQl1bmlxdWU6IGZ1bmN0aW9uICgpCgkJewoJCQlyZXR1cm4gbmV3IF9BcGkoIHRoaXMuY29udGV4dCwgX3VuaXF1ZSh0aGlzKSApOwoJCX0sCgkKCQoJCXVuc2hpZnQ6IF9fYXJyYXlQcm90by51bnNoaWZ0Cgl9ICk7CgkKCQoJX0FwaS5leHRlbmQgPSBmdW5jdGlvbiAoIHNjb3BlLCBvYmosIGV4dCApCgl7CgkJLy8gT25seSBleHRlbmQgQVBJIGluc3RhbmNlcyBhbmQgc3RhdGljIHByb3BlcnRpZXMgb2YgdGhlIEFQSQoJCWlmICggISBleHQubGVuZ3RoIHx8ICEgb2JqIHx8ICggISAob2JqIGluc3RhbmNlb2YgX0FwaSkgJiYgISBvYmouX19kdF93cmFwcGVyICkgKSB7CgkJCXJldHVybjsKCQl9CgkKCQl2YXIKCQkJaSwgaWVuLAoJCQlzdHJ1Y3QsCgkJCW1ldGhvZFNjb3BpbmcgPSBmdW5jdGlvbiAoIHNjb3BlLCBmbiwgc3RydWMgKSB7CgkJCQlyZXR1cm4gZnVuY3Rpb24gKCkgewoJCQkJCXZhciByZXQgPSBmbi5hcHBseSggc2NvcGUsIGFyZ3VtZW50cyApOwoJCgkJCQkJLy8gTWV0aG9kIGV4dGVuc2lvbgoJCQkJCV9BcGkuZXh0ZW5kKCByZXQsIHJldCwgc3RydWMubWV0aG9kRXh0ICk7CgkJCQkJcmV0dXJuIHJldDsKCQkJCX07CgkJCX07CgkKCQlmb3IgKCBpPTAsIGllbj1leHQubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCXN0cnVjdCA9IGV4dFtpXTsKCQoJCQkvLyBWYWx1ZQoJCQlvYmpbIHN0cnVjdC5uYW1lIF0gPSBzdHJ1Y3QudHlwZSA9PT0gJ2Z1bmN0aW9uJyA/CgkJCQltZXRob2RTY29waW5nKCBzY29wZSwgc3RydWN0LnZhbCwgc3RydWN0ICkgOgoJCQkJc3RydWN0LnR5cGUgPT09ICdvYmplY3QnID8KCQkJCQl7fSA6CgkJCQkJc3RydWN0LnZhbDsKCQoJCQlvYmpbIHN0cnVjdC5uYW1lIF0uX19kdF93cmFwcGVyID0gdHJ1ZTsKCQoJCQkvLyBQcm9wZXJ0eSBleHRlbnNpb24KCQkJX0FwaS5leHRlbmQoIHNjb3BlLCBvYmpbIHN0cnVjdC5uYW1lIF0sIHN0cnVjdC5wcm9wRXh0ICk7CgkJfQoJfTsKCQoJCgkvLyBAdG9kbyAtIElzIHRoZXJlIG5lZWQgZm9yIGFuIGF1Z21lbnQgZnVuY3Rpb24/CgkvLyBfQXBpLmF1Z21lbnQgPSBmdW5jdGlvbiAoIGluc3QsIG5hbWUgKQoJLy8gewoJLy8gCS8vIEZpbmQgc3JjIG9iamVjdCBpbiB0aGUgc3RydWN0dXJlIGZyb20gdGhlIG5hbWUKCS8vIAl2YXIgcGFydHMgPSBuYW1lLnNwbGl0KCcuJyk7CgkKCS8vIAlfQXBpLmV4dGVuZCggaW5zdCwgb2JqICk7CgkvLyB9OwoJCgkKCS8vICAgICBbCgkvLyAgICAgICB7CgkvLyAgICAgICAgIG5hbWU6ICAgICAgJ2RhdGEnICAgICAgICAgICAgICAgIC0tIHN0cmluZyAgIC0gUHJvcGVydHkgbmFtZQoJLy8gICAgICAgICB2YWw6ICAgICAgIGZ1bmN0aW9uICgpIHt9LCAgICAgICAtLSBmdW5jdGlvbiAtIEFwaSBtZXRob2QgKG9yIHVuZGVmaW5lZCBpZiBqdXN0IGFuIG9iamVjdAoJLy8gICAgICAgICBtZXRob2RFeHQ6IFsgLi4uIF0sICAgICAgICAgICAgICAtLSBhcnJheSAgICAtIEFycmF5IG9mIEFwaSBvYmplY3QgZGVmaW5pdGlvbnMgdG8gZXh0ZW5kIHRoZSBtZXRob2QgcmVzdWx0CgkvLyAgICAgICAgIHByb3BFeHQ6ICAgWyAuLi4gXSAgICAgICAgICAgICAgIC0tIGFycmF5ICAgIC0gQXJyYXkgb2YgQXBpIG9iamVjdCBkZWZpbml0aW9ucyB0byBleHRlbmQgdGhlIHByb3BlcnR5CgkvLyAgICAgICB9LAoJLy8gICAgICAgewoJLy8gICAgICAgICBuYW1lOiAgICAgJ3JvdycKCS8vICAgICAgICAgdmFsOiAgICAgICB7fSwKCS8vICAgICAgICAgbWV0aG9kRXh0OiBbIC4uLiBdLAoJLy8gICAgICAgICBwcm9wRXh0OiAgIFsKCS8vICAgICAgICAgICB7CgkvLyAgICAgICAgICAgICBuYW1lOiAgICAgICdkYXRhJwoJLy8gICAgICAgICAgICAgdmFsOiAgICAgICBmdW5jdGlvbiAoKSB7fSwKCS8vICAgICAgICAgICAgIG1ldGhvZEV4dDogWyAuLi4gXSwKCS8vICAgICAgICAgICAgIHByb3BFeHQ6ICAgWyAuLi4gXQoJLy8gICAgICAgICAgIH0sCgkvLyAgICAgICAgICAgLi4uCgkvLyAgICAgICAgIF0KCS8vICAgICAgIH0KCS8vICAgICBdCgkKCV9BcGkucmVnaXN0ZXIgPSBfYXBpX3JlZ2lzdGVyID0gZnVuY3Rpb24gKCBuYW1lLCB2YWwgKQoJewoJCWlmICggQXJyYXkuaXNBcnJheSggbmFtZSApICkgewoJCQlmb3IgKCB2YXIgaj0wLCBqZW49bmFtZS5sZW5ndGggOyBqPGplbiA7IGorKyApIHsKCQkJCV9BcGkucmVnaXN0ZXIoIG5hbWVbal0sIHZhbCApOwoJCQl9CgkJCXJldHVybjsKCQl9CgkKCQl2YXIKCQkJaSwgaWVuLAoJCQloZWlyID0gbmFtZS5zcGxpdCgnLicpLAoJCQlzdHJ1Y3QgPSBfX2FwaVN0cnVjdCwKCQkJa2V5LCBtZXRob2Q7CgkKCQl2YXIgZmluZCA9IGZ1bmN0aW9uICggc3JjLCBuYW1lICkgewoJCQlmb3IgKCB2YXIgaT0wLCBpZW49c3JjLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJaWYgKCBzcmNbaV0ubmFtZSA9PT0gbmFtZSApIHsKCQkJCQlyZXR1cm4gc3JjW2ldOwoJCQkJfQoJCQl9CgkJCXJldHVybiBudWxsOwoJCX07CgkKCQlmb3IgKCBpPTAsIGllbj1oZWlyLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQltZXRob2QgPSBoZWlyW2ldLmluZGV4T2YoJygpJykgIT09IC0xOwoJCQlrZXkgPSBtZXRob2QgPwoJCQkJaGVpcltpXS5yZXBsYWNlKCcoKScsICcnKSA6CgkJCQloZWlyW2ldOwoJCgkJCXZhciBzcmMgPSBmaW5kKCBzdHJ1Y3QsIGtleSApOwoJCQlpZiAoICEgc3JjICkgewoJCQkJc3JjID0gewoJCQkJCW5hbWU6ICAgICAga2V5LAoJCQkJCXZhbDogICAgICAge30sCgkJCQkJbWV0aG9kRXh0OiBbXSwKCQkJCQlwcm9wRXh0OiAgIFtdLAoJCQkJCXR5cGU6ICAgICAgJ29iamVjdCcKCQkJCX07CgkJCQlzdHJ1Y3QucHVzaCggc3JjICk7CgkJCX0KCQoJCQlpZiAoIGkgPT09IGllbi0xICkgewoJCQkJc3JjLnZhbCA9IHZhbDsKCQkJCXNyYy50eXBlID0gdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJyA/CgkJCQkJJ2Z1bmN0aW9uJyA6CgkJCQkJJC5pc1BsYWluT2JqZWN0KCB2YWwgKSA/CgkJCQkJCSdvYmplY3QnIDoKCQkJCQkJJ290aGVyJzsKCQkJfQoJCQllbHNlIHsKCQkJCXN0cnVjdCA9IG1ldGhvZCA/CgkJCQkJc3JjLm1ldGhvZEV4dCA6CgkJCQkJc3JjLnByb3BFeHQ7CgkJCX0KCQl9Cgl9OwoJCglfQXBpLnJlZ2lzdGVyUGx1cmFsID0gX2FwaV9yZWdpc3RlclBsdXJhbCA9IGZ1bmN0aW9uICggcGx1cmFsTmFtZSwgc2luZ3VsYXJOYW1lLCB2YWwgKSB7CgkJX0FwaS5yZWdpc3RlciggcGx1cmFsTmFtZSwgdmFsICk7CgkKCQlfQXBpLnJlZ2lzdGVyKCBzaW5ndWxhck5hbWUsIGZ1bmN0aW9uICgpIHsKCQkJdmFyIHJldCA9IHZhbC5hcHBseSggdGhpcywgYXJndW1lbnRzICk7CgkKCQkJaWYgKCByZXQgPT09IHRoaXMgKSB7CgkJCQkvLyBSZXR1cm5lZCBpdGVtIGlzIHRoZSBBUEkgaW5zdGFuY2UgdGhhdCB3YXMgcGFzc2VkIGluLCByZXR1cm4gaXQKCQkJCXJldHVybiB0aGlzOwoJCQl9CgkJCWVsc2UgaWYgKCByZXQgaW5zdGFuY2VvZiBfQXBpICkgewoJCQkJLy8gTmV3IEFQSSBpbnN0YW5jZSByZXR1cm5lZCwgd2FudCB0aGUgdmFsdWUgZnJvbSB0aGUgZmlyc3QgaXRlbQoJCQkJLy8gaW4gdGhlIHJldHVybmVkIGFycmF5IGZvciB0aGUgc2luZ3VsYXIgcmVzdWx0LgoJCQkJcmV0dXJuIHJldC5sZW5ndGggPwoJCQkJCUFycmF5LmlzQXJyYXkoIHJldFswXSApID8KCQkJCQkJbmV3IF9BcGkoIHJldC5jb250ZXh0LCByZXRbMF0gKSA6IC8vIEFycmF5IHJlc3VsdHMgYXJlICdlbmhhbmNlZCcKCQkJCQkJcmV0WzBdIDoKCQkJCQl1bmRlZmluZWQ7CgkJCX0KCQoJCQkvLyBOb24tQVBJIHJldHVybiAtIGp1c3QgZmlyZSBpdCBiYWNrCgkJCXJldHVybiByZXQ7CgkJfSApOwoJfTsKCQoJCgkvKioKCSAqIFNlbGVjdG9yIGZvciBIVE1MIHRhYmxlcy4gQXBwbHkgdGhlIGdpdmVuIHNlbGVjdG9yIHRvIHRoZSBnaXZlIGFycmF5IG9mCgkgKiBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdHMuCgkgKgoJICogQHBhcmFtIHtzdHJpbmd8aW50ZWdlcn0gW3NlbGVjdG9yXSBqUXVlcnkgc2VsZWN0b3Igc3RyaW5nIG9yIGludGVnZXIKCSAqIEBwYXJhbSAge2FycmF5fSBBcnJheSBvZiBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdHMgdG8gYmUgZmlsdGVyZWQKCSAqIEByZXR1cm4ge2FycmF5fQoJICogQGlnbm9yZQoJICovCgl2YXIgX190YWJsZV9zZWxlY3RvciA9IGZ1bmN0aW9uICggc2VsZWN0b3IsIGEgKQoJewoJCWlmICggQXJyYXkuaXNBcnJheShzZWxlY3RvcikgKSB7CgkJCXJldHVybiAkLm1hcCggc2VsZWN0b3IsIGZ1bmN0aW9uIChpdGVtKSB7CgkJCQlyZXR1cm4gX190YWJsZV9zZWxlY3RvcihpdGVtLCBhKTsKCQkJfSApOwoJCX0KCQoJCS8vIEludGVnZXIgaXMgdXNlZCB0byBwaWNrIG91dCBhIHRhYmxlIGJ5IGluZGV4CgkJaWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09ICdudW1iZXInICkgewoJCQlyZXR1cm4gWyBhWyBzZWxlY3RvciBdIF07CgkJfQoJCgkJLy8gUGVyZm9ybSBhIGpRdWVyeSBzZWxlY3RvciBvbiB0aGUgdGFibGUgbm9kZXMKCQl2YXIgbm9kZXMgPSAkLm1hcCggYSwgZnVuY3Rpb24gKGVsLCBpKSB7CgkJCXJldHVybiBlbC5uVGFibGU7CgkJfSApOwoJCgkJcmV0dXJuICQobm9kZXMpCgkJCS5maWx0ZXIoIHNlbGVjdG9yICkKCQkJLm1hcCggZnVuY3Rpb24gKGkpIHsKCQkJCS8vIE5lZWQgdG8gdHJhbnNsYXRlIGJhY2sgZnJvbSB0aGUgdGFibGUgbm9kZSB0byB0aGUgc2V0dGluZ3MKCQkJCXZhciBpZHggPSAkLmluQXJyYXkoIHRoaXMsIG5vZGVzICk7CgkJCQlyZXR1cm4gYVsgaWR4IF07CgkJCX0gKQoJCQkudG9BcnJheSgpOwoJfTsKCQoJCgkKCS8qKgoJICogQ29udGV4dCBzZWxlY3RvciBmb3IgdGhlIEFQSSdzIGNvbnRleHQgKGkuZS4gdGhlIHRhYmxlcyB0aGUgQVBJIGluc3RhbmNlCgkgKiByZWZlcnMgdG8uCgkgKgoJICogQG5hbWUgICAgRGF0YVRhYmxlLkFwaSN0YWJsZXMKCSAqIEBwYXJhbSB7c3RyaW5nfGludGVnZXJ9IFtzZWxlY3Rvcl0gU2VsZWN0b3IgdG8gcGljayB3aGljaCB0YWJsZXMgdGhlIGl0ZXJhdG9yCgkgKiAgIHNob3VsZCBvcGVyYXRlIG9uLiBJZiBub3QgZ2l2ZW4sIGFsbCB0YWJsZXMgaW4gdGhlIGN1cnJlbnQgY29udGV4dCBhcmUKCSAqICAgdXNlZC4gVGhpcyBjYW4gYmUgZ2l2ZW4gYXMgYSBqUXVlcnkgc2VsZWN0b3IgKGZvciBleGFtcGxlIGAnOmd0KDApJ2ApIHRvCgkgKiAgIHNlbGVjdCBtdWx0aXBsZSB0YWJsZXMgb3IgYXMgYW4gaW50ZWdlciB0byBzZWxlY3QgYSBzaW5nbGUgdGFibGUuCgkgKiBAcmV0dXJucyB7RGF0YVRhYmxlLkFwaX0gUmV0dXJucyBhIG5ldyBBUEkgaW5zdGFuY2UgaWYgYSBzZWxlY3RvciBpcyBnaXZlbi4KCSAqLwoJX2FwaV9yZWdpc3RlciggJ3RhYmxlcygpJywgZnVuY3Rpb24gKCBzZWxlY3RvciApIHsKCQkvLyBBIG5ldyBpbnN0YW5jZSBpcyBjcmVhdGVkIGlmIHRoZXJlIHdhcyBhIHNlbGVjdG9yIHNwZWNpZmllZAoJCXJldHVybiBzZWxlY3RvciAhPT0gdW5kZWZpbmVkICYmIHNlbGVjdG9yICE9PSBudWxsID8KCQkJbmV3IF9BcGkoIF9fdGFibGVfc2VsZWN0b3IoIHNlbGVjdG9yLCB0aGlzLmNvbnRleHQgKSApIDoKCQkJdGhpczsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCAndGFibGUoKScsIGZ1bmN0aW9uICggc2VsZWN0b3IgKSB7CgkJdmFyIHRhYmxlcyA9IHRoaXMudGFibGVzKCBzZWxlY3RvciApOwoJCXZhciBjdHggPSB0YWJsZXMuY29udGV4dDsKCQoJCS8vIFRydW5jYXRlIHRvIHRoZSBmaXJzdCBtYXRjaGVkIHRhYmxlCgkJcmV0dXJuIGN0eC5sZW5ndGggPwoJCQluZXcgX0FwaSggY3R4WzBdICkgOgoJCQl0YWJsZXM7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlclBsdXJhbCggJ3RhYmxlcygpLm5vZGVzKCknLCAndGFibGUoKS5ub2RlKCknICwgZnVuY3Rpb24gKCkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHsKCQkJcmV0dXJuIGN0eC5uVGFibGU7CgkJfSwgMSApOwoJfSApOwoJCgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICd0YWJsZXMoKS5ib2R5KCknLCAndGFibGUoKS5ib2R5KCknICwgZnVuY3Rpb24gKCkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHsKCQkJcmV0dXJuIGN0eC5uVEJvZHk7CgkJfSwgMSApOwoJfSApOwoJCgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICd0YWJsZXMoKS5oZWFkZXIoKScsICd0YWJsZSgpLmhlYWRlcigpJyAsIGZ1bmN0aW9uICgpIHsKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBjdHggKSB7CgkJCXJldHVybiBjdHgublRIZWFkOwoJCX0sIDEgKTsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyUGx1cmFsKCAndGFibGVzKCkuZm9vdGVyKCknLCAndGFibGUoKS5mb290ZXIoKScgLCBmdW5jdGlvbiAoKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggY3R4ICkgewoJCQlyZXR1cm4gY3R4Lm5URm9vdDsKCQl9LCAxICk7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlclBsdXJhbCggJ3RhYmxlcygpLmNvbnRhaW5lcnMoKScsICd0YWJsZSgpLmNvbnRhaW5lcigpJyAsIGZ1bmN0aW9uICgpIHsKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBjdHggKSB7CgkJCXJldHVybiBjdHgublRhYmxlV3JhcHBlcjsKCQl9LCAxICk7Cgl9ICk7CgkKCQoJCgkvKioKCSAqIFJlZHJhdyB0aGUgdGFibGVzIGluIHRoZSBjdXJyZW50IGNvbnRleHQuCgkgKi8KCV9hcGlfcmVnaXN0ZXIoICdkcmF3KCknLCBmdW5jdGlvbiAoIHBhZ2luZyApIHsKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHsKCQkJaWYgKCBwYWdpbmcgPT09ICdwYWdlJyApIHsKCQkJCV9mbkRyYXcoIHNldHRpbmdzICk7CgkJCX0KCQkJZWxzZSB7CgkJCQlpZiAoIHR5cGVvZiBwYWdpbmcgPT09ICdzdHJpbmcnICkgewoJCQkJCXBhZ2luZyA9IHBhZ2luZyA9PT0gJ2Z1bGwtaG9sZCcgPwoJCQkJCQlmYWxzZSA6CgkJCQkJCXRydWU7CgkJCQl9CgkKCQkJCV9mblJlRHJhdyggc2V0dGluZ3MsIHBhZ2luZz09PWZhbHNlICk7CgkJCX0KCQl9ICk7Cgl9ICk7CgkKCQoJCgkvKioKCSAqIEdldCB0aGUgY3VycmVudCBwYWdlIGluZGV4LgoJICoKCSAqIEByZXR1cm4ge2ludGVnZXJ9IEN1cnJlbnQgcGFnZSBpbmRleCAoemVybyBiYXNlZCkKCSAqLy8qKgoJICogU2V0IHRoZSBjdXJyZW50IHBhZ2UuCgkgKgoJICogTm90ZSB0aGF0IGlmIHlvdSBhdHRlbXB0IHRvIHNob3cgYSBwYWdlIHdoaWNoIGRvZXMgbm90IGV4aXN0LCBEYXRhVGFibGVzIHdpbGwKCSAqIG5vdCB0aHJvdyBhbiBlcnJvciwgYnV0IHJhdGhlciByZXNldCB0aGUgcGFnaW5nLgoJICoKCSAqIEBwYXJhbSB7aW50ZWdlcnxzdHJpbmd9IGFjdGlvbiBUaGUgcGFnaW5nIGFjdGlvbiB0byB0YWtlLiBUaGlzIGNhbiBiZSBvbmUgb2Y6CgkgKiAgKiBgaW50ZWdlcmAgLSBUaGUgcGFnZSBpbmRleCB0byBqdW1wIHRvCgkgKiAgKiBgc3RyaW5nYCAtIEFuIGFjdGlvbiB0byB0YWtlOgoJICogICAgKiBgZmlyc3RgIC0gSnVtcCB0byBmaXJzdCBwYWdlLgoJICogICAgKiBgbmV4dGAgLSBKdW1wIHRvIHRoZSBuZXh0IHBhZ2UKCSAqICAgICogYHByZXZpb3VzYCAtIEp1bXAgdG8gcHJldmlvdXMgcGFnZQoJICogICAgKiBgbGFzdGAgLSBKdW1wIHRvIHRoZSBsYXN0IHBhZ2UuCgkgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXMKCSAqLwoJX2FwaV9yZWdpc3RlciggJ3BhZ2UoKScsIGZ1bmN0aW9uICggYWN0aW9uICkgewoJCWlmICggYWN0aW9uID09PSB1bmRlZmluZWQgKSB7CgkJCXJldHVybiB0aGlzLnBhZ2UuaW5mbygpLnBhZ2U7IC8vIG5vdCBhbiBleHBlbnNpdmUgY2FsbAoJCX0KCQoJCS8vIGVsc2UsIGhhdmUgYW4gYWN0aW9uIHRvIHRha2Ugb24gYWxsIHRhYmxlcwoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkgewoJCQlfZm5QYWdlQ2hhbmdlKCBzZXR0aW5ncywgYWN0aW9uICk7CgkJfSApOwoJfSApOwoJCgkKCS8qKgoJICogUGFnaW5nIGluZm9ybWF0aW9uIGZvciB0aGUgZmlyc3QgdGFibGUgaW4gdGhlIGN1cnJlbnQgY29udGV4dC4KCSAqCgkgKiBJZiB5b3UgcmVxdWlyZSBwYWdpbmcgaW5mb3JtYXRpb24gZm9yIGFub3RoZXIgdGFibGUsIHVzZSB0aGUgYHRhYmxlKClgIG1ldGhvZAoJICogd2l0aCBhIHN1aXRhYmxlIHNlbGVjdG9yLgoJICoKCSAqIEByZXR1cm4ge29iamVjdH0gT2JqZWN0IHdpdGggdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzIHNldDoKCSAqICAqIGBwYWdlYCAtIEN1cnJlbnQgcGFnZSBpbmRleCAoemVybyBiYXNlZCAtIGkuZS4gdGhlIGZpcnN0IHBhZ2UgaXMgYDBgKQoJICogICogYHBhZ2VzYCAtIFRvdGFsIG51bWJlciBvZiBwYWdlcwoJICogICogYHN0YXJ0YCAtIERpc3BsYXkgaW5kZXggZm9yIHRoZSBmaXJzdCByZWNvcmQgc2hvd24gb24gdGhlIGN1cnJlbnQgcGFnZQoJICogICogYGVuZGAgLSBEaXNwbGF5IGluZGV4IGZvciB0aGUgbGFzdCByZWNvcmQgc2hvd24gb24gdGhlIGN1cnJlbnQgcGFnZQoJICogICogYGxlbmd0aGAgLSBEaXNwbGF5IGxlbmd0aCAobnVtYmVyIG9mIHJlY29yZHMpLiBOb3RlIHRoYXQgZ2VuZXJhbGx5IGBzdGFydAoJICogICAgKyBsZW5ndGggPSBlbmRgLCBidXQgdGhpcyBpcyBub3QgYWx3YXlzIHRydWUsIGZvciBleGFtcGxlIGlmIHRoZXJlIGFyZQoJICogICAgb25seSAyIHJlY29yZHMgdG8gc2hvdyBvbiB0aGUgZmluYWwgcGFnZSwgd2l0aCBhIGxlbmd0aCBvZiAxMC4KCSAqICAqIGByZWNvcmRzVG90YWxgIC0gRnVsbCBkYXRhIHNldCBsZW5ndGgKCSAqICAqIGByZWNvcmRzRGlzcGxheWAgLSBEYXRhIHNldCBsZW5ndGggb25jZSB0aGUgY3VycmVudCBmaWx0ZXJpbmcgY3JpdGVyaW9uCgkgKiAgICBhcmUgYXBwbGllZC4KCSAqLwoJX2FwaV9yZWdpc3RlciggJ3BhZ2UuaW5mbygpJywgZnVuY3Rpb24gKCBhY3Rpb24gKSB7CgkJaWYgKCB0aGlzLmNvbnRleHQubGVuZ3RoID09PSAwICkgewoJCQlyZXR1cm4gdW5kZWZpbmVkOwoJCX0KCQoJCXZhcgoJCQlzZXR0aW5ncyAgID0gdGhpcy5jb250ZXh0WzBdLAoJCQlzdGFydCAgICAgID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsCgkJCWxlbiAgICAgICAgPSBzZXR0aW5ncy5vRmVhdHVyZXMuYlBhZ2luYXRlID8gc2V0dGluZ3MuX2lEaXNwbGF5TGVuZ3RoIDogLTEsCgkJCXZpc1JlY29yZHMgPSBzZXR0aW5ncy5mblJlY29yZHNEaXNwbGF5KCksCgkJCWFsbCAgICAgICAgPSBsZW4gPT09IC0xOwoJCgkJcmV0dXJuIHsKCQkJInBhZ2UiOiAgICAgICAgICAgYWxsID8gMCA6IE1hdGguZmxvb3IoIHN0YXJ0IC8gbGVuICksCgkJCSJwYWdlcyI6ICAgICAgICAgIGFsbCA/IDEgOiBNYXRoLmNlaWwoIHZpc1JlY29yZHMgLyBsZW4gKSwKCQkJInN0YXJ0IjogICAgICAgICAgc3RhcnQsCgkJCSJlbmQiOiAgICAgICAgICAgIHNldHRpbmdzLmZuRGlzcGxheUVuZCgpLAoJCQkibGVuZ3RoIjogICAgICAgICBsZW4sCgkJCSJyZWNvcmRzVG90YWwiOiAgIHNldHRpbmdzLmZuUmVjb3Jkc1RvdGFsKCksCgkJCSJyZWNvcmRzRGlzcGxheSI6IHZpc1JlY29yZHMsCgkJCSJzZXJ2ZXJTaWRlIjogICAgIF9mbkRhdGFTb3VyY2UoIHNldHRpbmdzICkgPT09ICdzc3AnCgkJfTsKCX0gKTsKCQoJCgkvKioKCSAqIEdldCB0aGUgY3VycmVudCBwYWdlIGxlbmd0aC4KCSAqCgkgKiBAcmV0dXJuIHtpbnRlZ2VyfSBDdXJyZW50IHBhZ2UgbGVuZ3RoLiBOb3RlIGAtMWAgaW5kaWNhdGVzIHRoYXQgYWxsIHJlY29yZHMKCSAqICAgYXJlIHRvIGJlIHNob3duLgoJICovLyoqCgkgKiBTZXQgdGhlIGN1cnJlbnQgcGFnZSBsZW5ndGguCgkgKgoJICogQHBhcmFtIHtpbnRlZ2VyfSBQYWdlIGxlbmd0aCB0byBzZXQuIFVzZSBgLTFgIHRvIHNob3cgYWxsIHJlY29yZHMuCgkgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXMKCSAqLwoJX2FwaV9yZWdpc3RlciggJ3BhZ2UubGVuKCknLCBmdW5jdGlvbiAoIGxlbiApIHsKCQkvLyBOb3RlIHRoYXQgd2UgY2FuJ3QgY2FsbCB0aGlzIGZ1bmN0aW9uICdsZW5ndGgoKScgYmVjYXVzZSBgbGVuZ3RoYAoJCS8vIGlzIGEgSmF2YXNjcmlwdCBwcm9wZXJ0eSBvZiBmdW5jdGlvbnMgd2hpY2ggZGVmaW5lcyBob3cgbWFueSBhcmd1bWVudHMKCQkvLyB0aGUgZnVuY3Rpb24gZXhwZWN0cy4KCQlpZiAoIGxlbiA9PT0gdW5kZWZpbmVkICkgewoJCQlyZXR1cm4gdGhpcy5jb250ZXh0Lmxlbmd0aCAhPT0gMCA/CgkJCQl0aGlzLmNvbnRleHRbMF0uX2lEaXNwbGF5TGVuZ3RoIDoKCQkJCXVuZGVmaW5lZDsKCQl9CgkKCQkvLyBlbHNlLCBzZXQgdGhlIHBhZ2UgbGVuZ3RoCgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7CgkJCV9mbkxlbmd0aENoYW5nZSggc2V0dGluZ3MsIGxlbiApOwoJCX0gKTsKCX0gKTsKCQoJCgkKCXZhciBfX3JlbG9hZCA9IGZ1bmN0aW9uICggc2V0dGluZ3MsIGhvbGRQb3NpdGlvbiwgY2FsbGJhY2sgKSB7CgkJLy8gVXNlIHRoZSBkcmF3IGV2ZW50IHRvIHRyaWdnZXIgYSBjYWxsYmFjawoJCWlmICggY2FsbGJhY2sgKSB7CgkJCXZhciBhcGkgPSBuZXcgX0FwaSggc2V0dGluZ3MgKTsKCQoJCQlhcGkub25lKCAnZHJhdycsIGZ1bmN0aW9uICgpIHsKCQkJCWNhbGxiYWNrKCBhcGkuYWpheC5qc29uKCkgKTsKCQkJfSApOwoJCX0KCQoJCWlmICggX2ZuRGF0YVNvdXJjZSggc2V0dGluZ3MgKSA9PSAnc3NwJyApIHsKCQkJX2ZuUmVEcmF3KCBzZXR0aW5ncywgaG9sZFBvc2l0aW9uICk7CgkJfQoJCWVsc2UgewoJCQlfZm5Qcm9jZXNzaW5nRGlzcGxheSggc2V0dGluZ3MsIHRydWUgKTsKCQoJCQkvLyBDYW5jZWwgYW4gZXhpc3RpbmcgcmVxdWVzdAoJCQl2YXIgeGhyID0gc2V0dGluZ3MuanFYSFI7CgkJCWlmICggeGhyICYmIHhoci5yZWFkeVN0YXRlICE9PSA0ICkgewoJCQkJeGhyLmFib3J0KCk7CgkJCX0KCQoJCQkvLyBUcmlnZ2VyIHhocgoJCQlfZm5CdWlsZEFqYXgoIHNldHRpbmdzLCBbXSwgZnVuY3Rpb24oIGpzb24gKSB7CgkJCQlfZm5DbGVhclRhYmxlKCBzZXR0aW5ncyApOwoJCgkJCQl2YXIgZGF0YSA9IF9mbkFqYXhEYXRhU3JjKCBzZXR0aW5ncywganNvbiApOwoJCQkJZm9yICggdmFyIGk9MCwgaWVuPWRhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQkJX2ZuQWRkRGF0YSggc2V0dGluZ3MsIGRhdGFbaV0gKTsKCQkJCX0KCQoJCQkJX2ZuUmVEcmF3KCBzZXR0aW5ncywgaG9sZFBvc2l0aW9uICk7CgkJCQlfZm5Qcm9jZXNzaW5nRGlzcGxheSggc2V0dGluZ3MsIGZhbHNlICk7CgkJCX0gKTsKCQl9Cgl9OwoJCgkKCS8qKgoJICogR2V0IHRoZSBKU09OIHJlc3BvbnNlIGZyb20gdGhlIGxhc3QgQWpheCByZXF1ZXN0IHRoYXQgRGF0YVRhYmxlcyBtYWRlIHRvIHRoZQoJICogc2VydmVyLiBOb3RlIHRoYXQgdGhpcyByZXR1cm5zIHRoZSBKU09OIGZyb20gdGhlIGZpcnN0IHRhYmxlIGluIHRoZSBjdXJyZW50CgkgKiBjb250ZXh0LgoJICoKCSAqIEByZXR1cm4ge29iamVjdH0gSlNPTiByZWNlaXZlZCBmcm9tIHRoZSBzZXJ2ZXIuCgkgKi8KCV9hcGlfcmVnaXN0ZXIoICdhamF4Lmpzb24oKScsIGZ1bmN0aW9uICgpIHsKCQl2YXIgY3R4ID0gdGhpcy5jb250ZXh0OwoJCgkJaWYgKCBjdHgubGVuZ3RoID4gMCApIHsKCQkJcmV0dXJuIGN0eFswXS5qc29uOwoJCX0KCQoJCS8vIGVsc2UgcmV0dXJuIHVuZGVmaW5lZDsKCX0gKTsKCQoJCgkvKioKCSAqIEdldCB0aGUgZGF0YSBzdWJtaXR0ZWQgaW4gdGhlIGxhc3QgQWpheCByZXF1ZXN0CgkgKi8KCV9hcGlfcmVnaXN0ZXIoICdhamF4LnBhcmFtcygpJywgZnVuY3Rpb24gKCkgewoJCXZhciBjdHggPSB0aGlzLmNvbnRleHQ7CgkKCQlpZiAoIGN0eC5sZW5ndGggPiAwICkgewoJCQlyZXR1cm4gY3R4WzBdLm9BamF4RGF0YTsKCQl9CgkKCQkvLyBlbHNlIHJldHVybiB1bmRlZmluZWQ7Cgl9ICk7CgkKCQoJLyoqCgkgKiBSZWxvYWQgdGFibGVzIGZyb20gdGhlIEFqYXggZGF0YSBzb3VyY2UuIE5vdGUgdGhhdCB0aGlzIGZ1bmN0aW9uIHdpbGwKCSAqIGF1dG9tYXRpY2FsbHkgcmUtZHJhdyB0aGUgdGFibGUgd2hlbiB0aGUgcmVtb3RlIGRhdGEgaGFzIGJlZW4gbG9hZGVkLgoJICoKCSAqIEBwYXJhbSB7Ym9vbGVhbn0gW3Jlc2V0PXRydWVdIFJlc2V0IChkZWZhdWx0KSBvciBob2xkIHRoZSBjdXJyZW50IHBhZ2luZwoJICogICBwb3NpdGlvbi4gQSBmdWxsIHJlLXNvcnQgYW5kIHJlLWZpbHRlciBpcyBwZXJmb3JtZWQgd2hlbiB0aGlzIG1ldGhvZCBpcwoJICogICBjYWxsZWQsIHdoaWNoIGlzIHdoeSB0aGUgcGFnaW5hdGlvbiByZXNldCBpcyB0aGUgZGVmYXVsdCBhY3Rpb24uCgkgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXMKCSAqLwoJX2FwaV9yZWdpc3RlciggJ2FqYXgucmVsb2FkKCknLCBmdW5jdGlvbiAoIGNhbGxiYWNrLCByZXNldFBhZ2luZyApIHsKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKHNldHRpbmdzKSB7CgkJCV9fcmVsb2FkKCBzZXR0aW5ncywgcmVzZXRQYWdpbmc9PT1mYWxzZSwgY2FsbGJhY2sgKTsKCQl9ICk7Cgl9ICk7CgkKCQoJLyoqCgkgKiBHZXQgdGhlIGN1cnJlbnQgQWpheCBVUkwuIE5vdGUgdGhhdCB0aGlzIHJldHVybnMgdGhlIFVSTCBmcm9tIHRoZSBmaXJzdAoJICogdGFibGUgaW4gdGhlIGN1cnJlbnQgY29udGV4dC4KCSAqCgkgKiBAcmV0dXJuIHtzdHJpbmd9IEN1cnJlbnQgQWpheCBzb3VyY2UgVVJMCgkgKi8vKioKCSAqIFNldCB0aGUgQWpheCBVUkwuIE5vdGUgdGhhdCB0aGlzIHdpbGwgc2V0IHRoZSBVUkwgZm9yIGFsbCB0YWJsZXMgaW4gdGhlCgkgKiBjdXJyZW50IGNvbnRleHQuCgkgKgoJICogQHBhcmFtIHtzdHJpbmd9IHVybCBVUkwgdG8gc2V0LgoJICogQHJldHVybnMge0RhdGFUYWJsZXMuQXBpfSB0aGlzCgkgKi8KCV9hcGlfcmVnaXN0ZXIoICdhamF4LnVybCgpJywgZnVuY3Rpb24gKCB1cmwgKSB7CgkJdmFyIGN0eCA9IHRoaXMuY29udGV4dDsKCQoJCWlmICggdXJsID09PSB1bmRlZmluZWQgKSB7CgkJCS8vIGdldAoJCQlpZiAoIGN0eC5sZW5ndGggPT09IDAgKSB7CgkJCQlyZXR1cm4gdW5kZWZpbmVkOwoJCQl9CgkJCWN0eCA9IGN0eFswXTsKCQoJCQlyZXR1cm4gY3R4LmFqYXggPwoJCQkJJC5pc1BsYWluT2JqZWN0KCBjdHguYWpheCApID8KCQkJCQljdHguYWpheC51cmwgOgoJCQkJCWN0eC5hamF4IDoKCQkJCWN0eC5zQWpheFNvdXJjZTsKCQl9CgkKCQkvLyBzZXQKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHsKCQkJaWYgKCAkLmlzUGxhaW5PYmplY3QoIHNldHRpbmdzLmFqYXggKSApIHsKCQkJCXNldHRpbmdzLmFqYXgudXJsID0gdXJsOwoJCQl9CgkJCWVsc2UgewoJCQkJc2V0dGluZ3MuYWpheCA9IHVybDsKCQkJfQoJCQkvLyBObyBuZWVkIHRvIGNvbnNpZGVyIHNBamF4U291cmNlIGhlcmUgc2luY2UgRGF0YVRhYmxlcyBnaXZlcyBwcmlvcml0eQoJCQkvLyB0byBgYWpheGAgb3ZlciBgc0FqYXhTb3VyY2VgLiBTbyBzZXR0aW5nIGBhamF4YCBoZXJlLCByZW5kZXJzIGFueQoJCQkvLyB2YWx1ZSBvZiBgc0FqYXhTb3VyY2VgIHJlZHVuZGFudC4KCQl9ICk7Cgl9ICk7CgkKCQoJLyoqCgkgKiBMb2FkIGRhdGEgZnJvbSB0aGUgbmV3bHkgc2V0IEFqYXggVVJMLiBOb3RlIHRoYXQgdGhpcyBtZXRob2QgaXMgb25seQoJICogYXZhaWxhYmxlIHdoZW4gYGFqYXgudXJsKClgIGlzIHVzZWQgdG8gc2V0IGEgVVJMLiBBZGRpdGlvbmFsbHksIHRoaXMgbWV0aG9kCgkgKiBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzIGNhbGxpbmcgYGFqYXgucmVsb2FkKClgIGJ1dCBpcyBwcm92aWRlZCBmb3IKCSAqIGNvbnZlbmllbmNlIHdoZW4gc2V0dGluZyBhIG5ldyBVUkwuIExpa2UgYGFqYXgucmVsb2FkKClgIGl0IHdpbGwKCSAqIGF1dG9tYXRpY2FsbHkgcmVkcmF3IHRoZSB0YWJsZSBvbmNlIHRoZSByZW1vdGUgZGF0YSBoYXMgYmVlbiBsb2FkZWQuCgkgKgoJICogQHJldHVybnMge0RhdGFUYWJsZXMuQXBpfSB0aGlzCgkgKi8KCV9hcGlfcmVnaXN0ZXIoICdhamF4LnVybCgpLmxvYWQoKScsIGZ1bmN0aW9uICggY2FsbGJhY2ssIHJlc2V0UGFnaW5nICkgewoJCS8vIFNhbWUgYXMgYSByZWxvYWQsIGJ1dCBtYWtlcyBzZW5zZSB0byBwcmVzZW50IGl0IGZvciBlYXN5IGFjY2VzcyBhZnRlciBhCgkJLy8gdXJsIGNoYW5nZQoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHsKCQkJX19yZWxvYWQoIGN0eCwgcmVzZXRQYWdpbmc9PT1mYWxzZSwgY2FsbGJhY2sgKTsKCQl9ICk7Cgl9ICk7CgkKCQoJCgkKCXZhciBfc2VsZWN0b3JfcnVuID0gZnVuY3Rpb24gKCB0eXBlLCBzZWxlY3Rvciwgc2VsZWN0Rm4sIHNldHRpbmdzLCBvcHRzICkKCXsKCQl2YXIKCQkJb3V0ID0gW10sIHJlcywKCQkJYSwgaSwgaWVuLCBqLCBqZW4sCgkJCXNlbGVjdG9yVHlwZSA9IHR5cGVvZiBzZWxlY3RvcjsKCQoJCS8vIENhbid0IGp1c3QgY2hlY2sgZm9yIGlzQXJyYXkgaGVyZSwgYXMgYW4gQVBJIG9yIGpRdWVyeSBpbnN0YW5jZSBtaWdodCBiZQoJCS8vIGdpdmVuIHdpdGggdGhlaXIgYXJyYXkgbGlrZSBsb29rCgkJaWYgKCAhIHNlbGVjdG9yIHx8IHNlbGVjdG9yVHlwZSA9PT0gJ3N0cmluZycgfHwgc2VsZWN0b3JUeXBlID09PSAnZnVuY3Rpb24nIHx8IHNlbGVjdG9yLmxlbmd0aCA9PT0gdW5kZWZpbmVkICkgewoJCQlzZWxlY3RvciA9IFsgc2VsZWN0b3IgXTsKCQl9CgkKCQlmb3IgKCBpPTAsIGllbj1zZWxlY3Rvci5sZW5ndGggOyBpPGllbiA7IGkrKyApIHsKCQkJLy8gT25seSBzcGxpdCBvbiBzaW1wbGUgc3RyaW5ncyAtIGNvbXBsZXggZXhwcmVzc2lvbnMgd2lsbCBiZSBqUXVlcnkgc2VsZWN0b3JzCgkJCWEgPSBzZWxlY3RvcltpXSAmJiBzZWxlY3RvcltpXS5zcGxpdCAmJiAhIHNlbGVjdG9yW2ldLm1hdGNoKC9bXFtcKDpdLykgPwoJCQkJc2VsZWN0b3JbaV0uc3BsaXQoJywnKSA6CgkJCQlbIHNlbGVjdG9yW2ldIF07CgkKCQkJZm9yICggaj0wLCBqZW49YS5sZW5ndGggOyBqPGplbiA7IGorKyApIHsKCQkJCXJlcyA9IHNlbGVjdEZuKCB0eXBlb2YgYVtqXSA9PT0gJ3N0cmluZycgPyAoYVtqXSkudHJpbSgpIDogYVtqXSApOwoJCgkJCQlpZiAoIHJlcyAmJiByZXMubGVuZ3RoICkgewoJCQkJCW91dCA9IG91dC5jb25jYXQoIHJlcyApOwoJCQkJfQoJCQl9CgkJfQoJCgkJLy8gc2VsZWN0b3IgZXh0ZW5zaW9ucwoJCXZhciBleHQgPSBfZXh0LnNlbGVjdG9yWyB0eXBlIF07CgkJaWYgKCBleHQubGVuZ3RoICkgewoJCQlmb3IgKCBpPTAsIGllbj1leHQubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQlvdXQgPSBleHRbaV0oIHNldHRpbmdzLCBvcHRzLCBvdXQgKTsKCQkJfQoJCX0KCQoJCXJldHVybiBfdW5pcXVlKCBvdXQgKTsKCX07CgkKCQoJdmFyIF9zZWxlY3Rvcl9vcHRzID0gZnVuY3Rpb24gKCBvcHRzICkKCXsKCQlpZiAoICEgb3B0cyApIHsKCQkJb3B0cyA9IHt9OwoJCX0KCQoJCS8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IGZvciAxLjktIHdoaWNoIHVzZWQgdGhlIHRlcm1pbm9sb2d5IGZpbHRlciByYXRoZXIKCQkvLyB0aGFuIHNlYXJjaAoJCWlmICggb3B0cy5maWx0ZXIgJiYgb3B0cy5zZWFyY2ggPT09IHVuZGVmaW5lZCApIHsKCQkJb3B0cy5zZWFyY2ggPSBvcHRzLmZpbHRlcjsKCQl9CgkKCQlyZXR1cm4gJC5leHRlbmQoIHsKCQkJc2VhcmNoOiAnbm9uZScsCgkJCW9yZGVyOiAnY3VycmVudCcsCgkJCXBhZ2U6ICdhbGwnCgkJfSwgb3B0cyApOwoJfTsKCQoJCgl2YXIgX3NlbGVjdG9yX2ZpcnN0ID0gZnVuY3Rpb24gKCBpbnN0ICkKCXsKCQkvLyBSZWR1Y2UgdGhlIEFQSSBpbnN0YW5jZSB0byB0aGUgZmlyc3QgaXRlbSBmb3VuZAoJCWZvciAoIHZhciBpPTAsIGllbj1pbnN0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQlpZiAoIGluc3RbaV0ubGVuZ3RoID4gMCApIHsKCQkJCS8vIEFzc2lnbiB0aGUgZmlyc3QgZWxlbWVudCB0byB0aGUgZmlyc3QgaXRlbSBpbiB0aGUgaW5zdGFuY2UKCQkJCS8vIGFuZCB0cnVuY2F0ZSB0aGUgaW5zdGFuY2UgYW5kIGNvbnRleHQKCQkJCWluc3RbMF0gPSBpbnN0W2ldOwoJCQkJaW5zdFswXS5sZW5ndGggPSAxOwoJCQkJaW5zdC5sZW5ndGggPSAxOwoJCQkJaW5zdC5jb250ZXh0ID0gWyBpbnN0LmNvbnRleHRbaV0gXTsKCQoJCQkJcmV0dXJuIGluc3Q7CgkJCX0KCQl9CgkKCQkvLyBOb3QgZm91bmQgLSByZXR1cm4gYW4gZW1wdHkgaW5zdGFuY2UKCQlpbnN0Lmxlbmd0aCA9IDA7CgkJcmV0dXJuIGluc3Q7Cgl9OwoJCgkKCXZhciBfc2VsZWN0b3Jfcm93X2luZGV4ZXMgPSBmdW5jdGlvbiAoIHNldHRpbmdzLCBvcHRzICkKCXsKCQl2YXIKCQkJaSwgaWVuLCB0bXAsIGE9W10sCgkJCWRpc3BsYXlGaWx0ZXJlZCA9IHNldHRpbmdzLmFpRGlzcGxheSwKCQkJZGlzcGxheU1hc3RlciA9IHNldHRpbmdzLmFpRGlzcGxheU1hc3RlcjsKCQoJCXZhcgoJCQlzZWFyY2ggPSBvcHRzLnNlYXJjaCwgIC8vIG5vbmUsIGFwcGxpZWQsIHJlbW92ZWQKCQkJb3JkZXIgID0gb3B0cy5vcmRlciwgICAvLyBhcHBsaWVkLCBjdXJyZW50LCBpbmRleCAob3JpZ2luYWwgLSBjb21wYXRpYmlsaXR5IHdpdGggMS45KQoJCQlwYWdlICAgPSBvcHRzLnBhZ2U7ICAgIC8vIGFsbCwgY3VycmVudAoJCgkJaWYgKCBfZm5EYXRhU291cmNlKCBzZXR0aW5ncyApID09ICdzc3AnICkgewoJCQkvLyBJbiBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIG1vZGUsIG1vc3Qgb3B0aW9ucyBhcmUgaXJyZWxldmFudCBzaW5jZQoJCQkvLyByb3dzIG5vdCBzaG93biBkb24ndCBleGlzdCBhbmQgdGhlIGluZGV4IG9yZGVyIGlzIHRoZSBhcHBsaWVkIG9yZGVyCgkJCS8vIFJlbW92ZWQgaXMgYSBzcGVjaWFsIGNhc2UgLSBmb3IgY29uc2lzdGVuY3kganVzdCByZXR1cm4gYW4gZW1wdHkKCQkJLy8gYXJyYXkKCQkJcmV0dXJuIHNlYXJjaCA9PT0gJ3JlbW92ZWQnID8KCQkJCVtdIDoKCQkJCV9yYW5nZSggMCwgZGlzcGxheU1hc3Rlci5sZW5ndGggKTsKCQl9CgkJZWxzZSBpZiAoIHBhZ2UgPT0gJ2N1cnJlbnQnICkgewoJCQkvLyBDdXJyZW50IHBhZ2UgaW1wbGllcyB0aGF0IG9yZGVyPWN1cnJlbnQgYW5kIGZpbHRlcj1hcHBsaWVkLCBzaW5jZSBpdCBpcwoJCQkvLyBmYWlybHkgc2Vuc2VsZXNzIG90aGVyd2lzZSwgcmVnYXJkbGVzcyBvZiB3aGF0IG9yZGVyIGFuZCBzZWFyY2ggYWN0dWFsbHkKCQkJLy8gYXJlCgkJCWZvciAoIGk9c2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsIGllbj1zZXR0aW5ncy5mbkRpc3BsYXlFbmQoKSA7IGk8aWVuIDsgaSsrICkgewoJCQkJYS5wdXNoKCBkaXNwbGF5RmlsdGVyZWRbaV0gKTsKCQkJfQoJCX0KCQllbHNlIGlmICggb3JkZXIgPT0gJ2N1cnJlbnQnIHx8IG9yZGVyID09ICdhcHBsaWVkJyApIHsKCQkJaWYgKCBzZWFyY2ggPT0gJ25vbmUnKSB7CgkJCQlhID0gZGlzcGxheU1hc3Rlci5zbGljZSgpOwoJCQl9CgkJCWVsc2UgaWYgKCBzZWFyY2ggPT0gJ2FwcGxpZWQnICkgewoJCQkJYSA9IGRpc3BsYXlGaWx0ZXJlZC5zbGljZSgpOwoJCQl9CgkJCWVsc2UgaWYgKCBzZWFyY2ggPT0gJ3JlbW92ZWQnICkgewoJCQkJLy8gTyhuK20pIHNvbHV0aW9uIGJ5IGNyZWF0aW5nIGEgaGFzaCBtYXAKCQkJCXZhciBkaXNwbGF5RmlsdGVyZWRNYXAgPSB7fTsKCQoJCQkJZm9yICggdmFyIGk9MCwgaWVuPWRpc3BsYXlGaWx0ZXJlZC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHsKCQkJCQlkaXNwbGF5RmlsdGVyZWRNYXBbZGlzcGxheUZpbHRlcmVkW2ldXSA9IG51bGw7CgkJCQl9CgkKCQkJCWEgPSAkLm1hcCggZGlzcGxheU1hc3RlciwgZnVuY3Rpb24gKGVsKSB7CgkJCQkJcmV0dXJuICEgZGlzcGxheUZpbHRlcmVkTWFwLmhhc093blByb3BlcnR5KGVsKSA/CgkJCQkJCWVsIDoKCQkJCQkJbnVsbDsKCQkJCX0gKTsKCQkJfQoJCX0KCQllbHNlIGlmICggb3JkZXIgPT0gJ2luZGV4JyB8fCBvcmRlciA9PSAnb3JpZ2luYWwnICkgewoJCQlmb3IgKCBpPTAsIGllbj1zZXR0aW5ncy5hb0RhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQlpZiAoIHNlYXJjaCA9PSAnbm9uZScgKSB7CgkJCQkJYS5wdXNoKCBpICk7CgkJCQl9CgkJCQllbHNlIHsgLy8gYXBwbGllZCB8IHJlbW92ZWQKCQkJCQl0bXAgPSAkLmluQXJyYXkoIGksIGRpc3BsYXlGaWx0ZXJlZCApOwoJCgkJCQkJaWYgKCh0bXAgPT09IC0xICYmIHNlYXJjaCA9PSAncmVtb3ZlZCcpIHx8CgkJCQkJCSh0bXAgPj0gMCAgICYmIHNlYXJjaCA9PSAnYXBwbGllZCcpICkKCQkJCQl7CgkJCQkJCWEucHVzaCggaSApOwoJCQkJCX0KCQkJCX0KCQkJfQoJCX0KCQoJCXJldHVybiBhOwoJfTsKCQoJCgkvKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICoKCSAqIFJvd3MKCSAqCgkgKiB7fSAgICAgICAgICAtIG5vIHNlbGVjdG9yIC0gdXNlIGFsbCBhdmFpbGFibGUgcm93cwoJICoge2ludGVnZXJ9ICAgLSByb3cgYW9EYXRhIGluZGV4CgkgKiB7bm9kZX0gICAgICAtIFRSIG5vZGUKCSAqIHtzdHJpbmd9ICAgIC0galF1ZXJ5IHNlbGVjdG9yIHRvIGFwcGx5IHRvIHRoZSBUUiBlbGVtZW50cwoJICoge2FycmF5fSAgICAgLSBqUXVlcnkgYXJyYXkgb2Ygbm9kZXMsIG9yIHNpbXBseSBhbiBhcnJheSBvZiBUUiBub2RlcwoJICoKCSAqLwoJdmFyIF9fcm93X3NlbGVjdG9yID0gZnVuY3Rpb24gKCBzZXR0aW5ncywgc2VsZWN0b3IsIG9wdHMgKQoJewoJCXZhciByb3dzOwoJCXZhciBydW4gPSBmdW5jdGlvbiAoIHNlbCApIHsKCQkJdmFyIHNlbEludCA9IF9pbnRWYWwoIHNlbCApOwoJCQl2YXIgaSwgaWVuOwoJCQl2YXIgYW9EYXRhID0gc2V0dGluZ3MuYW9EYXRhOwoJCgkJCS8vIFNob3J0IGN1dCAtIHNlbGVjdG9yIGlzIGEgbnVtYmVyIGFuZCBubyBvcHRpb25zIHByb3ZpZGVkIChkZWZhdWx0IGlzCgkJCS8vIGFsbCByZWNvcmRzLCBzbyBubyBuZWVkIHRvIGNoZWNrIGlmIHRoZSBpbmRleCBpcyBpbiB0aGVyZSwgc2luY2UgaXQKCQkJLy8gbXVzdCBiZSAtIGRldiBlcnJvciBpZiB0aGUgaW5kZXggZG9lc24ndCBleGlzdCkuCgkJCWlmICggc2VsSW50ICE9PSBudWxsICYmICEgb3B0cyApIHsKCQkJCXJldHVybiBbIHNlbEludCBdOwoJCQl9CgkKCQkJaWYgKCAhIHJvd3MgKSB7CgkJCQlyb3dzID0gX3NlbGVjdG9yX3Jvd19pbmRleGVzKCBzZXR0aW5ncywgb3B0cyApOwoJCQl9CgkKCQkJaWYgKCBzZWxJbnQgIT09IG51bGwgJiYgJC5pbkFycmF5KCBzZWxJbnQsIHJvd3MgKSAhPT0gLTEgKSB7CgkJCQkvLyBTZWxlY3RvciAtIGludGVnZXIKCQkJCXJldHVybiBbIHNlbEludCBdOwoJCQl9CgkJCWVsc2UgaWYgKCBzZWwgPT09IG51bGwgfHwgc2VsID09PSB1bmRlZmluZWQgfHwgc2VsID09PSAnJyApIHsKCQkJCS8vIFNlbGVjdG9yIC0gbm9uZQoJCQkJcmV0dXJuIHJvd3M7CgkJCX0KCQoJCQkvLyBTZWxlY3RvciAtIGZ1bmN0aW9uCgkJCWlmICggdHlwZW9mIHNlbCA9PT0gJ2Z1bmN0aW9uJyApIHsKCQkJCXJldHVybiAkLm1hcCggcm93cywgZnVuY3Rpb24gKGlkeCkgewoJCQkJCXZhciByb3cgPSBhb0RhdGFbIGlkeCBdOwoJCQkJCXJldHVybiBzZWwoIGlkeCwgcm93Ll9hRGF0YSwgcm93Lm5UciApID8gaWR4IDogbnVsbDsKCQkJCX0gKTsKCQkJfQoJCgkJCS8vIFNlbGVjdG9yIC0gbm9kZQoJCQlpZiAoIHNlbC5ub2RlTmFtZSApIHsKCQkJCXZhciByb3dJZHggPSBzZWwuX0RUX1Jvd0luZGV4OyAgLy8gUHJvcGVydHkgYWRkZWQgYnkgRFQgZm9yIGZhc3QgbG9va3VwCgkJCQl2YXIgY2VsbElkeCA9IHNlbC5fRFRfQ2VsbEluZGV4OwoJCgkJCQlpZiAoIHJvd0lkeCAhPT0gdW5kZWZpbmVkICkgewoJCQkJCS8vIE1ha2Ugc3VyZSB0aGF0IHRoZSByb3cgaXMgYWN0dWFsbHkgc3RpbGwgcHJlc2VudCBpbiB0aGUgdGFibGUKCQkJCQlyZXR1cm4gYW9EYXRhWyByb3dJZHggXSAmJiBhb0RhdGFbIHJvd0lkeCBdLm5UciA9PT0gc2VsID8KCQkJCQkJWyByb3dJZHggXSA6CgkJCQkJCVtdOwoJCQkJfQoJCQkJZWxzZSBpZiAoIGNlbGxJZHggKSB7CgkJCQkJcmV0dXJuIGFvRGF0YVsgY2VsbElkeC5yb3cgXSAmJiBhb0RhdGFbIGNlbGxJZHgucm93IF0ublRyID09PSBzZWwucGFyZW50Tm9kZSA/CgkJCQkJCVsgY2VsbElkeC5yb3cgXSA6CgkJCQkJCVtdOwoJCQkJfQoJCQkJZWxzZSB7CgkJCQkJdmFyIGhvc3QgPSAkKHNlbCkuY2xvc2VzdCgnKltkYXRhLWR0LXJvd10nKTsKCQkJCQlyZXR1cm4gaG9zdC5sZW5ndGggPwoJCQkJCQlbIGhvc3QuZGF0YSgnZHQtcm93JykgXSA6CgkJCQkJCVtdOwoJCQkJfQoJCQl9CgkKCQkJLy8gSUQgc2VsZWN0b3IuIFdhbnQgdG8gYWx3YXlzIGJlIGFibGUgdG8gc2VsZWN0IHJvd3MgYnkgaWQsIHJlZ2FyZGxlc3MKCQkJLy8gb2YgaWYgdGhlIHRyIGVsZW1lbnQgaGFzIGJlZW4gY3JlYXRlZCBvciBub3QsIHNvIGNhbid0IHJlbHkgdXBvbgoJCQkvLyBqUXVlcnkgaGVyZSAtIGhlbmNlIGEgY3VzdG9tIGltcGxlbWVudGF0aW9uLiBUaGlzIGRvZXMgbm90IG1hdGNoCgkJCS8vIFNpenpsZSdzIGZhc3Qgc2VsZWN0b3Igb3IgSFRNTDQgLSBpbiBIVE1MNSB0aGUgSUQgY2FuIGJlIGFueXRoaW5nLAoJCQkvLyBidXQgdG8gc2VsZWN0IGl0IHVzaW5nIGEgQ1NTIHNlbGVjdG9yIGVuZ2luZSAobGlrZSBTaXp6bGUgb3IKCQkJLy8gcXVlcnlTZWxlY3QpIGl0IHdvdWxkIG5lZWQgdG8gbmVlZCB0byBiZSBlc2NhcGVkIGZvciBzb21lIGNoYXJhY3RlcnMuCgkJCS8vIERhdGFUYWJsZXMgc2ltcGxpZmllcyB0aGlzIGZvciByb3cgc2VsZWN0b3JzIHNpbmNlIHlvdSBjYW4gc2VsZWN0CgkJCS8vIG9ubHkgYSByb3cuIEEgIyBpbmRpY2F0ZXMgYW4gaWQgYW55IGFueXRoaW5nIHRoYXQgZm9sbG93cyBpcyB0aGUgaWQgLQoJCQkvLyB1bmVzY2FwZWQuCgkJCWlmICggdHlwZW9mIHNlbCA9PT0gJ3N0cmluZycgJiYgc2VsLmNoYXJBdCgwKSA9PT0gJyMnICkgewoJCQkJLy8gZ2V0IHJvdyBpbmRleCBmcm9tIGlkCgkJCQl2YXIgcm93T2JqID0gc2V0dGluZ3MuYUlkc1sgc2VsLnJlcGxhY2UoIC9eIy8sICcnICkgXTsKCQkJCWlmICggcm93T2JqICE9PSB1bmRlZmluZWQgKSB7CgkJCQkJcmV0dXJuIFsgcm93T2JqLmlkeCBdOwoJCQkJfQoJCgkJCQkvLyBuZWVkIHRvIGZhbGwgdGhyb3VnaCB0byBqUXVlcnkgaW4gY2FzZSB0aGVyZSBpcyBET00gaWQgdGhhdAoJCQkJLy8gbWF0Y2hlcwoJCQl9CgkJCQoJCQkvLyBHZXQgbm9kZXMgaW4gdGhlIG9yZGVyIGZyb20gdGhlIGByb3dzYCBhcnJheSB3aXRoIG51bGwgdmFsdWVzIHJlbW92ZWQKCQkJdmFyIG5vZGVzID0gX3JlbW92ZUVtcHR5KAoJCQkJX3BsdWNrX29yZGVyKCBzZXR0aW5ncy5hb0RhdGEsIHJvd3MsICduVHInICkKCQkJKTsKCQoJCQkvLyBTZWxlY3RvciAtIGpRdWVyeSBzZWxlY3RvciBzdHJpbmcsIGFycmF5IG9mIG5vZGVzIG9yIGpRdWVyeSBvYmplY3QvCgkJCS8vIEFzIGpRdWVyeSdzIC5maWx0ZXIoKSBhbGxvd3MgalF1ZXJ5IG9iamVjdHMgdG8gYmUgcGFzc2VkIGluIGZpbHRlciwKCQkJLy8gaXQgYWxzbyBhbGxvd3MgYXJyYXlzLCBzbyB0aGlzIHdpbGwgY29wZSB3aXRoIGFsbCB0aHJlZSBvcHRpb25zCgkJCXJldHVybiAkKG5vZGVzKQoJCQkJLmZpbHRlciggc2VsICkKCQkJCS5tYXAoIGZ1bmN0aW9uICgpIHsKCQkJCQlyZXR1cm4gdGhpcy5fRFRfUm93SW5kZXg7CgkJCQl9ICkKCQkJCS50b0FycmF5KCk7CgkJfTsKCQoJCXJldHVybiBfc2VsZWN0b3JfcnVuKCAncm93Jywgc2VsZWN0b3IsIHJ1biwgc2V0dGluZ3MsIG9wdHMgKTsKCX07CgkKCQoJX2FwaV9yZWdpc3RlciggJ3Jvd3MoKScsIGZ1bmN0aW9uICggc2VsZWN0b3IsIG9wdHMgKSB7CgkJLy8gYXJndW1lbnQgc2hpZnRpbmcKCQlpZiAoIHNlbGVjdG9yID09PSB1bmRlZmluZWQgKSB7CgkJCXNlbGVjdG9yID0gJyc7CgkJfQoJCWVsc2UgaWYgKCAkLmlzUGxhaW5PYmplY3QoIHNlbGVjdG9yICkgKSB7CgkJCW9wdHMgPSBzZWxlY3RvcjsKCQkJc2VsZWN0b3IgPSAnJzsKCQl9CgkKCQlvcHRzID0gX3NlbGVjdG9yX29wdHMoIG9wdHMgKTsKCQoJCXZhciBpbnN0ID0gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHsKCQkJcmV0dXJuIF9fcm93X3NlbGVjdG9yKCBzZXR0aW5ncywgc2VsZWN0b3IsIG9wdHMgKTsKCQl9LCAxICk7CgkKCQkvLyBXYW50IGFyZ3VtZW50IHNoaWZ0aW5nIGhlcmUgYW5kIGluIF9fcm93X3NlbGVjdG9yPwoJCWluc3Quc2VsZWN0b3Iucm93cyA9IHNlbGVjdG9yOwoJCWluc3Quc2VsZWN0b3Iub3B0cyA9IG9wdHM7CgkKCQlyZXR1cm4gaW5zdDsKCX0gKTsKCQoJX2FwaV9yZWdpc3RlciggJ3Jvd3MoKS5ub2RlcygpJywgZnVuY3Rpb24gKCkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAncm93JywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93ICkgewoJCQlyZXR1cm4gc2V0dGluZ3MuYW9EYXRhWyByb3cgXS5uVHIgfHwgdW5kZWZpbmVkOwoJCX0sIDEgKTsKCX0gKTsKCQoJX2FwaV9yZWdpc3RlciggJ3Jvd3MoKS5kYXRhKCknLCBmdW5jdGlvbiAoKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoIHRydWUsICdyb3dzJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93cyApIHsKCQkJcmV0dXJuIF9wbHVja19vcmRlciggc2V0dGluZ3MuYW9EYXRhLCByb3dzLCAnX2FEYXRhJyApOwoJCX0sIDEgKTsKCX0gKTsKCQoJX2FwaV9yZWdpc3RlclBsdXJhbCggJ3Jvd3MoKS5jYWNoZSgpJywgJ3JvdygpLmNhY2hlKCknLCBmdW5jdGlvbiAoIHR5cGUgKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdyb3cnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCByb3cgKSB7CgkJCXZhciByID0gc2V0dGluZ3MuYW9EYXRhWyByb3cgXTsKCQkJcmV0dXJuIHR5cGUgPT09ICdzZWFyY2gnID8gci5fYUZpbHRlckRhdGEgOiByLl9hU29ydERhdGE7CgkJfSwgMSApOwoJfSApOwoJCglfYXBpX3JlZ2lzdGVyUGx1cmFsKCAncm93cygpLmludmFsaWRhdGUoKScsICdyb3coKS5pbnZhbGlkYXRlKCknLCBmdW5jdGlvbiAoIHNyYyApIHsKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3JvdycsIGZ1bmN0aW9uICggc2V0dGluZ3MsIHJvdyApIHsKCQkJX2ZuSW52YWxpZGF0ZSggc2V0dGluZ3MsIHJvdywgc3JjICk7CgkJfSApOwoJfSApOwoJCglfYXBpX3JlZ2lzdGVyUGx1cmFsKCAncm93cygpLmluZGV4ZXMoKScsICdyb3coKS5pbmRleCgpJywgZnVuY3Rpb24gKCkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAncm93JywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93ICkgewoJCQlyZXR1cm4gcm93OwoJCX0sIDEgKTsKCX0gKTsKCQoJX2FwaV9yZWdpc3RlclBsdXJhbCggJ3Jvd3MoKS5pZHMoKScsICdyb3coKS5pZCgpJywgZnVuY3Rpb24gKCBoYXNoICkgewoJCXZhciBhID0gW107CgkJdmFyIGNvbnRleHQgPSB0aGlzLmNvbnRleHQ7CgkKCQkvLyBgaXRlcmF0b3JgIHdpbGwgZHJvcCB1bmRlZmluZWQgdmFsdWVzLCBidXQgaW4gdGhpcyBjYXNlIHdlIHdhbnQgdGhlbQoJCWZvciAoIHZhciBpPTAsIGllbj1jb250ZXh0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQlmb3IgKCB2YXIgaj0wLCBqZW49dGhpc1tpXS5sZW5ndGggOyBqPGplbiA7IGorKyApIHsKCQkJCXZhciBpZCA9IGNvbnRleHRbaV0ucm93SWRGbiggY29udGV4dFtpXS5hb0RhdGFbIHRoaXNbaV1bal0gXS5fYURhdGEgKTsKCQkJCWEucHVzaCggKGhhc2ggPT09IHRydWUgPyAnIycgOiAnJyApKyBpZCApOwoJCQl9CgkJfQoJCgkJcmV0dXJuIG5ldyBfQXBpKCBjb250ZXh0LCBhICk7Cgl9ICk7CgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICdyb3dzKCkucmVtb3ZlKCknLCAncm93KCkucmVtb3ZlKCknLCBmdW5jdGlvbiAoKSB7CgkJdmFyIHRoYXQgPSB0aGlzOwoJCgkJdGhpcy5pdGVyYXRvciggJ3JvdycsIGZ1bmN0aW9uICggc2V0dGluZ3MsIHJvdywgdGhhdElkeCApIHsKCQkJdmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGE7CgkJCXZhciByb3dEYXRhID0gZGF0YVsgcm93IF07CgkJCXZhciBpLCBpZW4sIGosIGplbjsKCQkJdmFyIGxvb3BSb3csIGxvb3BDZWxsczsKCQoJCQlkYXRhLnNwbGljZSggcm93LCAxICk7CgkKCQkJLy8gVXBkYXRlIHRoZSBjYWNoZWQgaW5kZXhlcwoJCQlmb3IgKCBpPTAsIGllbj1kYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJbG9vcFJvdyA9IGRhdGFbaV07CgkJCQlsb29wQ2VsbHMgPSBsb29wUm93LmFuQ2VsbHM7CgkKCQkJCS8vIFJvd3MKCQkJCWlmICggbG9vcFJvdy5uVHIgIT09IG51bGwgKSB7CgkJCQkJbG9vcFJvdy5uVHIuX0RUX1Jvd0luZGV4ID0gaTsKCQkJCX0KCQoJCQkJLy8gQ2VsbHMKCQkJCWlmICggbG9vcENlbGxzICE9PSBudWxsICkgewoJCQkJCWZvciAoIGo9MCwgamVuPWxvb3BDZWxscy5sZW5ndGggOyBqPGplbiA7IGorKyApIHsKCQkJCQkJbG9vcENlbGxzW2pdLl9EVF9DZWxsSW5kZXgucm93ID0gaTsKCQkJCQl9CgkJCQl9CgkJCX0KCQoJCQkvLyBEZWxldGUgZnJvbSB0aGUgZGlzcGxheSBhcnJheXMKCQkJX2ZuRGVsZXRlSW5kZXgoIHNldHRpbmdzLmFpRGlzcGxheU1hc3Rlciwgcm93ICk7CgkJCV9mbkRlbGV0ZUluZGV4KCBzZXR0aW5ncy5haURpc3BsYXksIHJvdyApOwoJCQlfZm5EZWxldGVJbmRleCggdGhhdFsgdGhhdElkeCBdLCByb3csIGZhbHNlICk7IC8vIG1haW50YWluIGxvY2FsIGluZGV4ZXMKCQoJCQkvLyBGb3Igc2VydmVyLXNpZGUgcHJvY2Vzc2luZyB0YWJsZXMgLSBzdWJ0cmFjdCB0aGUgZGVsZXRlZCByb3cgZnJvbSB0aGUgY291bnQKCQkJaWYgKCBzZXR0aW5ncy5faVJlY29yZHNEaXNwbGF5ID4gMCApIHsKCQkJCXNldHRpbmdzLl9pUmVjb3Jkc0Rpc3BsYXktLTsKCQkJfQoJCgkJCS8vIENoZWNrIGZvciBhbiAnb3ZlcmZsb3cnIHRoZXkgY2FzZSBmb3IgZGlzcGxheWluZyB0aGUgdGFibGUKCQkJX2ZuTGVuZ3RoT3ZlcmZsb3coIHNldHRpbmdzICk7CgkKCQkJLy8gUmVtb3ZlIHRoZSByb3cncyBJRCByZWZlcmVuY2UgaWYgdGhlcmUgaXMgb25lCgkJCXZhciBpZCA9IHNldHRpbmdzLnJvd0lkRm4oIHJvd0RhdGEuX2FEYXRhICk7CgkJCWlmICggaWQgIT09IHVuZGVmaW5lZCApIHsKCQkJCWRlbGV0ZSBzZXR0aW5ncy5hSWRzWyBpZCBdOwoJCQl9CgkJfSApOwoJCgkJdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHsKCQkJZm9yICggdmFyIGk9MCwgaWVuPXNldHRpbmdzLmFvRGF0YS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHsKCQkJCXNldHRpbmdzLmFvRGF0YVtpXS5pZHggPSBpOwoJCQl9CgkJfSApOwoJCgkJcmV0dXJuIHRoaXM7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggJ3Jvd3MuYWRkKCknLCBmdW5jdGlvbiAoIHJvd3MgKSB7CgkJdmFyIG5ld1Jvd3MgPSB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkgewoJCQkJdmFyIHJvdywgaSwgaWVuOwoJCQkJdmFyIG91dCA9IFtdOwoJCgkJCQlmb3IgKCBpPTAsIGllbj1yb3dzLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJCXJvdyA9IHJvd3NbaV07CgkKCQkJCQlpZiAoIHJvdy5ub2RlTmFtZSAmJiByb3cubm9kZU5hbWUudG9VcHBlckNhc2UoKSA9PT0gJ1RSJyApIHsKCQkJCQkJb3V0LnB1c2goIF9mbkFkZFRyKCBzZXR0aW5ncywgcm93IClbMF0gKTsKCQkJCQl9CgkJCQkJZWxzZSB7CgkJCQkJCW91dC5wdXNoKCBfZm5BZGREYXRhKCBzZXR0aW5ncywgcm93ICkgKTsKCQkJCQl9CgkJCQl9CgkKCQkJCXJldHVybiBvdXQ7CgkJCX0sIDEgKTsKCQoJCS8vIFJldHVybiBhbiBBcGkucm93cygpIGV4dGVuZGVkIGluc3RhbmNlLCBzbyByb3dzKCkubm9kZXMoKSBldGMgY2FuIGJlIHVzZWQKCQl2YXIgbW9kUm93cyA9IHRoaXMucm93cyggLTEgKTsKCQltb2RSb3dzLnBvcCgpOwoJCSQubWVyZ2UoIG1vZFJvd3MsIG5ld1Jvd3MgKTsKCQoJCXJldHVybiBtb2RSb3dzOwoJfSApOwoJCgkKCQoJCgkKCS8qKgoJICoKCSAqLwoJX2FwaV9yZWdpc3RlciggJ3JvdygpJywgZnVuY3Rpb24gKCBzZWxlY3Rvciwgb3B0cyApIHsKCQlyZXR1cm4gX3NlbGVjdG9yX2ZpcnN0KCB0aGlzLnJvd3MoIHNlbGVjdG9yLCBvcHRzICkgKTsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCAncm93KCkuZGF0YSgpJywgZnVuY3Rpb24gKCBkYXRhICkgewoJCXZhciBjdHggPSB0aGlzLmNvbnRleHQ7CgkKCQlpZiAoIGRhdGEgPT09IHVuZGVmaW5lZCApIHsKCQkJLy8gR2V0CgkJCXJldHVybiBjdHgubGVuZ3RoICYmIHRoaXMubGVuZ3RoID8KCQkJCWN0eFswXS5hb0RhdGFbIHRoaXNbMF0gXS5fYURhdGEgOgoJCQkJdW5kZWZpbmVkOwoJCX0KCQoJCS8vIFNldAoJCXZhciByb3cgPSBjdHhbMF0uYW9EYXRhWyB0aGlzWzBdIF07CgkJcm93Ll9hRGF0YSA9IGRhdGE7CgkKCQkvLyBJZiB0aGUgRE9NIGhhcyBhbiBpZCwgYW5kIHRoZSBkYXRhIHNvdXJjZSBpcyBhbiBhcnJheQoJCWlmICggQXJyYXkuaXNBcnJheSggZGF0YSApICYmIHJvdy5uVHIgJiYgcm93Lm5Uci5pZCApIHsKCQkJX2ZuU2V0T2JqZWN0RGF0YUZuKCBjdHhbMF0ucm93SWQgKSggZGF0YSwgcm93Lm5Uci5pZCApOwoJCX0KCQoJCS8vIEF1dG9tYXRpY2FsbHkgaW52YWxpZGF0ZQoJCV9mbkludmFsaWRhdGUoIGN0eFswXSwgdGhpc1swXSwgJ2RhdGEnICk7CgkKCQlyZXR1cm4gdGhpczsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCAncm93KCkubm9kZSgpJywgZnVuY3Rpb24gKCkgewoJCXZhciBjdHggPSB0aGlzLmNvbnRleHQ7CgkKCQlyZXR1cm4gY3R4Lmxlbmd0aCAmJiB0aGlzLmxlbmd0aCA/CgkJCWN0eFswXS5hb0RhdGFbIHRoaXNbMF0gXS5uVHIgfHwgbnVsbCA6CgkJCW51bGw7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggJ3Jvdy5hZGQoKScsIGZ1bmN0aW9uICggcm93ICkgewoJCS8vIEFsbG93IGEgalF1ZXJ5IG9iamVjdCB0byBiZSBwYXNzZWQgaW4gLSBvbmx5IGEgc2luZ2xlIHJvdyBpcyBhZGRlZCBmcm9tCgkJLy8gaXQgdGhvdWdoIC0gdGhlIGZpcnN0IGVsZW1lbnQgaW4gdGhlIHNldAoJCWlmICggcm93IGluc3RhbmNlb2YgJCAmJiByb3cubGVuZ3RoICkgewoJCQlyb3cgPSByb3dbMF07CgkJfQoJCgkJdmFyIHJvd3MgPSB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkgewoJCQlpZiAoIHJvdy5ub2RlTmFtZSAmJiByb3cubm9kZU5hbWUudG9VcHBlckNhc2UoKSA9PT0gJ1RSJyApIHsKCQkJCXJldHVybiBfZm5BZGRUciggc2V0dGluZ3MsIHJvdyApWzBdOwoJCQl9CgkJCXJldHVybiBfZm5BZGREYXRhKCBzZXR0aW5ncywgcm93ICk7CgkJfSApOwoJCgkJLy8gUmV0dXJuIGFuIEFwaS5yb3dzKCkgZXh0ZW5kZWQgaW5zdGFuY2UsIHdpdGggdGhlIG5ld2x5IGFkZGVkIHJvdyBzZWxlY3RlZAoJCXJldHVybiB0aGlzLnJvdyggcm93c1swXSApOwoJfSApOwoJCgkKCSQoZG9jdW1lbnQpLm9uKCdwbHVnaW4taW5pdC5kdCcsIGZ1bmN0aW9uIChlLCBjb250ZXh0KSB7CgkJdmFyIGFwaSA9IG5ldyBfQXBpKCBjb250ZXh0ICk7CgkKCQlhcGkub24oICdzdGF0ZVNhdmVQYXJhbXMnLCBmdW5jdGlvbiAoIGUsIHNldHRpbmdzLCBkICkgewoJCQkvLyBUaGlzIGNvdWxkIGJlIG1vcmUgY29tcGFjdCB3aXRoIHRoZSBBUEksIGJ1dCBpdCBpcyBhIGxvdCBmYXN0ZXIgYXMgYSBzaW1wbGUKCQkJLy8gaW50ZXJuYWwgbG9vcAoJCQl2YXIgaWRGbiA9IHNldHRpbmdzLnJvd0lkRm47CgkJCXZhciBkYXRhID0gc2V0dGluZ3MuYW9EYXRhOwoJCQl2YXIgaWRzID0gW107CgkKCQkJZm9yICh2YXIgaT0wIDsgaTxkYXRhLmxlbmd0aCA7IGkrKykgewoJCQkJaWYgKGRhdGFbaV0uX2RldGFpbHNTaG93KSB7CgkJCQkJaWRzLnB1c2goICcjJyArIGlkRm4oZGF0YVtpXS5fYURhdGEpICk7CgkJCQl9CgkJCX0KCQoJCQlkLmNoaWxkUm93cyA9IGlkczsKCQl9KQoJCgkJdmFyIGxvYWRlZCA9IGFwaS5zdGF0ZS5sb2FkZWQoKTsKCQoJCWlmICggbG9hZGVkICYmIGxvYWRlZC5jaGlsZFJvd3MgKSB7CgkJCWFwaQoJCQkJLnJvd3MoICQubWFwKGxvYWRlZC5jaGlsZFJvd3MsIGZ1bmN0aW9uIChpZCl7CgkJCQkJcmV0dXJuIGlkLnJlcGxhY2UoLzovZywgJ1xcOicpCgkJCQl9KSApCgkJCQkuZXZlcnkoIGZ1bmN0aW9uICgpIHsKCQkJCQlfZm5DYWxsYmFja0ZpcmUoIGNvbnRleHQsIG51bGwsICdyZXF1ZXN0Q2hpbGQnLCBbIHRoaXMgXSApCgkJCQl9KTsKCQl9Cgl9KTsKCQoJdmFyIF9fZGV0YWlsc19hZGQgPSBmdW5jdGlvbiAoIGN0eCwgcm93LCBkYXRhLCBrbGFzcyApCgl7CgkJLy8gQ29udmVydCB0byBhcnJheSBvZiBUUiBlbGVtZW50cwoJCXZhciByb3dzID0gW107CgkJdmFyIGFkZFJvdyA9IGZ1bmN0aW9uICggciwgayApIHsKCQkJLy8gUmVjdXJzaW9uIHRvIGFsbG93IGZvciBhcnJheXMgb2YgalF1ZXJ5IG9iamVjdHMKCQkJaWYgKCBBcnJheS5pc0FycmF5KCByICkgfHwgciBpbnN0YW5jZW9mICQgKSB7CgkJCQlmb3IgKCB2YXIgaT0wLCBpZW49ci5sZW5ndGggOyBpPGllbiA7IGkrKyApIHsKCQkJCQlhZGRSb3coIHJbaV0sIGsgKTsKCQkJCX0KCQkJCXJldHVybjsKCQkJfQoJCgkJCS8vIElmIHdlIGdldCBhIFRSIGVsZW1lbnQsIHRoZW4ganVzdCBhZGQgaXQgZGlyZWN0bHkgLSB1cCB0byB0aGUgZGV2CgkJCS8vIHRvIGFkZCB0aGUgY29ycmVjdCBudW1iZXIgb2YgY29sdW1ucyBldGMKCQkJaWYgKCByLm5vZGVOYW1lICYmIHIubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3RyJyApIHsKCQkJCXJvd3MucHVzaCggciApOwoJCQl9CgkJCWVsc2UgewoJCQkJLy8gT3RoZXJ3aXNlIGNyZWF0ZSBhIHJvdyB3aXRoIGEgd3JhcHBlcgoJCQkJdmFyIGNyZWF0ZWQgPSAkKCc8dHI+PHRkPjwvdGQ+PC90cj4nKS5hZGRDbGFzcyggayApOwoJCQkJJCgndGQnLCBjcmVhdGVkKQoJCQkJCS5hZGRDbGFzcyggayApCgkJCQkJLmh0bWwoIHIgKQoJCQkJCVswXS5jb2xTcGFuID0gX2ZuVmlzYmxlQ29sdW1ucyggY3R4ICk7CgkKCQkJCXJvd3MucHVzaCggY3JlYXRlZFswXSApOwoJCQl9CgkJfTsKCQoJCWFkZFJvdyggZGF0YSwga2xhc3MgKTsKCQoJCWlmICggcm93Ll9kZXRhaWxzICkgewoJCQlyb3cuX2RldGFpbHMuZGV0YWNoKCk7CgkJfQoJCgkJcm93Ll9kZXRhaWxzID0gJChyb3dzKTsKCQoJCS8vIElmIHRoZSBjaGlsZHJlbiB3ZXJlIGFscmVhZHkgc2hvd24sIHRoYXQgc3RhdGUgc2hvdWxkIGJlIHJldGFpbmVkCgkJaWYgKCByb3cuX2RldGFpbHNTaG93ICkgewoJCQlyb3cuX2RldGFpbHMuaW5zZXJ0QWZ0ZXIoIHJvdy5uVHIgKTsKCQl9Cgl9OwoJCgkKCS8vIE1ha2Ugc3RhdGUgc2F2aW5nIG9mIGNoaWxkIHJvdyBkZXRhaWxzIGFzeW5jIHRvIGFsbG93IHRoZW0gdG8gYmUgYmF0Y2ggcHJvY2Vzc2VkCgl2YXIgX19kZXRhaWxzX3N0YXRlID0gRGF0YVRhYmxlLnV0aWwudGhyb3R0bGUoCgkJZnVuY3Rpb24gKGN0eCkgewoJCQlfZm5TYXZlU3RhdGUoIGN0eFswXSApCgkJfSwKCQk1MDAKCSk7CgkKCQoJdmFyIF9fZGV0YWlsc19yZW1vdmUgPSBmdW5jdGlvbiAoIGFwaSwgaWR4ICkKCXsKCQl2YXIgY3R4ID0gYXBpLmNvbnRleHQ7CgkKCQlpZiAoIGN0eC5sZW5ndGggKSB7CgkJCXZhciByb3cgPSBjdHhbMF0uYW9EYXRhWyBpZHggIT09IHVuZGVmaW5lZCA/IGlkeCA6IGFwaVswXSBdOwoJCgkJCWlmICggcm93ICYmIHJvdy5fZGV0YWlscyApIHsKCQkJCXJvdy5fZGV0YWlscy5yZW1vdmUoKTsKCQoJCQkJcm93Ll9kZXRhaWxzU2hvdyA9IHVuZGVmaW5lZDsKCQkJCXJvdy5fZGV0YWlscyA9IHVuZGVmaW5lZDsKCQkJCSQoIHJvdy5uVHIgKS5yZW1vdmVDbGFzcyggJ2R0LWhhc0NoaWxkJyApOwoJCQkJX19kZXRhaWxzX3N0YXRlKCBjdHggKTsKCQkJfQoJCX0KCX07CgkKCQoJdmFyIF9fZGV0YWlsc19kaXNwbGF5ID0gZnVuY3Rpb24gKCBhcGksIHNob3cgKSB7CgkJdmFyIGN0eCA9IGFwaS5jb250ZXh0OwoJCgkJaWYgKCBjdHgubGVuZ3RoICYmIGFwaS5sZW5ndGggKSB7CgkJCXZhciByb3cgPSBjdHhbMF0uYW9EYXRhWyBhcGlbMF0gXTsKCQoJCQlpZiAoIHJvdy5fZGV0YWlscyApIHsKCQkJCXJvdy5fZGV0YWlsc1Nob3cgPSBzaG93OwoJCgkJCQlpZiAoIHNob3cgKSB7CgkJCQkJcm93Ll9kZXRhaWxzLmluc2VydEFmdGVyKCByb3cublRyICk7CgkJCQkJJCggcm93Lm5UciApLmFkZENsYXNzKCAnZHQtaGFzQ2hpbGQnICk7CgkJCQl9CgkJCQllbHNlIHsKCQkJCQlyb3cuX2RldGFpbHMuZGV0YWNoKCk7CgkJCQkJJCggcm93Lm5UciApLnJlbW92ZUNsYXNzKCAnZHQtaGFzQ2hpbGQnICk7CgkJCQl9CgkKCQkJCV9mbkNhbGxiYWNrRmlyZSggY3R4WzBdLCBudWxsLCAnY2hpbGRSb3cnLCBbIHNob3csIGFwaS5yb3coIGFwaVswXSApIF0gKQoJCgkJCQlfX2RldGFpbHNfZXZlbnRzKCBjdHhbMF0gKTsKCQkJCV9fZGV0YWlsc19zdGF0ZSggY3R4ICk7CgkJCX0KCQl9Cgl9OwoJCgkKCXZhciBfX2RldGFpbHNfZXZlbnRzID0gZnVuY3Rpb24gKCBzZXR0aW5ncyApCgl7CgkJdmFyIGFwaSA9IG5ldyBfQXBpKCBzZXR0aW5ncyApOwoJCXZhciBuYW1lc3BhY2UgPSAnLmR0LkRUX2RldGFpbHMnOwoJCXZhciBkcmF3RXZlbnQgPSAnZHJhdycrbmFtZXNwYWNlOwoJCXZhciBjb2x2aXNFdmVudCA9ICdjb2x1bW4tc2l6aW5nJytuYW1lc3BhY2U7CgkJdmFyIGRlc3Ryb3lFdmVudCA9ICdkZXN0cm95JytuYW1lc3BhY2U7CgkJdmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGE7CgkKCQlhcGkub2ZmKCBkcmF3RXZlbnQgKycgJysgY29sdmlzRXZlbnQgKycgJysgZGVzdHJveUV2ZW50ICk7CgkKCQlpZiAoIF9wbHVjayggZGF0YSwgJ19kZXRhaWxzJyApLmxlbmd0aCA+IDAgKSB7CgkJCS8vIE9uIGVhY2ggZHJhdywgaW5zZXJ0IHRoZSByZXF1aXJlZCBlbGVtZW50cyBpbnRvIHRoZSBkb2N1bWVudAoJCQlhcGkub24oIGRyYXdFdmVudCwgZnVuY3Rpb24gKCBlLCBjdHggKSB7CgkJCQlpZiAoIHNldHRpbmdzICE9PSBjdHggKSB7CgkJCQkJcmV0dXJuOwoJCQkJfQoJCgkJCQlhcGkucm93cygge3BhZ2U6J2N1cnJlbnQnfSApLmVxKDApLmVhY2goIGZ1bmN0aW9uIChpZHgpIHsKCQkJCQkvLyBJbnRlcm5hbCBkYXRhIGdyYWIKCQkJCQl2YXIgcm93ID0gZGF0YVsgaWR4IF07CgkKCQkJCQlpZiAoIHJvdy5fZGV0YWlsc1Nob3cgKSB7CgkJCQkJCXJvdy5fZGV0YWlscy5pbnNlcnRBZnRlciggcm93Lm5UciApOwoJCQkJCX0KCQkJCX0gKTsKCQkJfSApOwoJCgkJCS8vIENvbHVtbiB2aXNpYmlsaXR5IGNoYW5nZSAtIHVwZGF0ZSB0aGUgY29sc3BhbgoJCQlhcGkub24oIGNvbHZpc0V2ZW50LCBmdW5jdGlvbiAoIGUsIGN0eCwgaWR4LCB2aXMgKSB7CgkJCQlpZiAoIHNldHRpbmdzICE9PSBjdHggKSB7CgkJCQkJcmV0dXJuOwoJCQkJfQoJCgkJCQkvLyBVcGRhdGUgdGhlIGNvbHNwYW4gZm9yIHRoZSBkZXRhaWxzIHJvd3MgKG5vdGUsIG9ubHkgaWYgaXQgYWxyZWFkeSBoYXMKCQkJCS8vIGEgY29sc3BhbikKCQkJCXZhciByb3csIHZpc2libGUgPSBfZm5WaXNibGVDb2x1bW5zKCBjdHggKTsKCQoJCQkJZm9yICggdmFyIGk9MCwgaWVuPWRhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQkJcm93ID0gZGF0YVtpXTsKCQoJCQkJCWlmICggcm93Ll9kZXRhaWxzICkgewoJCQkJCQlyb3cuX2RldGFpbHMuY2hpbGRyZW4oJ3RkW2NvbHNwYW5dJykuYXR0cignY29sc3BhbicsIHZpc2libGUgKTsKCQkJCQl9CgkJCQl9CgkJCX0gKTsKCQoJCQkvLyBUYWJsZSBkZXN0cm95ZWQgLSBudWtlIGFueSBjaGlsZCByb3dzCgkJCWFwaS5vbiggZGVzdHJveUV2ZW50LCBmdW5jdGlvbiAoIGUsIGN0eCApIHsKCQkJCWlmICggc2V0dGluZ3MgIT09IGN0eCApIHsKCQkJCQlyZXR1cm47CgkJCQl9CgkKCQkJCWZvciAoIHZhciBpPTAsIGllbj1kYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkgewoJCQkJCWlmICggZGF0YVtpXS5fZGV0YWlscyApIHsKCQkJCQkJX19kZXRhaWxzX3JlbW92ZSggYXBpLCBpICk7CgkJCQkJfQoJCQkJfQoJCQl9ICk7CgkJfQoJfTsKCQoJLy8gU3RyaW5ncyBmb3IgdGhlIG1ldGhvZCBuYW1lcyB0byBoZWxwIG1pbmlmaWNhdGlvbgoJdmFyIF9lbXAgPSAnJzsKCXZhciBfY2hpbGRfb2JqID0gX2VtcCsncm93KCkuY2hpbGQnOwoJdmFyIF9jaGlsZF9tdGggPSBfY2hpbGRfb2JqKycoKSc7CgkKCS8vIGRhdGEgY2FuIGJlOgoJLy8gIHRyCgkvLyAgc3RyaW5nCgkvLyAgalF1ZXJ5IG9yIGFycmF5IG9mIGFueSBvZiB0aGUgYWJvdmUKCV9hcGlfcmVnaXN0ZXIoIF9jaGlsZF9tdGgsIGZ1bmN0aW9uICggZGF0YSwga2xhc3MgKSB7CgkJdmFyIGN0eCA9IHRoaXMuY29udGV4dDsKCQoJCWlmICggZGF0YSA9PT0gdW5kZWZpbmVkICkgewoJCQkvLyBnZXQKCQkJcmV0dXJuIGN0eC5sZW5ndGggJiYgdGhpcy5sZW5ndGggPwoJCQkJY3R4WzBdLmFvRGF0YVsgdGhpc1swXSBdLl9kZXRhaWxzIDoKCQkJCXVuZGVmaW5lZDsKCQl9CgkJZWxzZSBpZiAoIGRhdGEgPT09IHRydWUgKSB7CgkJCS8vIHNob3cKCQkJdGhpcy5jaGlsZC5zaG93KCk7CgkJfQoJCWVsc2UgaWYgKCBkYXRhID09PSBmYWxzZSApIHsKCQkJLy8gcmVtb3ZlCgkJCV9fZGV0YWlsc19yZW1vdmUoIHRoaXMgKTsKCQl9CgkJZWxzZSBpZiAoIGN0eC5sZW5ndGggJiYgdGhpcy5sZW5ndGggKSB7CgkJCS8vIHNldAoJCQlfX2RldGFpbHNfYWRkKCBjdHhbMF0sIGN0eFswXS5hb0RhdGFbIHRoaXNbMF0gXSwgZGF0YSwga2xhc3MgKTsKCQl9CgkKCQlyZXR1cm4gdGhpczsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCBbCgkJX2NoaWxkX29iaisnLnNob3coKScsCgkJX2NoaWxkX210aCsnLnNob3coKScgLy8gb25seSB3aGVuIGBjaGlsZCgpYCB3YXMgY2FsbGVkIHdpdGggcGFyYW1ldGVycyAod2l0aG91dAoJXSwgZnVuY3Rpb24gKCBzaG93ICkgeyAgIC8vIGl0IHJldHVybnMgYW4gb2JqZWN0IGFuZCB0aGlzIG1ldGhvZCBpcyBub3QgZXhlY3V0ZWQpCgkJX19kZXRhaWxzX2Rpc3BsYXkoIHRoaXMsIHRydWUgKTsKCQlyZXR1cm4gdGhpczsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCBbCgkJX2NoaWxkX29iaisnLmhpZGUoKScsCgkJX2NoaWxkX210aCsnLmhpZGUoKScgLy8gb25seSB3aGVuIGBjaGlsZCgpYCB3YXMgY2FsbGVkIHdpdGggcGFyYW1ldGVycyAod2l0aG91dAoJXSwgZnVuY3Rpb24gKCkgeyAgICAgICAgIC8vIGl0IHJldHVybnMgYW4gb2JqZWN0IGFuZCB0aGlzIG1ldGhvZCBpcyBub3QgZXhlY3V0ZWQpCgkJX19kZXRhaWxzX2Rpc3BsYXkoIHRoaXMsIGZhbHNlICk7CgkJcmV0dXJuIHRoaXM7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggWwoJCV9jaGlsZF9vYmorJy5yZW1vdmUoKScsCgkJX2NoaWxkX210aCsnLnJlbW92ZSgpJyAvLyBvbmx5IHdoZW4gYGNoaWxkKClgIHdhcyBjYWxsZWQgd2l0aCBwYXJhbWV0ZXJzICh3aXRob3V0CgldLCBmdW5jdGlvbiAoKSB7ICAgICAgICAgICAvLyBpdCByZXR1cm5zIGFuIG9iamVjdCBhbmQgdGhpcyBtZXRob2QgaXMgbm90IGV4ZWN1dGVkKQoJCV9fZGV0YWlsc19yZW1vdmUoIHRoaXMgKTsKCQlyZXR1cm4gdGhpczsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCBfY2hpbGRfb2JqKycuaXNTaG93bigpJywgZnVuY3Rpb24gKCkgewoJCXZhciBjdHggPSB0aGlzLmNvbnRleHQ7CgkKCQlpZiAoIGN0eC5sZW5ndGggJiYgdGhpcy5sZW5ndGggKSB7CgkJCS8vIF9kZXRhaWxzU2hvd24gYXMgZmFsc2Ugb3IgdW5kZWZpbmVkIHdpbGwgZmFsbCB0aHJvdWdoIHRvIHJldHVybiBmYWxzZQoJCQlyZXR1cm4gY3R4WzBdLmFvRGF0YVsgdGhpc1swXSBdLl9kZXRhaWxzU2hvdyB8fCBmYWxzZTsKCQl9CgkJcmV0dXJuIGZhbHNlOwoJfSApOwoJCgkKCQoJLyogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqCgkgKiBDb2x1bW5zCgkgKgoJICoge2ludGVnZXJ9ICAgICAgICAgICAtIGNvbHVtbiBpbmRleCAoPj0wIGNvdW50IGZyb20gbGVmdCwgPDAgY291bnQgZnJvbSByaWdodCkKCSAqICJ7aW50ZWdlcn06dmlzSWR4IiAgLSB2aXNpYmxlIGNvbHVtbiBpbmRleCAoaS5lLiB0cmFuc2xhdGUgdG8gY29sdW1uIGluZGV4KSAgKD49MCBjb3VudCBmcm9tIGxlZnQsIDwwIGNvdW50IGZyb20gcmlnaHQpCgkgKiAie2ludGVnZXJ9OnZpc2libGUiIC0gYWxpYXMgZm9yIHtpbnRlZ2VyfTp2aXNJZHggICg+PTAgY291bnQgZnJvbSBsZWZ0LCA8MCBjb3VudCBmcm9tIHJpZ2h0KQoJICogIntzdHJpbmd9Om5hbWUiICAgICAtIGNvbHVtbiBuYW1lCgkgKiAie3N0cmluZ30iICAgICAgICAgIC0galF1ZXJ5IHNlbGVjdG9yIG9uIGNvbHVtbiBoZWFkZXIgbm9kZXMKCSAqCgkgKi8KCQoJLy8gY2FuIGJlIGFuIGFycmF5IG9mIHRoZXNlIGl0ZW1zLCBjb21tYSBzZXBhcmF0ZWQgbGlzdCwgb3IgYW4gYXJyYXkgb2YgY29tbWEKCS8vIHNlcGFyYXRlZCBsaXN0cwoJCgl2YXIgX19yZV9jb2x1bW5fc2VsZWN0b3IgPSAvXihbXjpdKyk6KG5hbWV8dmlzSWR4fHZpc2libGUpJC87CgkKCQoJLy8gcjEgYW5kIHIyIGFyZSByZWR1bmRhbnQgLSBidXQgaXQgbWVhbnMgdGhhdCB0aGUgcGFyYW1ldGVycyBtYXRjaCBmb3IgdGhlCgkvLyBpdGVyYXRvciBjYWxsYmFjayBpbiBjb2x1bW5zKCkuZGF0YSgpCgl2YXIgX19jb2x1bW5EYXRhID0gZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uLCByMSwgcjIsIHJvd3MgKSB7CgkJdmFyIGEgPSBbXTsKCQlmb3IgKCB2YXIgcm93PTAsIGllbj1yb3dzLmxlbmd0aCA7IHJvdzxpZW4gOyByb3crKyApIHsKCQkJYS5wdXNoKCBfZm5HZXRDZWxsRGF0YSggc2V0dGluZ3MsIHJvd3Nbcm93XSwgY29sdW1uICkgKTsKCQl9CgkJcmV0dXJuIGE7Cgl9OwoJCgkKCXZhciBfX2NvbHVtbl9zZWxlY3RvciA9IGZ1bmN0aW9uICggc2V0dGluZ3MsIHNlbGVjdG9yLCBvcHRzICkKCXsKCQl2YXIKCQkJY29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1ucywKCQkJbmFtZXMgPSBfcGx1Y2soIGNvbHVtbnMsICdzTmFtZScgKSwKCQkJbm9kZXMgPSBfcGx1Y2soIGNvbHVtbnMsICduVGgnICk7CgkKCQl2YXIgcnVuID0gZnVuY3Rpb24gKCBzICkgewoJCQl2YXIgc2VsSW50ID0gX2ludFZhbCggcyApOwoJCgkJCS8vIFNlbGVjdG9yIC0gYWxsCgkJCWlmICggcyA9PT0gJycgKSB7CgkJCQlyZXR1cm4gX3JhbmdlKCBjb2x1bW5zLmxlbmd0aCApOwoJCQl9CgkKCQkJLy8gU2VsZWN0b3IgLSBpbmRleAoJCQlpZiAoIHNlbEludCAhPT0gbnVsbCApIHsKCQkJCXJldHVybiBbIHNlbEludCA+PSAwID8KCQkJCQlzZWxJbnQgOiAvLyBDb3VudCBmcm9tIGxlZnQKCQkJCQljb2x1bW5zLmxlbmd0aCArIHNlbEludCAvLyBDb3VudCBmcm9tIHJpZ2h0ICgrIGJlY2F1c2UgaXRzIGEgbmVnYXRpdmUgdmFsdWUpCgkJCQldOwoJCQl9CgkKCQkJLy8gU2VsZWN0b3IgPSBmdW5jdGlvbgoJCQlpZiAoIHR5cGVvZiBzID09PSAnZnVuY3Rpb24nICkgewoJCQkJdmFyIHJvd3MgPSBfc2VsZWN0b3Jfcm93X2luZGV4ZXMoIHNldHRpbmdzLCBvcHRzICk7CgkKCQkJCXJldHVybiAkLm1hcCggY29sdW1ucywgZnVuY3Rpb24gKGNvbCwgaWR4KSB7CgkJCQkJcmV0dXJuIHMoCgkJCQkJCQlpZHgsCgkJCQkJCQlfX2NvbHVtbkRhdGEoIHNldHRpbmdzLCBpZHgsIDAsIDAsIHJvd3MgKSwKCQkJCQkJCW5vZGVzWyBpZHggXQoJCQkJCQkpID8gaWR4IDogbnVsbDsKCQkJCX0gKTsKCQkJfQoJCgkJCS8vIGpRdWVyeSBvciBzdHJpbmcgc2VsZWN0b3IKCQkJdmFyIG1hdGNoID0gdHlwZW9mIHMgPT09ICdzdHJpbmcnID8KCQkJCXMubWF0Y2goIF9fcmVfY29sdW1uX3NlbGVjdG9yICkgOgoJCQkJJyc7CgkKCQkJaWYgKCBtYXRjaCApIHsKCQkJCXN3aXRjaCggbWF0Y2hbMl0gKSB7CgkJCQkJY2FzZSAndmlzSWR4JzoKCQkJCQljYXNlICd2aXNpYmxlJzoKCQkJCQkJdmFyIGlkeCA9IHBhcnNlSW50KCBtYXRjaFsxXSwgMTAgKTsKCQkJCQkJLy8gVmlzaWJsZSBpbmRleCBnaXZlbiwgY29udmVydCB0byBjb2x1bW4gaW5kZXgKCQkJCQkJaWYgKCBpZHggPCAwICkgewoJCQkJCQkJLy8gQ291bnRpbmcgZnJvbSB0aGUgcmlnaHQKCQkJCQkJCXZhciB2aXNDb2x1bW5zID0gJC5tYXAoIGNvbHVtbnMsIGZ1bmN0aW9uIChjb2wsaSkgewoJCQkJCQkJCXJldHVybiBjb2wuYlZpc2libGUgPyBpIDogbnVsbDsKCQkJCQkJCX0gKTsKCQkJCQkJCXJldHVybiBbIHZpc0NvbHVtbnNbIHZpc0NvbHVtbnMubGVuZ3RoICsgaWR4IF0gXTsKCQkJCQkJfQoJCQkJCQkvLyBDb3VudGluZyBmcm9tIHRoZSBsZWZ0CgkJCQkJCXJldHVybiBbIF9mblZpc2libGVUb0NvbHVtbkluZGV4KCBzZXR0aW5ncywgaWR4ICkgXTsKCQoJCQkJCWNhc2UgJ25hbWUnOgoJCQkJCQkvLyBtYXRjaCBieSBuYW1lLiBgbmFtZXNgIGlzIGNvbHVtbiBpbmRleCBjb21wbGV0ZSBhbmQgaW4gb3JkZXIKCQkJCQkJcmV0dXJuICQubWFwKCBuYW1lcywgZnVuY3Rpb24gKG5hbWUsIGkpIHsKCQkJCQkJCXJldHVybiBuYW1lID09PSBtYXRjaFsxXSA/IGkgOiBudWxsOwoJCQkJCQl9ICk7CgkKCQkJCQlkZWZhdWx0OgoJCQkJCQlyZXR1cm4gW107CgkJCQl9CgkJCX0KCQoJCQkvLyBDZWxsIGluIHRoZSB0YWJsZSBib2R5CgkJCWlmICggcy5ub2RlTmFtZSAmJiBzLl9EVF9DZWxsSW5kZXggKSB7CgkJCQlyZXR1cm4gWyBzLl9EVF9DZWxsSW5kZXguY29sdW1uIF07CgkJCX0KCQoJCQkvLyBqUXVlcnkgc2VsZWN0b3Igb24gdGhlIFRIIGVsZW1lbnRzIGZvciB0aGUgY29sdW1ucwoJCQl2YXIganFSZXN1bHQgPSAkKCBub2RlcyApCgkJCQkuZmlsdGVyKCBzICkKCQkJCS5tYXAoIGZ1bmN0aW9uICgpIHsKCQkJCQlyZXR1cm4gJC5pbkFycmF5KCB0aGlzLCBub2RlcyApOyAvLyBgbm9kZXNgIGlzIGNvbHVtbiBpbmRleCBjb21wbGV0ZSBhbmQgaW4gb3JkZXIKCQkJCX0gKQoJCQkJLnRvQXJyYXkoKTsKCQoJCQlpZiAoIGpxUmVzdWx0Lmxlbmd0aCB8fCAhIHMubm9kZU5hbWUgKSB7CgkJCQlyZXR1cm4ganFSZXN1bHQ7CgkJCX0KCQoJCQkvLyBPdGhlcndpc2UgYSBub2RlIHdoaWNoIG1pZ2h0IGhhdmUgYSBgZHQtY29sdW1uYCBkYXRhIGF0dHJpYnV0ZSwgb3IgYmUKCQkJLy8gYSBjaGlsZCBvciBzdWNoIGFuIGVsZW1lbnQKCQkJdmFyIGhvc3QgPSAkKHMpLmNsb3Nlc3QoJypbZGF0YS1kdC1jb2x1bW5dJyk7CgkJCXJldHVybiBob3N0Lmxlbmd0aCA/CgkJCQlbIGhvc3QuZGF0YSgnZHQtY29sdW1uJykgXSA6CgkJCQlbXTsKCQl9OwoJCgkJcmV0dXJuIF9zZWxlY3Rvcl9ydW4oICdjb2x1bW4nLCBzZWxlY3RvciwgcnVuLCBzZXR0aW5ncywgb3B0cyApOwoJfTsKCQoJCgl2YXIgX19zZXRDb2x1bW5WaXMgPSBmdW5jdGlvbiAoIHNldHRpbmdzLCBjb2x1bW4sIHZpcyApIHsKCQl2YXIKCQkJY29scyA9IHNldHRpbmdzLmFvQ29sdW1ucywKCQkJY29sICA9IGNvbHNbIGNvbHVtbiBdLAoJCQlkYXRhID0gc2V0dGluZ3MuYW9EYXRhLAoJCQlyb3csIGNlbGxzLCBpLCBpZW4sIHRyOwoJCgkJLy8gR2V0CgkJaWYgKCB2aXMgPT09IHVuZGVmaW5lZCApIHsKCQkJcmV0dXJuIGNvbC5iVmlzaWJsZTsKCQl9CgkKCQkvLyBTZXQKCQkvLyBObyBjaGFuZ2UKCQlpZiAoIGNvbC5iVmlzaWJsZSA9PT0gdmlzICkgewoJCQlyZXR1cm47CgkJfQoJCgkJaWYgKCB2aXMgKSB7CgkJCS8vIEluc2VydCBjb2x1bW4KCQkJLy8gTmVlZCB0byBkZWNpZGUgaWYgd2Ugc2hvdWxkIHVzZSBhcHBlbmRDaGlsZCBvciBpbnNlcnRCZWZvcmUKCQkJdmFyIGluc2VydEJlZm9yZSA9ICQuaW5BcnJheSggdHJ1ZSwgX3BsdWNrKGNvbHMsICdiVmlzaWJsZScpLCBjb2x1bW4rMSApOwoJCgkJCWZvciAoIGk9MCwgaWVuPWRhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQl0ciA9IGRhdGFbaV0ublRyOwoJCQkJY2VsbHMgPSBkYXRhW2ldLmFuQ2VsbHM7CgkKCQkJCWlmICggdHIgKSB7CgkJCQkJLy8gaW5zZXJ0QmVmb3JlIGNhbiBhY3QgbGlrZSBhcHBlbmRDaGlsZCBpZiAybmQgYXJnIGlzIG51bGwKCQkJCQl0ci5pbnNlcnRCZWZvcmUoIGNlbGxzWyBjb2x1bW4gXSwgY2VsbHNbIGluc2VydEJlZm9yZSBdIHx8IG51bGwgKTsKCQkJCX0KCQkJfQoJCX0KCQllbHNlIHsKCQkJLy8gUmVtb3ZlIGNvbHVtbgoJCQkkKCBfcGx1Y2soIHNldHRpbmdzLmFvRGF0YSwgJ2FuQ2VsbHMnLCBjb2x1bW4gKSApLmRldGFjaCgpOwoJCX0KCQoJCS8vIENvbW1vbiBhY3Rpb25zCgkJY29sLmJWaXNpYmxlID0gdmlzOwoJfTsKCQoJCglfYXBpX3JlZ2lzdGVyKCAnY29sdW1ucygpJywgZnVuY3Rpb24gKCBzZWxlY3Rvciwgb3B0cyApIHsKCQkvLyBhcmd1bWVudCBzaGlmdGluZwoJCWlmICggc2VsZWN0b3IgPT09IHVuZGVmaW5lZCApIHsKCQkJc2VsZWN0b3IgPSAnJzsKCQl9CgkJZWxzZSBpZiAoICQuaXNQbGFpbk9iamVjdCggc2VsZWN0b3IgKSApIHsKCQkJb3B0cyA9IHNlbGVjdG9yOwoJCQlzZWxlY3RvciA9ICcnOwoJCX0KCQoJCW9wdHMgPSBfc2VsZWN0b3Jfb3B0cyggb3B0cyApOwoJCgkJdmFyIGluc3QgPSB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkgewoJCQlyZXR1cm4gX19jb2x1bW5fc2VsZWN0b3IoIHNldHRpbmdzLCBzZWxlY3Rvciwgb3B0cyApOwoJCX0sIDEgKTsKCQoJCS8vIFdhbnQgYXJndW1lbnQgc2hpZnRpbmcgaGVyZSBhbmQgaW4gX3Jvd19zZWxlY3Rvcj8KCQlpbnN0LnNlbGVjdG9yLmNvbHMgPSBzZWxlY3RvcjsKCQlpbnN0LnNlbGVjdG9yLm9wdHMgPSBvcHRzOwoJCgkJcmV0dXJuIGluc3Q7Cgl9ICk7CgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjb2x1bW5zKCkuaGVhZGVyKCknLCAnY29sdW1uKCkuaGVhZGVyKCknLCBmdW5jdGlvbiAoIHNlbGVjdG9yLCBvcHRzICkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAnY29sdW1uJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uICkgewoJCQlyZXR1cm4gc2V0dGluZ3MuYW9Db2x1bW5zW2NvbHVtbl0ublRoOwoJCX0sIDEgKTsKCX0gKTsKCQoJX2FwaV9yZWdpc3RlclBsdXJhbCggJ2NvbHVtbnMoKS5mb290ZXIoKScsICdjb2x1bW4oKS5mb290ZXIoKScsIGZ1bmN0aW9uICggc2VsZWN0b3IsIG9wdHMgKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjb2x1bW4nLCBmdW5jdGlvbiAoIHNldHRpbmdzLCBjb2x1bW4gKSB7CgkJCXJldHVybiBzZXR0aW5ncy5hb0NvbHVtbnNbY29sdW1uXS5uVGY7CgkJfSwgMSApOwoJfSApOwoJCglfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmRhdGEoKScsICdjb2x1bW4oKS5kYXRhKCknLCBmdW5jdGlvbiAoKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjb2x1bW4tcm93cycsIF9fY29sdW1uRGF0YSwgMSApOwoJfSApOwoJCglfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmRhdGFTcmMoKScsICdjb2x1bW4oKS5kYXRhU3JjKCknLCBmdW5jdGlvbiAoKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjb2x1bW4nLCBmdW5jdGlvbiAoIHNldHRpbmdzLCBjb2x1bW4gKSB7CgkJCXJldHVybiBzZXR0aW5ncy5hb0NvbHVtbnNbY29sdW1uXS5tRGF0YTsKCQl9LCAxICk7Cgl9ICk7CgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjb2x1bW5zKCkuY2FjaGUoKScsICdjb2x1bW4oKS5jYWNoZSgpJywgZnVuY3Rpb24gKCB0eXBlICkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAnY29sdW1uLXJvd3MnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCBjb2x1bW4sIGksIGosIHJvd3MgKSB7CgkJCXJldHVybiBfcGx1Y2tfb3JkZXIoIHNldHRpbmdzLmFvRGF0YSwgcm93cywKCQkJCXR5cGUgPT09ICdzZWFyY2gnID8gJ19hRmlsdGVyRGF0YScgOiAnX2FTb3J0RGF0YScsIGNvbHVtbgoJCQkpOwoJCX0sIDEgKTsKCX0gKTsKCQoJX2FwaV9yZWdpc3RlclBsdXJhbCggJ2NvbHVtbnMoKS5ub2RlcygpJywgJ2NvbHVtbigpLm5vZGVzKCknLCBmdW5jdGlvbiAoKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjb2x1bW4tcm93cycsIGZ1bmN0aW9uICggc2V0dGluZ3MsIGNvbHVtbiwgaSwgaiwgcm93cyApIHsKCQkJcmV0dXJuIF9wbHVja19vcmRlciggc2V0dGluZ3MuYW9EYXRhLCByb3dzLCAnYW5DZWxscycsIGNvbHVtbiApIDsKCQl9LCAxICk7Cgl9ICk7CgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjb2x1bW5zKCkudmlzaWJsZSgpJywgJ2NvbHVtbigpLnZpc2libGUoKScsIGZ1bmN0aW9uICggdmlzLCBjYWxjICkgewoJCXZhciB0aGF0ID0gdGhpczsKCQl2YXIgcmV0ID0gdGhpcy5pdGVyYXRvciggJ2NvbHVtbicsIGZ1bmN0aW9uICggc2V0dGluZ3MsIGNvbHVtbiApIHsKCQkJaWYgKCB2aXMgPT09IHVuZGVmaW5lZCApIHsKCQkJCXJldHVybiBzZXR0aW5ncy5hb0NvbHVtbnNbIGNvbHVtbiBdLmJWaXNpYmxlOwoJCQl9IC8vIGVsc2UKCQkJX19zZXRDb2x1bW5WaXMoIHNldHRpbmdzLCBjb2x1bW4sIHZpcyApOwoJCX0gKTsKCQoJCS8vIEdyb3VwIHRoZSBjb2x1bW4gdmlzaWJpbGl0eSBjaGFuZ2VzCgkJaWYgKCB2aXMgIT09IHVuZGVmaW5lZCApIHsKCQkJdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHsKCQkJCS8vIFJlZHJhdyB0aGUgaGVhZGVyIGFmdGVyIGNoYW5nZXMKCQkJCV9mbkRyYXdIZWFkKCBzZXR0aW5ncywgc2V0dGluZ3MuYW9IZWFkZXIgKTsKCQkJCV9mbkRyYXdIZWFkKCBzZXR0aW5ncywgc2V0dGluZ3MuYW9Gb290ZXIgKTsKCQkKCQkJCS8vIFVwZGF0ZSBjb2xzcGFuIGZvciBubyByZWNvcmRzIGRpc3BsYXkuIENoaWxkIHJvd3MgYW5kIGV4dGVuc2lvbnMgd2lsbCB1c2UgdGhlaXIgb3duCgkJCQkvLyBsaXN0ZW5lcnMgdG8gZG8gdGhpcyAtIG9ubHkgbmVlZCB0byB1cGRhdGUgdGhlIGVtcHR5IHRhYmxlIGl0ZW0gaGVyZQoJCQkJaWYgKCAhIHNldHRpbmdzLmFpRGlzcGxheS5sZW5ndGggKSB7CgkJCQkJJChzZXR0aW5ncy5uVEJvZHkpLmZpbmQoJ3RkW2NvbHNwYW5dJykuYXR0cignY29sc3BhbicsIF9mblZpc2JsZUNvbHVtbnMoc2V0dGluZ3MpKTsKCQkJCX0KCQkKCQkJCV9mblNhdmVTdGF0ZSggc2V0dGluZ3MgKTsKCQoJCQkJLy8gU2Vjb25kIGxvb3Agb25jZSB0aGUgZmlyc3QgaXMgZG9uZSBmb3IgZXZlbnRzCgkJCQl0aGF0Lml0ZXJhdG9yKCAnY29sdW1uJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uICkgewoJCQkJCV9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsIG51bGwsICdjb2x1bW4tdmlzaWJpbGl0eScsIFtzZXR0aW5ncywgY29sdW1uLCB2aXMsIGNhbGNdICk7CgkJCQl9ICk7CgkKCQkJCWlmICggY2FsYyA9PT0gdW5kZWZpbmVkIHx8IGNhbGMgKSB7CgkJCQkJdGhhdC5jb2x1bW5zLmFkanVzdCgpOwoJCQkJfQoJCQl9KTsKCQl9CgkKCQlyZXR1cm4gcmV0OwoJfSApOwoJCglfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmluZGV4ZXMoKScsICdjb2x1bW4oKS5pbmRleCgpJywgZnVuY3Rpb24gKCB0eXBlICkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAnY29sdW1uJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uICkgewoJCQlyZXR1cm4gdHlwZSA9PT0gJ3Zpc2libGUnID8KCQkJCV9mbkNvbHVtbkluZGV4VG9WaXNpYmxlKCBzZXR0aW5ncywgY29sdW1uICkgOgoJCQkJY29sdW1uOwoJCX0sIDEgKTsKCX0gKTsKCQoJX2FwaV9yZWdpc3RlciggJ2NvbHVtbnMuYWRqdXN0KCknLCBmdW5jdGlvbiAoKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7CgkJCV9mbkFkanVzdENvbHVtblNpemluZyggc2V0dGluZ3MgKTsKCQl9LCAxICk7Cgl9ICk7CgkKCV9hcGlfcmVnaXN0ZXIoICdjb2x1bW4uaW5kZXgoKScsIGZ1bmN0aW9uICggdHlwZSwgaWR4ICkgewoJCWlmICggdGhpcy5jb250ZXh0Lmxlbmd0aCAhPT0gMCApIHsKCQkJdmFyIGN0eCA9IHRoaXMuY29udGV4dFswXTsKCQoJCQlpZiAoIHR5cGUgPT09ICdmcm9tVmlzaWJsZScgfHwgdHlwZSA9PT0gJ3RvRGF0YScgKSB7CgkJCQlyZXR1cm4gX2ZuVmlzaWJsZVRvQ29sdW1uSW5kZXgoIGN0eCwgaWR4ICk7CgkJCX0KCQkJZWxzZSBpZiAoIHR5cGUgPT09ICdmcm9tRGF0YScgfHwgdHlwZSA9PT0gJ3RvVmlzaWJsZScgKSB7CgkJCQlyZXR1cm4gX2ZuQ29sdW1uSW5kZXhUb1Zpc2libGUoIGN0eCwgaWR4ICk7CgkJCX0KCQl9Cgl9ICk7CgkKCV9hcGlfcmVnaXN0ZXIoICdjb2x1bW4oKScsIGZ1bmN0aW9uICggc2VsZWN0b3IsIG9wdHMgKSB7CgkJcmV0dXJuIF9zZWxlY3Rvcl9maXJzdCggdGhpcy5jb2x1bW5zKCBzZWxlY3Rvciwgb3B0cyApICk7Cgl9ICk7CgkKCXZhciBfX2NlbGxfc2VsZWN0b3IgPSBmdW5jdGlvbiAoIHNldHRpbmdzLCBzZWxlY3Rvciwgb3B0cyApCgl7CgkJdmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGE7CgkJdmFyIHJvd3MgPSBfc2VsZWN0b3Jfcm93X2luZGV4ZXMoIHNldHRpbmdzLCBvcHRzICk7CgkJdmFyIGNlbGxzID0gX3JlbW92ZUVtcHR5KCBfcGx1Y2tfb3JkZXIoIGRhdGEsIHJvd3MsICdhbkNlbGxzJyApICk7CgkJdmFyIGFsbENlbGxzID0gJChfZmxhdHRlbiggW10sIGNlbGxzICkpOwoJCXZhciByb3c7CgkJdmFyIGNvbHVtbnMgPSBzZXR0aW5ncy5hb0NvbHVtbnMubGVuZ3RoOwoJCXZhciBhLCBpLCBpZW4sIGosIG8sIGhvc3Q7CgkKCQl2YXIgcnVuID0gZnVuY3Rpb24gKCBzICkgewoJCQl2YXIgZm5TZWxlY3RvciA9IHR5cGVvZiBzID09PSAnZnVuY3Rpb24nOwoJCgkJCWlmICggcyA9PT0gbnVsbCB8fCBzID09PSB1bmRlZmluZWQgfHwgZm5TZWxlY3RvciApIHsKCQkJCS8vIEFsbCBjZWxscyBhbmQgZnVuY3Rpb24gc2VsZWN0b3JzCgkJCQlhID0gW107CgkKCQkJCWZvciAoIGk9MCwgaWVuPXJvd3MubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQkJcm93ID0gcm93c1tpXTsKCQoJCQkJCWZvciAoIGo9MCA7IGo8Y29sdW1ucyA7IGorKyApIHsKCQkJCQkJbyA9IHsKCQkJCQkJCXJvdzogcm93LAoJCQkJCQkJY29sdW1uOiBqCgkJCQkJCX07CgkKCQkJCQkJaWYgKCBmblNlbGVjdG9yICkgewoJCQkJCQkJLy8gU2VsZWN0b3IgLSBmdW5jdGlvbgoJCQkJCQkJaG9zdCA9IGRhdGFbIHJvdyBdOwoJCgkJCQkJCQlpZiAoIHMoIG8sIF9mbkdldENlbGxEYXRhKHNldHRpbmdzLCByb3csIGopLCBob3N0LmFuQ2VsbHMgPyBob3N0LmFuQ2VsbHNbal0gOiBudWxsICkgKSB7CgkJCQkJCQkJYS5wdXNoKCBvICk7CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQkvLyBTZWxlY3RvciAtIGFsbAoJCQkJCQkJYS5wdXNoKCBvICk7CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkKCQkJCXJldHVybiBhOwoJCQl9CgkJCQoJCQkvLyBTZWxlY3RvciAtIGluZGV4CgkJCWlmICggJC5pc1BsYWluT2JqZWN0KCBzICkgKSB7CgkJCQkvLyBWYWxpZCBjZWxsIGluZGV4IGFuZCBpdHMgaW4gdGhlIGFycmF5IG9mIHNlbGVjdGFibGUgcm93cwoJCQkJcmV0dXJuIHMuY29sdW1uICE9PSB1bmRlZmluZWQgJiYgcy5yb3cgIT09IHVuZGVmaW5lZCAmJiAkLmluQXJyYXkoIHMucm93LCByb3dzICkgIT09IC0xID8KCQkJCQlbc10gOgoJCQkJCVtdOwoJCQl9CgkKCQkJLy8gU2VsZWN0b3IgLSBqUXVlcnkgZmlsdGVyZWQgY2VsbHMKCQkJdmFyIGpxUmVzdWx0ID0gYWxsQ2VsbHMKCQkJCS5maWx0ZXIoIHMgKQoJCQkJLm1hcCggZnVuY3Rpb24gKGksIGVsKSB7CgkJCQkJcmV0dXJuIHsgLy8gdXNlIGEgbmV3IG9iamVjdCwgaW4gY2FzZSBzb21lb25lIGNoYW5nZXMgdGhlIHZhbHVlcwoJCQkJCQlyb3c6ICAgIGVsLl9EVF9DZWxsSW5kZXgucm93LAoJCQkJCQljb2x1bW46IGVsLl9EVF9DZWxsSW5kZXguY29sdW1uCgkgCQkJCX07CgkJCQl9ICkKCQkJCS50b0FycmF5KCk7CgkKCQkJaWYgKCBqcVJlc3VsdC5sZW5ndGggfHwgISBzLm5vZGVOYW1lICkgewoJCQkJcmV0dXJuIGpxUmVzdWx0OwoJCQl9CgkKCQkJLy8gT3RoZXJ3aXNlIHRoZSBzZWxlY3RvciBpcyBhIG5vZGUsIGFuZCB0aGVyZSBpcyBvbmUgbGFzdCBvcHRpb24gLSB0aGUKCQkJLy8gZWxlbWVudCBtaWdodCBiZSBhIGNoaWxkIG9mIGFuIGVsZW1lbnQgd2hpY2ggaGFzIGR0LXJvdyBhbmQgZHQtY29sdW1uCgkJCS8vIGRhdGEgYXR0cmlidXRlcwoJCQlob3N0ID0gJChzKS5jbG9zZXN0KCcqW2RhdGEtZHQtcm93XScpOwoJCQlyZXR1cm4gaG9zdC5sZW5ndGggPwoJCQkJWyB7CgkJCQkJcm93OiBob3N0LmRhdGEoJ2R0LXJvdycpLAoJCQkJCWNvbHVtbjogaG9zdC5kYXRhKCdkdC1jb2x1bW4nKQoJCQkJfSBdIDoKCQkJCVtdOwoJCX07CgkKCQlyZXR1cm4gX3NlbGVjdG9yX3J1biggJ2NlbGwnLCBzZWxlY3RvciwgcnVuLCBzZXR0aW5ncywgb3B0cyApOwoJfTsKCQoJCgkKCQoJX2FwaV9yZWdpc3RlciggJ2NlbGxzKCknLCBmdW5jdGlvbiAoIHJvd1NlbGVjdG9yLCBjb2x1bW5TZWxlY3Rvciwgb3B0cyApIHsKCQkvLyBBcmd1bWVudCBzaGlmdGluZwoJCWlmICggJC5pc1BsYWluT2JqZWN0KCByb3dTZWxlY3RvciApICkgewoJCQkvLyBJbmRleGVzCgkJCWlmICggcm93U2VsZWN0b3Iucm93ID09PSB1bmRlZmluZWQgKSB7CgkJCQkvLyBTZWxlY3RvciBvcHRpb25zIGluIGZpcnN0IHBhcmFtZXRlcgoJCQkJb3B0cyA9IHJvd1NlbGVjdG9yOwoJCQkJcm93U2VsZWN0b3IgPSBudWxsOwoJCQl9CgkJCWVsc2UgewoJCQkJLy8gQ2VsbCBpbmRleCBvYmplY3RzIGluIGZpcnN0IHBhcmFtZXRlcgoJCQkJb3B0cyA9IGNvbHVtblNlbGVjdG9yOwoJCQkJY29sdW1uU2VsZWN0b3IgPSBudWxsOwoJCQl9CgkJfQoJCWlmICggJC5pc1BsYWluT2JqZWN0KCBjb2x1bW5TZWxlY3RvciApICkgewoJCQlvcHRzID0gY29sdW1uU2VsZWN0b3I7CgkJCWNvbHVtblNlbGVjdG9yID0gbnVsbDsKCQl9CgkKCQkvLyBDZWxsIHNlbGVjdG9yCgkJaWYgKCBjb2x1bW5TZWxlY3RvciA9PT0gbnVsbCB8fCBjb2x1bW5TZWxlY3RvciA9PT0gdW5kZWZpbmVkICkgewoJCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHsKCQkJCXJldHVybiBfX2NlbGxfc2VsZWN0b3IoIHNldHRpbmdzLCByb3dTZWxlY3RvciwgX3NlbGVjdG9yX29wdHMoIG9wdHMgKSApOwoJCQl9ICk7CgkJfQoJCgkJLy8gVGhlIGRlZmF1bHQgYnVpbHQgaW4gb3B0aW9ucyBuZWVkIHRvIGFwcGx5IHRvIHJvdyBhbmQgY29sdW1ucwoJCXZhciBpbnRlcm5hbE9wdHMgPSBvcHRzID8gewoJCQlwYWdlOiBvcHRzLnBhZ2UsCgkJCW9yZGVyOiBvcHRzLm9yZGVyLAoJCQlzZWFyY2g6IG9wdHMuc2VhcmNoCgkJfSA6IHt9OwoJCgkJLy8gUm93ICsgY29sdW1uIHNlbGVjdG9yCgkJdmFyIGNvbHVtbnMgPSB0aGlzLmNvbHVtbnMoIGNvbHVtblNlbGVjdG9yLCBpbnRlcm5hbE9wdHMgKTsKCQl2YXIgcm93cyA9IHRoaXMucm93cyggcm93U2VsZWN0b3IsIGludGVybmFsT3B0cyApOwoJCXZhciBpLCBpZW4sIGosIGplbjsKCQoJCXZhciBjZWxsc05vT3B0cyA9IHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MsIGlkeCApIHsKCQkJdmFyIGEgPSBbXTsKCQoJCQlmb3IgKCBpPTAsIGllbj1yb3dzW2lkeF0ubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQlmb3IgKCBqPTAsIGplbj1jb2x1bW5zW2lkeF0ubGVuZ3RoIDsgajxqZW4gOyBqKysgKSB7CgkJCQkJYS5wdXNoKCB7CgkJCQkJCXJvdzogICAgcm93c1tpZHhdW2ldLAoJCQkJCQljb2x1bW46IGNvbHVtbnNbaWR4XVtqXQoJCQkJCX0gKTsKCQkJCX0KCQkJfQoJCgkJCXJldHVybiBhOwoJCX0sIDEgKTsKCQoJCS8vIFRoZXJlIGlzIGN1cnJlbnRseSBvbmx5IG9uZSBleHRlbnNpb24gd2hpY2ggdXNlcyBhIGNlbGwgc2VsZWN0b3IgZXh0ZW5zaW9uCgkJLy8gSXQgaXMgYSBfbWFqb3JfIHBlcmZvcm1hbmNlIGRyYWcgdG8gcnVuIHRoaXMgaWYgaXQgaXNuJ3QgbmVlZGVkLCBzbyB0aGlzIGlzCgkJLy8gYW4gZXh0ZW5zaW9uIHNwZWNpZmljIGNoZWNrIGF0IHRoZSBtb21lbnQKCQl2YXIgY2VsbHMgPSBvcHRzICYmIG9wdHMuc2VsZWN0ZWQgPwoJCQl0aGlzLmNlbGxzKCBjZWxsc05vT3B0cywgb3B0cyApIDoKCQkJY2VsbHNOb09wdHM7CgkKCQkkLmV4dGVuZCggY2VsbHMuc2VsZWN0b3IsIHsKCQkJY29sczogY29sdW1uU2VsZWN0b3IsCgkJCXJvd3M6IHJvd1NlbGVjdG9yLAoJCQlvcHRzOiBvcHRzCgkJfSApOwoJCgkJcmV0dXJuIGNlbGxzOwoJfSApOwoJCgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjZWxscygpLm5vZGVzKCknLCAnY2VsbCgpLm5vZGUoKScsIGZ1bmN0aW9uICgpIHsKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ2NlbGwnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCByb3csIGNvbHVtbiApIHsKCQkJdmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGFbIHJvdyBdOwoJCgkJCXJldHVybiBkYXRhICYmIGRhdGEuYW5DZWxscyA/CgkJCQlkYXRhLmFuQ2VsbHNbIGNvbHVtbiBdIDoKCQkJCXVuZGVmaW5lZDsKCQl9LCAxICk7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggJ2NlbGxzKCkuZGF0YSgpJywgZnVuY3Rpb24gKCkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAnY2VsbCcsIGZ1bmN0aW9uICggc2V0dGluZ3MsIHJvdywgY29sdW1uICkgewoJCQlyZXR1cm4gX2ZuR2V0Q2VsbERhdGEoIHNldHRpbmdzLCByb3csIGNvbHVtbiApOwoJCX0sIDEgKTsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY2VsbHMoKS5jYWNoZSgpJywgJ2NlbGwoKS5jYWNoZSgpJywgZnVuY3Rpb24gKCB0eXBlICkgewoJCXR5cGUgPSB0eXBlID09PSAnc2VhcmNoJyA/ICdfYUZpbHRlckRhdGEnIDogJ19hU29ydERhdGEnOwoJCgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjZWxsJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93LCBjb2x1bW4gKSB7CgkJCXJldHVybiBzZXR0aW5ncy5hb0RhdGFbIHJvdyBdWyB0eXBlIF1bIGNvbHVtbiBdOwoJCX0sIDEgKTsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY2VsbHMoKS5yZW5kZXIoKScsICdjZWxsKCkucmVuZGVyKCknLCBmdW5jdGlvbiAoIHR5cGUgKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjZWxsJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93LCBjb2x1bW4gKSB7CgkJCXJldHVybiBfZm5HZXRDZWxsRGF0YSggc2V0dGluZ3MsIHJvdywgY29sdW1uLCB0eXBlICk7CgkJfSwgMSApOwoJfSApOwoJCgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjZWxscygpLmluZGV4ZXMoKScsICdjZWxsKCkuaW5kZXgoKScsIGZ1bmN0aW9uICgpIHsKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ2NlbGwnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCByb3csIGNvbHVtbiApIHsKCQkJcmV0dXJuIHsKCQkJCXJvdzogcm93LAoJCQkJY29sdW1uOiBjb2x1bW4sCgkJCQljb2x1bW5WaXNpYmxlOiBfZm5Db2x1bW5JbmRleFRvVmlzaWJsZSggc2V0dGluZ3MsIGNvbHVtbiApCgkJCX07CgkJfSwgMSApOwoJfSApOwoJCgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjZWxscygpLmludmFsaWRhdGUoKScsICdjZWxsKCkuaW52YWxpZGF0ZSgpJywgZnVuY3Rpb24gKCBzcmMgKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjZWxsJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93LCBjb2x1bW4gKSB7CgkJCV9mbkludmFsaWRhdGUoIHNldHRpbmdzLCByb3csIHNyYywgY29sdW1uICk7CgkJfSApOwoJfSApOwoJCgkKCQoJX2FwaV9yZWdpc3RlciggJ2NlbGwoKScsIGZ1bmN0aW9uICggcm93U2VsZWN0b3IsIGNvbHVtblNlbGVjdG9yLCBvcHRzICkgewoJCXJldHVybiBfc2VsZWN0b3JfZmlyc3QoIHRoaXMuY2VsbHMoIHJvd1NlbGVjdG9yLCBjb2x1bW5TZWxlY3Rvciwgb3B0cyApICk7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggJ2NlbGwoKS5kYXRhKCknLCBmdW5jdGlvbiAoIGRhdGEgKSB7CgkJdmFyIGN0eCA9IHRoaXMuY29udGV4dDsKCQl2YXIgY2VsbCA9IHRoaXNbMF07CgkKCQlpZiAoIGRhdGEgPT09IHVuZGVmaW5lZCApIHsKCQkJLy8gR2V0CgkJCXJldHVybiBjdHgubGVuZ3RoICYmIGNlbGwubGVuZ3RoID8KCQkJCV9mbkdldENlbGxEYXRhKCBjdHhbMF0sIGNlbGxbMF0ucm93LCBjZWxsWzBdLmNvbHVtbiApIDoKCQkJCXVuZGVmaW5lZDsKCQl9CgkKCQkvLyBTZXQKCQlfZm5TZXRDZWxsRGF0YSggY3R4WzBdLCBjZWxsWzBdLnJvdywgY2VsbFswXS5jb2x1bW4sIGRhdGEgKTsKCQlfZm5JbnZhbGlkYXRlKCBjdHhbMF0sIGNlbGxbMF0ucm93LCAnZGF0YScsIGNlbGxbMF0uY29sdW1uICk7CgkKCQlyZXR1cm4gdGhpczsKCX0gKTsKCQoJCgkKCS8qKgoJICogR2V0IGN1cnJlbnQgb3JkZXJpbmcgKHNvcnRpbmcpIHRoYXQgaGFzIGJlZW4gYXBwbGllZCB0byB0aGUgdGFibGUuCgkgKgoJICogQHJldHVybnMge2FycmF5fSAyRCBhcnJheSBjb250YWluaW5nIHRoZSBzb3J0aW5nIGluZm9ybWF0aW9uIGZvciB0aGUgZmlyc3QKCSAqICAgdGFibGUgaW4gdGhlIGN1cnJlbnQgY29udGV4dC4gRWFjaCBlbGVtZW50IGluIHRoZSBwYXJlbnQgYXJyYXkgcmVwcmVzZW50cwoJICogICBhIGNvbHVtbiBiZWluZyBzb3J0ZWQgdXBvbiAoaS5lLiBtdWx0aS1zb3J0aW5nIHdpdGggdHdvIGNvbHVtbnMgd291bGQgaGF2ZQoJICogICAyIGlubmVyIGFycmF5cykuIFRoZSBpbm5lciBhcnJheXMgbWF5IGhhdmUgMiBvciAzIGVsZW1lbnRzLiBUaGUgZmlyc3QgaXMKCSAqICAgdGhlIGNvbHVtbiBpbmRleCB0aGF0IHRoZSBzb3J0aW5nIGNvbmRpdGlvbiBhcHBsaWVzIHRvLCB0aGUgc2Vjb25kIGlzIHRoZQoJICogICBkaXJlY3Rpb24gb2YgdGhlIHNvcnQgKGBkZXNjYCBvciBgYXNjYCkgYW5kLCBvcHRpb25hbGx5LCB0aGUgdGhpcmQgaXMgdGhlCgkgKiAgIGluZGV4IG9mIHRoZSBzb3J0aW5nIG9yZGVyIGZyb20gdGhlIGBjb2x1bW4uc29ydGluZ2AgaW5pdGlhbGlzYXRpb24gYXJyYXkuCgkgKi8vKioKCSAqIFNldCB0aGUgb3JkZXJpbmcgZm9yIHRoZSB0YWJsZS4KCSAqCgkgKiBAcGFyYW0ge2ludGVnZXJ9IG9yZGVyIENvbHVtbiBpbmRleCB0byBzb3J0IHVwb24uCgkgKiBAcGFyYW0ge3N0cmluZ30gZGlyZWN0aW9uIERpcmVjdGlvbiBvZiB0aGUgc29ydCB0byBiZSBhcHBsaWVkIChgYXNjYCBvciBgZGVzY2ApCgkgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXMKCSAqLy8qKgoJICogU2V0IHRoZSBvcmRlcmluZyBmb3IgdGhlIHRhYmxlLgoJICoKCSAqIEBwYXJhbSB7YXJyYXl9IG9yZGVyIDFEIGFycmF5IG9mIHNvcnRpbmcgaW5mb3JtYXRpb24gdG8gYmUgYXBwbGllZC4KCSAqIEBwYXJhbSB7YXJyYXl9IFsuLi5dIE9wdGlvbmFsIGFkZGl0aW9uYWwgc29ydGluZyBjb25kaXRpb25zCgkgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXMKCSAqLy8qKgoJICogU2V0IHRoZSBvcmRlcmluZyBmb3IgdGhlIHRhYmxlLgoJICoKCSAqIEBwYXJhbSB7YXJyYXl9IG9yZGVyIDJEIGFycmF5IG9mIHNvcnRpbmcgaW5mb3JtYXRpb24gdG8gYmUgYXBwbGllZC4KCSAqIEByZXR1cm5zIHtEYXRhVGFibGVzLkFwaX0gdGhpcwoJICovCglfYXBpX3JlZ2lzdGVyKCAnb3JkZXIoKScsIGZ1bmN0aW9uICggb3JkZXIsIGRpciApIHsKCQl2YXIgY3R4ID0gdGhpcy5jb250ZXh0OwoJCgkJaWYgKCBvcmRlciA9PT0gdW5kZWZpbmVkICkgewoJCQkvLyBnZXQKCQkJcmV0dXJuIGN0eC5sZW5ndGggIT09IDAgPwoJCQkJY3R4WzBdLmFhU29ydGluZyA6CgkJCQl1bmRlZmluZWQ7CgkJfQoJCgkJLy8gc2V0CgkJaWYgKCB0eXBlb2Ygb3JkZXIgPT09ICdudW1iZXInICkgewoJCQkvLyBTaW1wbGUgY29sdW1uIC8gZGlyZWN0aW9uIHBhc3NlZCBpbgoJCQlvcmRlciA9IFsgWyBvcmRlciwgZGlyIF0gXTsKCQl9CgkJZWxzZSBpZiAoIG9yZGVyLmxlbmd0aCAmJiAhIEFycmF5LmlzQXJyYXkoIG9yZGVyWzBdICkgKSB7CgkJCS8vIEFyZ3VtZW50cyBwYXNzZWQgaW4gKGxpc3Qgb2YgMUQgYXJyYXlzKQoJCQlvcmRlciA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKCBhcmd1bWVudHMgKTsKCQl9CgkJLy8gb3RoZXJ3aXNlIGEgMkQgYXJyYXkgd2FzIHBhc3NlZCBpbgoJCgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7CgkJCXNldHRpbmdzLmFhU29ydGluZyA9IG9yZGVyLnNsaWNlKCk7CgkJfSApOwoJfSApOwoJCgkKCS8qKgoJICogQXR0YWNoIGEgc29ydCBsaXN0ZW5lciB0byBhbiBlbGVtZW50IGZvciBhIGdpdmVuIGNvbHVtbgoJICoKCSAqIEBwYXJhbSB7bm9kZXxqUXVlcnl8c3RyaW5nfSBub2RlIElkZW50aWZpZXIgZm9yIHRoZSBlbGVtZW50KHMpIHRvIGF0dGFjaCB0aGUKCSAqICAgbGlzdGVuZXIgdG8uIFRoaXMgY2FuIHRha2UgdGhlIGZvcm0gb2YgYSBzaW5nbGUgRE9NIG5vZGUsIGEgalF1ZXJ5CgkgKiAgIGNvbGxlY3Rpb24gb2Ygbm9kZXMgb3IgYSBqUXVlcnkgc2VsZWN0b3Igd2hpY2ggd2lsbCBpZGVudGlmeSB0aGUgbm9kZShzKS4KCSAqIEBwYXJhbSB7aW50ZWdlcn0gY29sdW1uIHRoZSBjb2x1bW4gdGhhdCBhIGNsaWNrIG9uIHRoaXMgbm9kZSB3aWxsIHNvcnQgb24KCSAqIEBwYXJhbSB7ZnVuY3Rpb259IFtjYWxsYmFja10gY2FsbGJhY2sgZnVuY3Rpb24gd2hlbiBzb3J0IGlzIHJ1bgoJICogQHJldHVybnMge0RhdGFUYWJsZXMuQXBpfSB0aGlzCgkgKi8KCV9hcGlfcmVnaXN0ZXIoICdvcmRlci5saXN0ZW5lcigpJywgZnVuY3Rpb24gKCBub2RlLCBjb2x1bW4sIGNhbGxiYWNrICkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkgewoJCQlfZm5Tb3J0QXR0YWNoTGlzdGVuZXIoIHNldHRpbmdzLCBub2RlLCBjb2x1bW4sIGNhbGxiYWNrICk7CgkJfSApOwoJfSApOwoJCgkKCV9hcGlfcmVnaXN0ZXIoICdvcmRlci5maXhlZCgpJywgZnVuY3Rpb24gKCBzZXQgKSB7CgkJaWYgKCAhIHNldCApIHsKCQkJdmFyIGN0eCA9IHRoaXMuY29udGV4dDsKCQkJdmFyIGZpeGVkID0gY3R4Lmxlbmd0aCA/CgkJCQljdHhbMF0uYWFTb3J0aW5nRml4ZWQgOgoJCQkJdW5kZWZpbmVkOwoJCgkJCXJldHVybiBBcnJheS5pc0FycmF5KCBmaXhlZCApID8KCQkJCXsgcHJlOiBmaXhlZCB9IDoKCQkJCWZpeGVkOwoJCX0KCQoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkgewoJCQlzZXR0aW5ncy5hYVNvcnRpbmdGaXhlZCA9ICQuZXh0ZW5kKCB0cnVlLCB7fSwgc2V0ICk7CgkJfSApOwoJfSApOwoJCgkKCS8vIE9yZGVyIGJ5IHRoZSBzZWxlY3RlZCBjb2x1bW4ocykKCV9hcGlfcmVnaXN0ZXIoIFsKCQknY29sdW1ucygpLm9yZGVyKCknLAoJCSdjb2x1bW4oKS5vcmRlcigpJwoJXSwgZnVuY3Rpb24gKCBkaXIgKSB7CgkJdmFyIHRoYXQgPSB0aGlzOwoJCgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MsIGkgKSB7CgkJCXZhciBzb3J0ID0gW107CgkKCQkJJC5lYWNoKCB0aGF0W2ldLCBmdW5jdGlvbiAoaiwgY29sKSB7CgkJCQlzb3J0LnB1c2goIFsgY29sLCBkaXIgXSApOwoJCQl9ICk7CgkKCQkJc2V0dGluZ3MuYWFTb3J0aW5nID0gc29ydDsKCQl9ICk7Cgl9ICk7CgkKCQoJCglfYXBpX3JlZ2lzdGVyKCAnc2VhcmNoKCknLCBmdW5jdGlvbiAoIGlucHV0LCByZWdleCwgc21hcnQsIGNhc2VJbnNlbiApIHsKCQl2YXIgY3R4ID0gdGhpcy5jb250ZXh0OwoJCgkJaWYgKCBpbnB1dCA9PT0gdW5kZWZpbmVkICkgewoJCQkvLyBnZXQKCQkJcmV0dXJuIGN0eC5sZW5ndGggIT09IDAgPwoJCQkJY3R4WzBdLm9QcmV2aW91c1NlYXJjaC5zU2VhcmNoIDoKCQkJCXVuZGVmaW5lZDsKCQl9CgkKCQkvLyBzZXQKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHsKCQkJaWYgKCAhIHNldHRpbmdzLm9GZWF0dXJlcy5iRmlsdGVyICkgewoJCQkJcmV0dXJuOwoJCQl9CgkKCQkJX2ZuRmlsdGVyQ29tcGxldGUoIHNldHRpbmdzLCAkLmV4dGVuZCgge30sIHNldHRpbmdzLm9QcmV2aW91c1NlYXJjaCwgewoJCQkJInNTZWFyY2giOiBpbnB1dCsiIiwKCQkJCSJiUmVnZXgiOiAgcmVnZXggPT09IG51bGwgPyBmYWxzZSA6IHJlZ2V4LAoJCQkJImJTbWFydCI6ICBzbWFydCA9PT0gbnVsbCA/IHRydWUgIDogc21hcnQsCgkJCQkiYkNhc2VJbnNlbnNpdGl2ZSI6IGNhc2VJbnNlbiA9PT0gbnVsbCA/IHRydWUgOiBjYXNlSW5zZW4KCQkJfSApLCAxICk7CgkJfSApOwoJfSApOwoJCgkKCV9hcGlfcmVnaXN0ZXJQbHVyYWwoCgkJJ2NvbHVtbnMoKS5zZWFyY2goKScsCgkJJ2NvbHVtbigpLnNlYXJjaCgpJywKCQlmdW5jdGlvbiAoIGlucHV0LCByZWdleCwgc21hcnQsIGNhc2VJbnNlbiApIHsKCQkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjb2x1bW4nLCBmdW5jdGlvbiAoIHNldHRpbmdzLCBjb2x1bW4gKSB7CgkJCQl2YXIgcHJlU2VhcmNoID0gc2V0dGluZ3MuYW9QcmVTZWFyY2hDb2xzOwoJCgkJCQlpZiAoIGlucHV0ID09PSB1bmRlZmluZWQgKSB7CgkJCQkJLy8gZ2V0CgkJCQkJcmV0dXJuIHByZVNlYXJjaFsgY29sdW1uIF0uc1NlYXJjaDsKCQkJCX0KCQoJCQkJLy8gc2V0CgkJCQlpZiAoICEgc2V0dGluZ3Mub0ZlYXR1cmVzLmJGaWx0ZXIgKSB7CgkJCQkJcmV0dXJuOwoJCQkJfQoJCgkJCQkkLmV4dGVuZCggcHJlU2VhcmNoWyBjb2x1bW4gXSwgewoJCQkJCSJzU2VhcmNoIjogaW5wdXQrIiIsCgkJCQkJImJSZWdleCI6ICByZWdleCA9PT0gbnVsbCA/IGZhbHNlIDogcmVnZXgsCgkJCQkJImJTbWFydCI6ICBzbWFydCA9PT0gbnVsbCA/IHRydWUgIDogc21hcnQsCgkJCQkJImJDYXNlSW5zZW5zaXRpdmUiOiBjYXNlSW5zZW4gPT09IG51bGwgPyB0cnVlIDogY2FzZUluc2VuCgkJCQl9ICk7CgkKCQkJCV9mbkZpbHRlckNvbXBsZXRlKCBzZXR0aW5ncywgc2V0dGluZ3Mub1ByZXZpb3VzU2VhcmNoLCAxICk7CgkJCX0gKTsKCQl9CgkpOwoJCgkvKgoJICogU3RhdGUgQVBJIG1ldGhvZHMKCSAqLwoJCglfYXBpX3JlZ2lzdGVyKCAnc3RhdGUoKScsIGZ1bmN0aW9uICgpIHsKCQlyZXR1cm4gdGhpcy5jb250ZXh0Lmxlbmd0aCA/CgkJCXRoaXMuY29udGV4dFswXS5vU2F2ZWRTdGF0ZSA6CgkJCW51bGw7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggJ3N0YXRlLmNsZWFyKCknLCBmdW5jdGlvbiAoKSB7CgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7CgkJCS8vIFNhdmUgYW4gZW1wdHkgb2JqZWN0CgkJCXNldHRpbmdzLmZuU3RhdGVTYXZlQ2FsbGJhY2suY2FsbCggc2V0dGluZ3Mub0luc3RhbmNlLCBzZXR0aW5ncywge30gKTsKCQl9ICk7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggJ3N0YXRlLmxvYWRlZCgpJywgZnVuY3Rpb24gKCkgewoJCXJldHVybiB0aGlzLmNvbnRleHQubGVuZ3RoID8KCQkJdGhpcy5jb250ZXh0WzBdLm9Mb2FkZWRTdGF0ZSA6CgkJCW51bGw7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggJ3N0YXRlLnNhdmUoKScsIGZ1bmN0aW9uICgpIHsKCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHsKCQkJX2ZuU2F2ZVN0YXRlKCBzZXR0aW5ncyApOwoJCX0gKTsKCX0gKTsKCQoJCgkKCS8qKgoJICogUHJvdmlkZSBhIGNvbW1vbiBtZXRob2QgZm9yIHBsdWctaW5zIHRvIGNoZWNrIHRoZSB2ZXJzaW9uIG9mIERhdGFUYWJsZXMgYmVpbmcKCSAqIHVzZWQsIGluIG9yZGVyIHRvIGVuc3VyZSBjb21wYXRpYmlsaXR5LgoJICoKCSAqICBAcGFyYW0ge3N0cmluZ30gdmVyc2lvbiBWZXJzaW9uIHN0cmluZyB0byBjaGVjayBmb3IsIGluIHRoZSBmb3JtYXQgIlguWS5aIi4KCSAqICAgIE5vdGUgdGhhdCB0aGUgZm9ybWF0cyAiWCIgYW5kICJYLlkiIGFyZSBhbHNvIGFjY2VwdGFibGUuCgkgKiAgQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWYgdGhpcyB2ZXJzaW9uIG9mIERhdGFUYWJsZXMgaXMgZ3JlYXRlciBvciBlcXVhbCB0bwoJICogICAgdGhlIHJlcXVpcmVkIHZlcnNpb24sIG9yIGZhbHNlIGlmIHRoaXMgdmVyc2lvbiBvZiBEYXRhVGFsZXMgaXMgbm90CgkgKiAgICBzdWl0YWJsZQoJICogIEBzdGF0aWMKCSAqICBAZHRvcHQgQVBJLVN0YXRpYwoJICoKCSAqICBAZXhhbXBsZQoJICogICAgYWxlcnQoICQuZm4uZGF0YVRhYmxlLnZlcnNpb25DaGVjayggJzEuOS4wJyApICk7CgkgKi8KCURhdGFUYWJsZS52ZXJzaW9uQ2hlY2sgPSBEYXRhVGFibGUuZm5WZXJzaW9uQ2hlY2sgPSBmdW5jdGlvbiggdmVyc2lvbiApCgl7CgkJdmFyIGFUaGlzID0gRGF0YVRhYmxlLnZlcnNpb24uc3BsaXQoJy4nKTsKCQl2YXIgYVRoYXQgPSB2ZXJzaW9uLnNwbGl0KCcuJyk7CgkJdmFyIGlUaGlzLCBpVGhhdDsKCQoJCWZvciAoIHZhciBpPTAsIGlMZW49YVRoYXQubGVuZ3RoIDsgaTxpTGVuIDsgaSsrICkgewoJCQlpVGhpcyA9IHBhcnNlSW50KCBhVGhpc1tpXSwgMTAgKSB8fCAwOwoJCQlpVGhhdCA9IHBhcnNlSW50KCBhVGhhdFtpXSwgMTAgKSB8fCAwOwoJCgkJCS8vIFBhcnRzIGFyZSB0aGUgc2FtZSwga2VlcCBjb21wYXJpbmcKCQkJaWYgKGlUaGlzID09PSBpVGhhdCkgewoJCQkJY29udGludWU7CgkJCX0KCQoJCQkvLyBQYXJ0cyBhcmUgZGlmZmVyZW50LCByZXR1cm4gaW1tZWRpYXRlbHkKCQkJcmV0dXJuIGlUaGlzID4gaVRoYXQ7CgkJfQoJCgkJcmV0dXJuIHRydWU7Cgl9OwoJCgkKCS8qKgoJICogQ2hlY2sgaWYgYSBgPHRhYmxlPmAgbm9kZSBpcyBhIERhdGFUYWJsZSB0YWJsZSBhbHJlYWR5IG9yIG5vdC4KCSAqCgkgKiAgQHBhcmFtIHtub2RlfGpxdWVyeXxzdHJpbmd9IHRhYmxlIFRhYmxlIG5vZGUsIGpRdWVyeSBvYmplY3Qgb3IgalF1ZXJ5CgkgKiAgICAgIHNlbGVjdG9yIGZvciB0aGUgdGFibGUgdG8gdGVzdC4gTm90ZSB0aGF0IGlmIG1vcmUgdGhhbiBtb3JlIHRoYW4gb25lCgkgKiAgICAgIHRhYmxlIGlzIHBhc3NlZCBvbiwgb25seSB0aGUgZmlyc3Qgd2lsbCBiZSBjaGVja2VkCgkgKiAgQHJldHVybnMge2Jvb2xlYW59IHRydWUgdGhlIHRhYmxlIGdpdmVuIGlzIGEgRGF0YVRhYmxlLCBvciBmYWxzZSBvdGhlcndpc2UKCSAqICBAc3RhdGljCgkgKiAgQGR0b3B0IEFQSS1TdGF0aWMKCSAqCgkgKiAgQGV4YW1wbGUKCSAqICAgIGlmICggISAkLmZuLkRhdGFUYWJsZS5pc0RhdGFUYWJsZSggJyNleGFtcGxlJyApICkgewoJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpOwoJICogICAgfQoJICovCglEYXRhVGFibGUuaXNEYXRhVGFibGUgPSBEYXRhVGFibGUuZm5Jc0RhdGFUYWJsZSA9IGZ1bmN0aW9uICggdGFibGUgKQoJewoJCXZhciB0ID0gJCh0YWJsZSkuZ2V0KDApOwoJCXZhciBpcyA9IGZhbHNlOwoJCgkJaWYgKCB0YWJsZSBpbnN0YW5jZW9mIERhdGFUYWJsZS5BcGkgKSB7CgkJCXJldHVybiB0cnVlOwoJCX0KCQoJCSQuZWFjaCggRGF0YVRhYmxlLnNldHRpbmdzLCBmdW5jdGlvbiAoaSwgbykgewoJCQl2YXIgaGVhZCA9IG8ublNjcm9sbEhlYWQgPyAkKCd0YWJsZScsIG8ublNjcm9sbEhlYWQpWzBdIDogbnVsbDsKCQkJdmFyIGZvb3QgPSBvLm5TY3JvbGxGb290ID8gJCgndGFibGUnLCBvLm5TY3JvbGxGb290KVswXSA6IG51bGw7CgkKCQkJaWYgKCBvLm5UYWJsZSA9PT0gdCB8fCBoZWFkID09PSB0IHx8IGZvb3QgPT09IHQgKSB7CgkJCQlpcyA9IHRydWU7CgkJCX0KCQl9ICk7CgkKCQlyZXR1cm4gaXM7Cgl9OwoJCgkKCS8qKgoJICogR2V0IGFsbCBEYXRhVGFibGUgdGFibGVzIHRoYXQgaGF2ZSBiZWVuIGluaXRpYWxpc2VkIC0gb3B0aW9uYWxseSB5b3UgY2FuCgkgKiBzZWxlY3QgdG8gZ2V0IG9ubHkgY3VycmVudGx5IHZpc2libGUgdGFibGVzLgoJICoKCSAqICBAcGFyYW0ge2Jvb2xlYW59IFt2aXNpYmxlPWZhbHNlXSBGbGFnIHRvIGluZGljYXRlIGlmIHlvdSB3YW50IGFsbCAoZGVmYXVsdCkKCSAqICAgIG9yIHZpc2libGUgdGFibGVzIG9ubHkuCgkgKiAgQHJldHVybnMge2FycmF5fSBBcnJheSBvZiBgdGFibGVgIG5vZGVzIChub3QgRGF0YVRhYmxlIGluc3RhbmNlcykgd2hpY2ggYXJlCgkgKiAgICBEYXRhVGFibGVzCgkgKiAgQHN0YXRpYwoJICogIEBkdG9wdCBBUEktU3RhdGljCgkgKgoJICogIEBleGFtcGxlCgkgKiAgICAkLmVhY2goICQuZm4uZGF0YVRhYmxlLnRhYmxlcyh0cnVlKSwgZnVuY3Rpb24gKCkgewoJICogICAgICAkKHRhYmxlKS5EYXRhVGFibGUoKS5jb2x1bW5zLmFkanVzdCgpOwoJICogICAgfSApOwoJICovCglEYXRhVGFibGUudGFibGVzID0gRGF0YVRhYmxlLmZuVGFibGVzID0gZnVuY3Rpb24gKCB2aXNpYmxlICkKCXsKCQl2YXIgYXBpID0gZmFsc2U7CgkKCQlpZiAoICQuaXNQbGFpbk9iamVjdCggdmlzaWJsZSApICkgewoJCQlhcGkgPSB2aXNpYmxlLmFwaTsKCQkJdmlzaWJsZSA9IHZpc2libGUudmlzaWJsZTsKCQl9CgkKCQl2YXIgYSA9ICQubWFwKCBEYXRhVGFibGUuc2V0dGluZ3MsIGZ1bmN0aW9uIChvKSB7CgkJCWlmICggIXZpc2libGUgfHwgKHZpc2libGUgJiYgJChvLm5UYWJsZSkuaXMoJzp2aXNpYmxlJykpICkgewoJCQkJcmV0dXJuIG8ublRhYmxlOwoJCQl9CgkJfSApOwoJCgkJcmV0dXJuIGFwaSA/CgkJCW5ldyBfQXBpKCBhICkgOgoJCQlhOwoJfTsKCQoJCgkvKioKCSAqIENvbnZlcnQgZnJvbSBjYW1lbCBjYXNlIHBhcmFtZXRlcnMgdG8gSHVuZ2FyaWFuIG5vdGF0aW9uLiBUaGlzIGlzIG1hZGUgcHVibGljCgkgKiBmb3IgdGhlIGV4dGVuc2lvbnMgdG8gcHJvdmlkZSB0aGUgc2FtZSBhYmlsaXR5IGFzIERhdGFUYWJsZXMgY29yZSB0byBhY2NlcHQKCSAqIGVpdGhlciB0aGUgMS45IHN0eWxlIEh1bmdhcmlhbiBub3RhdGlvbiwgb3IgdGhlIDEuMTArIHN0eWxlIGNhbWVsQ2FzZQoJICogcGFyYW1ldGVycy4KCSAqCgkgKiAgQHBhcmFtIHtvYmplY3R9IHNyYyBUaGUgbW9kZWwgb2JqZWN0IHdoaWNoIGhvbGRzIGFsbCBwYXJhbWV0ZXJzIHRoYXQgY2FuIGJlCgkgKiAgICBtYXBwZWQuCgkgKiAgQHBhcmFtIHtvYmplY3R9IHVzZXIgVGhlIG9iamVjdCB0byBjb252ZXJ0IGZyb20gY2FtZWwgY2FzZSB0byBIdW5nYXJpYW4uCgkgKiAgQHBhcmFtIHtib29sZWFufSBmb3JjZSBXaGVuIHNldCB0byBgdHJ1ZWAsIHByb3BlcnRpZXMgd2hpY2ggYWxyZWFkeSBoYXZlIGEKCSAqICAgIEh1bmdhcmlhbiB2YWx1ZSBpbiB0aGUgYHVzZXJgIG9iamVjdCB3aWxsIGJlIG92ZXJ3cml0dGVuLiBPdGhlcndpc2UgdGhleQoJICogICAgd29uJ3QgYmUuCgkgKi8KCURhdGFUYWJsZS5jYW1lbFRvSHVuZ2FyaWFuID0gX2ZuQ2FtZWxUb0h1bmdhcmlhbjsKCQoJCgkKCS8qKgoJICoKCSAqLwoJX2FwaV9yZWdpc3RlciggJyQoKScsIGZ1bmN0aW9uICggc2VsZWN0b3IsIG9wdHMgKSB7CgkJdmFyCgkJCXJvd3MgICA9IHRoaXMucm93cyggb3B0cyApLm5vZGVzKCksIC8vIEdldCBhbGwgcm93cwoJCQlqcVJvd3MgPSAkKHJvd3MpOwoJCgkJcmV0dXJuICQoIFtdLmNvbmNhdCgKCQkJanFSb3dzLmZpbHRlciggc2VsZWN0b3IgKS50b0FycmF5KCksCgkJCWpxUm93cy5maW5kKCBzZWxlY3RvciApLnRvQXJyYXkoKQoJCSkgKTsKCX0gKTsKCQoJCgkvLyBqUXVlcnkgZnVuY3Rpb25zIHRvIG9wZXJhdGUgb24gdGhlIHRhYmxlcwoJJC5lYWNoKCBbICdvbicsICdvbmUnLCAnb2ZmJyBdLCBmdW5jdGlvbiAoaSwga2V5KSB7CgkJX2FwaV9yZWdpc3Rlcigga2V5KycoKScsIGZ1bmN0aW9uICggLyogZXZlbnQsIGhhbmRsZXIgKi8gKSB7CgkJCXZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTsKCQoJCQkvLyBBZGQgdGhlIGBkdGAgbmFtZXNwYWNlIGF1dG9tYXRpY2FsbHkgaWYgaXQgaXNuJ3QgYWxyZWFkeSBwcmVzZW50CgkJCWFyZ3NbMF0gPSAkLm1hcCggYXJnc1swXS5zcGxpdCggL1xzLyApLCBmdW5jdGlvbiAoIGUgKSB7CgkJCQlyZXR1cm4gISBlLm1hdGNoKC9cLmR0XGIvKSA/CgkJCQkJZSsnLmR0JyA6CgkJCQkJZTsKCQkJCX0gKS5qb2luKCAnICcgKTsKCQoJCQl2YXIgaW5zdCA9ICQoIHRoaXMudGFibGVzKCkubm9kZXMoKSApOwoJCQlpbnN0W2tleV0uYXBwbHkoIGluc3QsIGFyZ3MgKTsKCQkJcmV0dXJuIHRoaXM7CgkJfSApOwoJfSApOwoJCgkKCV9hcGlfcmVnaXN0ZXIoICdjbGVhcigpJywgZnVuY3Rpb24gKCkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkgewoJCQlfZm5DbGVhclRhYmxlKCBzZXR0aW5ncyApOwoJCX0gKTsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCAnc2V0dGluZ3MoKScsIGZ1bmN0aW9uICgpIHsKCQlyZXR1cm4gbmV3IF9BcGkoIHRoaXMuY29udGV4dCwgdGhpcy5jb250ZXh0ICk7Cgl9ICk7CgkKCQoJX2FwaV9yZWdpc3RlciggJ2luaXQoKScsIGZ1bmN0aW9uICgpIHsKCQl2YXIgY3R4ID0gdGhpcy5jb250ZXh0OwoJCXJldHVybiBjdHgubGVuZ3RoID8gY3R4WzBdLm9Jbml0IDogbnVsbDsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCAnZGF0YSgpJywgZnVuY3Rpb24gKCkgewoJCXJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkgewoJCQlyZXR1cm4gX3BsdWNrKCBzZXR0aW5ncy5hb0RhdGEsICdfYURhdGEnICk7CgkJfSApLmZsYXR0ZW4oKTsKCX0gKTsKCQoJCglfYXBpX3JlZ2lzdGVyKCAnZGVzdHJveSgpJywgZnVuY3Rpb24gKCByZW1vdmUgKSB7CgkJcmVtb3ZlID0gcmVtb3ZlIHx8IGZhbHNlOwoJCgkJcmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7CgkJCXZhciBjbGFzc2VzICAgPSBzZXR0aW5ncy5vQ2xhc3NlczsKCQkJdmFyIHRhYmxlICAgICA9IHNldHRpbmdzLm5UYWJsZTsKCQkJdmFyIHRib2R5ICAgICA9IHNldHRpbmdzLm5UQm9keTsKCQkJdmFyIHRoZWFkICAgICA9IHNldHRpbmdzLm5USGVhZDsKCQkJdmFyIHRmb290ICAgICA9IHNldHRpbmdzLm5URm9vdDsKCQkJdmFyIGpxVGFibGUgICA9ICQodGFibGUpOwoJCQl2YXIganFUYm9keSAgID0gJCh0Ym9keSk7CgkJCXZhciBqcVdyYXBwZXIgPSAkKHNldHRpbmdzLm5UYWJsZVdyYXBwZXIpOwoJCQl2YXIgcm93cyAgICAgID0gJC5tYXAoIHNldHRpbmdzLmFvRGF0YSwgZnVuY3Rpb24gKHIpIHsgcmV0dXJuIHIublRyOyB9ICk7CgkJCXZhciBpLCBpZW47CgkKCQkJLy8gRmxhZyB0byBub3RlIHRoYXQgdGhlIHRhYmxlIGlzIGN1cnJlbnRseSBiZWluZyBkZXN0cm95ZWQgLSBubyBhY3Rpb24KCQkJLy8gc2hvdWxkIGJlIHRha2VuCgkJCXNldHRpbmdzLmJEZXN0cm95aW5nID0gdHJ1ZTsKCQoJCQkvLyBGaXJlIG9mZiB0aGUgZGVzdHJveSBjYWxsYmFja3MgZm9yIHBsdWctaW5zIGV0YwoJCQlfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCAiYW9EZXN0cm95Q2FsbGJhY2siLCAiZGVzdHJveSIsIFtzZXR0aW5nc10gKTsKCQoJCQkvLyBJZiBub3QgYmVpbmcgcmVtb3ZlZCBmcm9tIHRoZSBkb2N1bWVudCwgbWFrZSBhbGwgY29sdW1ucyB2aXNpYmxlCgkJCWlmICggISByZW1vdmUgKSB7CgkJCQluZXcgX0FwaSggc2V0dGluZ3MgKS5jb2x1bW5zKCkudmlzaWJsZSggdHJ1ZSApOwoJCQl9CgkKCQkJLy8gQmxpdHogYWxsIGBEVGAgbmFtZXNwYWNlZCBldmVudHMgKHRoZXNlIGFyZSBpbnRlcm5hbCBldmVudHMsIHRoZQoJCQkvLyBsb3dlcmNhc2UsIGBkdGAgZXZlbnRzIGFyZSB1c2VyIHN1YnNjcmliZWQgYW5kIHRoZXkgYXJlIHJlc3BvbnNpYmxlCgkJCS8vIGZvciByZW1vdmluZyB0aGVtCgkJCWpxV3JhcHBlci5vZmYoJy5EVCcpLmZpbmQoJzpub3QodGJvZHkgKiknKS5vZmYoJy5EVCcpOwoJCQkkKHdpbmRvdykub2ZmKCcuRFQtJytzZXR0aW5ncy5zSW5zdGFuY2UpOwoJCgkJCS8vIFdoZW4gc2Nyb2xsaW5nIHdlIGhhZCB0byBicmVhayB0aGUgdGFibGUgdXAgLSByZXN0b3JlIGl0CgkJCWlmICggdGFibGUgIT0gdGhlYWQucGFyZW50Tm9kZSApIHsKCQkJCWpxVGFibGUuY2hpbGRyZW4oJ3RoZWFkJykuZGV0YWNoKCk7CgkJCQlqcVRhYmxlLmFwcGVuZCggdGhlYWQgKTsKCQkJfQoJCgkJCWlmICggdGZvb3QgJiYgdGFibGUgIT0gdGZvb3QucGFyZW50Tm9kZSApIHsKCQkJCWpxVGFibGUuY2hpbGRyZW4oJ3Rmb290JykuZGV0YWNoKCk7CgkJCQlqcVRhYmxlLmFwcGVuZCggdGZvb3QgKTsKCQkJfQoJCgkJCXNldHRpbmdzLmFhU29ydGluZyA9IFtdOwoJCQlzZXR0aW5ncy5hYVNvcnRpbmdGaXhlZCA9IFtdOwoJCQlfZm5Tb3J0aW5nQ2xhc3Nlcyggc2V0dGluZ3MgKTsKCQoJCQkkKCByb3dzICkucmVtb3ZlQ2xhc3MoIHNldHRpbmdzLmFzU3RyaXBlQ2xhc3Nlcy5qb2luKCcgJykgKTsKCQoJCQkkKCd0aCwgdGQnLCB0aGVhZCkucmVtb3ZlQ2xhc3MoIGNsYXNzZXMuc1NvcnRhYmxlKycgJysKCQkJCWNsYXNzZXMuc1NvcnRhYmxlQXNjKycgJytjbGFzc2VzLnNTb3J0YWJsZURlc2MrJyAnK2NsYXNzZXMuc1NvcnRhYmxlTm9uZQoJCQkpOwoJCgkJCS8vIEFkZCB0aGUgVFIgZWxlbWVudHMgYmFjayBpbnRvIHRoZSB0YWJsZSBpbiB0aGVpciBvcmlnaW5hbCBvcmRlcgoJCQlqcVRib2R5LmNoaWxkcmVuKCkuZGV0YWNoKCk7CgkJCWpxVGJvZHkuYXBwZW5kKCByb3dzICk7CgkKCQkJdmFyIG9yaWcgPSBzZXR0aW5ncy5uVGFibGVXcmFwcGVyLnBhcmVudE5vZGU7CgkKCQkJLy8gUmVtb3ZlIHRoZSBEYXRhVGFibGVzIGdlbmVyYXRlZCBub2RlcywgZXZlbnRzIGFuZCBjbGFzc2VzCgkJCXZhciByZW1vdmVkTWV0aG9kID0gcmVtb3ZlID8gJ3JlbW92ZScgOiAnZGV0YWNoJzsKCQkJanFUYWJsZVsgcmVtb3ZlZE1ldGhvZCBdKCk7CgkJCWpxV3JhcHBlclsgcmVtb3ZlZE1ldGhvZCBdKCk7CgkKCQkJLy8gSWYgd2UgbmVlZCB0byByZWF0dGFjaCB0aGUgdGFibGUgdG8gdGhlIGRvY3VtZW50CgkJCWlmICggISByZW1vdmUgJiYgb3JpZyApIHsKCQkJCS8vIGluc2VydEJlZm9yZSBhY3RzIGxpa2UgYXBwZW5kQ2hpbGQgaWYgIWFyZ1sxXQoJCQkJb3JpZy5pbnNlcnRCZWZvcmUoIHRhYmxlLCBzZXR0aW5ncy5uVGFibGVSZWluc2VydEJlZm9yZSApOwoJCgkJCQkvLyBSZXN0b3JlIHRoZSB3aWR0aCBvZiB0aGUgb3JpZ2luYWwgdGFibGUgLSB3YXMgcmVhZCBmcm9tIHRoZSBzdHlsZSBwcm9wZXJ0eSwKCQkJCS8vIHNvIHdlIGNhbiByZXN0b3JlIGRpcmVjdGx5IHRvIHRoYXQKCQkJCWpxVGFibGUKCQkJCQkuY3NzKCAnd2lkdGgnLCBzZXR0aW5ncy5zRGVzdHJveVdpZHRoICkKCQkJCQkucmVtb3ZlQ2xhc3MoIGNsYXNzZXMuc1RhYmxlICk7CgkKCQkJCS8vIElmIHRoZSB3ZXJlIG9yaWdpbmFsbHkgc3RyaXBlIGNsYXNzZXMgLSB0aGVuIHdlIGFkZCB0aGVtIGJhY2sgaGVyZS4KCQkJCS8vIE5vdGUgdGhpcyBpcyBub3QgZm9vbCBwcm9vZiAoZm9yIGV4YW1wbGUgaWYgbm90IGFsbCByb3dzIGhhZCBzdHJpcGUKCQkJCS8vIGNsYXNzZXMgLSBidXQgaXQncyBhIGdvb2QgZWZmb3J0IHdpdGhvdXQgZ2V0dGluZyBjYXJyaWVkIGF3YXkKCQkJCWllbiA9IHNldHRpbmdzLmFzRGVzdHJveVN0cmlwZXMubGVuZ3RoOwoJCgkJCQlpZiAoIGllbiApIHsKCQkJCQlqcVRib2R5LmNoaWxkcmVuKCkuZWFjaCggZnVuY3Rpb24gKGkpIHsKCQkJCQkJJCh0aGlzKS5hZGRDbGFzcyggc2V0dGluZ3MuYXNEZXN0cm95U3RyaXBlc1tpICUgaWVuXSApOwoJCQkJCX0gKTsKCQkJCX0KCQkJfQoJCgkJCS8qIFJlbW92ZSB0aGUgc2V0dGluZ3Mgb2JqZWN0IGZyb20gdGhlIHNldHRpbmdzIGFycmF5ICovCgkJCXZhciBpZHggPSAkLmluQXJyYXkoIHNldHRpbmdzLCBEYXRhVGFibGUuc2V0dGluZ3MgKTsKCQkJaWYgKCBpZHggIT09IC0xICkgewoJCQkJRGF0YVRhYmxlLnNldHRpbmdzLnNwbGljZSggaWR4LCAxICk7CgkJCX0KCQl9ICk7Cgl9ICk7CgkKCQoJLy8gQWRkIHRoZSBgZXZlcnkoKWAgbWV0aG9kIGZvciByb3dzLCBjb2x1bW5zIGFuZCBjZWxscyBpbiBhIGNvbXBhY3QgZm9ybQoJJC5lYWNoKCBbICdjb2x1bW4nLCAncm93JywgJ2NlbGwnIF0sIGZ1bmN0aW9uICggaSwgdHlwZSApIHsKCQlfYXBpX3JlZ2lzdGVyKCB0eXBlKydzKCkuZXZlcnkoKScsIGZ1bmN0aW9uICggZm4gKSB7CgkJCXZhciBvcHRzID0gdGhpcy5zZWxlY3Rvci5vcHRzOwoJCQl2YXIgYXBpID0gdGhpczsKCQoJCQlyZXR1cm4gdGhpcy5pdGVyYXRvciggdHlwZSwgZnVuY3Rpb24gKCBzZXR0aW5ncywgYXJnMSwgYXJnMiwgYXJnMywgYXJnNCApIHsKCQkJCS8vIFJvd3MgYW5kIGNvbHVtbnM6CgkJCQkvLyAgYXJnMSAtIGluZGV4CgkJCQkvLyAgYXJnMiAtIHRhYmxlIGNvdW50ZXIKCQkJCS8vICBhcmczIC0gbG9vcCBjb3VudGVyCgkJCQkvLyAgYXJnNCAtIHVuZGVmaW5lZAoJCQkJLy8gQ2VsbHM6CgkJCQkvLyAgYXJnMSAtIHJvdyBpbmRleAoJCQkJLy8gIGFyZzIgLSBjb2x1bW4gaW5kZXgKCQkJCS8vICBhcmczIC0gdGFibGUgY291bnRlcgoJCQkJLy8gIGFyZzQgLSBsb29wIGNvdW50ZXIKCQkJCWZuLmNhbGwoCgkJCQkJYXBpWyB0eXBlIF0oCgkJCQkJCWFyZzEsCgkJCQkJCXR5cGU9PT0nY2VsbCcgPyBhcmcyIDogb3B0cywKCQkJCQkJdHlwZT09PSdjZWxsJyA/IG9wdHMgOiB1bmRlZmluZWQKCQkJCQkpLAoJCQkJCWFyZzEsIGFyZzIsIGFyZzMsIGFyZzQKCQkJCSk7CgkJCX0gKTsKCQl9ICk7Cgl9ICk7CgkKCQoJLy8gaTE4biBtZXRob2QgZm9yIGV4dGVuc2lvbnMgdG8gYmUgYWJsZSB0byB1c2UgdGhlIGxhbmd1YWdlIG9iamVjdCBmcm9tIHRoZQoJLy8gRGF0YVRhYmxlCglfYXBpX3JlZ2lzdGVyKCAnaTE4bigpJywgZnVuY3Rpb24gKCB0b2tlbiwgZGVmLCBwbHVyYWwgKSB7CgkJdmFyIGN0eCA9IHRoaXMuY29udGV4dFswXTsKCQl2YXIgcmVzb2x2ZWQgPSBfZm5HZXRPYmplY3REYXRhRm4oIHRva2VuICkoIGN0eC5vTGFuZ3VhZ2UgKTsKCQoJCWlmICggcmVzb2x2ZWQgPT09IHVuZGVmaW5lZCApIHsKCQkJcmVzb2x2ZWQgPSBkZWY7CgkJfQoJCgkJaWYgKCBwbHVyYWwgIT09IHVuZGVmaW5lZCAmJiAkLmlzUGxhaW5PYmplY3QoIHJlc29sdmVkICkgKSB7CgkJCXJlc29sdmVkID0gcmVzb2x2ZWRbIHBsdXJhbCBdICE9PSB1bmRlZmluZWQgPwoJCQkJcmVzb2x2ZWRbIHBsdXJhbCBdIDoKCQkJCXJlc29sdmVkLl87CgkJfQoJCgkJcmV0dXJuIHJlc29sdmVkLnJlcGxhY2UoICclZCcsIHBsdXJhbCApOyAvLyBuYjogcGx1cmFsIG1pZ2h0IGJlIHVuZGVmaW5lZCwKCX0gKTsJCgkvKioKCSAqIFZlcnNpb24gc3RyaW5nIGZvciBwbHVnLWlucyB0byBjaGVjayBjb21wYXRpYmlsaXR5LiBBbGxvd2VkIGZvcm1hdCBpcwoJICogYGEuYi5jLWRgIHdoZXJlOiBhOmludCwgYjppbnQsIGM6aW50LCBkOnN0cmluZyhkZXZ8YmV0YXxhbHBoYSkuIGBkYCBpcyB1c2VkCgkgKiBvbmx5IGZvciBub24tcmVsZWFzZSBidWlsZHMuIFNlZSBodHRwOi8vc2VtdmVyLm9yZy8gZm9yIG1vcmUgaW5mb3JtYXRpb24uCgkgKiAgQG1lbWJlcgoJICogIEB0eXBlIHN0cmluZwoJICogIEBkZWZhdWx0IFZlcnNpb24gbnVtYmVyCgkgKi8KCURhdGFUYWJsZS52ZXJzaW9uID0gIjEuMTIuMSI7CgkKCS8qKgoJICogUHJpdmF0ZSBkYXRhIHN0b3JlLCBjb250YWluaW5nIGFsbCBvZiB0aGUgc2V0dGluZ3Mgb2JqZWN0cyB0aGF0IGFyZQoJICogY3JlYXRlZCBmb3IgdGhlIHRhYmxlcyBvbiBhIGdpdmVuIHBhZ2UuCgkgKgoJICogTm90ZSB0aGF0IHRoZSBgRGF0YVRhYmxlLnNldHRpbmdzYCBvYmplY3QgaXMgYWxpYXNlZCB0bwoJICogYGpRdWVyeS5mbi5kYXRhVGFibGVFeHRgIHRocm91Z2ggd2hpY2ggaXQgbWF5IGJlIGFjY2Vzc2VkIGFuZAoJICogbWFuaXB1bGF0ZWQsIG9yIGBqUXVlcnkuZm4uZGF0YVRhYmxlLnNldHRpbmdzYC4KCSAqICBAbWVtYmVyCgkgKiAgQHR5cGUgYXJyYXkKCSAqICBAZGVmYXVsdCBbXQoJICogIEBwcml2YXRlCgkgKi8KCURhdGFUYWJsZS5zZXR0aW5ncyA9IFtdOwoJCgkvKioKCSAqIE9iamVjdCBtb2RlbHMgY29udGFpbmVyLCBmb3IgdGhlIHZhcmlvdXMgbW9kZWxzIHRoYXQgRGF0YVRhYmxlcyBoYXMKCSAqIGF2YWlsYWJsZSB0byBpdC4gVGhlc2UgbW9kZWxzIGRlZmluZSB0aGUgb2JqZWN0cyB0aGF0IGFyZSB1c2VkIHRvIGhvbGQKCSAqIHRoZSBhY3RpdmUgc3RhdGUgYW5kIGNvbmZpZ3VyYXRpb24gb2YgdGhlIHRhYmxlLgoJICogIEBuYW1lc3BhY2UKCSAqLwoJRGF0YVRhYmxlLm1vZGVscyA9IHt9OwoJCgkKCQoJLyoqCgkgKiBUZW1wbGF0ZSBvYmplY3QgZm9yIHRoZSB3YXkgaW4gd2hpY2ggRGF0YVRhYmxlcyBob2xkcyBpbmZvcm1hdGlvbiBhYm91dAoJICogc2VhcmNoIGluZm9ybWF0aW9uIGZvciB0aGUgZ2xvYmFsIGZpbHRlciBhbmQgaW5kaXZpZHVhbCBjb2x1bW4gZmlsdGVycy4KCSAqICBAbmFtZXNwYWNlCgkgKi8KCURhdGFUYWJsZS5tb2RlbHMub1NlYXJjaCA9IHsKCQkvKioKCQkgKiBGbGFnIHRvIGluZGljYXRlIGlmIHRoZSBmaWx0ZXJpbmcgc2hvdWxkIGJlIGNhc2UgaW5zZW5zaXRpdmUgb3Igbm90CgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgdHJ1ZQoJCSAqLwoJCSJiQ2FzZUluc2Vuc2l0aXZlIjogdHJ1ZSwKCQoJCS8qKgoJCSAqIEFwcGxpZWQgc2VhcmNoIHRlcm0KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IDxpPkVtcHR5IHN0cmluZzwvaT4KCQkgKi8KCQkic1NlYXJjaCI6ICIiLAoJCgkJLyoqCgkJICogRmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgc2VhcmNoIHRlcm0gc2hvdWxkIGJlIGludGVycHJldGVkIGFzIGEKCQkgKiByZWd1bGFyIGV4cHJlc3Npb24gKHRydWUpIG9yIG5vdCAoZmFsc2UpIGFuZCB0aGVyZWZvcmUgYW5kIHNwZWNpYWwKCQkgKiByZWdleCBjaGFyYWN0ZXJzIGVzY2FwZWQuCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkgKi8KCQkiYlJlZ2V4IjogZmFsc2UsCgkKCQkvKioKCQkgKiBGbGFnIHRvIGluZGljYXRlIGlmIERhdGFUYWJsZXMgaXMgdG8gdXNlIGl0cyBzbWFydCBmaWx0ZXJpbmcgb3Igbm90LgoJCSAqICBAdHlwZSBib29sZWFuCgkJICogIEBkZWZhdWx0IHRydWUKCQkgKi8KCQkiYlNtYXJ0IjogdHJ1ZSwKCQoJCS8qKgoJCSAqIEZsYWcgdG8gaW5kaWNhdGUgaWYgRGF0YVRhYmxlcyBzaG91bGQgb25seSB0cmlnZ2VyIGEgc2VhcmNoIHdoZW4KCQkgKiB0aGUgcmV0dXJuIGtleSBpcyBwcmVzc2VkLgoJCSAqICBAdHlwZSBib29sZWFuCgkJICogIEBkZWZhdWx0IGZhbHNlCgkJICovCgkJInJldHVybiI6IGZhbHNlCgl9OwoJCgkKCQoJCgkvKioKCSAqIFRlbXBsYXRlIG9iamVjdCBmb3IgdGhlIHdheSBpbiB3aGljaCBEYXRhVGFibGVzIGhvbGRzIGluZm9ybWF0aW9uIGFib3V0CgkgKiBlYWNoIGluZGl2aWR1YWwgcm93LiBUaGlzIGlzIHRoZSBvYmplY3QgZm9ybWF0IHVzZWQgZm9yIHRoZSBzZXR0aW5ncwoJICogYW9EYXRhIGFycmF5LgoJICogIEBuYW1lc3BhY2UKCSAqLwoJRGF0YVRhYmxlLm1vZGVscy5vUm93ID0gewoJCS8qKgoJCSAqIFRSIGVsZW1lbnQgZm9yIHRoZSByb3cKCQkgKiAgQHR5cGUgbm9kZQoJCSAqICBAZGVmYXVsdCBudWxsCgkJICovCgkJIm5UciI6IG51bGwsCgkKCQkvKioKCQkgKiBBcnJheSBvZiBURCBlbGVtZW50cyBmb3IgZWFjaCByb3cuIFRoaXMgaXMgbnVsbCB1bnRpbCB0aGUgcm93IGhhcyBiZWVuCgkJICogY3JlYXRlZC4KCQkgKiAgQHR5cGUgYXJyYXkgbm9kZXMKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW5DZWxscyI6IG51bGwsCgkKCQkvKioKCQkgKiBEYXRhIG9iamVjdCBmcm9tIHRoZSBvcmlnaW5hbCBkYXRhIHNvdXJjZSBmb3IgdGhlIHJvdy4gVGhpcyBpcyBlaXRoZXIKCQkgKiBhbiBhcnJheSBpZiB1c2luZyB0aGUgdHJhZGl0aW9uYWwgZm9ybSBvZiBEYXRhVGFibGVzLCBvciBhbiBvYmplY3QgaWYKCQkgKiB1c2luZyBtRGF0YSBvcHRpb25zLiBUaGUgZXhhY3QgdHlwZSB3aWxsIGRlcGVuZCBvbiB0aGUgcGFzc2VkIGluCgkJICogZGF0YSBmcm9tIHRoZSBkYXRhIHNvdXJjZSwgb3Igd2lsbCBiZSBhbiBhcnJheSBpZiB1c2luZyBET00gYSBkYXRhCgkJICogc291cmNlLgoJCSAqICBAdHlwZSBhcnJheXxvYmplY3QKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiX2FEYXRhIjogW10sCgkKCQkvKioKCQkgKiBTb3J0aW5nIGRhdGEgY2FjaGUgLSB0aGlzIGFycmF5IGlzIG9zdGVuc2libHkgdGhlIHNhbWUgbGVuZ3RoIGFzIHRoZQoJCSAqIG51bWJlciBvZiBjb2x1bW5zIChhbHRob3VnaCBlYWNoIGluZGV4IGlzIGdlbmVyYXRlZCBvbmx5IGFzIGl0IGlzCgkJICogbmVlZGVkKSwgYW5kIGhvbGRzIHRoZSBkYXRhIHRoYXQgaXMgdXNlZCBmb3Igc29ydGluZyBlYWNoIGNvbHVtbiBpbiB0aGUKCQkgKiByb3cuIFdlIGRvIHRoaXMgY2FjaGUgZ2VuZXJhdGlvbiBhdCB0aGUgc3RhcnQgb2YgdGhlIHNvcnQgaW4gb3JkZXIgdGhhdAoJCSAqIHRoZSBmb3JtYXR0aW5nIG9mIHRoZSBzb3J0IGRhdGEgbmVlZCBiZSBkb25lIG9ubHkgb25jZSBmb3IgZWFjaCBjZWxsCgkJICogcGVyIHNvcnQuIFRoaXMgYXJyYXkgc2hvdWxkIG5vdCBiZSByZWFkIGZyb20gb3Igd3JpdHRlbiB0byBieSBhbnl0aGluZwoJCSAqIG90aGVyIHRoYW4gdGhlIG1hc3RlciBzb3J0aW5nIG1ldGhvZHMuCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IG51bGwKCQkgKiAgQHByaXZhdGUKCQkgKi8KCQkiX2FTb3J0RGF0YSI6IG51bGwsCgkKCQkvKioKCQkgKiBQZXIgY2VsbCBmaWx0ZXJpbmcgZGF0YSBjYWNoZS4gQXMgcGVyIHRoZSBzb3J0IGRhdGEgY2FjaGUsIHVzZWQgdG8KCQkgKiBpbmNyZWFzZSB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGZpbHRlcmluZyBpbiBEYXRhVGFibGVzCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IG51bGwKCQkgKiAgQHByaXZhdGUKCQkgKi8KCQkiX2FGaWx0ZXJEYXRhIjogbnVsbCwKCQoJCS8qKgoJCSAqIEZpbHRlcmluZyBkYXRhIGNhY2hlLiBUaGlzIGlzIHRoZSBzYW1lIGFzIHRoZSBjZWxsIGZpbHRlcmluZyBjYWNoZSwgYnV0CgkJICogaW4gdGhpcyBjYXNlIGEgc3RyaW5nIHJhdGhlciB0aGFuIGFuIGFycmF5LiBUaGlzIGlzIGVhc2lseSBjb21wdXRlZCB3aXRoCgkJICogYSBqb2luIG9uIGBfYUZpbHRlckRhdGFgLCBidXQgaXMgcHJvdmlkZWQgYXMgYSBjYWNoZSBzbyB0aGUgam9pbiBpc24ndAoJCSAqIG5lZWRlZCBvbiBldmVyeSBzZWFyY2ggKG1lbW9yeSB0cmFkZWQgZm9yIHBlcmZvcm1hbmNlKQoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBudWxsCgkJICogIEBwcml2YXRlCgkJICovCgkJIl9zRmlsdGVyUm93IjogbnVsbCwKCQoJCS8qKgoJCSAqIENhY2hlIG9mIHRoZSBjbGFzcyBuYW1lIHRoYXQgRGF0YVRhYmxlcyBoYXMgYXBwbGllZCB0byB0aGUgcm93LCBzbyB3ZQoJCSAqIGNhbiBxdWlja2x5IGxvb2sgYXQgdGhpcyB2YXJpYWJsZSByYXRoZXIgdGhhbiBuZWVkaW5nIHRvIGRvIGEgRE9NIGNoZWNrCgkJICogb24gY2xhc3NOYW1lIGZvciB0aGUgblRyIHByb3BlcnR5LgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgPGk+RW1wdHkgc3RyaW5nPC9pPgoJCSAqICBAcHJpdmF0ZQoJCSAqLwoJCSJfc1Jvd1N0cmlwZSI6ICIiLAoJCgkJLyoqCgkJICogRGVub3RlIGlmIHRoZSBvcmlnaW5hbCBkYXRhIHNvdXJjZSB3YXMgZnJvbSB0aGUgRE9NLCBvciB0aGUgZGF0YSBzb3VyY2UKCQkgKiBvYmplY3QuIFRoaXMgaXMgdXNlZCBmb3IgaW52YWxpZGF0aW5nIGRhdGEsIHNvIERhdGFUYWJsZXMgY2FuCgkJICogYXV0b21hdGljYWxseSByZWFkIGRhdGEgZnJvbSB0aGUgb3JpZ2luYWwgc291cmNlLCB1bmxlc3MgdW5pbnN0cnVjdGVkCgkJICogb3RoZXJ3aXNlLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqICBAcHJpdmF0ZQoJCSAqLwoJCSJzcmMiOiBudWxsLAoJCgkJLyoqCgkJICogSW5kZXggaW4gdGhlIGFvRGF0YSBhcnJheS4gVGhpcyBzYXZlcyBhbiBpbmRleE9mIGxvb2t1cCB3aGVuIHdlIGhhdmUgdGhlCgkJICogb2JqZWN0LCBidXQgd2FudCB0byBrbm93IHRoZSBpbmRleAoJCSAqICBAdHlwZSBpbnRlZ2VyCgkJICogIEBkZWZhdWx0IC0xCgkJICogIEBwcml2YXRlCgkJICovCgkJImlkeCI6IC0xCgl9OwoJCgkKCS8qKgoJICogVGVtcGxhdGUgb2JqZWN0IGZvciB0aGUgY29sdW1uIGluZm9ybWF0aW9uIG9iamVjdCBpbiBEYXRhVGFibGVzLiBUaGlzIG9iamVjdAoJICogaXMgaGVsZCBpbiB0aGUgc2V0dGluZ3MgYW9Db2x1bW5zIGFycmF5IGFuZCBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uIHRoYXQKCSAqIERhdGFUYWJsZXMgbmVlZHMgYWJvdXQgZWFjaCBpbmRpdmlkdWFsIGNvbHVtbi4KCSAqCgkgKiBOb3RlIHRoYXQgdGhpcyBvYmplY3QgaXMgcmVsYXRlZCB0byB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbn0KCSAqIGJ1dCB0aGlzIG9uZSBpcyB0aGUgaW50ZXJuYWwgZGF0YSBzdG9yZSBmb3IgRGF0YVRhYmxlcydzIGNhY2hlIG9mIGNvbHVtbnMuCgkgKiBJdCBzaG91bGQgTk9UIGJlIG1hbmlwdWxhdGVkIG91dHNpZGUgb2YgRGF0YVRhYmxlcy4gQW55IGNvbmZpZ3VyYXRpb24gc2hvdWxkCgkgKiBiZSBkb25lIHRocm91Z2ggdGhlIGluaXRpYWxpc2F0aW9uIG9wdGlvbnMuCgkgKiAgQG5hbWVzcGFjZQoJICovCglEYXRhVGFibGUubW9kZWxzLm9Db2x1bW4gPSB7CgkJLyoqCgkJICogQ29sdW1uIGluZGV4LiBUaGlzIGNvdWxkIGJlIHdvcmtlZCBvdXQgb24tdGhlLWZseSB3aXRoICQuaW5BcnJheSwgYnV0IGl0CgkJICogaXMgZmFzdGVyIHRvIGp1c3QgaG9sZCBpdCBhcyBhIHZhcmlhYmxlCgkJICogIEB0eXBlIGludGVnZXIKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJpZHgiOiBudWxsLAoJCgkJLyoqCgkJICogQSBsaXN0IG9mIHRoZSBjb2x1bW5zIHRoYXQgc29ydGluZyBzaG91bGQgb2NjdXIgb24gd2hlbiB0aGlzIGNvbHVtbgoJCSAqIGlzIHNvcnRlZC4gVGhhdCB0aGlzIHByb3BlcnR5IGlzIGFuIGFycmF5IGFsbG93cyBtdWx0aS1jb2x1bW4gc29ydGluZwoJCSAqIHRvIGJlIGRlZmluZWQgZm9yIGEgY29sdW1uIChmb3IgZXhhbXBsZSBmaXJzdCBuYW1lIC8gbGFzdCBuYW1lIGNvbHVtbnMKCQkgKiB3b3VsZCBiZW5lZml0IGZyb20gdGhpcykuIFRoZSB2YWx1ZXMgYXJlIGludGVnZXJzIHBvaW50aW5nIHRvIHRoZQoJCSAqIGNvbHVtbnMgdG8gYmUgc29ydGVkIG9uICh0eXBpY2FsbHkgaXQgd2lsbCBiZSBhIHNpbmdsZSBpbnRlZ2VyIHBvaW50aW5nCgkJICogYXQgaXRzZWxmLCBidXQgdGhhdCBkb2Vzbid0IG5lZWQgdG8gYmUgdGhlIGNhc2UpLgoJCSAqICBAdHlwZSBhcnJheQoJCSAqLwoJCSJhRGF0YVNvcnQiOiBudWxsLAoJCgkJLyoqCgkJICogRGVmaW5lIHRoZSBzb3J0aW5nIGRpcmVjdGlvbnMgdGhhdCBhcmUgYXBwbGllZCB0byB0aGUgY29sdW1uLCBpbiBzZXF1ZW5jZQoJCSAqIGFzIHRoZSBjb2x1bW4gaXMgcmVwZWF0ZWRseSBzb3J0ZWQgdXBvbiAtIGkuZS4gdGhlIGZpcnN0IHZhbHVlIGlzIHVzZWQKCQkgKiBhcyB0aGUgc29ydGluZyBkaXJlY3Rpb24gd2hlbiB0aGUgY29sdW1uIGlmIGZpcnN0IHNvcnRlZCAoY2xpY2tlZCBvbikuCgkJICogU29ydCBpdCBhZ2FpbiAoY2xpY2sgYWdhaW4pIGFuZCBpdCB3aWxsIG1vdmUgb24gdG8gdGhlIG5leHQgaW5kZXguCgkJICogUmVwZWF0IHVudGlsIGxvb3AuCgkJICogIEB0eXBlIGFycmF5CgkJICovCgkJImFzU29ydGluZyI6IG51bGwsCgkKCQkvKioKCQkgKiBGbGFnIHRvIGluZGljYXRlIGlmIHRoZSBjb2x1bW4gaXMgc2VhcmNoYWJsZSwgYW5kIHRodXMgc2hvdWxkIGJlIGluY2x1ZGVkCgkJICogaW4gdGhlIGZpbHRlcmluZyBvciBub3QuCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKi8KCQkiYlNlYXJjaGFibGUiOiBudWxsLAoJCgkJLyoqCgkJICogRmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgY29sdW1uIGlzIHNvcnRhYmxlIG9yIG5vdC4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqLwoJCSJiU29ydGFibGUiOiBudWxsLAoJCgkJLyoqCgkJICogRmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgY29sdW1uIGlzIGN1cnJlbnRseSB2aXNpYmxlIGluIHRoZSB0YWJsZSBvciBub3QKCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqLwoJCSJiVmlzaWJsZSI6IG51bGwsCgkKCQkvKioKCQkgKiBTdG9yZSBmb3IgbWFudWFsIHR5cGUgYXNzaWdubWVudCB1c2luZyB0aGUgYGNvbHVtbi50eXBlYCBvcHRpb24uIFRoaXMKCQkgKiBpcyBoZWxkIGluIHN0b3JlIHNvIHdlIGNhbiBtYW5pcHVsYXRlIHRoZSBjb2x1bW4ncyBgc1R5cGVgIHByb3BlcnR5LgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqICBAcHJpdmF0ZQoJCSAqLwoJCSJfc01hbnVhbFR5cGUiOiBudWxsLAoJCgkJLyoqCgkJICogRmxhZyB0byBpbmRpY2F0ZSBpZiBIVE1MNSBkYXRhIGF0dHJpYnV0ZXMgc2hvdWxkIGJlIHVzZWQgYXMgdGhlIGRhdGEKCQkgKiBzb3VyY2UgZm9yIGZpbHRlcmluZyBvciBzb3J0aW5nLiBUcnVlIGlzIGVpdGhlciBhcmUuCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkgKiAgQHByaXZhdGUKCQkgKi8KCQkiX2JBdHRyU3JjIjogZmFsc2UsCgkKCQkvKioKCQkgKiBEZXZlbG9wZXIgZGVmaW5hYmxlIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW5ldmVyIGEgY2VsbCBpcyBjcmVhdGVkIChBamF4IHNvdXJjZSwKCQkgKiBldGMpIG9yIHByb2Nlc3NlZCBmb3IgaW5wdXQgKERPTSBzb3VyY2UpLiBUaGlzIGNhbiBiZSB1c2VkIGFzIGEgY29tcGxpbWVudCB0byBtUmVuZGVyCgkJICogYWxsb3dpbmcgeW91IHRvIG1vZGlmeSB0aGUgRE9NIGVsZW1lbnQgKGFkZCBiYWNrZ3JvdW5kIGNvbG91ciBmb3IgZXhhbXBsZSkgd2hlbiB0aGUKCQkgKiBlbGVtZW50IGlzIGF2YWlsYWJsZS4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQHBhcmFtIHtlbGVtZW50fSBuVGQgVGhlIFREIG5vZGUgdGhhdCBoYXMgYmVlbiBjcmVhdGVkCgkJICogIEBwYXJhbSB7Kn0gc0RhdGEgVGhlIERhdGEgZm9yIHRoZSBjZWxsCgkJICogIEBwYXJhbSB7YXJyYXl8b2JqZWN0fSBvRGF0YSBUaGUgZGF0YSBmb3IgdGhlIHdob2xlIHJvdwoJCSAqICBAcGFyYW0ge2ludH0gaVJvdyBUaGUgcm93IGluZGV4IGZvciB0aGUgYW9EYXRhIGRhdGEgc3RvcmUKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJmbkNyZWF0ZWRDZWxsIjogbnVsbCwKCQoJCS8qKgoJCSAqIEZ1bmN0aW9uIHRvIGdldCBkYXRhIGZyb20gYSBjZWxsIGluIGEgY29sdW1uLiBZb3Ugc2hvdWxkIDxiPm5ldmVyPC9iPgoJCSAqIGFjY2VzcyBkYXRhIGRpcmVjdGx5IHRocm91Z2ggX2FEYXRhIGludGVybmFsbHkgaW4gRGF0YVRhYmxlcyAtIGFsd2F5cyB1c2UKCQkgKiB0aGUgbWV0aG9kIGF0dGFjaGVkIHRvIHRoaXMgcHJvcGVydHkuIEl0IGFsbG93cyBtRGF0YSB0byBmdW5jdGlvbiBhcwoJCSAqIHJlcXVpcmVkLiBUaGlzIGZ1bmN0aW9uIGlzIGF1dG9tYXRpY2FsbHkgYXNzaWduZWQgYnkgdGhlIGNvbHVtbgoJCSAqIGluaXRpYWxpc2F0aW9uIG1ldGhvZAoJCSAqICBAdHlwZSBmdW5jdGlvbgoJCSAqICBAcGFyYW0ge2FycmF5fG9iamVjdH0gb0RhdGEgVGhlIGRhdGEgYXJyYXkvb2JqZWN0IGZvciB0aGUgYXJyYXkKCQkgKiAgICAoaS5lLiBhb0RhdGFbXS5fYURhdGEpCgkJICogIEBwYXJhbSB7c3RyaW5nfSBzU3BlY2lmaWMgVGhlIHNwZWNpZmljIGRhdGEgdHlwZSB5b3Ugd2FudCB0byBnZXQgLQoJCSAqICAgICdkaXNwbGF5JywgJ3R5cGUnICdmaWx0ZXInICdzb3J0JwoJCSAqICBAcmV0dXJucyB7Kn0gVGhlIGRhdGEgZm9yIHRoZSBjZWxsIGZyb20gdGhlIGdpdmVuIHJvdydzIGRhdGEKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJmbkdldERhdGEiOiBudWxsLAoJCgkJLyoqCgkJICogRnVuY3Rpb24gdG8gc2V0IGRhdGEgZm9yIGEgY2VsbCBpbiB0aGUgY29sdW1uLiBZb3Ugc2hvdWxkIDxiPm5ldmVyPC9iPgoJCSAqIHNldCB0aGUgZGF0YSBkaXJlY3RseSB0byBfYURhdGEgaW50ZXJuYWxseSBpbiBEYXRhVGFibGVzIC0gYWx3YXlzIHVzZQoJCSAqIHRoaXMgbWV0aG9kLiBJdCBhbGxvd3MgbURhdGEgdG8gZnVuY3Rpb24gYXMgcmVxdWlyZWQuIFRoaXMgZnVuY3Rpb24KCQkgKiBpcyBhdXRvbWF0aWNhbGx5IGFzc2lnbmVkIGJ5IHRoZSBjb2x1bW4gaW5pdGlhbGlzYXRpb24gbWV0aG9kCgkJICogIEB0eXBlIGZ1bmN0aW9uCgkJICogIEBwYXJhbSB7YXJyYXl8b2JqZWN0fSBvRGF0YSBUaGUgZGF0YSBhcnJheS9vYmplY3QgZm9yIHRoZSBhcnJheQoJCSAqICAgIChpLmUuIGFvRGF0YVtdLl9hRGF0YSkKCQkgKiAgQHBhcmFtIHsqfSBzVmFsdWUgVmFsdWUgdG8gc2V0CgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkiZm5TZXREYXRhIjogbnVsbCwKCQoJCS8qKgoJCSAqIFByb3BlcnR5IHRvIHJlYWQgdGhlIHZhbHVlIGZvciB0aGUgY2VsbHMgaW4gdGhlIGNvbHVtbiBmcm9tIHRoZSBkYXRhCgkJICogc291cmNlIGFycmF5IC8gb2JqZWN0LiBJZiBudWxsLCB0aGVuIHRoZSBkZWZhdWx0IGNvbnRlbnQgaXMgdXNlZCwgaWYgYQoJCSAqIGZ1bmN0aW9uIGlzIGdpdmVuIHRoZW4gdGhlIHJldHVybiBmcm9tIHRoZSBmdW5jdGlvbiBpcyB1c2VkLgoJCSAqICBAdHlwZSBmdW5jdGlvbnxpbnR8c3RyaW5nfG51bGwKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJtRGF0YSI6IG51bGwsCgkKCQkvKioKCQkgKiBQYXJ0bmVyIHByb3BlcnR5IHRvIG1EYXRhIHdoaWNoIGlzIHVzZWQgKG9ubHkgd2hlbiBkZWZpbmVkKSB0byBnZXQKCQkgKiB0aGUgZGF0YSAtIGkuZS4gaXQgaXMgYmFzaWNhbGx5IHRoZSBzYW1lIGFzIG1EYXRhLCBidXQgd2l0aG91dCB0aGUKCQkgKiAnc2V0JyBvcHRpb24sIGFuZCBhbHNvIHRoZSBkYXRhIGZlZCB0byBpdCBpcyB0aGUgcmVzdWx0IGZyb20gbURhdGEuCgkJICogVGhpcyBpcyB0aGUgcmVuZGVyaW5nIG1ldGhvZCB0byBtYXRjaCB0aGUgZGF0YSBtZXRob2Qgb2YgbURhdGEuCgkJICogIEB0eXBlIGZ1bmN0aW9ufGludHxzdHJpbmd8bnVsbAoJCSAqICBAZGVmYXVsdCBudWxsCgkJICovCgkJIm1SZW5kZXIiOiBudWxsLAoJCgkJLyoqCgkJICogVW5pcXVlIGhlYWRlciBUSC9URCBlbGVtZW50IGZvciB0aGlzIGNvbHVtbiAtIHRoaXMgaXMgd2hhdCB0aGUgc29ydGluZwoJCSAqIGxpc3RlbmVyIGlzIGF0dGFjaGVkIHRvIChpZiBzb3J0aW5nIGlzIGVuYWJsZWQuKQoJCSAqICBAdHlwZSBub2RlCgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkiblRoIjogbnVsbCwKCQoJCS8qKgoJCSAqIFVuaXF1ZSBmb290ZXIgVEgvVEQgZWxlbWVudCBmb3IgdGhpcyBjb2x1bW4gKGlmIHRoZXJlIGlzIG9uZSkuIE5vdCB1c2VkCgkJICogaW4gRGF0YVRhYmxlcyBhcyBzdWNoLCBidXQgY2FuIGJlIHVzZWQgZm9yIHBsdWctaW5zIHRvIHJlZmVyZW5jZSB0aGUKCQkgKiBmb290ZXIgZm9yIGVhY2ggY29sdW1uLgoJCSAqICBAdHlwZSBub2RlCgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkiblRmIjogbnVsbCwKCQoJCS8qKgoJCSAqIFRoZSBjbGFzcyB0byBhcHBseSB0byBhbGwgVEQgZWxlbWVudHMgaW4gdGhlIHRhYmxlJ3MgVEJPRFkgZm9yIHRoZSBjb2x1bW4KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkic0NsYXNzIjogbnVsbCwKCQoJCS8qKgoJCSAqIFdoZW4gRGF0YVRhYmxlcyBjYWxjdWxhdGVzIHRoZSBjb2x1bW4gd2lkdGhzIHRvIGFzc2lnbiB0byBlYWNoIGNvbHVtbiwKCQkgKiBpdCBmaW5kcyB0aGUgbG9uZ2VzdCBzdHJpbmcgaW4gZWFjaCBjb2x1bW4gYW5kIHRoZW4gY29uc3RydWN0cyBhCgkJICogdGVtcG9yYXJ5IHRhYmxlIGFuZCByZWFkcyB0aGUgd2lkdGhzIGZyb20gdGhhdC4gVGhlIHByb2JsZW0gd2l0aCB0aGlzCgkJICogaXMgdGhhdCAibW1tIiBpcyBtdWNoIHdpZGVyIHRoZW4gImlpaWkiLCBidXQgdGhlIGxhdHRlciBpcyBhIGxvbmdlcgoJCSAqIHN0cmluZyAtIHRodXMgdGhlIGNhbGN1bGF0aW9uIGNhbiBnbyB3cm9uZyAoZG9pbmcgaXQgcHJvcGVybHkgYW5kIHB1dHRpbmcKCQkgKiBpdCBpbnRvIGFuIERPTSBvYmplY3QgYW5kIG1lYXN1cmluZyB0aGF0IGlzIGhvcnJpYmx5KCEpIHNsb3cpLiBUaHVzIGFzCgkJICogYSAid29yayBhcm91bmQiIHdlIHByb3ZpZGUgdGhpcyBvcHRpb24uIEl0IHdpbGwgYXBwZW5kIGl0cyB2YWx1ZSB0byB0aGUKCQkgKiB0ZXh0IHRoYXQgaXMgZm91bmQgdG8gYmUgdGhlIGxvbmdlc3Qgc3RyaW5nIGZvciB0aGUgY29sdW1uIC0gaS5lLiBwYWRkaW5nLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKi8KCQkic0NvbnRlbnRQYWRkaW5nIjogbnVsbCwKCQoJCS8qKgoJCSAqIEFsbG93cyBhIGRlZmF1bHQgdmFsdWUgdG8gYmUgZ2l2ZW4gZm9yIGEgY29sdW1uJ3MgZGF0YSwgYW5kIHdpbGwgYmUgdXNlZAoJCSAqIHdoZW5ldmVyIGEgbnVsbCBkYXRhIHNvdXJjZSBpcyBlbmNvdW50ZXJlZCAodGhpcyBjYW4gYmUgYmVjYXVzZSBtRGF0YQoJCSAqIGlzIHNldCB0byBudWxsLCBvciBiZWNhdXNlIHRoZSBkYXRhIHNvdXJjZSBpdHNlbGYgaXMgbnVsbCkuCgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCBudWxsCgkJICovCgkJInNEZWZhdWx0Q29udGVudCI6IG51bGwsCgkKCQkvKioKCQkgKiBOYW1lIGZvciB0aGUgY29sdW1uLCBhbGxvd2luZyByZWZlcmVuY2UgdG8gdGhlIGNvbHVtbiBieSBuYW1lIGFzIHdlbGwgYXMKCQkgKiBieSBpbmRleCAobmVlZHMgYSBsb29rdXAgdG8gd29yayBieSBuYW1lKS4KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICovCgkJInNOYW1lIjogbnVsbCwKCQoJCS8qKgoJCSAqIEN1c3RvbSBzb3J0aW5nIGRhdGEgdHlwZSAtIGRlZmluZXMgd2hpY2ggb2YgdGhlIGF2YWlsYWJsZSBwbHVnLWlucyBpbgoJCSAqIGFmblNvcnREYXRhIHRoZSBjdXN0b20gc29ydGluZyB3aWxsIHVzZSAtIGlmIGFueSBpcyBkZWZpbmVkLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgc3RkCgkJICovCgkJInNTb3J0RGF0YVR5cGUiOiAnc3RkJywKCQoJCS8qKgoJCSAqIENsYXNzIHRvIGJlIGFwcGxpZWQgdG8gdGhlIGhlYWRlciBlbGVtZW50IHdoZW4gc29ydGluZyBvbiB0aGlzIGNvbHVtbgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJzU29ydGluZ0NsYXNzIjogbnVsbCwKCQoJCS8qKgoJCSAqIENsYXNzIHRvIGJlIGFwcGxpZWQgdG8gdGhlIGhlYWRlciBlbGVtZW50IHdoZW4gc29ydGluZyBvbiB0aGlzIGNvbHVtbiAtCgkJICogd2hlbiBqUXVlcnkgVUkgdGhlbWluZyBpcyB1c2VkLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJzU29ydGluZ0NsYXNzSlVJIjogbnVsbCwKCQoJCS8qKgoJCSAqIFRpdGxlIG9mIHRoZSBjb2x1bW4gLSB3aGF0IGlzIHNlZW4gaW4gdGhlIFRIIGVsZW1lbnQgKG5UaCkuCgkJICogIEB0eXBlIHN0cmluZwoJCSAqLwoJCSJzVGl0bGUiOiBudWxsLAoJCgkJLyoqCgkJICogQ29sdW1uIHNvcnRpbmcgYW5kIGZpbHRlcmluZyB0eXBlCgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCBudWxsCgkJICovCgkJInNUeXBlIjogbnVsbCwKCQoJCS8qKgoJCSAqIFdpZHRoIG9mIHRoZSBjb2x1bW4KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkic1dpZHRoIjogbnVsbCwKCQoJCS8qKgoJCSAqIFdpZHRoIG9mIHRoZSBjb2x1bW4gd2hlbiBpdCB3YXMgZmlyc3QgImVuY291bnRlcmVkIgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJzV2lkdGhPcmlnIjogbnVsbAoJfTsKCQoJCgkvKgoJICogRGV2ZWxvcGVyIG5vdGU6IFRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBvYmplY3QgYmVsb3cgYXJlIGdpdmVuIGluIEh1bmdhcmlhbgoJICogbm90YXRpb24sIHRoYXQgd2FzIHVzZWQgYXMgdGhlIGludGVyZmFjZSBmb3IgRGF0YVRhYmxlcyBwcmlvciB0byB2MS4xMCwgaG93ZXZlcgoJICogZnJvbSB2MS4xMCBvbndhcmRzIHRoZSBwcmltYXJ5IGludGVyZmFjZSBpcyBjYW1lbCBjYXNlLiBJbiBvcmRlciB0byBhdm9pZAoJICogYnJlYWtpbmcgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgdXR0ZXJseSB3aXRoIHRoaXMgY2hhbmdlLCB0aGUgSHVuZ2FyaWFuCgkgKiB2ZXJzaW9uIGlzIHN0aWxsLCBpbnRlcm5hbGx5IHRoZSBwcmltYXJ5IGludGVyZmFjZSwgYnV0IGlzIGlzIG5vdCBkb2N1bWVudGVkCgkgKiAtIGhlbmNlIHRoZSBAbmFtZSB0YWdzIGluIGVhY2ggZG9jIGNvbW1lbnQuIFRoaXMgYWxsb3dzIGEgSmF2YXNjcmlwdCBmdW5jdGlvbgoJICogdG8gY3JlYXRlIGEgbWFwIGZyb20gSHVuZ2FyaWFuIG5vdGF0aW9uIHRvIGNhbWVsIGNhc2UgKGdvaW5nIHRoZSBvdGhlciBkaXJlY3Rpb24KCSAqIHdvdWxkIHJlcXVpcmUgZWFjaCBwcm9wZXJ0eSB0byBiZSBsaXN0ZWQsIHdoaWNoIHdvdWxkIGFkZCBhcm91bmQgM0sgdG8gdGhlIHNpemUKCSAqIG9mIERhdGFUYWJsZXMsIHdoaWxlIHRoaXMgbWV0aG9kIGlzIGFib3V0IGEgMC41SyBoaXQpLgoJICoKCSAqIFVsdGltYXRlbHkgdGhpcyBkb2VzIHBhdmUgdGhlIHdheSBmb3IgSHVuZ2FyaWFuIG5vdGF0aW9uIHRvIGJlIGRyb3BwZWQKCSAqIGNvbXBsZXRlbHksIGJ1dCB0aGF0IGlzIGEgbWFzc2l2ZSBhbW91bnQgb2Ygd29yayBhbmQgd2lsbCBicmVhayBjdXJyZW50CgkgKiBpbnN0YWxscyAodGhlcmVmb3JlIGlzIG9uLWhvbGQgdW50aWwgdjIpLgoJICovCgkKCS8qKgoJICogSW5pdGlhbGlzYXRpb24gb3B0aW9ucyB0aGF0IGNhbiBiZSBnaXZlbiB0byBEYXRhVGFibGVzIGF0IGluaXRpYWxpc2F0aW9uCgkgKiB0aW1lLgoJICogIEBuYW1lc3BhY2UKCSAqLwoJRGF0YVRhYmxlLmRlZmF1bHRzID0gewoJCS8qKgoJCSAqIEFuIGFycmF5IG9mIGRhdGEgdG8gdXNlIGZvciB0aGUgdGFibGUsIHBhc3NlZCBpbiBhdCBpbml0aWFsaXNhdGlvbiB3aGljaAoJCSAqIHdpbGwgYmUgdXNlZCBpbiBwcmVmZXJlbmNlIHRvIGFueSBkYXRhIHdoaWNoIGlzIGFscmVhZHkgaW4gdGhlIERPTS4gVGhpcyBpcwoJCSAqIHBhcnRpY3VsYXJseSB1c2VmdWwgZm9yIGNvbnN0cnVjdGluZyB0YWJsZXMgcHVyZWx5IGluIEphdmFzY3JpcHQsIGZvcgoJCSAqIGV4YW1wbGUgd2l0aCBhIGN1c3RvbSBBamF4IGNhbGwuCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IG51bGwKCQkgKgoJCSAqICBAZHRvcHQgT3B0aW9uCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5kYXRhCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBVc2luZyBhIDJEIGFycmF5IGRhdGEgc291cmNlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJkYXRhIjogWwoJCSAqICAgICAgICAgIFsnVHJpZGVudCcsICdJbnRlcm5ldCBFeHBsb3JlciA0LjAnLCAnV2luIDk1KycsIDQsICdYJ10sCgkJICogICAgICAgICAgWydUcmlkZW50JywgJ0ludGVybmV0IEV4cGxvcmVyIDUuMCcsICdXaW4gOTUrJywgNSwgJ0MnXSwKCQkgKiAgICAgICAgXSwKCQkgKiAgICAgICAgImNvbHVtbnMiOiBbCgkJICogICAgICAgICAgeyAidGl0bGUiOiAiRW5naW5lIiB9LAoJCSAqICAgICAgICAgIHsgInRpdGxlIjogIkJyb3dzZXIiIH0sCgkJICogICAgICAgICAgeyAidGl0bGUiOiAiUGxhdGZvcm0iIH0sCgkJICogICAgICAgICAgeyAidGl0bGUiOiAiVmVyc2lvbiIgfSwKCQkgKiAgICAgICAgICB7ICJ0aXRsZSI6ICJHcmFkZSIgfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYW4gYXJyYXkgb2Ygb2JqZWN0cyBhcyBhIGRhdGEgc291cmNlIChgZGF0YWApCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJkYXRhIjogWwoJCSAqICAgICAgICAgIHsKCQkgKiAgICAgICAgICAgICJlbmdpbmUiOiAgICJUcmlkZW50IiwKCQkgKiAgICAgICAgICAgICJicm93c2VyIjogICJJbnRlcm5ldCBFeHBsb3JlciA0LjAiLAoJCSAqICAgICAgICAgICAgInBsYXRmb3JtIjogIldpbiA5NSsiLAoJCSAqICAgICAgICAgICAgInZlcnNpb24iOiAgNCwKCQkgKiAgICAgICAgICAgICJncmFkZSI6ICAgICJYIgoJCSAqICAgICAgICAgIH0sCgkJICogICAgICAgICAgewoJCSAqICAgICAgICAgICAgImVuZ2luZSI6ICAgIlRyaWRlbnQiLAoJCSAqICAgICAgICAgICAgImJyb3dzZXIiOiAgIkludGVybmV0IEV4cGxvcmVyIDUuMCIsCgkJICogICAgICAgICAgICAicGxhdGZvcm0iOiAiV2luIDk1KyIsCgkJICogICAgICAgICAgICAidmVyc2lvbiI6ICA1LAoJCSAqICAgICAgICAgICAgImdyYWRlIjogICAgIkMiCgkJICogICAgICAgICAgfQoJCSAqICAgICAgICBdLAoJCSAqICAgICAgICAiY29sdW1ucyI6IFsKCQkgKiAgICAgICAgICB7ICJ0aXRsZSI6ICJFbmdpbmUiLCAgICJkYXRhIjogImVuZ2luZSIgfSwKCQkgKiAgICAgICAgICB7ICJ0aXRsZSI6ICJCcm93c2VyIiwgICJkYXRhIjogImJyb3dzZXIiIH0sCgkJICogICAgICAgICAgeyAidGl0bGUiOiAiUGxhdGZvcm0iLCAiZGF0YSI6ICJwbGF0Zm9ybSIgfSwKCQkgKiAgICAgICAgICB7ICJ0aXRsZSI6ICJWZXJzaW9uIiwgICJkYXRhIjogInZlcnNpb24iIH0sCgkJICogICAgICAgICAgeyAidGl0bGUiOiAiR3JhZGUiLCAgICAiZGF0YSI6ICJncmFkZSIgfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJhYURhdGEiOiBudWxsLAoJCgkKCQkvKioKCQkgKiBJZiBvcmRlcmluZyBpcyBlbmFibGVkLCB0aGVuIERhdGFUYWJsZXMgd2lsbCBwZXJmb3JtIGEgZmlyc3QgcGFzcyBzb3J0IG9uCgkJICogaW5pdGlhbGlzYXRpb24uIFlvdSBjYW4gZGVmaW5lIHdoaWNoIGNvbHVtbihzKSB0aGUgc29ydCBpcyBwZXJmb3JtZWQKCQkgKiB1cG9uLCBhbmQgdGhlIHNvcnRpbmcgZGlyZWN0aW9uLCB3aXRoIHRoaXMgdmFyaWFibGUuIFRoZSBgc29ydGluZ2AgYXJyYXkKCQkgKiBzaG91bGQgY29udGFpbiBhbiBhcnJheSBmb3IgZWFjaCBjb2x1bW4gdG8gYmUgc29ydGVkIGluaXRpYWxseSBjb250YWluaW5nCgkJICogdGhlIGNvbHVtbidzIGluZGV4IGFuZCBhIGRpcmVjdGlvbiBzdHJpbmcgKCdhc2MnIG9yICdkZXNjJykuCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtbMCwnYXNjJ11dCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMub3JkZXIKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFNvcnQgYnkgM3JkIGNvbHVtbiBmaXJzdCwgYW5kIHRoZW4gNHRoIGNvbHVtbgoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJvcmRlciI6IFtbMiwnYXNjJ10sIFszLCdkZXNjJ11dCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogICAgLy8gTm8gaW5pdGlhbCBzb3J0aW5nCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgIm9yZGVyIjogW10KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImFhU29ydGluZyI6IFtbMCwnYXNjJ11dLAoJCgkKCQkvKioKCQkgKiBUaGlzIHBhcmFtZXRlciBpcyBiYXNpY2FsbHkgaWRlbnRpY2FsIHRvIHRoZSBgc29ydGluZ2AgcGFyYW1ldGVyLCBidXQKCQkgKiBjYW5ub3QgYmUgb3ZlcnJpZGRlbiBieSB1c2VyIGludGVyYWN0aW9uIHdpdGggdGhlIHRhYmxlLiBXaGF0IHRoaXMgbWVhbnMKCQkgKiBpcyB0aGF0IHlvdSBjb3VsZCBoYXZlIGEgY29sdW1uICh2aXNpYmxlIG9yIGhpZGRlbikgd2hpY2ggdGhlIHNvcnRpbmcKCQkgKiB3aWxsIGFsd2F5cyBiZSBmb3JjZWQgb24gZmlyc3QgLSBhbnkgc29ydGluZyBhZnRlciB0aGF0IChmcm9tIHRoZSB1c2VyKQoJCSAqIHdpbGwgdGhlbiBiZSBwZXJmb3JtZWQgYXMgcmVxdWlyZWQuIFRoaXMgY2FuIGJlIHVzZWZ1bCBmb3IgZ3JvdXBpbmcgcm93cwoJCSAqIHRvZ2V0aGVyLgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBudWxsCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMub3JkZXJGaXhlZAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgIm9yZGVyRml4ZWQiOiBbWzAsJ2FzYyddXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKQoJCSAqLwoJCSJhYVNvcnRpbmdGaXhlZCI6IFtdLAoJCgkKCQkvKioKCQkgKiBEYXRhVGFibGVzIGNhbiBiZSBpbnN0cnVjdGVkIHRvIGxvYWQgZGF0YSB0byBkaXNwbGF5IGluIHRoZSB0YWJsZSBmcm9tIGEKCQkgKiBBamF4IHNvdXJjZS4gVGhpcyBvcHRpb24gZGVmaW5lcyBob3cgdGhhdCBBamF4IGNhbGwgaXMgbWFkZSBhbmQgd2hlcmUgdG8uCgkJICoKCQkgKiBUaGUgYGFqYXhgIHByb3BlcnR5IGhhcyB0aHJlZSBkaWZmZXJlbnQgbW9kZXMgb2Ygb3BlcmF0aW9uLCBkZXBlbmRpbmcgb24KCQkgKiBob3cgaXQgaXMgZGVmaW5lZC4gVGhlc2UgYXJlOgoJCSAqCgkJICogKiBgc3RyaW5nYCAtIFNldCB0aGUgVVJMIGZyb20gd2hlcmUgdGhlIGRhdGEgc2hvdWxkIGJlIGxvYWRlZCBmcm9tLgoJCSAqICogYG9iamVjdGAgLSBEZWZpbmUgcHJvcGVydGllcyBmb3IgYGpRdWVyeS5hamF4YC4KCQkgKiAqIGBmdW5jdGlvbmAgLSBDdXN0b20gZGF0YSBnZXQgZnVuY3Rpb24KCQkgKgoJCSAqIGBzdHJpbmdgCgkJICogLS0tLS0tLS0KCQkgKgoJCSAqIEFzIGEgc3RyaW5nLCB0aGUgYGFqYXhgIHByb3BlcnR5IHNpbXBseSBkZWZpbmVzIHRoZSBVUkwgZnJvbSB3aGljaAoJCSAqIERhdGFUYWJsZXMgd2lsbCBsb2FkIGRhdGEuCgkJICoKCQkgKiBgb2JqZWN0YAoJCSAqIC0tLS0tLS0tCgkJICoKCQkgKiBBcyBhbiBvYmplY3QsIHRoZSBwYXJhbWV0ZXJzIGluIHRoZSBvYmplY3QgYXJlIHBhc3NlZCB0bwoJCSAqIFtqUXVlcnkuYWpheF0oaHR0cDovL2FwaS5qcXVlcnkuY29tL2pRdWVyeS5hamF4LykgYWxsb3dpbmcgZmluZSBjb250cm9sCgkJICogb2YgdGhlIEFqYXggcmVxdWVzdC4gRGF0YVRhYmxlcyBoYXMgYSBudW1iZXIgb2YgZGVmYXVsdCBwYXJhbWV0ZXJzIHdoaWNoCgkJICogeW91IGNhbiBvdmVycmlkZSB1c2luZyB0aGlzIG9wdGlvbi4gUGxlYXNlIHJlZmVyIHRvIHRoZSBqUXVlcnkKCQkgKiBkb2N1bWVudGF0aW9uIGZvciBhIGZ1bGwgZGVzY3JpcHRpb24gb2YgdGhlIG9wdGlvbnMgYXZhaWxhYmxlLCBhbHRob3VnaAoJCSAqIHRoZSBmb2xsb3dpbmcgcGFyYW1ldGVycyBwcm92aWRlIGFkZGl0aW9uYWwgb3B0aW9ucyBpbiBEYXRhVGFibGVzIG9yCgkJICogcmVxdWlyZSBzcGVjaWFsIGNvbnNpZGVyYXRpb246CgkJICoKCQkgKiAqIGBkYXRhYCAtIEFzIHdpdGggalF1ZXJ5LCBgZGF0YWAgY2FuIGJlIHByb3ZpZGVkIGFzIGFuIG9iamVjdCwgYnV0IGl0CgkJICogICBjYW4gYWxzbyBiZSB1c2VkIGFzIGEgZnVuY3Rpb24gdG8gbWFuaXB1bGF0ZSB0aGUgZGF0YSBEYXRhVGFibGVzIHNlbmRzCgkJICogICB0byB0aGUgc2VydmVyLiBUaGUgZnVuY3Rpb24gdGFrZXMgYSBzaW5nbGUgcGFyYW1ldGVyLCBhbiBvYmplY3Qgb2YKCQkgKiAgIHBhcmFtZXRlcnMgd2l0aCB0aGUgdmFsdWVzIHRoYXQgRGF0YVRhYmxlcyBoYXMgcmVhZGllZCBmb3Igc2VuZGluZy4gQW4KCQkgKiAgIG9iamVjdCBtYXkgYmUgcmV0dXJuZWQgd2hpY2ggd2lsbCBiZSBtZXJnZWQgaW50byB0aGUgRGF0YVRhYmxlcwoJCSAqICAgZGVmYXVsdHMsIG9yIHlvdSBjYW4gYWRkIHRoZSBpdGVtcyB0byB0aGUgb2JqZWN0IHRoYXQgd2FzIHBhc3NlZCBpbiBhbmQKCQkgKiAgIG5vdCByZXR1cm4gYW55dGhpbmcgZnJvbSB0aGUgZnVuY3Rpb24uIFRoaXMgc3VwZXJzZWRlcyBgZm5TZXJ2ZXJQYXJhbXNgCgkJICogICBmcm9tIERhdGFUYWJsZXMgMS45LS4KCQkgKgoJCSAqICogYGRhdGFTcmNgIC0gQnkgZGVmYXVsdCBEYXRhVGFibGVzIHdpbGwgbG9vayBmb3IgdGhlIHByb3BlcnR5IGBkYXRhYCAob3IKCQkgKiAgIGBhYURhdGFgIGZvciBjb21wYXRpYmlsaXR5IHdpdGggRGF0YVRhYmxlcyAxLjktKSB3aGVuIG9idGFpbmluZyBkYXRhCgkJICogICBmcm9tIGFuIEFqYXggc291cmNlIG9yIGZvciBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIC0gdGhpcyBwYXJhbWV0ZXIKCQkgKiAgIGFsbG93cyB0aGF0IHByb3BlcnR5IHRvIGJlIGNoYW5nZWQuIFlvdSBjYW4gdXNlIEphdmFzY3JpcHQgZG90dGVkCgkJICogICBvYmplY3Qgbm90YXRpb24gdG8gZ2V0IGEgZGF0YSBzb3VyY2UgZm9yIG11bHRpcGxlIGxldmVscyBvZiBuZXN0aW5nLCBvcgoJCSAqICAgaXQgbXkgYmUgdXNlZCBhcyBhIGZ1bmN0aW9uLiBBcyBhIGZ1bmN0aW9uIGl0IHRha2VzIGEgc2luZ2xlIHBhcmFtZXRlciwKCQkgKiAgIHRoZSBKU09OIHJldHVybmVkIGZyb20gdGhlIHNlcnZlciwgd2hpY2ggY2FuIGJlIG1hbmlwdWxhdGVkIGFzCgkJICogICByZXF1aXJlZCwgd2l0aCB0aGUgcmV0dXJuZWQgdmFsdWUgYmVpbmcgdGhhdCB1c2VkIGJ5IERhdGFUYWJsZXMgYXMgdGhlCgkJICogICBkYXRhIHNvdXJjZSBmb3IgdGhlIHRhYmxlLiBUaGlzIHN1cGVyc2VkZXMgYHNBamF4RGF0YVByb3BgIGZyb20KCQkgKiAgIERhdGFUYWJsZXMgMS45LS4KCQkgKgoJCSAqICogYHN1Y2Nlc3NgIC0gU2hvdWxkIG5vdCBiZSBvdmVycmlkZGVuIGl0IGlzIHVzZWQgaW50ZXJuYWxseSBpbgoJCSAqICAgRGF0YVRhYmxlcy4gVG8gbWFuaXB1bGF0ZSAvIHRyYW5zZm9ybSB0aGUgZGF0YSByZXR1cm5lZCBieSB0aGUgc2VydmVyCgkJICogICB1c2UgYGFqYXguZGF0YVNyY2AsIG9yIHVzZSBgYWpheGAgYXMgYSBmdW5jdGlvbiAoc2VlIGJlbG93KS4KCQkgKgoJCSAqIGBmdW5jdGlvbmAKCQkgKiAtLS0tLS0tLS0tCgkJICoKCQkgKiBBcyBhIGZ1bmN0aW9uLCBtYWtpbmcgdGhlIEFqYXggY2FsbCBpcyBsZWZ0IHVwIHRvIHlvdXJzZWxmIGFsbG93aW5nCgkJICogY29tcGxldGUgY29udHJvbCBvZiB0aGUgQWpheCByZXF1ZXN0LiBJbmRlZWQsIGlmIGRlc2lyZWQsIGEgbWV0aG9kIG90aGVyCgkJICogdGhhbiBBamF4IGNvdWxkIGJlIHVzZWQgdG8gb2J0YWluIHRoZSByZXF1aXJlZCBkYXRhLCBzdWNoIGFzIFdlYiBzdG9yYWdlCgkJICogb3IgYW4gQUlSIGRhdGFiYXNlLgoJCSAqCgkJICogVGhlIGZ1bmN0aW9uIGlzIGdpdmVuIGZvdXIgcGFyYW1ldGVycyBhbmQgbm8gcmV0dXJuIGlzIHJlcXVpcmVkLiBUaGUKCQkgKiBwYXJhbWV0ZXJzIGFyZToKCQkgKgoJCSAqIDEuIF9vYmplY3RfIC0gRGF0YSB0byBzZW5kIHRvIHRoZSBzZXJ2ZXIKCQkgKiAyLiBfZnVuY3Rpb25fIC0gQ2FsbGJhY2sgZnVuY3Rpb24gdGhhdCBtdXN0IGJlIGV4ZWN1dGVkIHdoZW4gdGhlIHJlcXVpcmVkCgkJICogICAgZGF0YSBoYXMgYmVlbiBvYnRhaW5lZC4gVGhhdCBkYXRhIHNob3VsZCBiZSBwYXNzZWQgaW50byB0aGUgY2FsbGJhY2sKCQkgKiAgICBhcyB0aGUgb25seSBwYXJhbWV0ZXIKCQkgKiAzLiBfb2JqZWN0XyAtIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0IGZvciB0aGUgdGFibGUKCQkgKgoJCSAqIE5vdGUgdGhhdCB0aGlzIHN1cGVyc2VkZXMgYGZuU2VydmVyRGF0YWAgZnJvbSBEYXRhVGFibGVzIDEuOS0uCgkJICoKCQkgKiAgQHR5cGUgc3RyaW5nfG9iamVjdHxmdW5jdGlvbgoJCSAqICBAZGVmYXVsdCBudWxsCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuYWpheAoJCSAqICBAc2luY2UgMS4xMC4wCgkJICoKCQkgKiBAZXhhbXBsZQoJCSAqICAgLy8gR2V0IEpTT04gZGF0YSBmcm9tIGEgZmlsZSB2aWEgQWpheC4KCQkgKiAgIC8vIE5vdGUgRGF0YVRhYmxlcyBleHBlY3RzIGRhdGEgaW4gdGhlIGZvcm0gYHsgZGF0YTogWyAuLi5kYXRhLi4uIF0gfWAgYnkgZGVmYXVsdCkuCgkJICogICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAiYWpheCI6ICJkYXRhLmpzb24iCgkJICogICB9ICk7CgkJICoKCQkgKiBAZXhhbXBsZQoJCSAqICAgLy8gR2V0IEpTT04gZGF0YSBmcm9tIGEgZmlsZSB2aWEgQWpheCwgdXNpbmcgYGRhdGFTcmNgIHRvIGNoYW5nZQoJCSAqICAgLy8gYGRhdGFgIHRvIGB0YWJsZURhdGFgIChpLmUuIGB7IHRhYmxlRGF0YTogWyAuLi5kYXRhLi4uIF0gfWApCgkJICogICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAiYWpheCI6IHsKCQkgKiAgICAgICAidXJsIjogImRhdGEuanNvbiIsCgkJICogICAgICAgImRhdGFTcmMiOiAidGFibGVEYXRhIgoJCSAqICAgICB9CgkJICogICB9ICk7CgkJICoKCQkgKiBAZXhhbXBsZQoJCSAqICAgLy8gR2V0IEpTT04gZGF0YSBmcm9tIGEgZmlsZSB2aWEgQWpheCwgdXNpbmcgYGRhdGFTcmNgIHRvIHJlYWQgZGF0YQoJCSAqICAgLy8gZnJvbSBhIHBsYWluIGFycmF5IHJhdGhlciB0aGFuIGFuIGFycmF5IGluIGFuIG9iamVjdAoJCSAqICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgImFqYXgiOiB7CgkJICogICAgICAgInVybCI6ICJkYXRhLmpzb24iLAoJCSAqICAgICAgICJkYXRhU3JjIjogIiIKCQkgKiAgICAgfQoJCSAqICAgfSApOwoJCSAqCgkJICogQGV4YW1wbGUKCQkgKiAgIC8vIE1hbmlwdWxhdGUgdGhlIGRhdGEgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyIC0gYWRkIGEgbGluayB0byBkYXRhCgkJICogICAvLyAobm90ZSB0aGlzIGNhbiwgc2hvdWxkLCBiZSBkb25lIHVzaW5nIGByZW5kZXJgIGZvciB0aGUgY29sdW1uIC0gdGhpcwoJCSAqICAgLy8gaXMganVzdCBhIHNpbXBsZSBleGFtcGxlIG9mIGhvdyB0aGUgZGF0YSBjYW4gYmUgbWFuaXB1bGF0ZWQpLgoJCSAqICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgImFqYXgiOiB7CgkJICogICAgICAgInVybCI6ICJkYXRhLmpzb24iLAoJCSAqICAgICAgICJkYXRhU3JjIjogZnVuY3Rpb24gKCBqc29uICkgewoJCSAqICAgICAgICAgZm9yICggdmFyIGk9MCwgaWVuPWpzb24ubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJICogICAgICAgICAgIGpzb25baV1bMF0gPSAnPGEgaHJlZj0iL21lc3NhZ2UvJytqc29uW2ldWzBdKyc+VmlldyBtZXNzYWdlPC9hPic7CgkJICogICAgICAgICB9CgkJICogICAgICAgICByZXR1cm4ganNvbjsKCQkgKiAgICAgICB9CgkJICogICAgIH0KCQkgKiAgIH0gKTsKCQkgKgoJCSAqIEBleGFtcGxlCgkJICogICAvLyBBZGQgZGF0YSB0byB0aGUgcmVxdWVzdAoJCSAqICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgImFqYXgiOiB7CgkJICogICAgICAgInVybCI6ICJkYXRhLmpzb24iLAoJCSAqICAgICAgICJkYXRhIjogZnVuY3Rpb24gKCBkICkgewoJCSAqICAgICAgICAgcmV0dXJuIHsKCQkgKiAgICAgICAgICAgImV4dHJhX3NlYXJjaCI6ICQoJyNleHRyYScpLnZhbCgpCgkJICogICAgICAgICB9OwoJCSAqICAgICAgIH0KCQkgKiAgICAgfQoJCSAqICAgfSApOwoJCSAqCgkJICogQGV4YW1wbGUKCQkgKiAgIC8vIFNlbmQgcmVxdWVzdCBhcyBQT1NUCgkJICogICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAiYWpheCI6IHsKCQkgKiAgICAgICAidXJsIjogImRhdGEuanNvbiIsCgkJICogICAgICAgInR5cGUiOiAiUE9TVCIKCQkgKiAgICAgfQoJCSAqICAgfSApOwoJCSAqCgkJICogQGV4YW1wbGUKCQkgKiAgIC8vIEdldCB0aGUgZGF0YSBmcm9tIGxvY2FsU3RvcmFnZSAoY291bGQgaW50ZXJmYWNlIHdpdGggYSBmb3JtIGZvcgoJCSAqICAgLy8gYWRkaW5nLCBlZGl0aW5nIGFuZCByZW1vdmluZyByb3dzKS4KCQkgKiAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICJhamF4IjogZnVuY3Rpb24gKGRhdGEsIGNhbGxiYWNrLCBzZXR0aW5ncykgewoJCSAqICAgICAgIGNhbGxiYWNrKAoJCSAqICAgICAgICAgSlNPTi5wYXJzZSggbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2RhdGFUYWJsZXNEYXRhJykgKQoJCSAqICAgICAgICk7CgkJICogICAgIH0KCQkgKiAgIH0gKTsKCQkgKi8KCQkiYWpheCI6IG51bGwsCgkKCQoJCS8qKgoJCSAqIFRoaXMgcGFyYW1ldGVyIGFsbG93cyB5b3UgdG8gcmVhZGlseSBzcGVjaWZ5IHRoZSBlbnRyaWVzIGluIHRoZSBsZW5ndGggZHJvcAoJCSAqIGRvd24gbWVudSB0aGF0IERhdGFUYWJsZXMgc2hvd3Mgd2hlbiBwYWdpbmF0aW9uIGlzIGVuYWJsZWQuIEl0IGNhbiBiZQoJCSAqIGVpdGhlciBhIDFEIGFycmF5IG9mIG9wdGlvbnMgd2hpY2ggd2lsbCBiZSB1c2VkIGZvciBib3RoIHRoZSBkaXNwbGF5ZWQKCQkgKiBvcHRpb24gYW5kIHRoZSB2YWx1ZSwgb3IgYSAyRCBhcnJheSB3aGljaCB3aWxsIHVzZSB0aGUgYXJyYXkgaW4gdGhlIGZpcnN0CgkJICogcG9zaXRpb24gYXMgdGhlIHZhbHVlLCBhbmQgdGhlIGFycmF5IGluIHRoZSBzZWNvbmQgcG9zaXRpb24gYXMgdGhlCgkJICogZGlzcGxheWVkIG9wdGlvbnMgKHVzZWZ1bCBmb3IgbGFuZ3VhZ2Ugc3RyaW5ncyBzdWNoIGFzICdBbGwnKS4KCQkgKgoJCSAqIE5vdGUgdGhhdCB0aGUgYHBhZ2VMZW5ndGhgIHByb3BlcnR5IHdpbGwgYmUgYXV0b21hdGljYWxseSBzZXQgdG8gdGhlCgkJICogZmlyc3QgdmFsdWUgZ2l2ZW4gaW4gdGhpcyBhcnJheSwgdW5sZXNzIGBwYWdlTGVuZ3RoYCBpcyBhbHNvIHByb3ZpZGVkLgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbIDEwLCAyNSwgNTAsIDEwMCBdCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGVuZ3RoTWVudQoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImxlbmd0aE1lbnUiOiBbWzEwLCAyNSwgNTAsIC0xXSwgWzEwLCAyNSwgNTAsICJBbGwiXV0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImFMZW5ndGhNZW51IjogWyAxMCwgMjUsIDUwLCAxMDAgXSwKCQoJCgkJLyoqCgkJICogVGhlIGBjb2x1bW5zYCBvcHRpb24gaW4gdGhlIGluaXRpYWxpc2F0aW9uIHBhcmFtZXRlciBhbGxvd3MgeW91IHRvIGRlZmluZQoJCSAqIGRldGFpbHMgYWJvdXQgdGhlIHdheSBpbmRpdmlkdWFsIGNvbHVtbnMgYmVoYXZlLiBGb3IgYSBmdWxsIGxpc3Qgb2YKCQkgKiBjb2x1bW4gb3B0aW9ucyB0aGF0IGNhbiBiZSBzZXQsIHBsZWFzZSBzZWUKCQkgKiB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbn0uIE5vdGUgdGhhdCBpZiB5b3UgdXNlIGBjb2x1bW5zYCB0bwoJCSAqIGRlZmluZSB5b3VyIGNvbHVtbnMsIHlvdSBtdXN0IGhhdmUgYW4gZW50cnkgaW4gdGhlIGFycmF5IGZvciBldmVyeSBzaW5nbGUKCQkgKiBjb2x1bW4gdGhhdCB5b3UgaGF2ZSBpbiB5b3VyIHRhYmxlICh0aGVzZSBjYW4gYmUgbnVsbCBpZiB5b3UgZG9uJ3Qgd2hpY2gKCQkgKiB0byBzcGVjaWZ5IGFueSBvcHRpb25zKS4KCQkgKiAgQG1lbWJlcgoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4KCQkgKi8KCQkiYW9Db2x1bW5zIjogbnVsbCwKCQoJCS8qKgoJCSAqIFZlcnkgc2ltaWxhciB0byBgY29sdW1uc2AsIGBjb2x1bW5EZWZzYCBhbGxvd3MgeW91IHRvIHRhcmdldCBhIHNwZWNpZmljCgkJICogY29sdW1uLCBtdWx0aXBsZSBjb2x1bW5zLCBvciBhbGwgY29sdW1ucywgdXNpbmcgdGhlIGB0YXJnZXRzYCBwcm9wZXJ0eSBvZgoJCSAqIGVhY2ggb2JqZWN0IGluIHRoZSBhcnJheS4gVGhpcyBhbGxvd3MgZ3JlYXQgZmxleGliaWxpdHkgd2hlbiBjcmVhdGluZwoJCSAqIHRhYmxlcywgYXMgdGhlIGBjb2x1bW5EZWZzYCBhcnJheXMgY2FuIGJlIG9mIGFueSBsZW5ndGgsIHRhcmdldGluZyB0aGUKCQkgKiBjb2x1bW5zIHlvdSBzcGVjaWZpY2FsbHkgd2FudC4gYGNvbHVtbkRlZnNgIG1heSB1c2UgYW55IG9mIHRoZSBjb2x1bW4KCQkgKiBvcHRpb25zIGF2YWlsYWJsZToge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW59LCBidXQgaXQgX211c3RfCgkJICogaGF2ZSBgdGFyZ2V0c2AgZGVmaW5lZCBpbiBlYWNoIG9iamVjdCBpbiB0aGUgYXJyYXkuIFZhbHVlcyBpbiB0aGUgYHRhcmdldHNgCgkJICogYXJyYXkgbWF5IGJlOgoJCSAqICAgPHVsPgoJCSAqICAgICA8bGk+YSBzdHJpbmcgLSBjbGFzcyBuYW1lIHdpbGwgYmUgbWF0Y2hlZCBvbiB0aGUgVEggZm9yIHRoZSBjb2x1bW48L2xpPgoJCSAqICAgICA8bGk+MCBvciBhIHBvc2l0aXZlIGludGVnZXIgLSBjb2x1bW4gaW5kZXggY291bnRpbmcgZnJvbSB0aGUgbGVmdDwvbGk+CgkJICogICAgIDxsaT5hIG5lZ2F0aXZlIGludGVnZXIgLSBjb2x1bW4gaW5kZXggY291bnRpbmcgZnJvbSB0aGUgcmlnaHQ8L2xpPgoJCSAqICAgICA8bGk+dGhlIHN0cmluZyAiX2FsbCIgLSBhbGwgY29sdW1ucyAoaS5lLiBhc3NpZ24gYSBkZWZhdWx0KTwvbGk+CgkJICogICA8L3VsPgoJCSAqICBAbWVtYmVyCgkJICoKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbkRlZnMKCQkgKi8KCQkiYW9Db2x1bW5EZWZzIjogbnVsbCwKCQoJCgkJLyoqCgkJICogQmFzaWNhbGx5IHRoZSBzYW1lIGFzIGBzZWFyY2hgLCB0aGlzIHBhcmFtZXRlciBkZWZpbmVzIHRoZSBpbmRpdmlkdWFsIGNvbHVtbgoJCSAqIGZpbHRlcmluZyBzdGF0ZSBhdCBpbml0aWFsaXNhdGlvbiB0aW1lLiBUaGUgYXJyYXkgbXVzdCBiZSBvZiB0aGUgc2FtZSBzaXplCgkJICogYXMgdGhlIG51bWJlciBvZiBjb2x1bW5zLCBhbmQgZWFjaCBlbGVtZW50IGJlIGFuIG9iamVjdCB3aXRoIHRoZSBwYXJhbWV0ZXJzCgkJICogYHNlYXJjaGAgYW5kIGBlc2NhcGVSZWdleGAgKHRoZSBsYXR0ZXIgaXMgb3B0aW9uYWwpLiAnbnVsbCcgaXMgYWxzbwoJCSAqIGFjY2VwdGVkIGFuZCB0aGUgZGVmYXVsdCB3aWxsIGJlIHVzZWQuCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtdCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc2VhcmNoQ29scwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInNlYXJjaENvbHMiOiBbCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICB7ICJzZWFyY2giOiAiTXkgZmlsdGVyIiB9LAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgeyAic2VhcmNoIjogIl5bMC05XSIsICJlc2NhcGVSZWdleCI6IGZhbHNlIH0KCQkgKiAgICAgICAgXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKQoJCSAqLwoJCSJhb1NlYXJjaENvbHMiOiBbXSwKCQoJCgkJLyoqCgkJICogQW4gYXJyYXkgb2YgQ1NTIGNsYXNzZXMgdGhhdCBzaG91bGQgYmUgYXBwbGllZCB0byBkaXNwbGF5ZWQgcm93cy4gVGhpcwoJCSAqIGFycmF5IG1heSBiZSBvZiBhbnkgbGVuZ3RoLCBhbmQgRGF0YVRhYmxlcyB3aWxsIGFwcGx5IGVhY2ggY2xhc3MKCQkgKiBzZXF1ZW50aWFsbHksIGxvb3Bpbmcgd2hlbiByZXF1aXJlZC4KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgbnVsbCA8aT5XaWxsIHRha2UgdGhlIHZhbHVlcyBkZXRlcm1pbmVkIGJ5IHRoZSBgb0NsYXNzZXMuc3RyaXBlKmAKCQkgKiAgICBvcHRpb25zPC9pPgoJCSAqCgkJICogIEBkdG9wdCBPcHRpb24KCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnN0cmlwZUNsYXNzZXMKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJzdHJpcGVDbGFzc2VzIjogWyAnc3RyaXAxJywgJ3N0cmlwMicsICdzdHJpcDMnIF0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICkKCQkgKi8KCQkiYXNTdHJpcGVDbGFzc2VzIjogbnVsbCwKCQoJCgkJLyoqCgkJICogRW5hYmxlIG9yIGRpc2FibGUgYXV0b21hdGljIGNvbHVtbiB3aWR0aCBjYWxjdWxhdGlvbi4gVGhpcyBjYW4gYmUgZGlzYWJsZWQKCQkgKiBhcyBhbiBvcHRpbWlzYXRpb24gKGl0IHRha2VzIHNvbWUgdGltZSB0byBjYWxjdWxhdGUgdGhlIHdpZHRocykgaWYgdGhlCgkJICogdGFibGVzIHdpZHRocyBhcmUgcGFzc2VkIGluIHVzaW5nIGBjb2x1bW5zYC4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqICBAZGVmYXVsdCB0cnVlCgkJICoKCQkgKiAgQGR0b3B0IEZlYXR1cmVzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5hdXRvV2lkdGgKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiAoKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiYXV0b1dpZHRoIjogZmFsc2UKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImJBdXRvV2lkdGgiOiB0cnVlLAoJCgkKCQkvKioKCQkgKiBEZWZlcnJlZCByZW5kZXJpbmcgY2FuIHByb3ZpZGUgRGF0YVRhYmxlcyB3aXRoIGEgaHVnZSBzcGVlZCBib29zdCB3aGVuIHlvdQoJCSAqIGFyZSB1c2luZyBhbiBBamF4IG9yIEpTIGRhdGEgc291cmNlIGZvciB0aGUgdGFibGUuIFRoaXMgb3B0aW9uLCB3aGVuIHNldCB0bwoJCSAqIHRydWUsIHdpbGwgY2F1c2UgRGF0YVRhYmxlcyB0byBkZWZlciB0aGUgY3JlYXRpb24gb2YgdGhlIHRhYmxlIGVsZW1lbnRzIGZvcgoJCSAqIGVhY2ggcm93IHVudGlsIHRoZXkgYXJlIG5lZWRlZCBmb3IgYSBkcmF3IC0gc2F2aW5nIGEgc2lnbmlmaWNhbnQgYW1vdW50IG9mCgkJICogdGltZS4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqICBAZGVmYXVsdCBmYWxzZQoJCSAqCgkJICogIEBkdG9wdCBGZWF0dXJlcwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuZGVmZXJSZW5kZXIKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJhamF4IjogInNvdXJjZXMvYXJyYXlzLnR4dCIsCgkJICogICAgICAgICJkZWZlclJlbmRlciI6IHRydWUKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImJEZWZlclJlbmRlciI6IGZhbHNlLAoJCgkKCQkvKioKCQkgKiBSZXBsYWNlIGEgRGF0YVRhYmxlIHdoaWNoIG1hdGNoZXMgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCByZXBsYWNlIGl0IHdpdGgKCQkgKiBvbmUgd2hpY2ggaGFzIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBuZXcgaW5pdGlhbGlzYXRpb24gb2JqZWN0IHBhc3NlZC4gSWYgbm8KCQkgKiB0YWJsZSBtYXRjaGVzIHRoZSBzZWxlY3RvciwgdGhlbiB0aGUgbmV3IERhdGFUYWJsZSB3aWxsIGJlIGNvbnN0cnVjdGVkIGFzCgkJICogcGVyIG5vcm1hbC4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqICBAZGVmYXVsdCBmYWxzZQoJCSAqCgkJICogIEBkdG9wdCBPcHRpb25zCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5kZXN0cm95CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic3JvbGxZIjogIjIwMHB4IiwKCQkgKiAgICAgICAgInBhZ2luYXRlIjogZmFsc2UKCQkgKiAgICAgIH0gKTsKCQkgKgoJCSAqICAgICAgLy8gU29tZSB0aW1lIGxhdGVyLi4uLgoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImZpbHRlciI6IGZhbHNlLAoJCSAqICAgICAgICAiZGVzdHJveSI6IHRydWUKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImJEZXN0cm95IjogZmFsc2UsCgkKCQoJCS8qKgoJCSAqIEVuYWJsZSBvciBkaXNhYmxlIGZpbHRlcmluZyBvZiBkYXRhLiBGaWx0ZXJpbmcgaW4gRGF0YVRhYmxlcyBpcyAic21hcnQiIGluCgkJICogdGhhdCBpdCBhbGxvd3MgdGhlIGVuZCB1c2VyIHRvIGlucHV0IG11bHRpcGxlIHdvcmRzIChzcGFjZSBzZXBhcmF0ZWQpIGFuZAoJCSAqIHdpbGwgbWF0Y2ggYSByb3cgY29udGFpbmluZyB0aG9zZSB3b3JkcywgZXZlbiBpZiBub3QgaW4gdGhlIG9yZGVyIHRoYXQgd2FzCgkJICogc3BlY2lmaWVkICh0aGlzIGFsbG93IG1hdGNoaW5nIGFjcm9zcyBtdWx0aXBsZSBjb2x1bW5zKS4gTm90ZSB0aGF0IGlmIHlvdQoJCSAqIHdpc2ggdG8gdXNlIGZpbHRlcmluZyBpbiBEYXRhVGFibGVzIHRoaXMgbXVzdCByZW1haW4gJ3RydWUnIC0gdG8gcmVtb3ZlIHRoZQoJCSAqIGRlZmF1bHQgZmlsdGVyaW5nIGlucHV0IGJveCBhbmQgcmV0YWluIGZpbHRlcmluZyBhYmlsaXRpZXMsIHBsZWFzZSB1c2UKCQkgKiB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzLmRvbX0uCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgdHJ1ZQoJCSAqCgkJICogIEBkdG9wdCBGZWF0dXJlcwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc2VhcmNoaW5nCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInNlYXJjaGluZyI6IGZhbHNlCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJiRmlsdGVyIjogdHJ1ZSwKCQoJCgkJLyoqCgkJICogRW5hYmxlIG9yIGRpc2FibGUgdGhlIHRhYmxlIGluZm9ybWF0aW9uIGRpc3BsYXkuIFRoaXMgc2hvd3MgaW5mb3JtYXRpb24KCQkgKiBhYm91dCB0aGUgZGF0YSB0aGF0IGlzIGN1cnJlbnRseSB2aXNpYmxlIG9uIHRoZSBwYWdlLCBpbmNsdWRpbmcgaW5mb3JtYXRpb24KCQkgKiBhYm91dCBmaWx0ZXJlZCBkYXRhIGlmIHRoYXQgYWN0aW9uIGlzIGJlaW5nIHBlcmZvcm1lZC4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqICBAZGVmYXVsdCB0cnVlCgkJICoKCQkgKiAgQGR0b3B0IEZlYXR1cmVzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5pbmZvCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImluZm8iOiBmYWxzZQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkiYkluZm8iOiB0cnVlLAoJCgkKCQkvKioKCQkgKiBBbGxvd3MgdGhlIGVuZCB1c2VyIHRvIHNlbGVjdCB0aGUgc2l6ZSBvZiBhIGZvcm1hdHRlZCBwYWdlIGZyb20gYSBzZWxlY3QKCQkgKiBtZW51IChzaXplcyBhcmUgMTAsIDI1LCA1MCBhbmQgMTAwKS4gUmVxdWlyZXMgcGFnaW5hdGlvbiAoYHBhZ2luYXRlYCkuCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgdHJ1ZQoJCSAqCgkJICogIEBkdG9wdCBGZWF0dXJlcwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGVuZ3RoQ2hhbmdlCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImxlbmd0aENoYW5nZSI6IGZhbHNlCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJiTGVuZ3RoQ2hhbmdlIjogdHJ1ZSwKCQoJCgkJLyoqCgkJICogRW5hYmxlIG9yIGRpc2FibGUgcGFnaW5hdGlvbi4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqICBAZGVmYXVsdCB0cnVlCgkJICoKCQkgKiAgQGR0b3B0IEZlYXR1cmVzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5wYWdpbmcKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiAoKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAicGFnaW5nIjogZmFsc2UKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImJQYWdpbmF0ZSI6IHRydWUsCgkKCQoJCS8qKgoJCSAqIEVuYWJsZSBvciBkaXNhYmxlIHRoZSBkaXNwbGF5IG9mIGEgJ3Byb2Nlc3NpbmcnIGluZGljYXRvciB3aGVuIHRoZSB0YWJsZSBpcwoJCSAqIGJlaW5nIHByb2Nlc3NlZCAoZS5nLiBhIHNvcnQpLiBUaGlzIGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgZm9yIHRhYmxlcyB3aXRoCgkJICogbGFyZ2UgYW1vdW50cyBvZiBkYXRhIHdoZXJlIGl0IGNhbiB0YWtlIGEgbm90aWNlYWJsZSBhbW91bnQgb2YgdGltZSB0byBzb3J0CgkJICogdGhlIGVudHJpZXMuCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkgKgoJCSAqICBAZHRvcHQgRmVhdHVyZXMKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnByb2Nlc3NpbmcKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiAoKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAicHJvY2Vzc2luZyI6IHRydWUKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImJQcm9jZXNzaW5nIjogZmFsc2UsCgkKCQoJCS8qKgoJCSAqIFJldHJpZXZlIHRoZSBEYXRhVGFibGVzIG9iamVjdCBmb3IgdGhlIGdpdmVuIHNlbGVjdG9yLiBOb3RlIHRoYXQgaWYgdGhlCgkJICogdGFibGUgaGFzIGFscmVhZHkgYmVlbiBpbml0aWFsaXNlZCwgdGhpcyBwYXJhbWV0ZXIgd2lsbCBjYXVzZSBEYXRhVGFibGVzCgkJICogdG8gc2ltcGx5IHJldHVybiB0aGUgb2JqZWN0IHRoYXQgaGFzIGFscmVhZHkgYmVlbiBzZXQgdXAgLSBpdCB3aWxsIG5vdCB0YWtlCgkJICogYWNjb3VudCBvZiBhbnkgY2hhbmdlcyB5b3UgbWlnaHQgaGF2ZSBtYWRlIHRvIHRoZSBpbml0aWFsaXNhdGlvbiBvYmplY3QKCQkgKiBwYXNzZWQgdG8gRGF0YVRhYmxlcyAoc2V0dGluZyB0aGlzIHBhcmFtZXRlciB0byB0cnVlIGlzIGFuIGFja25vd2xlZGdlbWVudAoJCSAqIHRoYXQgeW91IHVuZGVyc3RhbmQgdGhpcykuIGBkZXN0cm95YCBjYW4gYmUgdXNlZCB0byByZWluaXRpYWxpc2UgYSB0YWJsZSBpZgoJCSAqIHlvdSBuZWVkLgoJCSAqICBAdHlwZSBib29sZWFuCgkJICogIEBkZWZhdWx0IGZhbHNlCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbnMKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnJldHJpZXZlCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICBpbml0VGFibGUoKTsKCQkgKiAgICAgIHRhYmxlQWN0aW9ucygpOwoJCSAqICAgIH0gKTsKCQkgKgoJCSAqICAgIGZ1bmN0aW9uIGluaXRUYWJsZSAoKQoJCSAqICAgIHsKCQkgKiAgICAgIHJldHVybiAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic2Nyb2xsWSI6ICIyMDBweCIsCgkJICogICAgICAgICJwYWdpbmF0ZSI6IGZhbHNlLAoJCSAqICAgICAgICAicmV0cmlldmUiOiB0cnVlCgkJICogICAgICB9ICk7CgkJICogICAgfQoJCSAqCgkJICogICAgZnVuY3Rpb24gdGFibGVBY3Rpb25zICgpCgkJICogICAgewoJCSAqICAgICAgdmFyIHRhYmxlID0gaW5pdFRhYmxlKCk7CgkJICogICAgICAvLyBwZXJmb3JtIEFQSSBvcGVyYXRpb25zIHdpdGggb1RhYmxlCgkJICogICAgfQoJCSAqLwoJCSJiUmV0cmlldmUiOiBmYWxzZSwKCQoJCgkJLyoqCgkJICogV2hlbiB2ZXJ0aWNhbCAoeSkgc2Nyb2xsaW5nIGlzIGVuYWJsZWQsIERhdGFUYWJsZXMgd2lsbCBmb3JjZSB0aGUgaGVpZ2h0IG9mCgkJICogdGhlIHRhYmxlJ3Mgdmlld3BvcnQgdG8gdGhlIGdpdmVuIGhlaWdodCBhdCBhbGwgdGltZXMgKHVzZWZ1bCBmb3IgbGF5b3V0KS4KCQkgKiBIb3dldmVyLCB0aGlzIGNhbiBsb29rIG9kZCB3aGVuIGZpbHRlcmluZyBkYXRhIGRvd24gdG8gYSBzbWFsbCBkYXRhIHNldCwKCQkgKiBhbmQgdGhlIGZvb3RlciBpcyBsZWZ0ICJmbG9hdGluZyIgZnVydGhlciBkb3duLiBUaGlzIHBhcmFtZXRlciAod2hlbgoJCSAqIGVuYWJsZWQpIHdpbGwgY2F1c2UgRGF0YVRhYmxlcyB0byBjb2xsYXBzZSB0aGUgdGFibGUncyB2aWV3cG9ydCBkb3duIHdoZW4KCQkgKiB0aGUgcmVzdWx0IHNldCB3aWxsIGZpdCB3aXRoaW4gdGhlIGdpdmVuIFkgaGVpZ2h0LgoJCSAqICBAdHlwZSBib29sZWFuCgkJICogIEBkZWZhdWx0IGZhbHNlCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbnMKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNjcm9sbENvbGxhcHNlCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic2Nyb2xsWSI6ICIyMDAiLAoJCSAqICAgICAgICAic2Nyb2xsQ29sbGFwc2UiOiB0cnVlCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJiU2Nyb2xsQ29sbGFwc2UiOiBmYWxzZSwKCQoJCgkJLyoqCgkJICogQ29uZmlndXJlIERhdGFUYWJsZXMgdG8gdXNlIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcuIE5vdGUgdGhhdCB0aGUKCQkgKiBgYWpheGAgcGFyYW1ldGVyIG11c3QgYWxzbyBiZSBnaXZlbiBpbiBvcmRlciB0byBnaXZlIERhdGFUYWJsZXMgYQoJCSAqIHNvdXJjZSB0byBvYnRhaW4gdGhlIHJlcXVpcmVkIGRhdGEgZm9yIGVhY2ggZHJhdy4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqICBAZGVmYXVsdCBmYWxzZQoJCSAqCgkJICogIEBkdG9wdCBGZWF0dXJlcwoJCSAqICBAZHRvcHQgU2VydmVyLXNpZGUKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNlcnZlclNpZGUKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiAoKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic2VydmVyU2lkZSI6IHRydWUsCgkJICogICAgICAgICJhamF4IjogInhoci5waHAiCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJiU2VydmVyU2lkZSI6IGZhbHNlLAoJCgkKCQkvKioKCQkgKiBFbmFibGUgb3IgZGlzYWJsZSBzb3J0aW5nIG9mIGNvbHVtbnMuIFNvcnRpbmcgb2YgaW5kaXZpZHVhbCBjb2x1bW5zIGNhbiBiZQoJCSAqIGRpc2FibGVkIGJ5IHRoZSBgc29ydGFibGVgIG9wdGlvbiBmb3IgZWFjaCBjb2x1bW4uCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgdHJ1ZQoJCSAqCgkJICogIEBkdG9wdCBGZWF0dXJlcwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMub3JkZXJpbmcKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiAoKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAib3JkZXJpbmciOiBmYWxzZQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkiYlNvcnQiOiB0cnVlLAoJCgkKCQkvKioKCQkgKiBFbmFibGUgb3IgZGlzcGxheSBEYXRhVGFibGVzJyBhYmlsaXR5IHRvIHNvcnQgbXVsdGlwbGUgY29sdW1ucyBhdCB0aGUKCQkgKiBzYW1lIHRpbWUgKGFjdGl2YXRlZCBieSBzaGlmdC1jbGljayBieSB0aGUgdXNlcikuCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgdHJ1ZQoJCSAqCgkJICogIEBkdG9wdCBPcHRpb25zCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5vcmRlck11bHRpCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBEaXNhYmxlIG11bHRpcGxlIGNvbHVtbiBzb3J0aW5nIGFiaWxpdHkKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgIm9yZGVyTXVsdGkiOiBmYWxzZQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkiYlNvcnRNdWx0aSI6IHRydWUsCgkKCQoJCS8qKgoJCSAqIEFsbG93cyBjb250cm9sIG92ZXIgd2hldGhlciBEYXRhVGFibGVzIHNob3VsZCB1c2UgdGhlIHRvcCAodHJ1ZSkgdW5pcXVlCgkJICogY2VsbCB0aGF0IGlzIGZvdW5kIGZvciBhIHNpbmdsZSBjb2x1bW4sIG9yIHRoZSBib3R0b20gKGZhbHNlIC0gZGVmYXVsdCkuCgkJICogVGhpcyBpcyB1c2VmdWwgd2hlbiB1c2luZyBjb21wbGV4IGhlYWRlcnMuCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkgKgoJCSAqICBAZHRvcHQgT3B0aW9ucwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMub3JkZXJDZWxsc1RvcAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgIm9yZGVyQ2VsbHNUb3AiOiB0cnVlCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJiU29ydENlbGxzVG9wIjogZmFsc2UsCgkKCQoJCS8qKgoJCSAqIEVuYWJsZSBvciBkaXNhYmxlIHRoZSBhZGRpdGlvbiBvZiB0aGUgY2xhc3NlcyBgc29ydGluZ1xfMWAsIGBzb3J0aW5nXF8yYCBhbmQKCQkgKiBgc29ydGluZ1xfM2AgdG8gdGhlIGNvbHVtbnMgd2hpY2ggYXJlIGN1cnJlbnRseSBiZWluZyBzb3J0ZWQgb24uIFRoaXMgaXMKCQkgKiBwcmVzZW50ZWQgYXMgYSBmZWF0dXJlIHN3aXRjaCBhcyBpdCBjYW4gaW5jcmVhc2UgcHJvY2Vzc2luZyB0aW1lICh3aGlsZQoJCSAqIGNsYXNzZXMgYXJlIHJlbW92ZWQgYW5kIGFkZGVkKSBzbyBmb3IgbGFyZ2UgZGF0YSBzZXRzIHlvdSBtaWdodCB3YW50IHRvCgkJICogdHVybiB0aGlzIG9mZi4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqICBAZGVmYXVsdCB0cnVlCgkJICoKCQkgKiAgQGR0b3B0IEZlYXR1cmVzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5vcmRlckNsYXNzZXMKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiAoKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAib3JkZXJDbGFzc2VzIjogZmFsc2UKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImJTb3J0Q2xhc3NlcyI6IHRydWUsCgkKCQoJCS8qKgoJCSAqIEVuYWJsZSBvciBkaXNhYmxlIHN0YXRlIHNhdmluZy4gV2hlbiBlbmFibGVkIEhUTUw1IGBsb2NhbFN0b3JhZ2VgIHdpbGwgYmUKCQkgKiB1c2VkIHRvIHNhdmUgdGFibGUgZGlzcGxheSBpbmZvcm1hdGlvbiBzdWNoIGFzIHBhZ2luYXRpb24gaW5mb3JtYXRpb24sCgkJICogZGlzcGxheSBsZW5ndGgsIGZpbHRlcmluZyBhbmQgc29ydGluZy4gQXMgc3VjaCB3aGVuIHRoZSBlbmQgdXNlciByZWxvYWRzCgkJICogdGhlIHBhZ2UgdGhlIGRpc3BsYXkgZGlzcGxheSB3aWxsIG1hdGNoIHdoYXQgdGh5IGhhZCBwcmV2aW91c2x5IHNldCB1cC4KCQkgKgoJCSAqIER1ZSB0byB0aGUgdXNlIG9mIGBsb2NhbFN0b3JhZ2VgIHRoZSBkZWZhdWx0IHN0YXRlIHNhdmluZyBpcyBub3Qgc3VwcG9ydGVkCgkJICogaW4gSUU2IG9yIDcuIElmIHN0YXRlIHNhdmluZyBpcyByZXF1aXJlZCBpbiB0aG9zZSBicm93c2VycywgdXNlCgkJICogYHN0YXRlU2F2ZUNhbGxiYWNrYCB0byBwcm92aWRlIGEgc3RvcmFnZSBzb2x1dGlvbiBzdWNoIGFzIGNvb2tpZXMuCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkgKgoJCSAqICBAZHRvcHQgRmVhdHVyZXMKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnN0YXRlU2F2ZQoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJzdGF0ZVNhdmUiOiB0cnVlCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJiU3RhdGVTYXZlIjogZmFsc2UsCgkKCQoJCS8qKgoJCSAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdoZW4gYSBUUiBlbGVtZW50IGlzIGNyZWF0ZWQgKGFuZCBhbGwgVEQgY2hpbGQKCQkgKiBlbGVtZW50cyBoYXZlIGJlZW4gaW5zZXJ0ZWQpLCBvciByZWdpc3RlcmVkIGlmIHVzaW5nIGEgRE9NIHNvdXJjZSwgYWxsb3dpbmcKCQkgKiBtYW5pcHVsYXRpb24gb2YgdGhlIFRSIGVsZW1lbnQgKGFkZGluZyBjbGFzc2VzIGV0YykuCgkJICogIEB0eXBlIGZ1bmN0aW9uCgkJICogIEBwYXJhbSB7bm9kZX0gcm93ICJUUiIgZWxlbWVudCBmb3IgdGhlIGN1cnJlbnQgcm93CgkJICogIEBwYXJhbSB7YXJyYXl9IGRhdGEgUmF3IGRhdGEgYXJyYXkgZm9yIHRoaXMgcm93CgkJICogIEBwYXJhbSB7aW50fSBkYXRhSW5kZXggVGhlIGluZGV4IG9mIHRoaXMgcm93IGluIHRoZSBpbnRlcm5hbCBhb0RhdGEgYXJyYXkKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jcmVhdGVkUm93CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY3JlYXRlZFJvdyI6IGZ1bmN0aW9uKCByb3csIGRhdGEsIGRhdGFJbmRleCApIHsKCQkgKiAgICAgICAgICAvLyBCb2xkIHRoZSBncmFkZSBmb3IgYWxsICdBJyBncmFkZSBicm93c2VycwoJCSAqICAgICAgICAgIGlmICggZGF0YVs0XSA9PSAiQSIgKQoJCSAqICAgICAgICAgIHsKCQkgKiAgICAgICAgICAgICQoJ3RkOmVxKDQpJywgcm93KS5odG1sKCAnPGI+QTwvYj4nICk7CgkJICogICAgICAgICAgfQoJCSAqICAgICAgICB9CgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJmbkNyZWF0ZWRSb3ciOiBudWxsLAoJCgkKCQkvKioKCQkgKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBldmVyeSAnZHJhdycgZXZlbnQsIGFuZCBhbGxvd3MgeW91IHRvCgkJICogZHluYW1pY2FsbHkgbW9kaWZ5IGFueSBhc3BlY3QgeW91IHdhbnQgYWJvdXQgdGhlIGNyZWF0ZWQgRE9NLgoJCSAqICBAdHlwZSBmdW5jdGlvbgoJCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5kcmF3Q2FsbGJhY2sKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJkcmF3Q2FsbGJhY2siOiBmdW5jdGlvbiggc2V0dGluZ3MgKSB7CgkJICogICAgICAgICAgYWxlcnQoICdEYXRhVGFibGVzIGhhcyByZWRyYXduIHRoZSB0YWJsZScgKTsKCQkgKiAgICAgICAgfQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkiZm5EcmF3Q2FsbGJhY2siOiBudWxsLAoJCgkKCQkvKioKCQkgKiBJZGVudGljYWwgdG8gZm5IZWFkZXJDYWxsYmFjaygpIGJ1dCBmb3IgdGhlIHRhYmxlIGZvb3RlciB0aGlzIGZ1bmN0aW9uCgkJICogYWxsb3dzIHlvdSB0byBtb2RpZnkgdGhlIHRhYmxlIGZvb3RlciBvbiBldmVyeSAnZHJhdycgZXZlbnQuCgkJICogIEB0eXBlIGZ1bmN0aW9uCgkJICogIEBwYXJhbSB7bm9kZX0gZm9vdCAiVFIiIGVsZW1lbnQgZm9yIHRoZSBmb290ZXIKCQkgKiAgQHBhcmFtIHthcnJheX0gZGF0YSBGdWxsIHRhYmxlIGRhdGEgKGFzIGRlcml2ZWQgZnJvbSB0aGUgb3JpZ2luYWwgSFRNTCkKCQkgKiAgQHBhcmFtIHtpbnR9IHN0YXJ0IEluZGV4IGZvciB0aGUgY3VycmVudCBkaXNwbGF5IHN0YXJ0aW5nIHBvaW50IGluIHRoZQoJCSAqICAgIGRpc3BsYXkgYXJyYXkKCQkgKiAgQHBhcmFtIHtpbnR9IGVuZCBJbmRleCBmb3IgdGhlIGN1cnJlbnQgZGlzcGxheSBlbmRpbmcgcG9pbnQgaW4gdGhlCgkJICogICAgZGlzcGxheSBhcnJheQoJCSAqICBAcGFyYW0ge2FycmF5IGludH0gZGlzcGxheSBJbmRleCBhcnJheSB0byB0cmFuc2xhdGUgdGhlIHZpc3VhbCBwb3NpdGlvbgoJCSAqICAgIHRvIHRoZSBmdWxsIGRhdGEgYXJyYXkKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5mb290ZXJDYWxsYmFjawoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImZvb3RlckNhbGxiYWNrIjogZnVuY3Rpb24oIHRmb290LCBkYXRhLCBzdGFydCwgZW5kLCBkaXNwbGF5ICkgewoJCSAqICAgICAgICAgIHRmb290LmdldEVsZW1lbnRzQnlUYWdOYW1lKCd0aCcpWzBdLmlubmVySFRNTCA9ICJTdGFydGluZyBpbmRleCBpcyAiK3N0YXJ0OwoJCSAqICAgICAgICB9CgkJICogICAgICB9ICk7CgkJICogICAgfSApCgkJICovCgkJImZuRm9vdGVyQ2FsbGJhY2siOiBudWxsLAoJCgkKCQkvKioKCQkgKiBXaGVuIHJlbmRlcmluZyBsYXJnZSBudW1iZXJzIGluIHRoZSBpbmZvcm1hdGlvbiBlbGVtZW50IGZvciB0aGUgdGFibGUKCQkgKiAoaS5lLiAiU2hvd2luZyAxIHRvIDEwIG9mIDU3IGVudHJpZXMiKSBEYXRhVGFibGVzIHdpbGwgcmVuZGVyIGxhcmdlIG51bWJlcnMKCQkgKiB0byBoYXZlIGEgY29tbWEgc2VwYXJhdG9yIGZvciB0aGUgJ3Rob3VzYW5kcycgdW5pdHMgKGUuZy4gMSBtaWxsaW9uIGlzCgkJICogcmVuZGVyZWQgYXMgIjEsMDAwLDAwMCIpIHRvIGhlbHAgcmVhZGFiaWxpdHkgZm9yIHRoZSBlbmQgdXNlci4gVGhpcwoJCSAqIGZ1bmN0aW9uIHdpbGwgb3ZlcnJpZGUgdGhlIGRlZmF1bHQgbWV0aG9kIERhdGFUYWJsZXMgdXNlcy4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQG1lbWJlcgoJCSAqICBAcGFyYW0ge2ludH0gdG9Gb3JtYXQgbnVtYmVyIHRvIGJlIGZvcm1hdHRlZAoJCSAqICBAcmV0dXJucyB7c3RyaW5nfSBmb3JtYXR0ZWQgc3RyaW5nIGZvciBEYXRhVGFibGVzIHRvIHNob3cgdGhlIG51bWJlcgoJCSAqCgkJICogIEBkdG9wdCBDYWxsYmFja3MKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmZvcm1hdE51bWJlcgoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gRm9ybWF0IGEgbnVtYmVyIHVzaW5nIGEgc2luZ2xlIHF1b3RlIGZvciB0aGUgc2VwYXJhdG9yIChub3RlIHRoYXQKCQkgKiAgICAvLyB0aGlzIGNhbiBhbHNvIGJlIGRvbmUgd2l0aCB0aGUgbGFuZ3VhZ2UudGhvdXNhbmRzIG9wdGlvbikKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiZm9ybWF0TnVtYmVyIjogZnVuY3Rpb24gKCB0b0Zvcm1hdCApIHsKCQkgKiAgICAgICAgICByZXR1cm4gdG9Gb3JtYXQudG9TdHJpbmcoKS5yZXBsYWNlKAoJCSAqICAgICAgICAgICAgL1xCKD89KFxkezN9KSsoPyFcZCkpL2csICInIgoJCSAqICAgICAgICAgICk7CgkJICogICAgICAgIH07CgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJmbkZvcm1hdE51bWJlciI6IGZ1bmN0aW9uICggdG9Gb3JtYXQgKSB7CgkJCXJldHVybiB0b0Zvcm1hdC50b1N0cmluZygpLnJlcGxhY2UoCgkJCQkvXEIoPz0oXGR7M30pKyg/IVxkKSkvZywKCQkJCXRoaXMub0xhbmd1YWdlLnNUaG91c2FuZHMKCQkJKTsKCQl9LAoJCgkKCQkvKioKCQkgKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBldmVyeSAnZHJhdycgZXZlbnQsIGFuZCBhbGxvd3MgeW91IHRvCgkJICogZHluYW1pY2FsbHkgbW9kaWZ5IHRoZSBoZWFkZXIgcm93LiBUaGlzIGNhbiBiZSB1c2VkIHRvIGNhbGN1bGF0ZSBhbmQKCQkgKiBkaXNwbGF5IHVzZWZ1bCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdGFibGUuCgkJICogIEB0eXBlIGZ1bmN0aW9uCgkJICogIEBwYXJhbSB7bm9kZX0gaGVhZCAiVFIiIGVsZW1lbnQgZm9yIHRoZSBoZWFkZXIKCQkgKiAgQHBhcmFtIHthcnJheX0gZGF0YSBGdWxsIHRhYmxlIGRhdGEgKGFzIGRlcml2ZWQgZnJvbSB0aGUgb3JpZ2luYWwgSFRNTCkKCQkgKiAgQHBhcmFtIHtpbnR9IHN0YXJ0IEluZGV4IGZvciB0aGUgY3VycmVudCBkaXNwbGF5IHN0YXJ0aW5nIHBvaW50IGluIHRoZQoJCSAqICAgIGRpc3BsYXkgYXJyYXkKCQkgKiAgQHBhcmFtIHtpbnR9IGVuZCBJbmRleCBmb3IgdGhlIGN1cnJlbnQgZGlzcGxheSBlbmRpbmcgcG9pbnQgaW4gdGhlCgkJICogICAgZGlzcGxheSBhcnJheQoJCSAqICBAcGFyYW0ge2FycmF5IGludH0gZGlzcGxheSBJbmRleCBhcnJheSB0byB0cmFuc2xhdGUgdGhlIHZpc3VhbCBwb3NpdGlvbgoJCSAqICAgIHRvIHRoZSBmdWxsIGRhdGEgYXJyYXkKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5oZWFkZXJDYWxsYmFjawoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImZoZWFkZXJDYWxsYmFjayI6IGZ1bmN0aW9uKCBoZWFkLCBkYXRhLCBzdGFydCwgZW5kLCBkaXNwbGF5ICkgewoJCSAqICAgICAgICAgIGhlYWQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3RoJylbMF0uaW5uZXJIVE1MID0gIkRpc3BsYXlpbmcgIisoZW5kLXN0YXJ0KSsiIHJlY29yZHMiOwoJCSAqICAgICAgICB9CgkJICogICAgICB9ICk7CgkJICogICAgfSApCgkJICovCgkJImZuSGVhZGVyQ2FsbGJhY2siOiBudWxsLAoJCgkKCQkvKioKCQkgKiBUaGUgaW5mb3JtYXRpb24gZWxlbWVudCBjYW4gYmUgdXNlZCB0byBjb252ZXkgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGN1cnJlbnQKCQkgKiBzdGF0ZSBvZiB0aGUgdGFibGUuIEFsdGhvdWdoIHRoZSBpbnRlcm5hdGlvbmFsaXNhdGlvbiBvcHRpb25zIHByZXNlbnRlZCBieQoJCSAqIERhdGFUYWJsZXMgYXJlIHF1aXRlIGNhcGFibGUgb2YgZGVhbGluZyB3aXRoIG1vc3QgY3VzdG9taXNhdGlvbnMsIHRoZXJlIG1heQoJCSAqIGJlIHRpbWVzIHdoZXJlIHlvdSB3aXNoIHRvIGN1c3RvbWlzZSB0aGUgc3RyaW5nIGZ1cnRoZXIuIFRoaXMgY2FsbGJhY2sKCQkgKiBhbGxvd3MgeW91IHRvIGRvIGV4YWN0bHkgdGhhdC4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJCSAqICBAcGFyYW0ge2ludH0gc3RhcnQgU3RhcnRpbmcgcG9zaXRpb24gaW4gZGF0YSBmb3IgdGhlIGRyYXcKCQkgKiAgQHBhcmFtIHtpbnR9IGVuZCBFbmQgcG9zaXRpb24gaW4gZGF0YSBmb3IgdGhlIGRyYXcKCQkgKiAgQHBhcmFtIHtpbnR9IG1heCBUb3RhbCBudW1iZXIgb2Ygcm93cyBpbiB0aGUgdGFibGUgKHJlZ2FyZGxlc3Mgb2YKCQkgKiAgICBmaWx0ZXJpbmcpCgkJICogIEBwYXJhbSB7aW50fSB0b3RhbCBUb3RhbCBudW1iZXIgb2Ygcm93cyBpbiB0aGUgZGF0YSBzZXQsIGFmdGVyIGZpbHRlcmluZwoJCSAqICBAcGFyYW0ge3N0cmluZ30gcHJlIFRoZSBzdHJpbmcgdGhhdCBEYXRhVGFibGVzIGhhcyBmb3JtYXR0ZWQgdXNpbmcgaXQncwoJCSAqICAgIG93biBydWxlcwoJCSAqICBAcmV0dXJucyB7c3RyaW5nfSBUaGUgc3RyaW5nIHRvIGJlIGRpc3BsYXllZCBpbiB0aGUgaW5mb3JtYXRpb24gZWxlbWVudC4KCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5pbmZvQ2FsbGJhY2sKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAiaW5mb0NhbGxiYWNrIjogZnVuY3Rpb24oIHNldHRpbmdzLCBzdGFydCwgZW5kLCBtYXgsIHRvdGFsLCBwcmUgKSB7CgkJICogICAgICAgIHJldHVybiBzdGFydCArIiB0byAiKyBlbmQ7CgkJICogICAgICB9CgkJICogICAgfSApOwoJCSAqLwoJCSJmbkluZm9DYWxsYmFjayI6IG51bGwsCgkKCQoJCS8qKgoJCSAqIENhbGxlZCB3aGVuIHRoZSB0YWJsZSBoYXMgYmVlbiBpbml0aWFsaXNlZC4gTm9ybWFsbHkgRGF0YVRhYmxlcyB3aWxsCgkJICogaW5pdGlhbGlzZSBzZXF1ZW50aWFsbHkgYW5kIHRoZXJlIHdpbGwgYmUgbm8gbmVlZCBmb3IgdGhpcyBmdW5jdGlvbiwKCQkgKiBob3dldmVyLCB0aGlzIGRvZXMgbm90IGhvbGQgdHJ1ZSB3aGVuIHVzaW5nIGV4dGVybmFsIGxhbmd1YWdlIGluZm9ybWF0aW9uCgkJICogc2luY2UgdGhhdCBpcyBvYnRhaW5lZCB1c2luZyBhbiBhc3luYyBYSFIgY2FsbC4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkJICogIEBwYXJhbSB7b2JqZWN0fSBqc29uIFRoZSBKU09OIG9iamVjdCByZXF1ZXN0IGZyb20gdGhlIHNlcnZlciAtIG9ubHkKCQkgKiAgICBwcmVzZW50IGlmIGNsaWVudC1zaWRlIEFqYXggc291cmNlZCBkYXRhIGlzIHVzZWQKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5pbml0Q29tcGxldGUKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJpbml0Q29tcGxldGUiOiBmdW5jdGlvbihzZXR0aW5ncywganNvbikgewoJCSAqICAgICAgICAgIGFsZXJ0KCAnRGF0YVRhYmxlcyBoYXMgZmluaXNoZWQgaXRzIGluaXRpYWxpc2F0aW9uLicgKTsKCQkgKiAgICAgICAgfQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKQoJCSAqLwoJCSJmbkluaXRDb21wbGV0ZSI6IG51bGwsCgkKCQoJCS8qKgoJCSAqIENhbGxlZCBhdCB0aGUgdmVyeSBzdGFydCBvZiBlYWNoIHRhYmxlIGRyYXcgYW5kIGNhbiBiZSB1c2VkIHRvIGNhbmNlbCB0aGUKCQkgKiBkcmF3IGJ5IHJldHVybmluZyBmYWxzZSwgYW55IG90aGVyIHJldHVybiAoaW5jbHVkaW5nIHVuZGVmaW5lZCkgcmVzdWx0cyBpbgoJCSAqIHRoZSBmdWxsIGRyYXcgb2NjdXJyaW5nKS4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0CgkJICogIEByZXR1cm5zIHtib29sZWFufSBGYWxzZSB3aWxsIGNhbmNlbCB0aGUgZHJhdywgYW55dGhpbmcgZWxzZSAoaW5jbHVkaW5nIG5vCgkJICogICAgcmV0dXJuKSB3aWxsIGFsbG93IGl0IHRvIGNvbXBsZXRlLgoJCSAqCgkJICogIEBkdG9wdCBDYWxsYmFja3MKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnByZURyYXdDYWxsYmFjawoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInByZURyYXdDYWxsYmFjayI6IGZ1bmN0aW9uKCBzZXR0aW5ncyApIHsKCQkgKiAgICAgICAgICBpZiAoICQoJyN0ZXN0JykudmFsKCkgPT0gMSApIHsKCQkgKiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKCQkgKiAgICAgICAgICB9CgkJICogICAgICAgIH0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImZuUHJlRHJhd0NhbGxiYWNrIjogbnVsbCwKCQoJCgkJLyoqCgkJICogVGhpcyBmdW5jdGlvbiBhbGxvd3MgeW91IHRvICdwb3N0IHByb2Nlc3MnIGVhY2ggcm93IGFmdGVyIGl0IGhhdmUgYmVlbgoJCSAqIGdlbmVyYXRlZCBmb3IgZWFjaCB0YWJsZSBkcmF3LCBidXQgYmVmb3JlIGl0IGlzIHJlbmRlcmVkIG9uIHNjcmVlbi4gVGhpcwoJCSAqIGZ1bmN0aW9uIG1pZ2h0IGJlIHVzZWQgZm9yIHNldHRpbmcgdGhlIHJvdyBjbGFzcyBuYW1lIGV0Yy4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQHBhcmFtIHtub2RlfSByb3cgIlRSIiBlbGVtZW50IGZvciB0aGUgY3VycmVudCByb3cKCQkgKiAgQHBhcmFtIHthcnJheX0gZGF0YSBSYXcgZGF0YSBhcnJheSBmb3IgdGhpcyByb3cKCQkgKiAgQHBhcmFtIHtpbnR9IGRpc3BsYXlJbmRleCBUaGUgZGlzcGxheSBpbmRleCBmb3IgdGhlIGN1cnJlbnQgdGFibGUgZHJhdwoJCSAqICBAcGFyYW0ge2ludH0gZGlzcGxheUluZGV4RnVsbCBUaGUgaW5kZXggb2YgdGhlIGRhdGEgaW4gdGhlIGZ1bGwgbGlzdCBvZgoJCSAqICAgIHJvd3MgKGFmdGVyIGZpbHRlcmluZykKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5yb3dDYWxsYmFjawoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInJvd0NhbGxiYWNrIjogZnVuY3Rpb24oIHJvdywgZGF0YSwgZGlzcGxheUluZGV4LCBkaXNwbGF5SW5kZXhGdWxsICkgewoJCSAqICAgICAgICAgIC8vIEJvbGQgdGhlIGdyYWRlIGZvciBhbGwgJ0EnIGdyYWRlIGJyb3dzZXJzCgkJICogICAgICAgICAgaWYgKCBkYXRhWzRdID09ICJBIiApIHsKCQkgKiAgICAgICAgICAgICQoJ3RkOmVxKDQpJywgcm93KS5odG1sKCAnPGI+QTwvYj4nICk7CgkJICogICAgICAgICAgfQoJCSAqICAgICAgICB9CgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJmblJvd0NhbGxiYWNrIjogbnVsbCwKCQoJCgkJLyoqCgkJICogX19EZXByZWNhdGVkX18gVGhlIGZ1bmN0aW9uYWxpdHkgcHJvdmlkZWQgYnkgdGhpcyBwYXJhbWV0ZXIgaGFzIG5vdyBiZWVuCgkJICogc3VwZXJzZWRlZCBieSB0aGF0IHByb3ZpZGVkIHRocm91Z2ggYGFqYXhgLCB3aGljaCBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkLgoJCSAqCgkJICogVGhpcyBwYXJhbWV0ZXIgYWxsb3dzIHlvdSB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBmdW5jdGlvbiB3aGljaCBvYnRhaW5zCgkJICogdGhlIGRhdGEgZnJvbSB0aGUgc2VydmVyIHNvIHNvbWV0aGluZyBtb3JlIHN1aXRhYmxlIGZvciB5b3VyIGFwcGxpY2F0aW9uLgoJCSAqIEZvciBleGFtcGxlIHlvdSBjb3VsZCB1c2UgUE9TVCBkYXRhLCBvciBwdWxsIGluZm9ybWF0aW9uIGZyb20gYSBHZWFycyBvcgoJCSAqIEFJUiBkYXRhYmFzZS4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQG1lbWJlcgoJCSAqICBAcGFyYW0ge3N0cmluZ30gc291cmNlIEhUVFAgc291cmNlIHRvIG9idGFpbiB0aGUgZGF0YSBmcm9tIChgYWpheGApCgkJICogIEBwYXJhbSB7YXJyYXl9IGRhdGEgQSBrZXkvdmFsdWUgcGFpciBvYmplY3QgY29udGFpbmluZyB0aGUgZGF0YSB0byBzZW5kCgkJICogICAgdG8gdGhlIHNlcnZlcgoJCSAqICBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayB0byBiZSBjYWxsZWQgb24gY29tcGxldGlvbiBvZiB0aGUgZGF0YSBnZXQKCQkgKiAgICBwcm9jZXNzIHRoYXQgd2lsbCBkcmF3IHRoZSBkYXRhIG9uIHRoZSBwYWdlLgoJCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBkdG9wdCBTZXJ2ZXItc2lkZQoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc2VydmVyRGF0YQoJCSAqCgkJICogIEBkZXByZWNhdGVkIDEuMTAuIFBsZWFzZSB1c2UgYGFqYXhgIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHkgbm93LgoJCSAqLwoJCSJmblNlcnZlckRhdGEiOiBudWxsLAoJCgkKCQkvKioKCQkgKiBfX0RlcHJlY2F0ZWRfXyBUaGUgZnVuY3Rpb25hbGl0eSBwcm92aWRlZCBieSB0aGlzIHBhcmFtZXRlciBoYXMgbm93IGJlZW4KCQkgKiBzdXBlcnNlZGVkIGJ5IHRoYXQgcHJvdmlkZWQgdGhyb3VnaCBgYWpheGAsIHdoaWNoIHNob3VsZCBiZSB1c2VkIGluc3RlYWQuCgkJICoKCQkgKiAgSXQgaXMgb2Z0ZW4gdXNlZnVsIHRvIHNlbmQgZXh0cmEgZGF0YSB0byB0aGUgc2VydmVyIHdoZW4gbWFraW5nIGFuIEFqYXgKCQkgKiByZXF1ZXN0IC0gZm9yIGV4YW1wbGUgY3VzdG9tIGZpbHRlcmluZyBpbmZvcm1hdGlvbiwgYW5kIHRoaXMgY2FsbGJhY2sKCQkgKiBmdW5jdGlvbiBtYWtlcyBpdCB0cml2aWFsIHRvIHNlbmQgZXh0cmEgaW5mb3JtYXRpb24gdG8gdGhlIHNlcnZlci4gVGhlCgkJICogcGFzc2VkIGluIHBhcmFtZXRlciBpcyB0aGUgZGF0YSBzZXQgdGhhdCBoYXMgYmVlbiBjb25zdHJ1Y3RlZCBieQoJCSAqIERhdGFUYWJsZXMsIGFuZCB5b3UgY2FuIGFkZCB0byB0aGlzIG9yIG1vZGlmeSBpdCBhcyB5b3UgcmVxdWlyZS4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQHBhcmFtIHthcnJheX0gZGF0YSBEYXRhIGFycmF5IChhcnJheSBvZiBvYmplY3RzIHdoaWNoIGFyZSBuYW1lL3ZhbHVlCgkJICogICAgcGFpcnMpIHRoYXQgaGFzIGJlZW4gY29uc3RydWN0ZWQgYnkgRGF0YVRhYmxlcyBhbmQgd2lsbCBiZSBzZW50IHRvIHRoZQoJCSAqICAgIHNlcnZlci4gSW4gdGhlIGNhc2Ugb2YgQWpheCBzb3VyY2VkIGRhdGEgd2l0aCBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nCgkJICogICAgdGhpcyB3aWxsIGJlIGFuIGVtcHR5IGFycmF5LCBmb3Igc2VydmVyLXNpZGUgcHJvY2Vzc2luZyB0aGVyZSB3aWxsIGJlIGEKCQkgKiAgICBzaWduaWZpY2FudCBudW1iZXIgb2YgcGFyYW1ldGVycyEKCQkgKiAgQHJldHVybnMge3VuZGVmaW5lZH0gRW5zdXJlIHRoYXQgeW91IG1vZGlmeSB0aGUgZGF0YSBhcnJheSBwYXNzZWQgaW4sCgkJICogICAgYXMgdGhpcyBpcyBwYXNzZWQgYnkgcmVmZXJlbmNlLgoJCSAqCgkJICogIEBkdG9wdCBDYWxsYmFja3MKCQkgKiAgQGR0b3B0IFNlcnZlci1zaWRlCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zZXJ2ZXJQYXJhbXMKCQkgKgoJCSAqICBAZGVwcmVjYXRlZCAxLjEwLiBQbGVhc2UgdXNlIGBhamF4YCBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5IG5vdy4KCQkgKi8KCQkiZm5TZXJ2ZXJQYXJhbXMiOiBudWxsLAoJCgkKCQkvKioKCQkgKiBMb2FkIHRoZSB0YWJsZSBzdGF0ZS4gV2l0aCB0aGlzIGZ1bmN0aW9uIHlvdSBjYW4gZGVmaW5lIGZyb20gd2hlcmUsIGFuZCBob3csIHRoZQoJCSAqIHN0YXRlIG9mIGEgdGFibGUgaXMgbG9hZGVkLiBCeSBkZWZhdWx0IERhdGFUYWJsZXMgd2lsbCBsb2FkIGZyb20gYGxvY2FsU3RvcmFnZWAKCQkgKiBidXQgeW91IG1pZ2h0IHdpc2ggdG8gdXNlIGEgc2VydmVyLXNpZGUgZGF0YWJhc2Ugb3IgY29va2llcy4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKiAgQG1lbWJlcgoJCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCQkgKiAgQHBhcmFtIHtvYmplY3R9IGNhbGxiYWNrIENhbGxiYWNrIHRoYXQgY2FuIGJlIGV4ZWN1dGVkIHdoZW4gZG9uZS4gSXQKCQkgKiAgICBzaG91bGQgYmUgcGFzc2VkIHRoZSBsb2FkZWQgc3RhdGUgb2JqZWN0LgoJCSAqICBAcmV0dXJuIHtvYmplY3R9IFRoZSBEYXRhVGFibGVzIHN0YXRlIG9iamVjdCB0byBiZSBsb2FkZWQKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zdGF0ZUxvYWRDYWxsYmFjawoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInN0YXRlU2F2ZSI6IHRydWUsCgkJICogICAgICAgICJzdGF0ZUxvYWRDYWxsYmFjayI6IGZ1bmN0aW9uIChzZXR0aW5ncywgY2FsbGJhY2spIHsKCQkgKiAgICAgICAgICAkLmFqYXgoIHsKCQkgKiAgICAgICAgICAgICJ1cmwiOiAiL3N0YXRlX2xvYWQiLAoJCSAqICAgICAgICAgICAgImRhdGFUeXBlIjogImpzb24iLAoJCSAqICAgICAgICAgICAgInN1Y2Nlc3MiOiBmdW5jdGlvbiAoanNvbikgewoJCSAqICAgICAgICAgICAgICBjYWxsYmFjaygganNvbiApOwoJCSAqICAgICAgICAgICAgfQoJCSAqICAgICAgICAgIH0gKTsKCQkgKiAgICAgICAgfQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkiZm5TdGF0ZUxvYWRDYWxsYmFjayI6IGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7CgkJCXRyeSB7CgkJCQlyZXR1cm4gSlNPTi5wYXJzZSgKCQkJCQkoc2V0dGluZ3MuaVN0YXRlRHVyYXRpb24gPT09IC0xID8gc2Vzc2lvblN0b3JhZ2UgOiBsb2NhbFN0b3JhZ2UpLmdldEl0ZW0oCgkJCQkJCSdEYXRhVGFibGVzXycrc2V0dGluZ3Muc0luc3RhbmNlKydfJytsb2NhdGlvbi5wYXRobmFtZQoJCQkJCSkKCQkJCSk7CgkJCX0gY2F0Y2ggKGUpIHsKCQkJCXJldHVybiB7fTsKCQkJfQoJCX0sCgkKCQoJCS8qKgoJCSAqIENhbGxiYWNrIHdoaWNoIGFsbG93cyBtb2RpZmljYXRpb24gb2YgdGhlIHNhdmVkIHN0YXRlIHByaW9yIHRvIGxvYWRpbmcgdGhhdCBzdGF0ZS4KCQkgKiBUaGlzIGNhbGxiYWNrIGlzIGNhbGxlZCB3aGVuIHRoZSB0YWJsZSBpcyBsb2FkaW5nIHN0YXRlIGZyb20gdGhlIHN0b3JlZCBkYXRhLCBidXQKCQkgKiBwcmlvciB0byB0aGUgc2V0dGluZ3Mgb2JqZWN0IGJlaW5nIG1vZGlmaWVkIGJ5IHRoZSBzYXZlZCBzdGF0ZS4gTm90ZSB0aGF0IGZvcgoJCSAqIHBsdWctaW4gYXV0aG9ycywgeW91IHNob3VsZCB1c2UgdGhlIGBzdGF0ZUxvYWRQYXJhbXNgIGV2ZW50IHRvIGxvYWQgcGFyYW1ldGVycyBmb3IKCQkgKiBhIHBsdWctaW4uCgkJICogIEB0eXBlIGZ1bmN0aW9uCgkJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJCSAqICBAcGFyYW0ge29iamVjdH0gZGF0YSBUaGUgc3RhdGUgb2JqZWN0IHRoYXQgaXMgdG8gYmUgbG9hZGVkCgkJICoKCQkgKiAgQGR0b3B0IENhbGxiYWNrcwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc3RhdGVMb2FkUGFyYW1zCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBSZW1vdmUgYSBzYXZlZCBmaWx0ZXIsIHNvIGZpbHRlcmluZyBpcyBuZXZlciBsb2FkZWQKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic3RhdGVTYXZlIjogdHJ1ZSwKCQkgKiAgICAgICAgInN0YXRlTG9hZFBhcmFtcyI6IGZ1bmN0aW9uIChzZXR0aW5ncywgZGF0YSkgewoJCSAqICAgICAgICAgIGRhdGEub1NlYXJjaC5zU2VhcmNoID0gIiI7CgkJICogICAgICAgIH0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBEaXNhbGxvdyBzdGF0ZSBsb2FkaW5nIGJ5IHJldHVybmluZyBmYWxzZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJzdGF0ZVNhdmUiOiB0cnVlLAoJCSAqICAgICAgICAic3RhdGVMb2FkUGFyYW1zIjogZnVuY3Rpb24gKHNldHRpbmdzLCBkYXRhKSB7CgkJICogICAgICAgICAgcmV0dXJuIGZhbHNlOwoJCSAqICAgICAgICB9CgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJmblN0YXRlTG9hZFBhcmFtcyI6IG51bGwsCgkKCQoJCS8qKgoJCSAqIENhbGxiYWNrIHRoYXQgaXMgY2FsbGVkIHdoZW4gdGhlIHN0YXRlIGhhcyBiZWVuIGxvYWRlZCBmcm9tIHRoZSBzdGF0ZSBzYXZpbmcgbWV0aG9kCgkJICogYW5kIHRoZSBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdCBoYXMgYmVlbiBtb2RpZmllZCBhcyBhIHJlc3VsdCBvZiB0aGUgbG9hZGVkIHN0YXRlLgoJCSAqICBAdHlwZSBmdW5jdGlvbgoJCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCQkgKiAgQHBhcmFtIHtvYmplY3R9IGRhdGEgVGhlIHN0YXRlIG9iamVjdCB0aGF0IHdhcyBsb2FkZWQKCQkgKgoJCSAqICBAZHRvcHQgQ2FsbGJhY2tzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zdGF0ZUxvYWRlZAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gU2hvdyBhbiBhbGVydCB3aXRoIHRoZSBmaWx0ZXJpbmcgdmFsdWUgdGhhdCB3YXMgc2F2ZWQKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic3RhdGVTYXZlIjogdHJ1ZSwKCQkgKiAgICAgICAgInN0YXRlTG9hZGVkIjogZnVuY3Rpb24gKHNldHRpbmdzLCBkYXRhKSB7CgkJICogICAgICAgICAgYWxlcnQoICdTYXZlZCBmaWx0ZXIgd2FzOiAnK2RhdGEub1NlYXJjaC5zU2VhcmNoICk7CgkJICogICAgICAgIH0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImZuU3RhdGVMb2FkZWQiOiBudWxsLAoJCgkKCQkvKioKCQkgKiBTYXZlIHRoZSB0YWJsZSBzdGF0ZS4gVGhpcyBmdW5jdGlvbiBhbGxvd3MgeW91IHRvIGRlZmluZSB3aGVyZSBhbmQgaG93IHRoZSBzdGF0ZQoJCSAqIGluZm9ybWF0aW9uIGZvciB0aGUgdGFibGUgaXMgc3RvcmVkIEJ5IGRlZmF1bHQgRGF0YVRhYmxlcyB3aWxsIHVzZSBgbG9jYWxTdG9yYWdlYAoJCSAqIGJ1dCB5b3UgbWlnaHQgd2lzaCB0byB1c2UgYSBzZXJ2ZXItc2lkZSBkYXRhYmFzZSBvciBjb29raWVzLgoJCSAqICBAdHlwZSBmdW5jdGlvbgoJCSAqICBAbWVtYmVyCgkJICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdAoJCSAqICBAcGFyYW0ge29iamVjdH0gZGF0YSBUaGUgc3RhdGUgb2JqZWN0IHRvIGJlIHNhdmVkCgkJICoKCQkgKiAgQGR0b3B0IENhbGxiYWNrcwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc3RhdGVTYXZlQ2FsbGJhY2sKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJzdGF0ZVNhdmUiOiB0cnVlLAoJCSAqICAgICAgICAic3RhdGVTYXZlQ2FsbGJhY2siOiBmdW5jdGlvbiAoc2V0dGluZ3MsIGRhdGEpIHsKCQkgKiAgICAgICAgICAvLyBTZW5kIGFuIEFqYXggcmVxdWVzdCB0byB0aGUgc2VydmVyIHdpdGggdGhlIHN0YXRlIG9iamVjdAoJCSAqICAgICAgICAgICQuYWpheCggewoJCSAqICAgICAgICAgICAgInVybCI6ICIvc3RhdGVfc2F2ZSIsCgkJICogICAgICAgICAgICAiZGF0YSI6IGRhdGEsCgkJICogICAgICAgICAgICAiZGF0YVR5cGUiOiAianNvbiIsCgkJICogICAgICAgICAgICAibWV0aG9kIjogIlBPU1QiCgkJICogICAgICAgICAgICAic3VjY2VzcyI6IGZ1bmN0aW9uICgpIHt9CgkJICogICAgICAgICAgfSApOwoJCSAqICAgICAgICB9CgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJmblN0YXRlU2F2ZUNhbGxiYWNrIjogZnVuY3Rpb24gKCBzZXR0aW5ncywgZGF0YSApIHsKCQkJdHJ5IHsKCQkJCShzZXR0aW5ncy5pU3RhdGVEdXJhdGlvbiA9PT0gLTEgPyBzZXNzaW9uU3RvcmFnZSA6IGxvY2FsU3RvcmFnZSkuc2V0SXRlbSgKCQkJCQknRGF0YVRhYmxlc18nK3NldHRpbmdzLnNJbnN0YW5jZSsnXycrbG9jYXRpb24ucGF0aG5hbWUsCgkJCQkJSlNPTi5zdHJpbmdpZnkoIGRhdGEgKQoJCQkJKTsKCQkJfSBjYXRjaCAoZSkge30KCQl9LAoJCgkKCQkvKioKCQkgKiBDYWxsYmFjayB3aGljaCBhbGxvd3MgbW9kaWZpY2F0aW9uIG9mIHRoZSBzdGF0ZSB0byBiZSBzYXZlZC4gQ2FsbGVkIHdoZW4gdGhlIHRhYmxlCgkJICogaGFzIGNoYW5nZWQgc3RhdGUgYSBuZXcgc3RhdGUgc2F2ZSBpcyByZXF1aXJlZC4gVGhpcyBtZXRob2QgYWxsb3dzIG1vZGlmaWNhdGlvbiBvZgoJCSAqIHRoZSBzdGF0ZSBzYXZpbmcgb2JqZWN0IHByaW9yIHRvIGFjdHVhbGx5IGRvaW5nIHRoZSBzYXZlLCBpbmNsdWRpbmcgYWRkaXRpb24gb3IKCQkgKiBvdGhlciBzdGF0ZSBwcm9wZXJ0aWVzIG9yIG1vZGlmaWNhdGlvbi4gTm90ZSB0aGF0IGZvciBwbHVnLWluIGF1dGhvcnMsIHlvdSBzaG91bGQKCQkgKiB1c2UgdGhlIGBzdGF0ZVNhdmVQYXJhbXNgIGV2ZW50IHRvIHNhdmUgcGFyYW1ldGVycyBmb3IgYSBwbHVnLWluLgoJCSAqICBAdHlwZSBmdW5jdGlvbgoJCSAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QKCQkgKiAgQHBhcmFtIHtvYmplY3R9IGRhdGEgVGhlIHN0YXRlIG9iamVjdCB0byBiZSBzYXZlZAoJCSAqCgkJICogIEBkdG9wdCBDYWxsYmFja3MKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnN0YXRlU2F2ZVBhcmFtcwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gUmVtb3ZlIGEgc2F2ZWQgZmlsdGVyLCBzbyBmaWx0ZXJpbmcgaXMgbmV2ZXIgc2F2ZWQKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic3RhdGVTYXZlIjogdHJ1ZSwKCQkgKiAgICAgICAgInN0YXRlU2F2ZVBhcmFtcyI6IGZ1bmN0aW9uIChzZXR0aW5ncywgZGF0YSkgewoJCSAqICAgICAgICAgIGRhdGEub1NlYXJjaC5zU2VhcmNoID0gIiI7CgkJICogICAgICAgIH0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImZuU3RhdGVTYXZlUGFyYW1zIjogbnVsbCwKCQoJCgkJLyoqCgkJICogRHVyYXRpb24gZm9yIHdoaWNoIHRoZSBzYXZlZCBzdGF0ZSBpbmZvcm1hdGlvbiBpcyBjb25zaWRlcmVkIHZhbGlkLiBBZnRlciB0aGlzIHBlcmlvZAoJCSAqIGhhcyBlbGFwc2VkIHRoZSBzdGF0ZSB3aWxsIGJlIHJldHVybmVkIHRvIHRoZSBkZWZhdWx0LgoJCSAqIFZhbHVlIGlzIGdpdmVuIGluIHNlY29uZHMuCgkJICogIEB0eXBlIGludAoJCSAqICBAZGVmYXVsdCA3MjAwIDxpPigyIGhvdXJzKTwvaT4KCQkgKgoJCSAqICBAZHRvcHQgT3B0aW9ucwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc3RhdGVEdXJhdGlvbgoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInN0YXRlRHVyYXRpb24iOiA2MCo2MCoyNDsgLy8gMSBkYXkKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICkKCQkgKi8KCQkiaVN0YXRlRHVyYXRpb24iOiA3MjAwLAoJCgkKCQkvKioKCQkgKiBXaGVuIGVuYWJsZWQgRGF0YVRhYmxlcyB3aWxsIG5vdCBtYWtlIGEgcmVxdWVzdCB0byB0aGUgc2VydmVyIGZvciB0aGUgZmlyc3QKCQkgKiBwYWdlIGRyYXcgLSByYXRoZXIgaXQgd2lsbCB1c2UgdGhlIGRhdGEgYWxyZWFkeSBvbiB0aGUgcGFnZSAobm8gc29ydGluZyBldGMKCQkgKiB3aWxsIGJlIGFwcGxpZWQgdG8gaXQpLCB0aHVzIHNhdmluZyBvbiBhbiBYSFIgYXQgbG9hZCB0aW1lLiBgZGVmZXJMb2FkaW5nYAoJCSAqIGlzIHVzZWQgdG8gaW5kaWNhdGUgdGhhdCBkZWZlcnJlZCBsb2FkaW5nIGlzIHJlcXVpcmVkLCBidXQgaXQgaXMgYWxzbyB1c2VkCgkJICogdG8gdGVsbCBEYXRhVGFibGVzIGhvdyBtYW55IHJlY29yZHMgdGhlcmUgYXJlIGluIHRoZSBmdWxsIHRhYmxlIChhbGxvd2luZwoJCSAqIHRoZSBpbmZvcm1hdGlvbiBlbGVtZW50IGFuZCBwYWdpbmF0aW9uIHRvIGJlIGRpc3BsYXllZCBjb3JyZWN0bHkpLiBJbiB0aGUgY2FzZQoJCSAqIHdoZXJlIGEgZmlsdGVyaW5nIGlzIGFwcGxpZWQgdG8gdGhlIHRhYmxlIG9uIGluaXRpYWwgbG9hZCwgdGhpcyBjYW4gYmUKCQkgKiBpbmRpY2F0ZWQgYnkgZ2l2aW5nIHRoZSBwYXJhbWV0ZXIgYXMgYW4gYXJyYXksIHdoZXJlIHRoZSBmaXJzdCBlbGVtZW50IGlzCgkJICogdGhlIG51bWJlciBvZiByZWNvcmRzIGF2YWlsYWJsZSBhZnRlciBmaWx0ZXJpbmcgYW5kIHRoZSBzZWNvbmQgZWxlbWVudCBpcyB0aGUKCQkgKiBudW1iZXIgb2YgcmVjb3JkcyB3aXRob3V0IGZpbHRlcmluZyAoYWxsb3dpbmcgdGhlIHRhYmxlIGluZm9ybWF0aW9uIGVsZW1lbnQKCQkgKiB0byBiZSBzaG93biBjb3JyZWN0bHkpLgoJCSAqICBAdHlwZSBpbnQgfCBhcnJheQoJCSAqICBAZGVmYXVsdCBudWxsCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbnMKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmRlZmVyTG9hZGluZwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gNTcgcmVjb3JkcyBhdmFpbGFibGUgaW4gdGhlIHRhYmxlLCBubyBmaWx0ZXJpbmcgYXBwbGllZAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJzZXJ2ZXJTaWRlIjogdHJ1ZSwKCQkgKiAgICAgICAgImFqYXgiOiAic2NyaXB0cy9zZXJ2ZXJfcHJvY2Vzc2luZy5waHAiLAoJCSAqICAgICAgICAiZGVmZXJMb2FkaW5nIjogNTcKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyA1NyByZWNvcmRzIGFmdGVyIGZpbHRlcmluZywgMTAwIHdpdGhvdXQgZmlsdGVyaW5nIChhbiBpbml0aWFsIGZpbHRlciBhcHBsaWVkKQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJzZXJ2ZXJTaWRlIjogdHJ1ZSwKCQkgKiAgICAgICAgImFqYXgiOiAic2NyaXB0cy9zZXJ2ZXJfcHJvY2Vzc2luZy5waHAiLAoJCSAqICAgICAgICAiZGVmZXJMb2FkaW5nIjogWyA1NywgMTAwIF0sCgkJICogICAgICAgICJzZWFyY2giOiB7CgkJICogICAgICAgICAgInNlYXJjaCI6ICJteV9maWx0ZXIiCgkJICogICAgICAgIH0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImlEZWZlckxvYWRpbmciOiBudWxsLAoJCgkKCQkvKioKCQkgKiBOdW1iZXIgb2Ygcm93cyB0byBkaXNwbGF5IG9uIGEgc2luZ2xlIHBhZ2Ugd2hlbiB1c2luZyBwYWdpbmF0aW9uLiBJZgoJCSAqIGZlYXR1cmUgZW5hYmxlZCAoYGxlbmd0aENoYW5nZWApIHRoZW4gdGhlIGVuZCB1c2VyIHdpbGwgYmUgYWJsZSB0byBvdmVycmlkZQoJCSAqIHRoaXMgdG8gYSBjdXN0b20gc2V0dGluZyB1c2luZyBhIHBvcC11cCBtZW51LgoJCSAqICBAdHlwZSBpbnQKCQkgKiAgQGRlZmF1bHQgMTAKCQkgKgoJCSAqICBAZHRvcHQgT3B0aW9ucwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMucGFnZUxlbmd0aAoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInBhZ2VMZW5ndGgiOiA1MAoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKQoJCSAqLwoJCSJpRGlzcGxheUxlbmd0aCI6IDEwLAoJCgkKCQkvKioKCQkgKiBEZWZpbmUgdGhlIHN0YXJ0aW5nIHBvaW50IGZvciBkYXRhIGRpc3BsYXkgd2hlbiB1c2luZyBEYXRhVGFibGVzIHdpdGgKCQkgKiBwYWdpbmF0aW9uLiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgaXMgdGhlIG51bWJlciBvZiByZWNvcmRzLCByYXRoZXIgdGhhbgoJCSAqIHRoZSBwYWdlIG51bWJlciwgc28gaWYgeW91IGhhdmUgMTAgcmVjb3JkcyBwZXIgcGFnZSBhbmQgd2FudCB0byBzdGFydCBvbgoJCSAqIHRoZSB0aGlyZCBwYWdlLCBpdCBzaG91bGQgYmUgIjIwIi4KCQkgKiAgQHR5cGUgaW50CgkJICogIEBkZWZhdWx0IDAKCQkgKgoJCSAqICBAZHRvcHQgT3B0aW9ucwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuZGlzcGxheVN0YXJ0CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiZGlzcGxheVN0YXJ0IjogMjAKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICkKCQkgKi8KCQkiaURpc3BsYXlTdGFydCI6IDAsCgkKCQoJCS8qKgoJCSAqIEJ5IGRlZmF1bHQgRGF0YVRhYmxlcyBhbGxvd3Mga2V5Ym9hcmQgbmF2aWdhdGlvbiBvZiB0aGUgdGFibGUgKHNvcnRpbmcsIHBhZ2luZywKCQkgKiBhbmQgZmlsdGVyaW5nKSBieSBhZGRpbmcgYSBgdGFiaW5kZXhgIGF0dHJpYnV0ZSB0byB0aGUgcmVxdWlyZWQgZWxlbWVudHMuIFRoaXMKCQkgKiBhbGxvd3MgeW91IHRvIHRhYiB0aHJvdWdoIHRoZSBjb250cm9scyBhbmQgcHJlc3MgdGhlIGVudGVyIGtleSB0byBhY3RpdmF0ZSB0aGVtLgoJCSAqIFRoZSB0YWJpbmRleCBpcyBkZWZhdWx0IDAsIG1lYW5pbmcgdGhhdCB0aGUgdGFiIGZvbGxvd3MgdGhlIGZsb3cgb2YgdGhlIGRvY3VtZW50LgoJCSAqIFlvdSBjYW4gb3ZlcnJ1bGUgdGhpcyB1c2luZyB0aGlzIHBhcmFtZXRlciBpZiB5b3Ugd2lzaC4gVXNlIGEgdmFsdWUgb2YgLTEgdG8KCQkgKiBkaXNhYmxlIGJ1aWx0LWluIGtleWJvYXJkIG5hdmlnYXRpb24uCgkJICogIEB0eXBlIGludAoJCSAqICBAZGVmYXVsdCAwCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbnMKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnRhYkluZGV4CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAidGFiSW5kZXgiOiAxCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJpVGFiSW5kZXgiOiAwLAoJCgkKCQkvKioKCQkgKiBDbGFzc2VzIHRoYXQgRGF0YVRhYmxlcyBhc3NpZ25zIHRvIHRoZSB2YXJpb3VzIGNvbXBvbmVudHMgYW5kIGZlYXR1cmVzCgkJICogdGhhdCBpdCBhZGRzIHRvIHRoZSBIVE1MIHRhYmxlLiBUaGlzIGFsbG93cyBjbGFzc2VzIHRvIGJlIGNvbmZpZ3VyZWQKCQkgKiBkdXJpbmcgaW5pdGlhbGlzYXRpb24gaW4gYWRkaXRpb24gdG8gdGhyb3VnaCB0aGUgc3RhdGljCgkJICoge0BsaW5rIERhdGFUYWJsZS5leHQub1N0ZENsYXNzZXN9IG9iamVjdCkuCgkJICogIEBuYW1lc3BhY2UKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNsYXNzZXMKCQkgKi8KCQkib0NsYXNzZXMiOiB7fSwKCQoJCgkJLyoqCgkJICogQWxsIHN0cmluZ3MgdGhhdCBEYXRhVGFibGVzIHVzZXMgaW4gdGhlIHVzZXIgaW50ZXJmYWNlIHRoYXQgaXQgY3JlYXRlcwoJCSAqIGFyZSBkZWZpbmVkIGluIHRoaXMgb2JqZWN0LCBhbGxvd2luZyB5b3UgdG8gbW9kaWZpZWQgdGhlbSBpbmRpdmlkdWFsbHkgb3IKCQkgKiBjb21wbGV0ZWx5IHJlcGxhY2UgdGhlbSBhbGwgYXMgcmVxdWlyZWQuCgkJICogIEBuYW1lc3BhY2UKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlCgkJICovCgkJIm9MYW5ndWFnZSI6IHsKCQkJLyoqCgkJCSAqIFN0cmluZ3MgdGhhdCBhcmUgdXNlZCBmb3IgV0FJLUFSSUEgbGFiZWxzIGFuZCBjb250cm9scyBvbmx5ICh0aGVzZSBhcmUgbm90CgkJCSAqIGFjdHVhbGx5IHZpc2libGUgb24gdGhlIHBhZ2UsIGJ1dCB3aWxsIGJlIHJlYWQgYnkgc2NyZWVucmVhZGVycywgYW5kIHRodXMKCQkJICogbXVzdCBiZSBpbnRlcm5hdGlvbmFsaXNlZCBhcyB3ZWxsKS4KCQkJICogIEBuYW1lc3BhY2UKCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5hcmlhCgkJCSAqLwoJCQkib0FyaWEiOiB7CgkJCQkvKioKCQkJCSAqIEFSSUEgbGFiZWwgdGhhdCBpcyBhZGRlZCB0byB0aGUgdGFibGUgaGVhZGVycyB3aGVuIHRoZSBjb2x1bW4gbWF5IGJlCgkJCQkgKiBzb3J0ZWQgYXNjZW5kaW5nIGJ5IGFjdGl2aW5nIHRoZSBjb2x1bW4gKGNsaWNrIG9yIHJldHVybiB3aGVuIGZvY3VzZWQpLgoJCQkJICogTm90ZSB0aGF0IHRoZSBjb2x1bW4gaGVhZGVyIGlzIHByZWZpeGVkIHRvIHRoaXMgc3RyaW5nLgoJCQkJICogIEB0eXBlIHN0cmluZwoJCQkJICogIEBkZWZhdWx0IDogYWN0aXZhdGUgdG8gc29ydCBjb2x1bW4gYXNjZW5kaW5nCgkJCQkgKgoJCQkJICogIEBkdG9wdCBMYW5ndWFnZQoJCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5hcmlhLnNvcnRBc2NlbmRpbmcKCQkJCSAqCgkJCQkgKiAgQGV4YW1wbGUKCQkJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkJCSAqICAgICAgICAibGFuZ3VhZ2UiOiB7CgkJCQkgKiAgICAgICAgICAiYXJpYSI6IHsKCQkJCSAqICAgICAgICAgICAgInNvcnRBc2NlbmRpbmciOiAiIC0gY2xpY2svcmV0dXJuIHRvIHNvcnQgYXNjZW5kaW5nIgoJCQkJICogICAgICAgICAgfQoJCQkJICogICAgICAgIH0KCQkJCSAqICAgICAgfSApOwoJCQkJICogICAgfSApOwoJCQkJICovCgkJCQkic1NvcnRBc2NlbmRpbmciOiAiOiBhY3RpdmF0ZSB0byBzb3J0IGNvbHVtbiBhc2NlbmRpbmciLAoJCgkJCQkvKioKCQkJCSAqIEFSSUEgbGFiZWwgdGhhdCBpcyBhZGRlZCB0byB0aGUgdGFibGUgaGVhZGVycyB3aGVuIHRoZSBjb2x1bW4gbWF5IGJlCgkJCQkgKiBzb3J0ZWQgZGVzY2VuZGluZyBieSBhY3RpdmluZyB0aGUgY29sdW1uIChjbGljayBvciByZXR1cm4gd2hlbiBmb2N1c2VkKS4KCQkJCSAqIE5vdGUgdGhhdCB0aGUgY29sdW1uIGhlYWRlciBpcyBwcmVmaXhlZCB0byB0aGlzIHN0cmluZy4KCQkJCSAqICBAdHlwZSBzdHJpbmcKCQkJCSAqICBAZGVmYXVsdCA6IGFjdGl2YXRlIHRvIHNvcnQgY29sdW1uIGFzY2VuZGluZwoJCQkJICoKCQkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UuYXJpYS5zb3J0RGVzY2VuZGluZwoJCQkJICoKCQkJCSAqICBAZXhhbXBsZQoJCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJCSAqICAgICAgICAgICJhcmlhIjogewoJCQkJICogICAgICAgICAgICAic29ydERlc2NlbmRpbmciOiAiIC0gY2xpY2svcmV0dXJuIHRvIHNvcnQgZGVzY2VuZGluZyIKCQkJCSAqICAgICAgICAgIH0KCQkJCSAqICAgICAgICB9CgkJCQkgKiAgICAgIH0gKTsKCQkJCSAqICAgIH0gKTsKCQkJCSAqLwoJCQkJInNTb3J0RGVzY2VuZGluZyI6ICI6IGFjdGl2YXRlIHRvIHNvcnQgY29sdW1uIGRlc2NlbmRpbmciCgkJCX0sCgkKCQkJLyoqCgkJCSAqIFBhZ2luYXRpb24gc3RyaW5nIHVzZWQgYnkgRGF0YVRhYmxlcyBmb3IgdGhlIGJ1aWx0LWluIHBhZ2luYXRpb24KCQkJICogY29udHJvbCB0eXBlcy4KCQkJICogIEBuYW1lc3BhY2UKCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5wYWdpbmF0ZQoJCQkgKi8KCQkJIm9QYWdpbmF0ZSI6IHsKCQkJCS8qKgoJCQkJICogVGV4dCB0byB1c2Ugd2hlbiB1c2luZyB0aGUgJ2Z1bGxfbnVtYmVycycgdHlwZSBvZiBwYWdpbmF0aW9uIGZvciB0aGUKCQkJCSAqIGJ1dHRvbiB0byB0YWtlIHRoZSB1c2VyIHRvIHRoZSBmaXJzdCBwYWdlLgoJCQkJICogIEB0eXBlIHN0cmluZwoJCQkJICogIEBkZWZhdWx0IEZpcnN0CgkJCQkgKgoJCQkJICogIEBkdG9wdCBMYW5ndWFnZQoJCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5wYWdpbmF0ZS5maXJzdAoJCQkJICoKCQkJCSAqICBAZXhhbXBsZQoJCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJCSAqICAgICAgICAgICJwYWdpbmF0ZSI6IHsKCQkJCSAqICAgICAgICAgICAgImZpcnN0IjogIkZpcnN0IHBhZ2UiCgkJCQkgKiAgICAgICAgICB9CgkJCQkgKiAgICAgICAgfQoJCQkJICogICAgICB9ICk7CgkJCQkgKiAgICB9ICk7CgkJCQkgKi8KCQkJCSJzRmlyc3QiOiAiRmlyc3QiLAoJCgkKCQkJCS8qKgoJCQkJICogVGV4dCB0byB1c2Ugd2hlbiB1c2luZyB0aGUgJ2Z1bGxfbnVtYmVycycgdHlwZSBvZiBwYWdpbmF0aW9uIGZvciB0aGUKCQkJCSAqIGJ1dHRvbiB0byB0YWtlIHRoZSB1c2VyIHRvIHRoZSBsYXN0IHBhZ2UuCgkJCQkgKiAgQHR5cGUgc3RyaW5nCgkJCQkgKiAgQGRlZmF1bHQgTGFzdAoJCQkJICoKCQkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UucGFnaW5hdGUubGFzdAoJCQkJICoKCQkJCSAqICBAZXhhbXBsZQoJCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJCSAqICAgICAgICAgICJwYWdpbmF0ZSI6IHsKCQkJCSAqICAgICAgICAgICAgImxhc3QiOiAiTGFzdCBwYWdlIgoJCQkJICogICAgICAgICAgfQoJCQkJICogICAgICAgIH0KCQkJCSAqICAgICAgfSApOwoJCQkJICogICAgfSApOwoJCQkJICovCgkJCQkic0xhc3QiOiAiTGFzdCIsCgkKCQoJCQkJLyoqCgkJCQkgKiBUZXh0IHRvIHVzZSBmb3IgdGhlICduZXh0JyBwYWdpbmF0aW9uIGJ1dHRvbiAodG8gdGFrZSB0aGUgdXNlciB0byB0aGUKCQkJCSAqIG5leHQgcGFnZSkuCgkJCQkgKiAgQHR5cGUgc3RyaW5nCgkJCQkgKiAgQGRlZmF1bHQgTmV4dAoJCQkJICoKCQkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UucGFnaW5hdGUubmV4dAoJCQkJICoKCQkJCSAqICBAZXhhbXBsZQoJCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJCSAqICAgICAgICAgICJwYWdpbmF0ZSI6IHsKCQkJCSAqICAgICAgICAgICAgIm5leHQiOiAiTmV4dCBwYWdlIgoJCQkJICogICAgICAgICAgfQoJCQkJICogICAgICAgIH0KCQkJCSAqICAgICAgfSApOwoJCQkJICogICAgfSApOwoJCQkJICovCgkJCQkic05leHQiOiAiTmV4dCIsCgkKCQoJCQkJLyoqCgkJCQkgKiBUZXh0IHRvIHVzZSBmb3IgdGhlICdwcmV2aW91cycgcGFnaW5hdGlvbiBidXR0b24gKHRvIHRha2UgdGhlIHVzZXIgdG8KCQkJCSAqIHRoZSBwcmV2aW91cyBwYWdlKS4KCQkJCSAqICBAdHlwZSBzdHJpbmcKCQkJCSAqICBAZGVmYXVsdCBQcmV2aW91cwoJCQkJICoKCQkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UucGFnaW5hdGUucHJldmlvdXMKCQkJCSAqCgkJCQkgKiAgQGV4YW1wbGUKCQkJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkJCSAqICAgICAgICAibGFuZ3VhZ2UiOiB7CgkJCQkgKiAgICAgICAgICAicGFnaW5hdGUiOiB7CgkJCQkgKiAgICAgICAgICAgICJwcmV2aW91cyI6ICJQcmV2aW91cyBwYWdlIgoJCQkJICogICAgICAgICAgfQoJCQkJICogICAgICAgIH0KCQkJCSAqICAgICAgfSApOwoJCQkJICogICAgfSApOwoJCQkJICovCgkJCQkic1ByZXZpb3VzIjogIlByZXZpb3VzIgoJCQl9LAoJCgkJCS8qKgoJCQkgKiBUaGlzIHN0cmluZyBpcyBzaG93biBpbiBwcmVmZXJlbmNlIHRvIGB6ZXJvUmVjb3Jkc2Agd2hlbiB0aGUgdGFibGUgaXMKCQkJICogZW1wdHkgb2YgZGF0YSAocmVnYXJkbGVzcyBvZiBmaWx0ZXJpbmcpLiBOb3RlIHRoYXQgdGhpcyBpcyBhbiBvcHRpb25hbAoJCQkgKiBwYXJhbWV0ZXIgLSBpZiBpdCBpcyBub3QgZ2l2ZW4sIHRoZSB2YWx1ZSBvZiBgemVyb1JlY29yZHNgIHdpbGwgYmUgdXNlZAoJCQkgKiBpbnN0ZWFkIChlaXRoZXIgdGhlIGRlZmF1bHQgb3IgZ2l2ZW4gdmFsdWUpLgoJCQkgKiAgQHR5cGUgc3RyaW5nCgkJCSAqICBAZGVmYXVsdCBObyBkYXRhIGF2YWlsYWJsZSBpbiB0YWJsZQoJCQkgKgoJCQkgKiAgQGR0b3B0IExhbmd1YWdlCgkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UuZW1wdHlUYWJsZQoJCQkgKgoJCQkgKiAgQGV4YW1wbGUKCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJCSAqICAgICAgICAibGFuZ3VhZ2UiOiB7CgkJCSAqICAgICAgICAgICJlbXB0eVRhYmxlIjogIk5vIGRhdGEgYXZhaWxhYmxlIGluIHRhYmxlIgoJCQkgKiAgICAgICAgfQoJCQkgKiAgICAgIH0gKTsKCQkJICogICAgfSApOwoJCQkgKi8KCQkJInNFbXB0eVRhYmxlIjogIk5vIGRhdGEgYXZhaWxhYmxlIGluIHRhYmxlIiwKCQoJCgkJCS8qKgoJCQkgKiBUaGlzIHN0cmluZyBnaXZlcyBpbmZvcm1hdGlvbiB0byB0aGUgZW5kIHVzZXIgYWJvdXQgdGhlIGluZm9ybWF0aW9uCgkJCSAqIHRoYXQgaXMgY3VycmVudCBvbiBkaXNwbGF5IG9uIHRoZSBwYWdlLiBUaGUgZm9sbG93aW5nIHRva2VucyBjYW4gYmUKCQkJICogdXNlZCBpbiB0aGUgc3RyaW5nIGFuZCB3aWxsIGJlIGR5bmFtaWNhbGx5IHJlcGxhY2VkIGFzIHRoZSB0YWJsZQoJCQkgKiBkaXNwbGF5IHVwZGF0ZXMuIFRoaXMgdG9rZW5zIGNhbiBiZSBwbGFjZWQgYW55d2hlcmUgaW4gdGhlIHN0cmluZywgb3IKCQkJICogcmVtb3ZlZCBhcyBuZWVkZWQgYnkgdGhlIGxhbmd1YWdlIHJlcXVpcmVzOgoJCQkgKgoJCQkgKiAqIGBcX1NUQVJUXF9gIC0gRGlzcGxheSBpbmRleCBvZiB0aGUgZmlyc3QgcmVjb3JkIG9uIHRoZSBjdXJyZW50IHBhZ2UKCQkJICogKiBgXF9FTkRcX2AgLSBEaXNwbGF5IGluZGV4IG9mIHRoZSBsYXN0IHJlY29yZCBvbiB0aGUgY3VycmVudCBwYWdlCgkJCSAqICogYFxfVE9UQUxcX2AgLSBOdW1iZXIgb2YgcmVjb3JkcyBpbiB0aGUgdGFibGUgYWZ0ZXIgZmlsdGVyaW5nCgkJCSAqICogYFxfTUFYXF9gIC0gTnVtYmVyIG9mIHJlY29yZHMgaW4gdGhlIHRhYmxlIHdpdGhvdXQgZmlsdGVyaW5nCgkJCSAqICogYFxfUEFHRVxfYCAtIEN1cnJlbnQgcGFnZSBudW1iZXIKCQkJICogKiBgXF9QQUdFU1xfYCAtIFRvdGFsIG51bWJlciBvZiBwYWdlcyBvZiBkYXRhIGluIHRoZSB0YWJsZQoJCQkgKgoJCQkgKiAgQHR5cGUgc3RyaW5nCgkJCSAqICBAZGVmYXVsdCBTaG93aW5nIF9TVEFSVF8gdG8gX0VORF8gb2YgX1RPVEFMXyBlbnRyaWVzCgkJCSAqCgkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5pbmZvCgkJCSAqCgkJCSAqICBAZXhhbXBsZQoJCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJICogICAgICAgICAgImluZm8iOiAiU2hvd2luZyBwYWdlIF9QQUdFXyBvZiBfUEFHRVNfIgoJCQkgKiAgICAgICAgfQoJCQkgKiAgICAgIH0gKTsKCQkJICogICAgfSApOwoJCQkgKi8KCQkJInNJbmZvIjogIlNob3dpbmcgX1NUQVJUXyB0byBfRU5EXyBvZiBfVE9UQUxfIGVudHJpZXMiLAoJCgkKCQkJLyoqCgkJCSAqIERpc3BsYXkgaW5mb3JtYXRpb24gc3RyaW5nIGZvciB3aGVuIHRoZSB0YWJsZSBpcyBlbXB0eS4gVHlwaWNhbGx5IHRoZQoJCQkgKiBmb3JtYXQgb2YgdGhpcyBzdHJpbmcgc2hvdWxkIG1hdGNoIGBpbmZvYC4KCQkJICogIEB0eXBlIHN0cmluZwoJCQkgKiAgQGRlZmF1bHQgU2hvd2luZyAwIHRvIDAgb2YgMCBlbnRyaWVzCgkJCSAqCgkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5pbmZvRW1wdHkKCQkJICoKCQkJICogIEBleGFtcGxlCgkJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkgKiAgICAgICAgImxhbmd1YWdlIjogewoJCQkgKiAgICAgICAgICAiaW5mb0VtcHR5IjogIk5vIGVudHJpZXMgdG8gc2hvdyIKCQkJICogICAgICAgIH0KCQkJICogICAgICB9ICk7CgkJCSAqICAgIH0gKTsKCQkJICovCgkJCSJzSW5mb0VtcHR5IjogIlNob3dpbmcgMCB0byAwIG9mIDAgZW50cmllcyIsCgkKCQoJCQkvKioKCQkJICogV2hlbiBhIHVzZXIgZmlsdGVycyB0aGUgaW5mb3JtYXRpb24gaW4gYSB0YWJsZSwgdGhpcyBzdHJpbmcgaXMgYXBwZW5kZWQKCQkJICogdG8gdGhlIGluZm9ybWF0aW9uIChgaW5mb2ApIHRvIGdpdmUgYW4gaWRlYSBvZiBob3cgc3Ryb25nIHRoZSBmaWx0ZXJpbmcKCQkJICogaXMuIFRoZSB2YXJpYWJsZSBfTUFYXyBpcyBkeW5hbWljYWxseSB1cGRhdGVkLgoJCQkgKiAgQHR5cGUgc3RyaW5nCgkJCSAqICBAZGVmYXVsdCAoZmlsdGVyZWQgZnJvbSBfTUFYXyB0b3RhbCBlbnRyaWVzKQoJCQkgKgoJCQkgKiAgQGR0b3B0IExhbmd1YWdlCgkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UuaW5mb0ZpbHRlcmVkCgkJCSAqCgkJCSAqICBAZXhhbXBsZQoJCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJICogICAgICAgICAgImluZm9GaWx0ZXJlZCI6ICIgLSBmaWx0ZXJpbmcgZnJvbSBfTUFYXyByZWNvcmRzIgoJCQkgKiAgICAgICAgfQoJCQkgKiAgICAgIH0gKTsKCQkJICogICAgfSApOwoJCQkgKi8KCQkJInNJbmZvRmlsdGVyZWQiOiAiKGZpbHRlcmVkIGZyb20gX01BWF8gdG90YWwgZW50cmllcykiLAoJCgkKCQkJLyoqCgkJCSAqIElmIGNhbiBiZSB1c2VmdWwgdG8gYXBwZW5kIGV4dHJhIGluZm9ybWF0aW9uIHRvIHRoZSBpbmZvIHN0cmluZyBhdCB0aW1lcywKCQkJICogYW5kIHRoaXMgdmFyaWFibGUgZG9lcyBleGFjdGx5IHRoYXQuIFRoaXMgaW5mb3JtYXRpb24gd2lsbCBiZSBhcHBlbmRlZCB0bwoJCQkgKiB0aGUgYGluZm9gIChgaW5mb0VtcHR5YCBhbmQgYGluZm9GaWx0ZXJlZGAgaW4gd2hhdGV2ZXIgY29tYmluYXRpb24gdGhleSBhcmUKCQkJICogYmVpbmcgdXNlZCkgYXQgYWxsIHRpbWVzLgoJCQkgKiAgQHR5cGUgc3RyaW5nCgkJCSAqICBAZGVmYXVsdCA8aT5FbXB0eSBzdHJpbmc8L2k+CgkJCSAqCgkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5pbmZvUG9zdEZpeAoJCQkgKgoJCQkgKiAgQGV4YW1wbGUKCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJCSAqICAgICAgICAibGFuZ3VhZ2UiOiB7CgkJCSAqICAgICAgICAgICJpbmZvUG9zdEZpeCI6ICJBbGwgcmVjb3JkcyBzaG93biBhcmUgZGVyaXZlZCBmcm9tIHJlYWwgaW5mb3JtYXRpb24uIgoJCQkgKiAgICAgICAgfQoJCQkgKiAgICAgIH0gKTsKCQkJICogICAgfSApOwoJCQkgKi8KCQkJInNJbmZvUG9zdEZpeCI6ICIiLAoJCgkKCQkJLyoqCgkJCSAqIFRoaXMgZGVjaW1hbCBwbGFjZSBvcGVyYXRvciBpcyBhIGxpdHRsZSBkaWZmZXJlbnQgZnJvbSB0aGUgb3RoZXIKCQkJICogbGFuZ3VhZ2Ugb3B0aW9ucyBzaW5jZSBEYXRhVGFibGVzIGRvZXNuJ3Qgb3V0cHV0IGZsb2F0aW5nIHBvaW50CgkJCSAqIG51bWJlcnMsIHNvIGl0IHdvbid0IGV2ZXIgdXNlIHRoaXMgZm9yIGRpc3BsYXkgb2YgYSBudW1iZXIuIFJhdGhlciwKCQkJICogd2hhdCB0aGlzIHBhcmFtZXRlciBkb2VzIGlzIG1vZGlmeSB0aGUgc29ydCBtZXRob2RzIG9mIHRoZSB0YWJsZSBzbwoJCQkgKiB0aGF0IG51bWJlcnMgd2hpY2ggYXJlIGluIGEgZm9ybWF0IHdoaWNoIGhhcyBhIGNoYXJhY3RlciBvdGhlciB0aGFuCgkJCSAqIGEgcGVyaW9kIChgLmApIGFzIGEgZGVjaW1hbCBwbGFjZSB3aWxsIGJlIHNvcnRlZCBudW1lcmljYWxseS4KCQkJICoKCQkJICogTm90ZSB0aGF0IG51bWJlcnMgd2l0aCBkaWZmZXJlbnQgZGVjaW1hbCBwbGFjZXMgY2Fubm90IGJlIHNob3duIGluCgkJCSAqIHRoZSBzYW1lIHRhYmxlIGFuZCBzdGlsbCBiZSBzb3J0YWJsZSwgdGhlIHRhYmxlIG11c3QgYmUgY29uc2lzdGVudC4KCQkJICogSG93ZXZlciwgbXVsdGlwbGUgZGlmZmVyZW50IHRhYmxlcyBvbiB0aGUgcGFnZSBjYW4gdXNlIGRpZmZlcmVudAoJCQkgKiBkZWNpbWFsIHBsYWNlIGNoYXJhY3RlcnMuCgkJCSAqICBAdHlwZSBzdHJpbmcKCQkJICogIEBkZWZhdWx0IAoJCQkgKgoJCQkgKiAgQGR0b3B0IExhbmd1YWdlCgkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UuZGVjaW1hbAoJCQkgKgoJCQkgKiAgQGV4YW1wbGUKCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJCSAqICAgICAgICAibGFuZ3VhZ2UiOiB7CgkJCSAqICAgICAgICAgICJkZWNpbWFsIjogIiwiCgkJCSAqICAgICAgICAgICJ0aG91c2FuZHMiOiAiLiIKCQkJICogICAgICAgIH0KCQkJICogICAgICB9ICk7CgkJCSAqICAgIH0gKTsKCQkJICovCgkJCSJzRGVjaW1hbCI6ICIiLAoJCgkKCQkJLyoqCgkJCSAqIERhdGFUYWJsZXMgaGFzIGEgYnVpbGQgaW4gbnVtYmVyIGZvcm1hdHRlciAoYGZvcm1hdE51bWJlcmApIHdoaWNoIGlzCgkJCSAqIHVzZWQgdG8gZm9ybWF0IGxhcmdlIG51bWJlcnMgdGhhdCBhcmUgdXNlZCBpbiB0aGUgdGFibGUgaW5mb3JtYXRpb24uCgkJCSAqIEJ5IGRlZmF1bHQgYSBjb21tYSBpcyB1c2VkLCBidXQgdGhpcyBjYW4gYmUgdHJpdmlhbGx5IGNoYW5nZWQgdG8gYW55CgkJCSAqIGNoYXJhY3RlciB5b3Ugd2lzaCB3aXRoIHRoaXMgcGFyYW1ldGVyLgoJCQkgKiAgQHR5cGUgc3RyaW5nCgkJCSAqICBAZGVmYXVsdCAsCgkJCSAqCgkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS50aG91c2FuZHMKCQkJICoKCQkJICogIEBleGFtcGxlCgkJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkgKiAgICAgICAgImxhbmd1YWdlIjogewoJCQkgKiAgICAgICAgICAidGhvdXNhbmRzIjogIiciCgkJCSAqICAgICAgICB9CgkJCSAqICAgICAgfSApOwoJCQkgKiAgICB9ICk7CgkJCSAqLwoJCQkic1Rob3VzYW5kcyI6ICIsIiwKCQoJCgkJCS8qKgoJCQkgKiBEZXRhaWwgdGhlIGFjdGlvbiB0aGF0IHdpbGwgYmUgdGFrZW4gd2hlbiB0aGUgZHJvcCBkb3duIG1lbnUgZm9yIHRoZQoJCQkgKiBwYWdpbmF0aW9uIGxlbmd0aCBvcHRpb24gaXMgY2hhbmdlZC4gVGhlICdfTUVOVV8nIHZhcmlhYmxlIGlzIHJlcGxhY2VkCgkJCSAqIHdpdGggYSBkZWZhdWx0IHNlbGVjdCBsaXN0IG9mIDEwLCAyNSwgNTAgYW5kIDEwMCwgYW5kIGNhbiBiZSByZXBsYWNlZAoJCQkgKiB3aXRoIGEgY3VzdG9tIHNlbGVjdCBib3ggaWYgcmVxdWlyZWQuCgkJCSAqICBAdHlwZSBzdHJpbmcKCQkJICogIEBkZWZhdWx0IFNob3cgX01FTlVfIGVudHJpZXMKCQkJICoKCQkJICogIEBkdG9wdCBMYW5ndWFnZQoJCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLmxlbmd0aE1lbnUKCQkJICoKCQkJICogIEBleGFtcGxlCgkJCSAqICAgIC8vIExhbmd1YWdlIGNoYW5nZSBvbmx5CgkJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkgKiAgICAgICAgImxhbmd1YWdlIjogewoJCQkgKiAgICAgICAgICAibGVuZ3RoTWVudSI6ICJEaXNwbGF5IF9NRU5VXyByZWNvcmRzIgoJCQkgKiAgICAgICAgfQoJCQkgKiAgICAgIH0gKTsKCQkJICogICAgfSApOwoJCQkgKgoJCQkgKiAgQGV4YW1wbGUKCQkJICogICAgLy8gTGFuZ3VhZ2UgYW5kIG9wdGlvbnMgY2hhbmdlCgkJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkgKiAgICAgICAgImxhbmd1YWdlIjogewoJCQkgKiAgICAgICAgICAibGVuZ3RoTWVudSI6ICdEaXNwbGF5IDxzZWxlY3Q+JysKCQkJICogICAgICAgICAgICAnPG9wdGlvbiB2YWx1ZT0iMTAiPjEwPC9vcHRpb24+JysKCQkJICogICAgICAgICAgICAnPG9wdGlvbiB2YWx1ZT0iMjAiPjIwPC9vcHRpb24+JysKCQkJICogICAgICAgICAgICAnPG9wdGlvbiB2YWx1ZT0iMzAiPjMwPC9vcHRpb24+JysKCQkJICogICAgICAgICAgICAnPG9wdGlvbiB2YWx1ZT0iNDAiPjQwPC9vcHRpb24+JysKCQkJICogICAgICAgICAgICAnPG9wdGlvbiB2YWx1ZT0iNTAiPjUwPC9vcHRpb24+JysKCQkJICogICAgICAgICAgICAnPG9wdGlvbiB2YWx1ZT0iLTEiPkFsbDwvb3B0aW9uPicrCgkJCSAqICAgICAgICAgICAgJzwvc2VsZWN0PiByZWNvcmRzJwoJCQkgKiAgICAgICAgfQoJCQkgKiAgICAgIH0gKTsKCQkJICogICAgfSApOwoJCQkgKi8KCQkJInNMZW5ndGhNZW51IjogIlNob3cgX01FTlVfIGVudHJpZXMiLAoJCgkKCQkJLyoqCgkJCSAqIFdoZW4gdXNpbmcgQWpheCBzb3VyY2VkIGRhdGEgYW5kIGR1cmluZyB0aGUgZmlyc3QgZHJhdyB3aGVuIERhdGFUYWJsZXMgaXMKCQkJICogZ2F0aGVyaW5nIHRoZSBkYXRhLCB0aGlzIG1lc3NhZ2UgaXMgc2hvd24gaW4gYW4gZW1wdHkgcm93IGluIHRoZSB0YWJsZSB0bwoJCQkgKiBpbmRpY2F0ZSB0byB0aGUgZW5kIHVzZXIgdGhlIHRoZSBkYXRhIGlzIGJlaW5nIGxvYWRlZC4gTm90ZSB0aGF0IHRoaXMKCQkJICogcGFyYW1ldGVyIGlzIG5vdCB1c2VkIHdoZW4gbG9hZGluZyBkYXRhIGJ5IHNlcnZlci1zaWRlIHByb2Nlc3NpbmcsIGp1c3QKCQkJICogQWpheCBzb3VyY2VkIGRhdGEgd2l0aCBjbGllbnQtc2lkZSBwcm9jZXNzaW5nLgoJCQkgKiAgQHR5cGUgc3RyaW5nCgkJCSAqICBAZGVmYXVsdCBMb2FkaW5nLi4uCgkJCSAqCgkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5sb2FkaW5nUmVjb3JkcwoJCQkgKgoJCQkgKiAgQGV4YW1wbGUKCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJCSAqICAgICAgICAibGFuZ3VhZ2UiOiB7CgkJCSAqICAgICAgICAgICJsb2FkaW5nUmVjb3JkcyI6ICJQbGVhc2Ugd2FpdCAtIGxvYWRpbmcuLi4iCgkJCSAqICAgICAgICB9CgkJCSAqICAgICAgfSApOwoJCQkgKiAgICB9ICk7CgkJCSAqLwoJCQkic0xvYWRpbmdSZWNvcmRzIjogIkxvYWRpbmcuLi4iLAoJCgkKCQkJLyoqCgkJCSAqIFRleHQgd2hpY2ggaXMgZGlzcGxheWVkIHdoZW4gdGhlIHRhYmxlIGlzIHByb2Nlc3NpbmcgYSB1c2VyIGFjdGlvbgoJCQkgKiAodXN1YWxseSBhIHNvcnQgY29tbWFuZCBvciBzaW1pbGFyKS4KCQkJICogIEB0eXBlIHN0cmluZwoJCQkgKgoJCQkgKiAgQGR0b3B0IExhbmd1YWdlCgkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UucHJvY2Vzc2luZwoJCQkgKgoJCQkgKiAgQGV4YW1wbGUKCQkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJCSAqICAgICAgICAibGFuZ3VhZ2UiOiB7CgkJCSAqICAgICAgICAgICJwcm9jZXNzaW5nIjogIkRhdGFUYWJsZXMgaXMgY3VycmVudGx5IGJ1c3kiCgkJCSAqICAgICAgICB9CgkJCSAqICAgICAgfSApOwoJCQkgKiAgICB9ICk7CgkJCSAqLwoJCQkic1Byb2Nlc3NpbmciOiAiIiwKCQoJCgkJCS8qKgoJCQkgKiBEZXRhaWxzIHRoZSBhY3Rpb25zIHRoYXQgd2lsbCBiZSB0YWtlbiB3aGVuIHRoZSB1c2VyIHR5cGVzIGludG8gdGhlCgkJCSAqIGZpbHRlcmluZyBpbnB1dCB0ZXh0IGJveC4gVGhlIHZhcmlhYmxlICJfSU5QVVRfIiwgaWYgdXNlZCBpbiB0aGUgc3RyaW5nLAoJCQkgKiBpcyByZXBsYWNlZCB3aXRoIHRoZSBIVE1MIHRleHQgYm94IGZvciB0aGUgZmlsdGVyaW5nIGlucHV0IGFsbG93aW5nCgkJCSAqIGNvbnRyb2wgb3ZlciB3aGVyZSBpdCBhcHBlYXJzIGluIHRoZSBzdHJpbmcuIElmICJfSU5QVVRfIiBpcyBub3QgZ2l2ZW4KCQkJICogdGhlbiB0aGUgaW5wdXQgYm94IGlzIGFwcGVuZGVkIHRvIHRoZSBzdHJpbmcgYXV0b21hdGljYWxseS4KCQkJICogIEB0eXBlIHN0cmluZwoJCQkgKiAgQGRlZmF1bHQgU2VhcmNoOgoJCQkgKgoJCQkgKiAgQGR0b3B0IExhbmd1YWdlCgkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2Uuc2VhcmNoCgkJCSAqCgkJCSAqICBAZXhhbXBsZQoJCQkgKiAgICAvLyBJbnB1dCB0ZXh0IGJveCB3aWxsIGJlIGFwcGVuZGVkIGF0IHRoZSBlbmQgYXV0b21hdGljYWxseQoJCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJICogICAgICAgICAgInNlYXJjaCI6ICJGaWx0ZXIgcmVjb3JkczoiCgkJCSAqICAgICAgICB9CgkJCSAqICAgICAgfSApOwoJCQkgKiAgICB9ICk7CgkJCSAqCgkJCSAqICBAZXhhbXBsZQoJCQkgKiAgICAvLyBTcGVjaWZ5IHdoZXJlIHRoZSBmaWx0ZXIgc2hvdWxkIGFwcGVhcgoJCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJICogICAgICAgICAgInNlYXJjaCI6ICJBcHBseSBmaWx0ZXIgX0lOUFVUXyB0byB0YWJsZSIKCQkJICogICAgICAgIH0KCQkJICogICAgICB9ICk7CgkJCSAqICAgIH0gKTsKCQkJICovCgkJCSJzU2VhcmNoIjogIlNlYXJjaDoiLAoJCgkKCQkJLyoqCgkJCSAqIEFzc2lnbiBhIGBwbGFjZWhvbGRlcmAgYXR0cmlidXRlIHRvIHRoZSBzZWFyY2ggYGlucHV0YCBlbGVtZW50CgkJCSAqICBAdHlwZSBzdHJpbmcKCQkJICogIEBkZWZhdWx0IAoJCQkgKgoJCQkgKiAgQGR0b3B0IExhbmd1YWdlCgkJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2Uuc2VhcmNoUGxhY2Vob2xkZXIKCQkJICovCgkJCSJzU2VhcmNoUGxhY2Vob2xkZXIiOiAiIiwKCQoJCgkJCS8qKgoJCQkgKiBBbGwgb2YgdGhlIGxhbmd1YWdlIGluZm9ybWF0aW9uIGNhbiBiZSBzdG9yZWQgaW4gYSBmaWxlIG9uIHRoZQoJCQkgKiBzZXJ2ZXItc2lkZSwgd2hpY2ggRGF0YVRhYmxlcyB3aWxsIGxvb2sgdXAgaWYgdGhpcyBwYXJhbWV0ZXIgaXMgcGFzc2VkLgoJCQkgKiBJdCBtdXN0IHN0b3JlIHRoZSBVUkwgb2YgdGhlIGxhbmd1YWdlIGZpbGUsIHdoaWNoIGlzIGluIGEgSlNPTiBmb3JtYXQsCgkJCSAqIGFuZCB0aGUgb2JqZWN0IGhhcyB0aGUgc2FtZSBwcm9wZXJ0aWVzIGFzIHRoZSBvTGFuZ3VhZ2Ugb2JqZWN0IGluIHRoZQoJCQkgKiBpbml0aWFsaXNlciBvYmplY3QgKGkuZS4gdGhlIGFib3ZlIHBhcmFtZXRlcnMpLiBQbGVhc2UgcmVmZXIgdG8gb25lIG9mCgkJCSAqIHRoZSBleGFtcGxlIGxhbmd1YWdlIGZpbGVzIHRvIHNlZSBob3cgdGhpcyB3b3JrcyBpbiBhY3Rpb24uCgkJCSAqICBAdHlwZSBzdHJpbmcKCQkJICogIEBkZWZhdWx0IDxpPkVtcHR5IHN0cmluZyAtIGkuZS4gZGlzYWJsZWQ8L2k+CgkJCSAqCgkJCSAqICBAZHRvcHQgTGFuZ3VhZ2UKCQkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS51cmwKCQkJICoKCQkJICogIEBleGFtcGxlCgkJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCQkgKiAgICAgICAgImxhbmd1YWdlIjogewoJCQkgKiAgICAgICAgICAidXJsIjogImh0dHA6Ly93d3cuc3ByeW1lZGlhLmNvLnVrL2RhdGFUYWJsZXMvbGFuZy50eHQiCgkJCSAqICAgICAgICB9CgkJCSAqICAgICAgfSApOwoJCQkgKiAgICB9ICk7CgkJCSAqLwoJCQkic1VybCI6ICIiLAoJCgkKCQkJLyoqCgkJCSAqIFRleHQgc2hvd24gaW5zaWRlIHRoZSB0YWJsZSByZWNvcmRzIHdoZW4gdGhlIGlzIG5vIGluZm9ybWF0aW9uIHRvIGJlCgkJCSAqIGRpc3BsYXllZCBhZnRlciBmaWx0ZXJpbmcuIGBlbXB0eVRhYmxlYCBpcyBzaG93biB3aGVuIHRoZXJlIGlzIHNpbXBseSBubwoJCQkgKiBpbmZvcm1hdGlvbiBpbiB0aGUgdGFibGUgYXQgYWxsIChyZWdhcmRsZXNzIG9mIGZpbHRlcmluZykuCgkJCSAqICBAdHlwZSBzdHJpbmcKCQkJICogIEBkZWZhdWx0IE5vIG1hdGNoaW5nIHJlY29yZHMgZm91bmQKCQkJICoKCQkJICogIEBkdG9wdCBMYW5ndWFnZQoJCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLnplcm9SZWNvcmRzCgkJCSAqCgkJCSAqICBAZXhhbXBsZQoJCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkJICogICAgICAgICJsYW5ndWFnZSI6IHsKCQkJICogICAgICAgICAgInplcm9SZWNvcmRzIjogIk5vIHJlY29yZHMgdG8gZGlzcGxheSIKCQkJICogICAgICAgIH0KCQkJICogICAgICB9ICk7CgkJCSAqICAgIH0gKTsKCQkJICovCgkJCSJzWmVyb1JlY29yZHMiOiAiTm8gbWF0Y2hpbmcgcmVjb3JkcyBmb3VuZCIKCQl9LAoJCgkKCQkvKioKCQkgKiBUaGlzIHBhcmFtZXRlciBhbGxvd3MgeW91IHRvIGhhdmUgZGVmaW5lIHRoZSBnbG9iYWwgZmlsdGVyaW5nIHN0YXRlIGF0CgkJICogaW5pdGlhbGlzYXRpb24gdGltZS4gQXMgYW4gb2JqZWN0IHRoZSBgc2VhcmNoYCBwYXJhbWV0ZXIgbXVzdCBiZQoJCSAqIGRlZmluZWQsIGJ1dCBhbGwgb3RoZXIgcGFyYW1ldGVycyBhcmUgb3B0aW9uYWwuIFdoZW4gYHJlZ2V4YCBpcyB0cnVlLAoJCSAqIHRoZSBzZWFyY2ggc3RyaW5nIHdpbGwgYmUgdHJlYXRlZCBhcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiwgd2hlbiBmYWxzZQoJCSAqIChkZWZhdWx0KSBpdCB3aWxsIGJlIHRyZWF0ZWQgYXMgYSBzdHJhaWdodCBzdHJpbmcuIFdoZW4gYHNtYXJ0YAoJCSAqIERhdGFUYWJsZXMgd2lsbCB1c2UgaXQncyBzbWFydCBmaWx0ZXJpbmcgbWV0aG9kcyAodG8gd29yZCBtYXRjaCBhdAoJCSAqIGFueSBwb2ludCBpbiB0aGUgZGF0YSksIHdoZW4gZmFsc2UgdGhpcyB3aWxsIG5vdCBiZSBkb25lLgoJCSAqICBAbmFtZXNwYWNlCgkJICogIEBleHRlbmRzIERhdGFUYWJsZS5tb2RlbHMub1NlYXJjaAoJCSAqCgkJICogIEBkdG9wdCBPcHRpb25zCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zZWFyY2gKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJzZWFyY2giOiB7InNlYXJjaCI6ICJJbml0aWFsIHNlYXJjaCJ9CgkJICogICAgICB9ICk7CgkJICogICAgfSApCgkJICovCgkJIm9TZWFyY2giOiAkLmV4dGVuZCgge30sIERhdGFUYWJsZS5tb2RlbHMub1NlYXJjaCApLAoJCgkKCQkvKioKCQkgKiBfX0RlcHJlY2F0ZWRfXyBUaGUgZnVuY3Rpb25hbGl0eSBwcm92aWRlZCBieSB0aGlzIHBhcmFtZXRlciBoYXMgbm93IGJlZW4KCQkgKiBzdXBlcnNlZGVkIGJ5IHRoYXQgcHJvdmlkZWQgdGhyb3VnaCBgYWpheGAsIHdoaWNoIHNob3VsZCBiZSB1c2VkIGluc3RlYWQuCgkJICoKCQkgKiBCeSBkZWZhdWx0IERhdGFUYWJsZXMgd2lsbCBsb29rIGZvciB0aGUgcHJvcGVydHkgYGRhdGFgIChvciBgYWFEYXRhYCBmb3IKCQkgKiBjb21wYXRpYmlsaXR5IHdpdGggRGF0YVRhYmxlcyAxLjktKSB3aGVuIG9idGFpbmluZyBkYXRhIGZyb20gYW4gQWpheAoJCSAqIHNvdXJjZSBvciBmb3Igc2VydmVyLXNpZGUgcHJvY2Vzc2luZyAtIHRoaXMgcGFyYW1ldGVyIGFsbG93cyB0aGF0CgkJICogcHJvcGVydHkgdG8gYmUgY2hhbmdlZC4gWW91IGNhbiB1c2UgSmF2YXNjcmlwdCBkb3R0ZWQgb2JqZWN0IG5vdGF0aW9uIHRvCgkJICogZ2V0IGEgZGF0YSBzb3VyY2UgZm9yIG11bHRpcGxlIGxldmVscyBvZiBuZXN0aW5nLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgZGF0YQoJCSAqCgkJICogIEBkdG9wdCBPcHRpb25zCgkJICogIEBkdG9wdCBTZXJ2ZXItc2lkZQoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuYWpheERhdGFQcm9wCgkJICoKCQkgKiAgQGRlcHJlY2F0ZWQgMS4xMC4gUGxlYXNlIHVzZSBgYWpheGAgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSBub3cuCgkJICovCgkJInNBamF4RGF0YVByb3AiOiAiZGF0YSIsCgkKCQoJCS8qKgoJCSAqIF9fRGVwcmVjYXRlZF9fIFRoZSBmdW5jdGlvbmFsaXR5IHByb3ZpZGVkIGJ5IHRoaXMgcGFyYW1ldGVyIGhhcyBub3cgYmVlbgoJCSAqIHN1cGVyc2VkZWQgYnkgdGhhdCBwcm92aWRlZCB0aHJvdWdoIGBhamF4YCwgd2hpY2ggc2hvdWxkIGJlIHVzZWQgaW5zdGVhZC4KCQkgKgoJCSAqIFlvdSBjYW4gaW5zdHJ1Y3QgRGF0YVRhYmxlcyB0byBsb2FkIGRhdGEgZnJvbSBhbiBleHRlcm5hbAoJCSAqIHNvdXJjZSB1c2luZyB0aGlzIHBhcmFtZXRlciAodXNlIGFEYXRhIGlmIHlvdSB3YW50IHRvIHBhc3MgZGF0YSBpbiB5b3UKCQkgKiBhbHJlYWR5IGhhdmUpLiBTaW1wbHkgcHJvdmlkZSBhIHVybCBhIEpTT04gb2JqZWN0IGNhbiBiZSBvYnRhaW5lZCBmcm9tLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqCgkJICogIEBkdG9wdCBPcHRpb25zCgkJICogIEBkdG9wdCBTZXJ2ZXItc2lkZQoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuYWpheFNvdXJjZQoJCSAqCgkJICogIEBkZXByZWNhdGVkIDEuMTAuIFBsZWFzZSB1c2UgYGFqYXhgIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHkgbm93LgoJCSAqLwoJCSJzQWpheFNvdXJjZSI6IG51bGwsCgkKCQoJCS8qKgoJCSAqIFRoaXMgaW5pdGlhbGlzYXRpb24gdmFyaWFibGUgYWxsb3dzIHlvdSB0byBzcGVjaWZ5IGV4YWN0bHkgd2hlcmUgaW4gdGhlCgkJICogRE9NIHlvdSB3YW50IERhdGFUYWJsZXMgdG8gaW5qZWN0IHRoZSB2YXJpb3VzIGNvbnRyb2xzIGl0IGFkZHMgdG8gdGhlIHBhZ2UKCQkgKiAoZm9yIGV4YW1wbGUgeW91IG1pZ2h0IHdhbnQgdGhlIHBhZ2luYXRpb24gY29udHJvbHMgYXQgdGhlIHRvcCBvZiB0aGUKCQkgKiB0YWJsZSkuIERJViBlbGVtZW50cyAod2l0aCBvciB3aXRob3V0IGEgY3VzdG9tIGNsYXNzKSBjYW4gYWxzbyBiZSBhZGRlZCB0bwoJCSAqIGFpZCBzdHlsaW5nLiBUaGUgZm9sbG93IHN5bnRheCBpcyB1c2VkOgoJCSAqICAgPHVsPgoJCSAqICAgICA8bGk+VGhlIGZvbGxvd2luZyBvcHRpb25zIGFyZSBhbGxvd2VkOgoJCSAqICAgICAgIDx1bD4KCQkgKiAgICAgICAgIDxsaT4nbCcgLSBMZW5ndGggY2hhbmdpbmc8L2xpPgoJCSAqICAgICAgICAgPGxpPidmJyAtIEZpbHRlcmluZyBpbnB1dDwvbGk+CgkJICogICAgICAgICA8bGk+J3QnIC0gVGhlIHRhYmxlITwvbGk+CgkJICogICAgICAgICA8bGk+J2knIC0gSW5mb3JtYXRpb248L2xpPgoJCSAqICAgICAgICAgPGxpPidwJyAtIFBhZ2luYXRpb248L2xpPgoJCSAqICAgICAgICAgPGxpPidyJyAtIHBSb2Nlc3Npbmc8L2xpPgoJCSAqICAgICAgIDwvdWw+CgkJICogICAgIDwvbGk+CgkJICogICAgIDxsaT5UaGUgZm9sbG93aW5nIGNvbnN0YW50cyBhcmUgYWxsb3dlZDoKCQkgKiAgICAgICA8dWw+CgkJICogICAgICAgICA8bGk+J0gnIC0galF1ZXJ5VUkgdGhlbWUgImhlYWRlciIgY2xhc3NlcyAoJ2ZnLXRvb2xiYXIgdWktd2lkZ2V0LWhlYWRlciB1aS1jb3JuZXItdGwgdWktY29ybmVyLXRyIHVpLWhlbHBlci1jbGVhcmZpeCcpPC9saT4KCQkgKiAgICAgICAgIDxsaT4nRicgLSBqUXVlcnlVSSB0aGVtZSAiZm9vdGVyIiBjbGFzc2VzICgnZmctdG9vbGJhciB1aS13aWRnZXQtaGVhZGVyIHVpLWNvcm5lci1ibCB1aS1jb3JuZXItYnIgdWktaGVscGVyLWNsZWFyZml4Jyk8L2xpPgoJCSAqICAgICAgIDwvdWw+CgkJICogICAgIDwvbGk+CgkJICogICAgIDxsaT5UaGUgZm9sbG93aW5nIHN5bnRheCBpcyBleHBlY3RlZDoKCQkgKiAgICAgICA8dWw+CgkJICogICAgICAgICA8bGk+JyZsdDsnIGFuZCAnJmd0OycgLSBkaXYgZWxlbWVudHM8L2xpPgoJCSAqICAgICAgICAgPGxpPicmbHQ7ImNsYXNzIiBhbmQgJyZndDsnIC0gZGl2IHdpdGggYSBjbGFzczwvbGk+CgkJICogICAgICAgICA8bGk+JyZsdDsiI2lkIiBhbmQgJyZndDsnIC0gZGl2IHdpdGggYW4gSUQ8L2xpPgoJCSAqICAgICAgIDwvdWw+CgkJICogICAgIDwvbGk+CgkJICogICAgIDxsaT5FeGFtcGxlczoKCQkgKiAgICAgICA8dWw+CgkJICogICAgICAgICA8bGk+JyZsdDsid3JhcHBlciJmbGlwdCZndDsnPC9saT4KCQkgKiAgICAgICAgIDxsaT4nJmx0O2xmJmx0O3QmZ3Q7aXAmZ3Q7JzwvbGk+CgkJICogICAgICAgPC91bD4KCQkgKiAgICAgPC9saT4KCQkgKiAgIDwvdWw+CgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCBsZnJ0aXAgPGk+KHdoZW4gYGpRdWVyeVVJYCBpcyBmYWxzZSk8L2k+IDxiPm9yPC9iPgoJCSAqICAgIDwiSCJsZnI+dDwiRiJpcD4gPGk+KHdoZW4gYGpRdWVyeVVJYCBpcyB0cnVlKTwvaT4KCQkgKgoJCSAqICBAZHRvcHQgT3B0aW9ucwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuZG9tCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiZG9tIjogJyZsdDsidG9wImkmZ3Q7cnQmbHQ7ImJvdHRvbSJmbHAmZ3Q7Jmx0OyJjbGVhciImZ3Q7JwoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic0RvbSI6ICJsZnJ0aXAiLAoJCgkKCQkvKioKCQkgKiBTZWFyY2ggZGVsYXkgb3B0aW9uLiBUaGlzIHdpbGwgdGhyb3R0bGUgZnVsbCB0YWJsZSBzZWFyY2hlcyB0aGF0IHVzZSB0aGUKCQkgKiBEYXRhVGFibGVzIHByb3ZpZGVkIHNlYXJjaCBpbnB1dCBlbGVtZW50IChpdCBkb2VzIG5vdCBlZmZlY3QgY2FsbHMgdG8KCQkgKiBgZHQtYXBpIHNlYXJjaCgpYCwgcHJvdmlkaW5nIGEgZGVsYXkgYmVmb3JlIHRoZSBzZWFyY2ggaXMgbWFkZS4KCQkgKiAgQHR5cGUgaW50ZWdlcgoJCSAqICBAZGVmYXVsdCAwCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbnMKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNlYXJjaERlbGF5CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic2VhcmNoRGVsYXkiOiAyMDAKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICkKCQkgKi8KCQkic2VhcmNoRGVsYXkiOiBudWxsLAoJCgkKCQkvKioKCQkgKiBEYXRhVGFibGVzIGZlYXR1cmVzIHNpeCBkaWZmZXJlbnQgYnVpbHQtaW4gb3B0aW9ucyBmb3IgdGhlIGJ1dHRvbnMgdG8KCQkgKiBkaXNwbGF5IGZvciBwYWdpbmF0aW9uIGNvbnRyb2w6CgkJICoKCQkgKiAqIGBudW1iZXJzYCAtIFBhZ2UgbnVtYmVyIGJ1dHRvbnMgb25seQoJCSAqICogYHNpbXBsZWAgLSAnUHJldmlvdXMnIGFuZCAnTmV4dCcgYnV0dG9ucyBvbmx5CgkJICogKiAnc2ltcGxlX251bWJlcnNgIC0gJ1ByZXZpb3VzJyBhbmQgJ05leHQnIGJ1dHRvbnMsIHBsdXMgcGFnZSBudW1iZXJzCgkJICogKiBgZnVsbGAgLSAnRmlyc3QnLCAnUHJldmlvdXMnLCAnTmV4dCcgYW5kICdMYXN0JyBidXR0b25zCgkJICogKiBgZnVsbF9udW1iZXJzYCAtICdGaXJzdCcsICdQcmV2aW91cycsICdOZXh0JyBhbmQgJ0xhc3QnIGJ1dHRvbnMsIHBsdXMgcGFnZSBudW1iZXJzCgkJICogKiBgZmlyc3RfbGFzdF9udW1iZXJzYCAtICdGaXJzdCcgYW5kICdMYXN0JyBidXR0b25zLCBwbHVzIHBhZ2UgbnVtYmVycwoJCSAqICAKCQkgKiBGdXJ0aGVyIG1ldGhvZHMgY2FuIGJlIGFkZGVkIHVzaW5nIHtAbGluayBEYXRhVGFibGUuZXh0Lm9QYWdpbmF0aW9ufS4KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IHNpbXBsZV9udW1iZXJzCgkJICoKCQkgKiAgQGR0b3B0IE9wdGlvbnMKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnBhZ2luZ1R5cGUKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJwYWdpbmdUeXBlIjogImZ1bGxfbnVtYmVycyIKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICkKCQkgKi8KCQkic1BhZ2luYXRpb25UeXBlIjogInNpbXBsZV9udW1iZXJzIiwKCQoJCgkJLyoqCgkJICogRW5hYmxlIGhvcml6b250YWwgc2Nyb2xsaW5nLiBXaGVuIGEgdGFibGUgaXMgdG9vIHdpZGUgdG8gZml0IGludG8gYQoJCSAqIGNlcnRhaW4gbGF5b3V0LCBvciB5b3UgaGF2ZSBhIGxhcmdlIG51bWJlciBvZiBjb2x1bW5zIGluIHRoZSB0YWJsZSwgeW91CgkJICogY2FuIGVuYWJsZSB4LXNjcm9sbGluZyB0byBzaG93IHRoZSB0YWJsZSBpbiBhIHZpZXdwb3J0LCB3aGljaCBjYW4gYmUKCQkgKiBzY3JvbGxlZC4gVGhpcyBwcm9wZXJ0eSBjYW4gYmUgYHRydWVgIHdoaWNoIHdpbGwgYWxsb3cgdGhlIHRhYmxlIHRvCgkJICogc2Nyb2xsIGhvcml6b250YWxseSB3aGVuIG5lZWRlZCwgb3IgYW55IENTUyB1bml0LCBvciBhIG51bWJlciAoaW4gd2hpY2gKCQkgKiBjYXNlIGl0IHdpbGwgYmUgdHJlYXRlZCBhcyBhIHBpeGVsIG1lYXN1cmVtZW50KS4gU2V0dGluZyBhcyBzaW1wbHkgYHRydWVgCgkJICogaXMgcmVjb21tZW5kZWQuCgkJICogIEB0eXBlIGJvb2xlYW58c3RyaW5nCgkJICogIEBkZWZhdWx0IDxpPmJsYW5rIHN0cmluZyAtIGkuZS4gZGlzYWJsZWQ8L2k+CgkJICoKCQkgKiAgQGR0b3B0IEZlYXR1cmVzCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zY3JvbGxYCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic2Nyb2xsWCI6IHRydWUsCgkJICogICAgICAgICJzY3JvbGxDb2xsYXBzZSI6IHRydWUKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJInNTY3JvbGxYIjogIiIsCgkKCQoJCS8qKgoJCSAqIFRoaXMgcHJvcGVydHkgY2FuIGJlIHVzZWQgdG8gZm9yY2UgYSBEYXRhVGFibGUgdG8gdXNlIG1vcmUgd2lkdGggdGhhbiBpdAoJCSAqIG1pZ2h0IG90aGVyd2lzZSBkbyB3aGVuIHgtc2Nyb2xsaW5nIGlzIGVuYWJsZWQuIEZvciBleGFtcGxlIGlmIHlvdSBoYXZlIGEKCQkgKiB0YWJsZSB3aGljaCByZXF1aXJlcyB0byBiZSB3ZWxsIHNwYWNlZCwgdGhpcyBwYXJhbWV0ZXIgaXMgdXNlZnVsIGZvcgoJCSAqICJvdmVyLXNpemluZyIgdGhlIHRhYmxlLCBhbmQgdGh1cyBmb3JjaW5nIHNjcm9sbGluZy4gVGhpcyBwcm9wZXJ0eSBjYW4gYnkKCQkgKiBhbnkgQ1NTIHVuaXQsIG9yIGEgbnVtYmVyIChpbiB3aGljaCBjYXNlIGl0IHdpbGwgYmUgdHJlYXRlZCBhcyBhIHBpeGVsCgkJICogbWVhc3VyZW1lbnQpLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgPGk+Ymxhbmsgc3RyaW5nIC0gaS5lLiBkaXNhYmxlZDwvaT4KCQkgKgoJCSAqICBAZHRvcHQgT3B0aW9ucwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc2Nyb2xsWElubmVyCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAic2Nyb2xsWCI6ICIxMDAlIiwKCQkgKiAgICAgICAgInNjcm9sbFhJbm5lciI6ICIxMTAlIgoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic1Njcm9sbFhJbm5lciI6ICIiLAoJCgkKCQkvKioKCQkgKiBFbmFibGUgdmVydGljYWwgc2Nyb2xsaW5nLiBWZXJ0aWNhbCBzY3JvbGxpbmcgd2lsbCBjb25zdHJhaW4gdGhlIERhdGFUYWJsZQoJCSAqIHRvIHRoZSBnaXZlbiBoZWlnaHQsIGFuZCBlbmFibGUgc2Nyb2xsaW5nIGZvciBhbnkgZGF0YSB3aGljaCBvdmVyZmxvd3MgdGhlCgkJICogY3VycmVudCB2aWV3cG9ydC4gVGhpcyBjYW4gYmUgdXNlZCBhcyBhbiBhbHRlcm5hdGl2ZSB0byBwYWdpbmcgdG8gZGlzcGxheQoJCSAqIGEgbG90IG9mIGRhdGEgaW4gYSBzbWFsbCBhcmVhIChhbHRob3VnaCBwYWdpbmcgYW5kIHNjcm9sbGluZyBjYW4gYm90aCBiZQoJCSAqIGVuYWJsZWQgYXQgdGhlIHNhbWUgdGltZSkuIFRoaXMgcHJvcGVydHkgY2FuIGJlIGFueSBDU1MgdW5pdCwgb3IgYSBudW1iZXIKCQkgKiAoaW4gd2hpY2ggY2FzZSBpdCB3aWxsIGJlIHRyZWF0ZWQgYXMgYSBwaXhlbCBtZWFzdXJlbWVudCkuCgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCA8aT5ibGFuayBzdHJpbmcgLSBpLmUuIGRpc2FibGVkPC9pPgoJCSAqCgkJICogIEBkdG9wdCBGZWF0dXJlcwoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc2Nyb2xsWQoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgInNjcm9sbFkiOiAiMjAwcHgiLAoJCSAqICAgICAgICAicGFnaW5hdGUiOiBmYWxzZQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic1Njcm9sbFkiOiAiIiwKCQoJCgkJLyoqCgkJICogX19EZXByZWNhdGVkX18gVGhlIGZ1bmN0aW9uYWxpdHkgcHJvdmlkZWQgYnkgdGhpcyBwYXJhbWV0ZXIgaGFzIG5vdyBiZWVuCgkJICogc3VwZXJzZWRlZCBieSB0aGF0IHByb3ZpZGVkIHRocm91Z2ggYGFqYXhgLCB3aGljaCBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkLgoJCSAqCgkJICogU2V0IHRoZSBIVFRQIG1ldGhvZCB0aGF0IGlzIHVzZWQgdG8gbWFrZSB0aGUgQWpheCBjYWxsIGZvciBzZXJ2ZXItc2lkZQoJCSAqIHByb2Nlc3Npbmcgb3IgQWpheCBzb3VyY2VkIGRhdGEuCgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCBHRVQKCQkgKgoJCSAqICBAZHRvcHQgT3B0aW9ucwoJCSAqICBAZHRvcHQgU2VydmVyLXNpZGUKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNlcnZlck1ldGhvZAoJCSAqCgkJICogIEBkZXByZWNhdGVkIDEuMTAuIFBsZWFzZSB1c2UgYGFqYXhgIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHkgbm93LgoJCSAqLwoJCSJzU2VydmVyTWV0aG9kIjogIkdFVCIsCgkKCQoJCS8qKgoJCSAqIERhdGFUYWJsZXMgbWFrZXMgdXNlIG9mIHJlbmRlcmVycyB3aGVuIGRpc3BsYXlpbmcgSFRNTCBlbGVtZW50cyBmb3IKCQkgKiBhIHRhYmxlLiBUaGVzZSByZW5kZXJlcnMgY2FuIGJlIGFkZGVkIG9yIG1vZGlmaWVkIGJ5IHBsdWctaW5zIHRvCgkJICogZ2VuZXJhdGUgc3VpdGFibGUgbWFyay11cCBmb3IgYSBzaXRlLiBGb3IgZXhhbXBsZSB0aGUgQm9vdHN0cmFwCgkJICogaW50ZWdyYXRpb24gcGx1Zy1pbiBmb3IgRGF0YVRhYmxlcyB1c2VzIGEgcGFnaW5nIGJ1dHRvbiByZW5kZXJlciB0bwoJCSAqIGRpc3BsYXkgcGFnaW5hdGlvbiBidXR0b25zIGluIHRoZSBtYXJrLXVwIHJlcXVpcmVkIGJ5IEJvb3RzdHJhcC4KCQkgKgoJCSAqIEZvciBmdXJ0aGVyIGluZm9ybWF0aW9uIGFib3V0IHRoZSByZW5kZXJlcnMgYXZhaWxhYmxlIHNlZQoJCSAqIERhdGFUYWJsZS5leHQucmVuZGVyZXIKCQkgKiAgQHR5cGUgc3RyaW5nfG9iamVjdAoJCSAqICBAZGVmYXVsdCBudWxsCgkJICoKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnJlbmRlcmVyCgkJICoKCQkgKi8KCQkicmVuZGVyZXIiOiBudWxsLAoJCgkKCQkvKioKCQkgKiBTZXQgdGhlIGRhdGEgcHJvcGVydHkgbmFtZSB0aGF0IERhdGFUYWJsZXMgc2hvdWxkIHVzZSB0byBnZXQgYSByb3cncyBpZAoJCSAqIHRvIHNldCBhcyB0aGUgYGlkYCBwcm9wZXJ0eSBpbiB0aGUgbm9kZS4KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IERUX1Jvd0lkCgkJICoKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnJvd0lkCgkJICovCgkJInJvd0lkIjogIkRUX1Jvd0lkIgoJfTsKCQoJX2ZuSHVuZ2FyaWFuTWFwKCBEYXRhVGFibGUuZGVmYXVsdHMgKTsKCQoJCgkKCS8qCgkgKiBEZXZlbG9wZXIgbm90ZSAtIFNlZSBub3RlIGluIG1vZGVsLmRlZmF1bHRzLmpzIGFib3V0IHRoZSB1c2Ugb2YgSHVuZ2FyaWFuCgkgKiBub3RhdGlvbiBhbmQgY2FtZWwgY2FzZS4KCSAqLwoJCgkvKioKCSAqIENvbHVtbiBvcHRpb25zIHRoYXQgY2FuIGJlIGdpdmVuIHRvIERhdGFUYWJsZXMgYXQgaW5pdGlhbGlzYXRpb24gdGltZS4KCSAqICBAbmFtZXNwYWNlCgkgKi8KCURhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4gPSB7CgkJLyoqCgkJICogRGVmaW5lIHdoaWNoIGNvbHVtbihzKSBhbiBvcmRlciB3aWxsIG9jY3VyIG9uIGZvciB0aGlzIGNvbHVtbi4gVGhpcwoJCSAqIGFsbG93cyBhIGNvbHVtbidzIG9yZGVyaW5nIHRvIHRha2UgbXVsdGlwbGUgY29sdW1ucyBpbnRvIGFjY291bnQgd2hlbgoJCSAqIGRvaW5nIGEgc29ydCBvciB1c2UgdGhlIGRhdGEgZnJvbSBhIGRpZmZlcmVudCBjb2x1bW4uIEZvciBleGFtcGxlIGZpcnN0CgkJICogbmFtZSAvIGxhc3QgbmFtZSBjb2x1bW5zIG1ha2Ugc2Vuc2UgdG8gZG8gYSBtdWx0aS1jb2x1bW4gc29ydCBvdmVyIHRoZQoJCSAqIHR3byBjb2x1bW5zLgoJCSAqICBAdHlwZSBhcnJheXxpbnQKCQkgKiAgQGRlZmF1bHQgbnVsbCA8aT5UYWtlcyB0aGUgdmFsdWUgb2YgdGhlIGNvbHVtbiBpbmRleCBhdXRvbWF0aWNhbGx5PC9pPgoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4ub3JkZXJEYXRhCgkJICogIEBkdG9wdCBDb2x1bW5zCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBVc2luZyBgY29sdW1uRGVmc2AKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1uRGVmcyI6IFsKCQkgKiAgICAgICAgICB7ICJvcmRlckRhdGEiOiBbIDAsIDEgXSwgInRhcmdldHMiOiBbIDAgXSB9LAoJCSAqICAgICAgICAgIHsgIm9yZGVyRGF0YSI6IFsgMSwgMCBdLCAidGFyZ2V0cyI6IFsgMSBdIH0sCgkJICogICAgICAgICAgeyAib3JkZXJEYXRhIjogMiwgInRhcmdldHMiOiBbIDIgXSB9CgkJICogICAgICAgIF0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBVc2luZyBgY29sdW1uc2AKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1ucyI6IFsKCQkgKiAgICAgICAgICB7ICJvcmRlckRhdGEiOiBbIDAsIDEgXSB9LAoJCSAqICAgICAgICAgIHsgIm9yZGVyRGF0YSI6IFsgMSwgMCBdIH0sCgkJICogICAgICAgICAgeyAib3JkZXJEYXRhIjogMiB9LAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbAoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJhRGF0YVNvcnQiOiBudWxsLAoJCSJpRGF0YVNvcnQiOiAtMSwKCQoJCgkJLyoqCgkJICogWW91IGNhbiBjb250cm9sIHRoZSBkZWZhdWx0IG9yZGVyaW5nIGRpcmVjdGlvbiwgYW5kIGV2ZW4gYWx0ZXIgdGhlCgkJICogYmVoYXZpb3VyIG9mIHRoZSBzb3J0IGhhbmRsZXIgKGkuZS4gb25seSBhbGxvdyBhc2NlbmRpbmcgb3JkZXJpbmcgZXRjKQoJCSAqIHVzaW5nIHRoaXMgcGFyYW1ldGVyLgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbICdhc2MnLCAnZGVzYycgXQoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4ub3JkZXJTZXF1ZW5jZQoJCSAqICBAZHRvcHQgQ29sdW1ucwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbkRlZnMiOiBbCgkJICogICAgICAgICAgeyAib3JkZXJTZXF1ZW5jZSI6IFsgImFzYyIgXSwgInRhcmdldHMiOiBbIDEgXSB9LAoJCSAqICAgICAgICAgIHsgIm9yZGVyU2VxdWVuY2UiOiBbICJkZXNjIiwgImFzYyIsICJhc2MiIF0sICJ0YXJnZXRzIjogWyAyIF0gfSwKCQkgKiAgICAgICAgICB7ICJvcmRlclNlcXVlbmNlIjogWyAiZGVzYyIgXSwgInRhcmdldHMiOiBbIDMgXSB9CgkJICogICAgICAgIF0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBVc2luZyBgY29sdW1uc2AKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1ucyI6IFsKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIHsgIm9yZGVyU2VxdWVuY2UiOiBbICJhc2MiIF0gfSwKCQkgKiAgICAgICAgICB7ICJvcmRlclNlcXVlbmNlIjogWyAiZGVzYyIsICJhc2MiLCAiYXNjIiBdIH0sCgkJICogICAgICAgICAgeyAib3JkZXJTZXF1ZW5jZSI6IFsgImRlc2MiIF0gfSwKCQkgKiAgICAgICAgICBudWxsCgkJICogICAgICAgIF0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImFzU29ydGluZyI6IFsgJ2FzYycsICdkZXNjJyBdLAoJCgkKCQkvKioKCQkgKiBFbmFibGUgb3IgZGlzYWJsZSBmaWx0ZXJpbmcgb24gdGhlIGRhdGEgaW4gdGhpcyBjb2x1bW4uCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgdHJ1ZQoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4uc2VhcmNoYWJsZQoJCSAqICBAZHRvcHQgQ29sdW1ucwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbkRlZnMiOiBbCgkJICogICAgICAgICAgeyAic2VhcmNoYWJsZSI6IGZhbHNlLCAidGFyZ2V0cyI6IFsgMCBdIH0KCQkgKiAgICAgICAgXSB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbnMiOiBbCgkJICogICAgICAgICAgeyAic2VhcmNoYWJsZSI6IGZhbHNlIH0sCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbAoJCSAqICAgICAgICBdIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImJTZWFyY2hhYmxlIjogdHJ1ZSwKCQoJCgkJLyoqCgkJICogRW5hYmxlIG9yIGRpc2FibGUgb3JkZXJpbmcgb24gdGhpcyBjb2x1bW4uCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgdHJ1ZQoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4ub3JkZXJhYmxlCgkJICogIEBkdG9wdCBDb2x1bW5zCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBVc2luZyBgY29sdW1uRGVmc2AKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1uRGVmcyI6IFsKCQkgKiAgICAgICAgICB7ICJvcmRlcmFibGUiOiBmYWxzZSwgInRhcmdldHMiOiBbIDAgXSB9CgkJICogICAgICAgIF0gfSApOwoJCSAqICAgIH0gKTsKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFVzaW5nIGBjb2x1bW5zYAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5zIjogWwoJCSAqICAgICAgICAgIHsgIm9yZGVyYWJsZSI6IGZhbHNlIH0sCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbAoJCSAqICAgICAgICBdIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJImJTb3J0YWJsZSI6IHRydWUsCgkKCQoJCS8qKgoJCSAqIEVuYWJsZSBvciBkaXNhYmxlIHRoZSBkaXNwbGF5IG9mIHRoaXMgY29sdW1uLgoJCSAqICBAdHlwZSBib29sZWFuCgkJICogIEBkZWZhdWx0IHRydWUKCQkgKgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLnZpc2libGUKCQkgKiAgQGR0b3B0IENvbHVtbnMKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFVzaW5nIGBjb2x1bW5EZWZzYAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWwoJCSAqICAgICAgICAgIHsgInZpc2libGUiOiBmYWxzZSwgInRhcmdldHMiOiBbIDAgXSB9CgkJICogICAgICAgIF0gfSApOwoJCSAqICAgIH0gKTsKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFVzaW5nIGBjb2x1bW5zYAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5zIjogWwoJCSAqICAgICAgICAgIHsgInZpc2libGUiOiBmYWxzZSB9LAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwKCQkgKiAgICAgICAgXSB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJiVmlzaWJsZSI6IHRydWUsCgkKCQoJCS8qKgoJCSAqIERldmVsb3BlciBkZWZpbmFibGUgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbmV2ZXIgYSBjZWxsIGlzIGNyZWF0ZWQgKEFqYXggc291cmNlLAoJCSAqIGV0Yykgb3IgcHJvY2Vzc2VkIGZvciBpbnB1dCAoRE9NIHNvdXJjZSkuIFRoaXMgY2FuIGJlIHVzZWQgYXMgYSBjb21wbGltZW50IHRvIG1SZW5kZXIKCQkgKiBhbGxvd2luZyB5b3UgdG8gbW9kaWZ5IHRoZSBET00gZWxlbWVudCAoYWRkIGJhY2tncm91bmQgY29sb3VyIGZvciBleGFtcGxlKSB3aGVuIHRoZQoJCSAqIGVsZW1lbnQgaXMgYXZhaWxhYmxlLgoJCSAqICBAdHlwZSBmdW5jdGlvbgoJCSAqICBAcGFyYW0ge2VsZW1lbnR9IHRkIFRoZSBURCBub2RlIHRoYXQgaGFzIGJlZW4gY3JlYXRlZAoJCSAqICBAcGFyYW0geyp9IGNlbGxEYXRhIFRoZSBEYXRhIGZvciB0aGUgY2VsbAoJCSAqICBAcGFyYW0ge2FycmF5fG9iamVjdH0gcm93RGF0YSBUaGUgZGF0YSBmb3IgdGhlIHdob2xlIHJvdwoJCSAqICBAcGFyYW0ge2ludH0gcm93IFRoZSByb3cgaW5kZXggZm9yIHRoZSBhb0RhdGEgZGF0YSBzdG9yZQoJCSAqICBAcGFyYW0ge2ludH0gY29sIFRoZSBjb2x1bW4gaW5kZXggZm9yIGFvQ29sdW1ucwoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4uY3JlYXRlZENlbGwKCQkgKiAgQGR0b3B0IENvbHVtbnMKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWyB7CgkJICogICAgICAgICAgInRhcmdldHMiOiBbM10sCgkJICogICAgICAgICAgImNyZWF0ZWRDZWxsIjogZnVuY3Rpb24gKHRkLCBjZWxsRGF0YSwgcm93RGF0YSwgcm93LCBjb2wpIHsKCQkgKiAgICAgICAgICAgIGlmICggY2VsbERhdGEgPT0gIjEuNyIgKSB7CgkJICogICAgICAgICAgICAgICQodGQpLmNzcygnY29sb3InLCAnYmx1ZScpCgkJICogICAgICAgICAgICB9CgkJICogICAgICAgICAgfQoJCSAqICAgICAgICB9IF0KCQkgKiAgICAgIH0pOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkiZm5DcmVhdGVkQ2VsbCI6IG51bGwsCgkKCQoJCS8qKgoJCSAqIFRoaXMgcGFyYW1ldGVyIGhhcyBiZWVuIHJlcGxhY2VkIGJ5IGBkYXRhYCBpbiBEYXRhVGFibGVzIHRvIGVuc3VyZSBuYW1pbmcKCQkgKiBjb25zaXN0ZW5jeS4gYGRhdGFQcm9wYCBjYW4gc3RpbGwgYmUgdXNlZCwgYXMgdGhlcmUgaXMgYmFja3dhcmRzCgkJICogY29tcGF0aWJpbGl0eSBpbiBEYXRhVGFibGVzIGZvciB0aGlzIG9wdGlvbiwgYnV0IGl0IGlzIHN0cm9uZ2x5CgkJICogcmVjb21tZW5kZWQgdGhhdCB5b3UgdXNlIGBkYXRhYCBpbiBwcmVmZXJlbmNlIHRvIGBkYXRhUHJvcGAuCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4uZGF0YVByb3AKCQkgKi8KCQoJCgkJLyoqCgkJICogVGhpcyBwcm9wZXJ0eSBjYW4gYmUgdXNlZCB0byByZWFkIGRhdGEgZnJvbSBhbnkgZGF0YSBzb3VyY2UgcHJvcGVydHksCgkJICogaW5jbHVkaW5nIGRlZXBseSBuZXN0ZWQgb2JqZWN0cyAvIHByb3BlcnRpZXMuIGBkYXRhYCBjYW4gYmUgZ2l2ZW4gaW4gYQoJCSAqIG51bWJlciBvZiBkaWZmZXJlbnQgd2F5cyB3aGljaCBlZmZlY3QgaXRzIGJlaGF2aW91cjoKCQkgKgoJCSAqICogYGludGVnZXJgIC0gdHJlYXRlZCBhcyBhbiBhcnJheSBpbmRleCBmb3IgdGhlIGRhdGEgc291cmNlLiBUaGlzIGlzIHRoZQoJCSAqICAgZGVmYXVsdCB0aGF0IERhdGFUYWJsZXMgdXNlcyAoaW5jcmVtZW50YWxseSBpbmNyZWFzZWQgZm9yIGVhY2ggY29sdW1uKS4KCQkgKiAqIGBzdHJpbmdgIC0gcmVhZCBhbiBvYmplY3QgcHJvcGVydHkgZnJvbSB0aGUgZGF0YSBzb3VyY2UuIFRoZXJlIGFyZQoJCSAqICAgdGhyZWUgJ3NwZWNpYWwnIG9wdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCBpbiB0aGUgc3RyaW5nIHRvIGFsdGVyIGhvdwoJCSAqICAgRGF0YVRhYmxlcyByZWFkcyB0aGUgZGF0YSBmcm9tIHRoZSBzb3VyY2Ugb2JqZWN0OgoJCSAqICAgICogYC5gIC0gRG90dGVkIEphdmFzY3JpcHQgbm90YXRpb24uIEp1c3QgYXMgeW91IHVzZSBhIGAuYCBpbgoJCSAqICAgICAgSmF2YXNjcmlwdCB0byByZWFkIGZyb20gbmVzdGVkIG9iamVjdHMsIHNvIHRvIGNhbiB0aGUgb3B0aW9ucwoJCSAqICAgICAgc3BlY2lmaWVkIGluIGBkYXRhYC4gRm9yIGV4YW1wbGU6IGBicm93c2VyLnZlcnNpb25gIG9yCgkJICogICAgICBgYnJvd3Nlci5uYW1lYC4gSWYgeW91ciBvYmplY3QgcGFyYW1ldGVyIG5hbWUgY29udGFpbnMgYSBwZXJpb2QsIHVzZQoJCSAqICAgICAgYFxcYCB0byBlc2NhcGUgaXQgLSBpLmUuIGBmaXJzdFxcLm5hbWVgLgoJCSAqICAgICogYFtdYCAtIEFycmF5IG5vdGF0aW9uLiBEYXRhVGFibGVzIGNhbiBhdXRvbWF0aWNhbGx5IGNvbWJpbmUgZGF0YQoJCSAqICAgICAgZnJvbSBhbmQgYXJyYXkgc291cmNlLCBqb2luaW5nIHRoZSBkYXRhIHdpdGggdGhlIGNoYXJhY3RlcnMgcHJvdmlkZWQKCQkgKiAgICAgIGJldHdlZW4gdGhlIHR3byBicmFja2V0cy4gRm9yIGV4YW1wbGU6IGBuYW1lWywgXWAgd291bGQgcHJvdmlkZSBhCgkJICogICAgICBjb21tYS1zcGFjZSBzZXBhcmF0ZWQgbGlzdCBmcm9tIHRoZSBzb3VyY2UgYXJyYXkuIElmIG5vIGNoYXJhY3RlcnMKCQkgKiAgICAgIGFyZSBwcm92aWRlZCBiZXR3ZWVuIHRoZSBicmFja2V0cywgdGhlIG9yaWdpbmFsIGFycmF5IHNvdXJjZSBpcwoJCSAqICAgICAgcmV0dXJuZWQuCgkJICogICAgKiBgKClgIC0gRnVuY3Rpb24gbm90YXRpb24uIEFkZGluZyBgKClgIHRvIHRoZSBlbmQgb2YgYSBwYXJhbWV0ZXIgd2lsbAoJCSAqICAgICAgZXhlY3V0ZSBhIGZ1bmN0aW9uIG9mIHRoZSBuYW1lIGdpdmVuLiBGb3IgZXhhbXBsZTogYGJyb3dzZXIoKWAgZm9yIGEKCQkgKiAgICAgIHNpbXBsZSBmdW5jdGlvbiBvbiB0aGUgZGF0YSBzb3VyY2UsIGBicm93c2VyLnZlcnNpb24oKWAgZm9yIGEKCQkgKiAgICAgIGZ1bmN0aW9uIGluIGEgbmVzdGVkIHByb3BlcnR5IG9yIGV2ZW4gYGJyb3dzZXIoKS52ZXJzaW9uYCB0byBnZXQgYW4KCQkgKiAgICAgIG9iamVjdCBwcm9wZXJ0eSBpZiB0aGUgZnVuY3Rpb24gY2FsbGVkIHJldHVybnMgYW4gb2JqZWN0LiBOb3RlIHRoYXQKCQkgKiAgICAgIGZ1bmN0aW9uIG5vdGF0aW9uIGlzIHJlY29tbWVuZGVkIGZvciB1c2UgaW4gYHJlbmRlcmAgcmF0aGVyIHRoYW4KCQkgKiAgICAgIGBkYXRhYCBhcyBpdCBpcyBtdWNoIHNpbXBsZXIgdG8gdXNlIGFzIGEgcmVuZGVyZXIuCgkJICogKiBgbnVsbGAgLSB1c2UgdGhlIG9yaWdpbmFsIGRhdGEgc291cmNlIGZvciB0aGUgcm93IHJhdGhlciB0aGFuIHBsdWNraW5nCgkJICogICBkYXRhIGRpcmVjdGx5IGZyb20gaXQuIFRoaXMgYWN0aW9uIGhhcyBlZmZlY3RzIG9uIHR3byBvdGhlcgoJCSAqICAgaW5pdGlhbGlzYXRpb24gb3B0aW9uczoKCQkgKiAgICAqIGBkZWZhdWx0Q29udGVudGAgLSBXaGVuIG51bGwgaXMgZ2l2ZW4gYXMgdGhlIGBkYXRhYCBvcHRpb24gYW5kCgkJICogICAgICBgZGVmYXVsdENvbnRlbnRgIGlzIHNwZWNpZmllZCBmb3IgdGhlIGNvbHVtbiwgdGhlIHZhbHVlIGRlZmluZWQgYnkKCQkgKiAgICAgIGBkZWZhdWx0Q29udGVudGAgd2lsbCBiZSB1c2VkIGZvciB0aGUgY2VsbC4KCQkgKiAgICAqIGByZW5kZXJgIC0gV2hlbiBudWxsIGlzIHVzZWQgZm9yIHRoZSBgZGF0YWAgb3B0aW9uIGFuZCB0aGUgYHJlbmRlcmAKCQkgKiAgICAgIG9wdGlvbiBpcyBzcGVjaWZpZWQgZm9yIHRoZSBjb2x1bW4sIHRoZSB3aG9sZSBkYXRhIHNvdXJjZSBmb3IgdGhlCgkJICogICAgICByb3cgaXMgdXNlZCBmb3IgdGhlIHJlbmRlcmVyLgoJCSAqICogYGZ1bmN0aW9uYCAtIHRoZSBmdW5jdGlvbiBnaXZlbiB3aWxsIGJlIGV4ZWN1dGVkIHdoZW5ldmVyIERhdGFUYWJsZXMKCQkgKiAgIG5lZWRzIHRvIHNldCBvciBnZXQgdGhlIGRhdGEgZm9yIGEgY2VsbCBpbiB0aGUgY29sdW1uLiBUaGUgZnVuY3Rpb24KCQkgKiAgIHRha2VzIHRocmVlIHBhcmFtZXRlcnM6CgkJICogICAgKiBQYXJhbWV0ZXJzOgoJCSAqICAgICAgKiBge2FycmF5fG9iamVjdH1gIFRoZSBkYXRhIHNvdXJjZSBmb3IgdGhlIHJvdwoJCSAqICAgICAgKiBge3N0cmluZ31gIFRoZSB0eXBlIGNhbGwgZGF0YSByZXF1ZXN0ZWQgLSB0aGlzIHdpbGwgYmUgJ3NldCcgd2hlbgoJCSAqICAgICAgICBzZXR0aW5nIGRhdGEgb3IgJ2ZpbHRlcicsICdkaXNwbGF5JywgJ3R5cGUnLCAnc29ydCcgb3IgdW5kZWZpbmVkCgkJICogICAgICAgIHdoZW4gZ2F0aGVyaW5nIGRhdGEuIE5vdGUgdGhhdCB3aGVuIGB1bmRlZmluZWRgIGlzIGdpdmVuIGZvciB0aGUKCQkgKiAgICAgICAgdHlwZSBEYXRhVGFibGVzIGV4cGVjdHMgdG8gZ2V0IHRoZSByYXcgZGF0YSBmb3IgdGhlIG9iamVjdCBiYWNrPAoJCSAqICAgICAgKiBgeyp9YCBEYXRhIHRvIHNldCB3aGVuIHRoZSBzZWNvbmQgcGFyYW1ldGVyIGlzICdzZXQnLgoJCSAqICAgICogUmV0dXJuOgoJCSAqICAgICAgKiBUaGUgcmV0dXJuIHZhbHVlIGZyb20gdGhlIGZ1bmN0aW9uIGlzIG5vdCByZXF1aXJlZCB3aGVuICdzZXQnIGlzCgkJICogICAgICAgIHRoZSB0eXBlIG9mIGNhbGwsIGJ1dCBvdGhlcndpc2UgdGhlIHJldHVybiBpcyB3aGF0IHdpbGwgYmUgdXNlZAoJCSAqICAgICAgICBmb3IgdGhlIGRhdGEgcmVxdWVzdGVkLgoJCSAqCgkJICogTm90ZSB0aGF0IGBkYXRhYCBpcyBhIGdldHRlciBhbmQgc2V0dGVyIG9wdGlvbi4gSWYgeW91IGp1c3QgcmVxdWlyZQoJCSAqIGZvcm1hdHRpbmcgb2YgZGF0YSBmb3Igb3V0cHV0LCB5b3Ugd2lsbCBsaWtlbHkgd2FudCB0byB1c2UgYHJlbmRlcmAgd2hpY2gKCQkgKiBpcyBzaW1wbHkgYSBnZXR0ZXIgYW5kIHRodXMgc2ltcGxlciB0byB1c2UuCgkJICoKCQkgKiBOb3RlIHRoYXQgcHJpb3IgdG8gRGF0YVRhYmxlcyAxLjkuMiBgZGF0YWAgd2FzIGNhbGxlZCBgbURhdGFQcm9wYC4gVGhlCgkJICogbmFtZSBjaGFuZ2UgcmVmbGVjdHMgdGhlIGZsZXhpYmlsaXR5IG9mIHRoaXMgcHJvcGVydHkgYW5kIGlzIGNvbnNpc3RlbnQKCQkgKiB3aXRoIHRoZSBuYW1pbmcgb2YgbVJlbmRlci4gSWYgJ21EYXRhUHJvcCcgaXMgZ2l2ZW4sIHRoZW4gaXQgd2lsbCBzdGlsbAoJCSAqIGJlIHVzZWQgYnkgRGF0YVRhYmxlcywgYXMgaXQgYXV0b21hdGljYWxseSBtYXBzIHRoZSBvbGQgbmFtZSB0byB0aGUgbmV3CgkJICogaWYgcmVxdWlyZWQuCgkJICoKCQkgKiAgQHR5cGUgc3RyaW5nfGludHxmdW5jdGlvbnxudWxsCgkJICogIEBkZWZhdWx0IG51bGwgPGk+VXNlIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZCBjb2x1bW4gaW5kZXg8L2k+CgkJICoKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbi5kYXRhCgkJICogIEBkdG9wdCBDb2x1bW5zCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBSZWFkIHRhYmxlIGRhdGEgZnJvbSBvYmplY3RzCgkJICogICAgLy8gSlNPTiBzdHJ1Y3R1cmUgZm9yIGVhY2ggcm93OgoJCSAqICAgIC8vICAgewoJCSAqICAgIC8vICAgICAgImVuZ2luZSI6IHt2YWx1ZX0sCgkJICogICAgLy8gICAgICAiYnJvd3NlciI6IHt2YWx1ZX0sCgkJICogICAgLy8gICAgICAicGxhdGZvcm0iOiB7dmFsdWV9LAoJCSAqICAgIC8vICAgICAgInZlcnNpb24iOiB7dmFsdWV9LAoJCSAqICAgIC8vICAgICAgImdyYWRlIjoge3ZhbHVlfQoJCSAqICAgIC8vICAgfQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJhamF4U291cmNlIjogInNvdXJjZXMvb2JqZWN0cy50eHQiLAoJCSAqICAgICAgICAiY29sdW1ucyI6IFsKCQkgKiAgICAgICAgICB7ICJkYXRhIjogImVuZ2luZSIgfSwKCQkgKiAgICAgICAgICB7ICJkYXRhIjogImJyb3dzZXIiIH0sCgkJICogICAgICAgICAgeyAiZGF0YSI6ICJwbGF0Zm9ybSIgfSwKCQkgKiAgICAgICAgICB7ICJkYXRhIjogInZlcnNpb24iIH0sCgkJICogICAgICAgICAgeyAiZGF0YSI6ICJncmFkZSIgfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gUmVhZCBpbmZvcm1hdGlvbiBmcm9tIGRlZXBseSBuZXN0ZWQgb2JqZWN0cwoJCSAqICAgIC8vIEpTT04gc3RydWN0dXJlIGZvciBlYWNoIHJvdzoKCQkgKiAgICAvLyAgIHsKCQkgKiAgICAvLyAgICAgICJlbmdpbmUiOiB7dmFsdWV9LAoJCSAqICAgIC8vICAgICAgImJyb3dzZXIiOiB7dmFsdWV9LAoJCSAqICAgIC8vICAgICAgInBsYXRmb3JtIjogewoJCSAqICAgIC8vICAgICAgICAgImlubmVyIjoge3ZhbHVlfQoJCSAqICAgIC8vICAgICAgfSwKCQkgKiAgICAvLyAgICAgICJkZXRhaWxzIjogWwoJCSAqICAgIC8vICAgICAgICAge3ZhbHVlfSwge3ZhbHVlfQoJCSAqICAgIC8vICAgICAgXQoJCSAqICAgIC8vICAgfQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJhamF4U291cmNlIjogInNvdXJjZXMvZGVlcC50eHQiLAoJCSAqICAgICAgICAiY29sdW1ucyI6IFsKCQkgKiAgICAgICAgICB7ICJkYXRhIjogImVuZ2luZSIgfSwKCQkgKiAgICAgICAgICB7ICJkYXRhIjogImJyb3dzZXIiIH0sCgkJICogICAgICAgICAgeyAiZGF0YSI6ICJwbGF0Zm9ybS5pbm5lciIgfSwKCQkgKiAgICAgICAgICB7ICJkYXRhIjogImRldGFpbHMuMCIgfSwKCQkgKiAgICAgICAgICB7ICJkYXRhIjogImRldGFpbHMuMSIgfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGRhdGFgIGFzIGEgZnVuY3Rpb24gdG8gcHJvdmlkZSBkaWZmZXJlbnQgaW5mb3JtYXRpb24gZm9yCgkJICogICAgLy8gc29ydGluZywgZmlsdGVyaW5nIGFuZCBkaXNwbGF5LiBJbiB0aGlzIGNhc2UsIGN1cnJlbmN5IChwcmljZSkKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1uRGVmcyI6IFsgewoJCSAqICAgICAgICAgICJ0YXJnZXRzIjogWyAwIF0sCgkJICogICAgICAgICAgImRhdGEiOiBmdW5jdGlvbiAoIHNvdXJjZSwgdHlwZSwgdmFsICkgewoJCSAqICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdzZXQnKSB7CgkJICogICAgICAgICAgICAgIHNvdXJjZS5wcmljZSA9IHZhbDsKCQkgKiAgICAgICAgICAgICAgLy8gU3RvcmUgdGhlIGNvbXB1dGVkIGRpc3BsYXkgYW5kIGZpbHRlciB2YWx1ZXMgZm9yIGVmZmljaWVuY3kKCQkgKiAgICAgICAgICAgICAgc291cmNlLnByaWNlX2Rpc3BsYXkgPSB2YWw9PSIiID8gIiIgOiAiJCIrbnVtYmVyRm9ybWF0KHZhbCk7CgkJICogICAgICAgICAgICAgIHNvdXJjZS5wcmljZV9maWx0ZXIgID0gdmFsPT0iIiA/ICIiIDogIiQiK251bWJlckZvcm1hdCh2YWwpKyIgIit2YWw7CgkJICogICAgICAgICAgICAgIHJldHVybjsKCQkgKiAgICAgICAgICAgIH0KCQkgKiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGUgPT09ICdkaXNwbGF5JykgewoJCSAqICAgICAgICAgICAgICByZXR1cm4gc291cmNlLnByaWNlX2Rpc3BsYXk7CgkJICogICAgICAgICAgICB9CgkJICogICAgICAgICAgICBlbHNlIGlmICh0eXBlID09PSAnZmlsdGVyJykgewoJCSAqICAgICAgICAgICAgICByZXR1cm4gc291cmNlLnByaWNlX2ZpbHRlcjsKCQkgKiAgICAgICAgICAgIH0KCQkgKiAgICAgICAgICAgIC8vICdzb3J0JywgJ3R5cGUnIGFuZCB1bmRlZmluZWQgYWxsIGp1c3QgdXNlIHRoZSBpbnRlZ2VyCgkJICogICAgICAgICAgICByZXR1cm4gc291cmNlLnByaWNlOwoJCSAqICAgICAgICAgIH0KCQkgKiAgICAgICAgfSBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgZGVmYXVsdCBjb250ZW50CgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbkRlZnMiOiBbIHsKCQkgKiAgICAgICAgICAidGFyZ2V0cyI6IFsgMCBdLAoJCSAqICAgICAgICAgICJkYXRhIjogbnVsbCwKCQkgKiAgICAgICAgICAiZGVmYXVsdENvbnRlbnQiOiAiQ2xpY2sgdG8gZWRpdCIKCQkgKiAgICAgICAgfSBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYXJyYXkgbm90YXRpb24gLSBvdXRwdXR0aW5nIGEgbGlzdCBmcm9tIGFuIGFycmF5CgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbkRlZnMiOiBbIHsKCQkgKiAgICAgICAgICAidGFyZ2V0cyI6IFsgMCBdLAoJCSAqICAgICAgICAgICJkYXRhIjogIm5hbWVbLCBdIgoJCSAqICAgICAgICB9IF0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKi8KCQkibURhdGEiOiBudWxsLAoJCgkKCQkvKioKCQkgKiBUaGlzIHByb3BlcnR5IGlzIHRoZSByZW5kZXJpbmcgcGFydG5lciB0byBgZGF0YWAgYW5kIGl0IGlzIHN1Z2dlc3RlZCB0aGF0CgkJICogd2hlbiB5b3Ugd2FudCB0byBtYW5pcHVsYXRlIGRhdGEgZm9yIGRpc3BsYXkgKGluY2x1ZGluZyBmaWx0ZXJpbmcsCgkJICogc29ydGluZyBldGMpIHdpdGhvdXQgYWx0ZXJpbmcgdGhlIHVuZGVybHlpbmcgZGF0YSBmb3IgdGhlIHRhYmxlLCB1c2UgdGhpcwoJCSAqIHByb3BlcnR5LiBgcmVuZGVyYCBjYW4gYmUgY29uc2lkZXJlZCB0byBiZSB0aGUgdGhlIHJlYWQgb25seSBjb21wYW5pb24gdG8KCQkgKiBgZGF0YWAgd2hpY2ggaXMgcmVhZCAvIHdyaXRlICh0aGVuIGFzIHN1Y2ggbW9yZSBjb21wbGV4KS4gTGlrZSBgZGF0YWAKCQkgKiB0aGlzIG9wdGlvbiBjYW4gYmUgZ2l2ZW4gaW4gYSBudW1iZXIgb2YgZGlmZmVyZW50IHdheXMgdG8gZWZmZWN0IGl0cwoJCSAqIGJlaGF2aW91cjoKCQkgKgoJCSAqICogYGludGVnZXJgIC0gdHJlYXRlZCBhcyBhbiBhcnJheSBpbmRleCBmb3IgdGhlIGRhdGEgc291cmNlLiBUaGlzIGlzIHRoZQoJCSAqICAgZGVmYXVsdCB0aGF0IERhdGFUYWJsZXMgdXNlcyAoaW5jcmVtZW50YWxseSBpbmNyZWFzZWQgZm9yIGVhY2ggY29sdW1uKS4KCQkgKiAqIGBzdHJpbmdgIC0gcmVhZCBhbiBvYmplY3QgcHJvcGVydHkgZnJvbSB0aGUgZGF0YSBzb3VyY2UuIFRoZXJlIGFyZQoJCSAqICAgdGhyZWUgJ3NwZWNpYWwnIG9wdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCBpbiB0aGUgc3RyaW5nIHRvIGFsdGVyIGhvdwoJCSAqICAgRGF0YVRhYmxlcyByZWFkcyB0aGUgZGF0YSBmcm9tIHRoZSBzb3VyY2Ugb2JqZWN0OgoJCSAqICAgICogYC5gIC0gRG90dGVkIEphdmFzY3JpcHQgbm90YXRpb24uIEp1c3QgYXMgeW91IHVzZSBhIGAuYCBpbgoJCSAqICAgICAgSmF2YXNjcmlwdCB0byByZWFkIGZyb20gbmVzdGVkIG9iamVjdHMsIHNvIHRvIGNhbiB0aGUgb3B0aW9ucwoJCSAqICAgICAgc3BlY2lmaWVkIGluIGBkYXRhYC4gRm9yIGV4YW1wbGU6IGBicm93c2VyLnZlcnNpb25gIG9yCgkJICogICAgICBgYnJvd3Nlci5uYW1lYC4gSWYgeW91ciBvYmplY3QgcGFyYW1ldGVyIG5hbWUgY29udGFpbnMgYSBwZXJpb2QsIHVzZQoJCSAqICAgICAgYFxcYCB0byBlc2NhcGUgaXQgLSBpLmUuIGBmaXJzdFxcLm5hbWVgLgoJCSAqICAgICogYFtdYCAtIEFycmF5IG5vdGF0aW9uLiBEYXRhVGFibGVzIGNhbiBhdXRvbWF0aWNhbGx5IGNvbWJpbmUgZGF0YQoJCSAqICAgICAgZnJvbSBhbmQgYXJyYXkgc291cmNlLCBqb2luaW5nIHRoZSBkYXRhIHdpdGggdGhlIGNoYXJhY3RlcnMgcHJvdmlkZWQKCQkgKiAgICAgIGJldHdlZW4gdGhlIHR3byBicmFja2V0cy4gRm9yIGV4YW1wbGU6IGBuYW1lWywgXWAgd291bGQgcHJvdmlkZSBhCgkJICogICAgICBjb21tYS1zcGFjZSBzZXBhcmF0ZWQgbGlzdCBmcm9tIHRoZSBzb3VyY2UgYXJyYXkuIElmIG5vIGNoYXJhY3RlcnMKCQkgKiAgICAgIGFyZSBwcm92aWRlZCBiZXR3ZWVuIHRoZSBicmFja2V0cywgdGhlIG9yaWdpbmFsIGFycmF5IHNvdXJjZSBpcwoJCSAqICAgICAgcmV0dXJuZWQuCgkJICogICAgKiBgKClgIC0gRnVuY3Rpb24gbm90YXRpb24uIEFkZGluZyBgKClgIHRvIHRoZSBlbmQgb2YgYSBwYXJhbWV0ZXIgd2lsbAoJCSAqICAgICAgZXhlY3V0ZSBhIGZ1bmN0aW9uIG9mIHRoZSBuYW1lIGdpdmVuLiBGb3IgZXhhbXBsZTogYGJyb3dzZXIoKWAgZm9yIGEKCQkgKiAgICAgIHNpbXBsZSBmdW5jdGlvbiBvbiB0aGUgZGF0YSBzb3VyY2UsIGBicm93c2VyLnZlcnNpb24oKWAgZm9yIGEKCQkgKiAgICAgIGZ1bmN0aW9uIGluIGEgbmVzdGVkIHByb3BlcnR5IG9yIGV2ZW4gYGJyb3dzZXIoKS52ZXJzaW9uYCB0byBnZXQgYW4KCQkgKiAgICAgIG9iamVjdCBwcm9wZXJ0eSBpZiB0aGUgZnVuY3Rpb24gY2FsbGVkIHJldHVybnMgYW4gb2JqZWN0LgoJCSAqICogYG9iamVjdGAgLSB1c2UgZGlmZmVyZW50IGRhdGEgZm9yIHRoZSBkaWZmZXJlbnQgZGF0YSB0eXBlcyByZXF1ZXN0ZWQgYnkKCQkgKiAgIERhdGFUYWJsZXMgKCdmaWx0ZXInLCAnZGlzcGxheScsICd0eXBlJyBvciAnc29ydCcpLiBUaGUgcHJvcGVydHkgbmFtZXMKCQkgKiAgIG9mIHRoZSBvYmplY3QgaXMgdGhlIGRhdGEgdHlwZSB0aGUgcHJvcGVydHkgcmVmZXJzIHRvIGFuZCB0aGUgdmFsdWUgY2FuCgkJICogICBkZWZpbmVkIHVzaW5nIGFuIGludGVnZXIsIHN0cmluZyBvciBmdW5jdGlvbiB1c2luZyB0aGUgc2FtZSBydWxlcyBhcwoJCSAqICAgYHJlbmRlcmAgbm9ybWFsbHkgZG9lcy4gTm90ZSB0aGF0IGFuIGBfYCBvcHRpb24gX211c3RfIGJlIHNwZWNpZmllZC4KCQkgKiAgIFRoaXMgaXMgdGhlIGRlZmF1bHQgdmFsdWUgdG8gdXNlIGlmIHlvdSBoYXZlbid0IHNwZWNpZmllZCBhIHZhbHVlIGZvcgoJCSAqICAgdGhlIGRhdGEgdHlwZSByZXF1ZXN0ZWQgYnkgRGF0YVRhYmxlcy4KCQkgKiAqIGBmdW5jdGlvbmAgLSB0aGUgZnVuY3Rpb24gZ2l2ZW4gd2lsbCBiZSBleGVjdXRlZCB3aGVuZXZlciBEYXRhVGFibGVzCgkJICogICBuZWVkcyB0byBzZXQgb3IgZ2V0IHRoZSBkYXRhIGZvciBhIGNlbGwgaW4gdGhlIGNvbHVtbi4gVGhlIGZ1bmN0aW9uCgkJICogICB0YWtlcyB0aHJlZSBwYXJhbWV0ZXJzOgoJCSAqICAgICogUGFyYW1ldGVyczoKCQkgKiAgICAgICoge2FycmF5fG9iamVjdH0gVGhlIGRhdGEgc291cmNlIGZvciB0aGUgcm93IChiYXNlZCBvbiBgZGF0YWApCgkJICogICAgICAqIHtzdHJpbmd9IFRoZSB0eXBlIGNhbGwgZGF0YSByZXF1ZXN0ZWQgLSB0aGlzIHdpbGwgYmUgJ2ZpbHRlcicsCgkJICogICAgICAgICdkaXNwbGF5JywgJ3R5cGUnIG9yICdzb3J0Jy4KCQkgKiAgICAgICoge2FycmF5fG9iamVjdH0gVGhlIGZ1bGwgZGF0YSBzb3VyY2UgZm9yIHRoZSByb3cgKG5vdCBiYXNlZCBvbgoJCSAqICAgICAgICBgZGF0YWApCgkJICogICAgKiBSZXR1cm46CgkJICogICAgICAqIFRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgZnVuY3Rpb24gaXMgd2hhdCB3aWxsIGJlIHVzZWQgZm9yIHRoZQoJCSAqICAgICAgICBkYXRhIHJlcXVlc3RlZC4KCQkgKgoJCSAqICBAdHlwZSBzdHJpbmd8aW50fGZ1bmN0aW9ufG9iamVjdHxudWxsCgkJICogIEBkZWZhdWx0IG51bGwgVXNlIHRoZSBkYXRhIHNvdXJjZSB2YWx1ZS4KCQkgKgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLnJlbmRlcgoJCSAqICBAZHRvcHQgQ29sdW1ucwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gQ3JlYXRlIGEgY29tbWEgc2VwYXJhdGVkIGxpc3QgZnJvbSBhbiBhcnJheSBvZiBvYmplY3RzCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImFqYXhTb3VyY2UiOiAic291cmNlcy9kZWVwLnR4dCIsCgkJICogICAgICAgICJjb2x1bW5zIjogWwoJCSAqICAgICAgICAgIHsgImRhdGEiOiAiZW5naW5lIiB9LAoJCSAqICAgICAgICAgIHsgImRhdGEiOiAiYnJvd3NlciIgfSwKCQkgKiAgICAgICAgICB7CgkJICogICAgICAgICAgICAiZGF0YSI6ICJwbGF0Zm9ybSIsCgkJICogICAgICAgICAgICAicmVuZGVyIjogIlssIF0ubmFtZSIKCQkgKiAgICAgICAgICB9CgkJICogICAgICAgIF0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBFeGVjdXRlIGEgZnVuY3Rpb24gdG8gb2J0YWluIGRhdGEKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1uRGVmcyI6IFsgewoJCSAqICAgICAgICAgICJ0YXJnZXRzIjogWyAwIF0sCgkJICogICAgICAgICAgImRhdGEiOiBudWxsLCAvLyBVc2UgdGhlIGZ1bGwgZGF0YSBzb3VyY2Ugb2JqZWN0IGZvciB0aGUgcmVuZGVyZXIncyBzb3VyY2UKCQkgKiAgICAgICAgICAicmVuZGVyIjogImJyb3dzZXJOYW1lKCkiCgkJICogICAgICAgIH0gXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIEFzIGFuIG9iamVjdCwgZXh0cmFjdGluZyBkaWZmZXJlbnQgZGF0YSBmb3IgdGhlIGRpZmZlcmVudCB0eXBlcwoJCSAqICAgIC8vIFRoaXMgd291bGQgYmUgdXNlZCB3aXRoIGEgZGF0YSBzb3VyY2Ugc3VjaCBhczoKCQkgKiAgICAvLyAgIHsgInBob25lIjogNTU1MjM2OCwgInBob25lX2ZpbHRlciI6ICI1NTUyMzY4IDU1NS0yMzY4IiwgInBob25lX2Rpc3BsYXkiOiAiNTU1LTIzNjgiIH0KCQkgKiAgICAvLyBIZXJlIHRoZSBgcGhvbmVgIGludGVnZXIgaXMgdXNlZCBmb3Igc29ydGluZyBhbmQgdHlwZSBkZXRlY3Rpb24sIHdoaWxlIGBwaG9uZV9maWx0ZXJgCgkJICogICAgLy8gKHdoaWNoIGhhcyBib3RoIGZvcm1zKSBpcyB1c2VkIGZvciBmaWx0ZXJpbmcgZm9yIGlmIGEgdXNlciBpbnB1dHMgZWl0aGVyIGZvcm1hdCwgd2hpbGUKCQkgKiAgICAvLyB0aGUgZm9ybWF0dGVkIHBob25lIG51bWJlciBpcyB0aGUgb25lIHRoYXQgaXMgc2hvd24gaW4gdGhlIHRhYmxlLgoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWyB7CgkJICogICAgICAgICAgInRhcmdldHMiOiBbIDAgXSwKCQkgKiAgICAgICAgICAiZGF0YSI6IG51bGwsIC8vIFVzZSB0aGUgZnVsbCBkYXRhIHNvdXJjZSBvYmplY3QgZm9yIHRoZSByZW5kZXJlcidzIHNvdXJjZQoJCSAqICAgICAgICAgICJyZW5kZXIiOiB7CgkJICogICAgICAgICAgICAiXyI6ICJwaG9uZSIsCgkJICogICAgICAgICAgICAiZmlsdGVyIjogInBob25lX2ZpbHRlciIsCgkJICogICAgICAgICAgICAiZGlzcGxheSI6ICJwaG9uZV9kaXNwbGF5IgoJCSAqICAgICAgICAgIH0KCQkgKiAgICAgICAgfSBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNlIGFzIGEgZnVuY3Rpb24gdG8gY3JlYXRlIGEgbGluayBmcm9tIHRoZSBkYXRhIHNvdXJjZQoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWyB7CgkJICogICAgICAgICAgInRhcmdldHMiOiBbIDAgXSwKCQkgKiAgICAgICAgICAiZGF0YSI6ICJkb3dubG9hZF9saW5rIiwKCQkgKiAgICAgICAgICAicmVuZGVyIjogZnVuY3Rpb24gKCBkYXRhLCB0eXBlLCBmdWxsICkgewoJCSAqICAgICAgICAgICAgcmV0dXJuICc8YSBocmVmPSInK2RhdGErJyI+RG93bmxvYWQ8L2E+JzsKCQkgKiAgICAgICAgICB9CgkJICogICAgICAgIH0gXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkibVJlbmRlciI6IG51bGwsCgkKCQoJCS8qKgoJCSAqIENoYW5nZSB0aGUgY2VsbCB0eXBlIGNyZWF0ZWQgZm9yIHRoZSBjb2x1bW4gLSBlaXRoZXIgVEQgY2VsbHMgb3IgVEggY2VsbHMuIFRoaXMKCQkgKiBjYW4gYmUgdXNlZnVsIGFzIFRIIGNlbGxzIGhhdmUgc2VtYW50aWMgbWVhbmluZyBpbiB0aGUgdGFibGUgYm9keSwgYWxsb3dpbmcgdGhlbQoJCSAqIHRvIGFjdCBhcyBhIGhlYWRlciBmb3IgYSByb3cgKHlvdSBtYXkgd2lzaCB0byBhZGQgc2NvcGU9J3JvdycgdG8gdGhlIFRIIGVsZW1lbnRzKS4KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IHRkCgkJICoKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbi5jZWxsVHlwZQoJCSAqICBAZHRvcHQgQ29sdW1ucwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gTWFrZSB0aGUgZmlyc3QgY29sdW1uIHVzZSBUSCBjZWxscwoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWyB7CgkJICogICAgICAgICAgInRhcmdldHMiOiBbIDAgXSwKCQkgKiAgICAgICAgICAiY2VsbFR5cGUiOiAidGgiCgkJICogICAgICAgIH0gXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic0NlbGxUeXBlIjogInRkIiwKCQoJCgkJLyoqCgkJICogQ2xhc3MgdG8gZ2l2ZSB0byBlYWNoIGNlbGwgaW4gdGhpcyBjb2x1bW4uCgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCA8aT5FbXB0eSBzdHJpbmc8L2k+CgkJICoKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbi5jbGFzcwoJCSAqICBAZHRvcHQgQ29sdW1ucwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbkRlZnMiOiBbCgkJICogICAgICAgICAgeyAiY2xhc3MiOiAibXlfY2xhc3MiLCAidGFyZ2V0cyI6IFsgMCBdIH0KCQkgKiAgICAgICAgXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFVzaW5nIGBjb2x1bW5zYAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5zIjogWwoJCSAqICAgICAgICAgIHsgImNsYXNzIjogIm15X2NsYXNzIiB9LAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwKCQkgKiAgICAgICAgXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic0NsYXNzIjogIiIsCgkKCQkvKioKCQkgKiBXaGVuIERhdGFUYWJsZXMgY2FsY3VsYXRlcyB0aGUgY29sdW1uIHdpZHRocyB0byBhc3NpZ24gdG8gZWFjaCBjb2x1bW4sCgkJICogaXQgZmluZHMgdGhlIGxvbmdlc3Qgc3RyaW5nIGluIGVhY2ggY29sdW1uIGFuZCB0aGVuIGNvbnN0cnVjdHMgYQoJCSAqIHRlbXBvcmFyeSB0YWJsZSBhbmQgcmVhZHMgdGhlIHdpZHRocyBmcm9tIHRoYXQuIFRoZSBwcm9ibGVtIHdpdGggdGhpcwoJCSAqIGlzIHRoYXQgIm1tbSIgaXMgbXVjaCB3aWRlciB0aGVuICJpaWlpIiwgYnV0IHRoZSBsYXR0ZXIgaXMgYSBsb25nZXIKCQkgKiBzdHJpbmcgLSB0aHVzIHRoZSBjYWxjdWxhdGlvbiBjYW4gZ28gd3JvbmcgKGRvaW5nIGl0IHByb3Blcmx5IGFuZCBwdXR0aW5nCgkJICogaXQgaW50byBhbiBET00gb2JqZWN0IGFuZCBtZWFzdXJpbmcgdGhhdCBpcyBob3JyaWJseSghKSBzbG93KS4gVGh1cyBhcwoJCSAqIGEgIndvcmsgYXJvdW5kIiB3ZSBwcm92aWRlIHRoaXMgb3B0aW9uLiBJdCB3aWxsIGFwcGVuZCBpdHMgdmFsdWUgdG8gdGhlCgkJICogdGV4dCB0aGF0IGlzIGZvdW5kIHRvIGJlIHRoZSBsb25nZXN0IHN0cmluZyBmb3IgdGhlIGNvbHVtbiAtIGkuZS4gcGFkZGluZy4KCQkgKiBHZW5lcmFsbHkgeW91IHNob3VsZG4ndCBuZWVkIHRoaXMhCgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCA8aT5FbXB0eSBzdHJpbmc8aT4KCQkgKgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLmNvbnRlbnRQYWRkaW5nCgkJICogIEBkdG9wdCBDb2x1bW5zCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBVc2luZyBgY29sdW1uc2AKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1ucyI6IFsKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICB7CgkJICogICAgICAgICAgICAiY29udGVudFBhZGRpbmciOiAibW1tIgoJCSAqICAgICAgICAgIH0KCQkgKiAgICAgICAgXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic0NvbnRlbnRQYWRkaW5nIjogIiIsCgkKCQoJCS8qKgoJCSAqIEFsbG93cyBhIGRlZmF1bHQgdmFsdWUgdG8gYmUgZ2l2ZW4gZm9yIGEgY29sdW1uJ3MgZGF0YSwgYW5kIHdpbGwgYmUgdXNlZAoJCSAqIHdoZW5ldmVyIGEgbnVsbCBkYXRhIHNvdXJjZSBpcyBlbmNvdW50ZXJlZCAodGhpcyBjYW4gYmUgYmVjYXVzZSBgZGF0YWAKCQkgKiBpcyBzZXQgdG8gbnVsbCwgb3IgYmVjYXVzZSB0aGUgZGF0YSBzb3VyY2UgaXRzZWxmIGlzIG51bGwpLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4uZGVmYXVsdENvbnRlbnQKCQkgKiAgQGR0b3B0IENvbHVtbnMKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFVzaW5nIGBjb2x1bW5EZWZzYAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWwoJCSAqICAgICAgICAgIHsKCQkgKiAgICAgICAgICAgICJkYXRhIjogbnVsbCwKCQkgKiAgICAgICAgICAgICJkZWZhdWx0Q29udGVudCI6ICJFZGl0IiwKCQkgKiAgICAgICAgICAgICJ0YXJnZXRzIjogWyAtMSBdCgkJICogICAgICAgICAgfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbnMiOiBbCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgewoJCSAqICAgICAgICAgICAgImRhdGEiOiBudWxsLAoJCSAqICAgICAgICAgICAgImRlZmF1bHRDb250ZW50IjogIkVkaXQiCgkJICogICAgICAgICAgfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJzRGVmYXVsdENvbnRlbnQiOiBudWxsLAoJCgkKCQkvKioKCQkgKiBUaGlzIHBhcmFtZXRlciBpcyBvbmx5IHVzZWQgaW4gRGF0YVRhYmxlcycgc2VydmVyLXNpZGUgcHJvY2Vzc2luZy4gSXQgY2FuCgkJICogYmUgZXhjZXB0aW9uYWxseSB1c2VmdWwgdG8ga25vdyB3aGF0IGNvbHVtbnMgYXJlIGJlaW5nIGRpc3BsYXllZCBvbiB0aGUKCQkgKiBjbGllbnQgc2lkZSwgYW5kIHRvIG1hcCB0aGVzZSB0byBkYXRhYmFzZSBmaWVsZHMuIFdoZW4gZGVmaW5lZCwgdGhlIG5hbWVzCgkJICogYWxzbyBhbGxvdyBEYXRhVGFibGVzIHRvIHJlb3JkZXIgaW5mb3JtYXRpb24gZnJvbSB0aGUgc2VydmVyIGlmIGl0IGNvbWVzCgkJICogYmFjayBpbiBhbiB1bmV4cGVjdGVkIG9yZGVyIChpLmUuIGlmIHlvdSBzd2l0Y2ggeW91ciBjb2x1bW5zIGFyb3VuZCBvbiB0aGUKCQkgKiBjbGllbnQtc2lkZSwgeW91ciBzZXJ2ZXItc2lkZSBjb2RlIGRvZXMgbm90IGFsc28gbmVlZCB1cGRhdGluZykuCgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCA8aT5FbXB0eSBzdHJpbmc8L2k+CgkJICoKCQkgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbi5uYW1lCgkJICogIEBkdG9wdCBDb2x1bW5zCgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBVc2luZyBgY29sdW1uRGVmc2AKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1uRGVmcyI6IFsKCQkgKiAgICAgICAgICB7ICJuYW1lIjogImVuZ2luZSIsICJ0YXJnZXRzIjogWyAwIF0gfSwKCQkgKiAgICAgICAgICB7ICJuYW1lIjogImJyb3dzZXIiLCAidGFyZ2V0cyI6IFsgMSBdIH0sCgkJICogICAgICAgICAgeyAibmFtZSI6ICJwbGF0Zm9ybSIsICJ0YXJnZXRzIjogWyAyIF0gfSwKCQkgKiAgICAgICAgICB7ICJuYW1lIjogInZlcnNpb24iLCAidGFyZ2V0cyI6IFsgMyBdIH0sCgkJICogICAgICAgICAgeyAibmFtZSI6ICJncmFkZSIsICJ0YXJnZXRzIjogWyA0IF0gfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbnMiOiBbCgkJICogICAgICAgICAgeyAibmFtZSI6ICJlbmdpbmUiIH0sCgkJICogICAgICAgICAgeyAibmFtZSI6ICJicm93c2VyIiB9LAoJCSAqICAgICAgICAgIHsgIm5hbWUiOiAicGxhdGZvcm0iIH0sCgkJICogICAgICAgICAgeyAibmFtZSI6ICJ2ZXJzaW9uIiB9LAoJCSAqICAgICAgICAgIHsgIm5hbWUiOiAiZ3JhZGUiIH0KCQkgKiAgICAgICAgXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic05hbWUiOiAiIiwKCQoJCgkJLyoqCgkJICogRGVmaW5lcyBhIGRhdGEgc291cmNlIHR5cGUgZm9yIHRoZSBvcmRlcmluZyB3aGljaCBjYW4gYmUgdXNlZCB0byByZWFkCgkJICogcmVhbC10aW1lIGluZm9ybWF0aW9uIGZyb20gdGhlIHRhYmxlICh1cGRhdGluZyB0aGUgaW50ZXJuYWxseSBjYWNoZWQKCQkgKiB2ZXJzaW9uKSBwcmlvciB0byBvcmRlcmluZy4gVGhpcyBhbGxvd3Mgb3JkZXJpbmcgdG8gb2NjdXIgb24gdXNlcgoJCSAqIGVkaXRhYmxlIGVsZW1lbnRzIHN1Y2ggYXMgZm9ybSBpbnB1dHMuCgkJICogIEB0eXBlIHN0cmluZwoJCSAqICBAZGVmYXVsdCBzdGQKCQkgKgoJCSAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLm9yZGVyRGF0YVR5cGUKCQkgKiAgQGR0b3B0IENvbHVtbnMKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFVzaW5nIGBjb2x1bW5EZWZzYAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWwoJCSAqICAgICAgICAgIHsgIm9yZGVyRGF0YVR5cGUiOiAiZG9tLXRleHQiLCAidGFyZ2V0cyI6IFsgMiwgMyBdIH0sCgkJICogICAgICAgICAgeyAidHlwZSI6ICJudW1lcmljIiwgInRhcmdldHMiOiBbIDMgXSB9LAoJCSAqICAgICAgICAgIHsgIm9yZGVyRGF0YVR5cGUiOiAiZG9tLXNlbGVjdCIsICJ0YXJnZXRzIjogWyA0IF0gfSwKCQkgKiAgICAgICAgICB7ICJvcmRlckRhdGFUeXBlIjogImRvbS1jaGVja2JveCIsICJ0YXJnZXRzIjogWyA1IF0gfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbnMiOiBbCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIHsgIm9yZGVyRGF0YVR5cGUiOiAiZG9tLXRleHQiIH0sCgkJICogICAgICAgICAgeyAib3JkZXJEYXRhVHlwZSI6ICJkb20tdGV4dCIsICJ0eXBlIjogIm51bWVyaWMiIH0sCgkJICogICAgICAgICAgeyAib3JkZXJEYXRhVHlwZSI6ICJkb20tc2VsZWN0IiB9LAoJCSAqICAgICAgICAgIHsgIm9yZGVyRGF0YVR5cGUiOiAiZG9tLWNoZWNrYm94IiB9CgkJICogICAgICAgIF0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICovCgkJInNTb3J0RGF0YVR5cGUiOiAic3RkIiwKCQoJCgkJLyoqCgkJICogVGhlIHRpdGxlIG9mIHRoaXMgY29sdW1uLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbCA8aT5EZXJpdmVkIGZyb20gdGhlICdUSCcgdmFsdWUgZm9yIHRoaXMgY29sdW1uIGluIHRoZQoJCSAqICAgIG9yaWdpbmFsIEhUTUwgdGFibGUuPC9pPgoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4udGl0bGUKCQkgKiAgQGR0b3B0IENvbHVtbnMKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFVzaW5nIGBjb2x1bW5EZWZzYAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWwoJCSAqICAgICAgICAgIHsgInRpdGxlIjogIk15IGNvbHVtbiB0aXRsZSIsICJ0YXJnZXRzIjogWyAwIF0gfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbnMiOiBbCgkJICogICAgICAgICAgeyAidGl0bGUiOiAiTXkgY29sdW1uIHRpdGxlIiB9LAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwKCQkgKiAgICAgICAgXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic1RpdGxlIjogbnVsbCwKCQoJCgkJLyoqCgkJICogVGhlIHR5cGUgYWxsb3dzIHlvdSB0byBzcGVjaWZ5IGhvdyB0aGUgZGF0YSBmb3IgdGhpcyBjb2x1bW4gd2lsbCBiZQoJCSAqIG9yZGVyZWQuIEZvdXIgdHlwZXMgKHN0cmluZywgbnVtZXJpYywgZGF0ZSBhbmQgaHRtbCAod2hpY2ggd2lsbCBzdHJpcAoJCSAqIEhUTUwgdGFncyBiZWZvcmUgb3JkZXJpbmcpKSBhcmUgY3VycmVudGx5IGF2YWlsYWJsZS4gTm90ZSB0aGF0IG9ubHkgZGF0ZQoJCSAqIGZvcm1hdHMgdW5kZXJzdG9vZCBieSBKYXZhc2NyaXB0J3MgRGF0ZSgpIG9iamVjdCB3aWxsIGJlIGFjY2VwdGVkIGFzIHR5cGUKCQkgKiBkYXRlLiBGb3IgZXhhbXBsZTogIk1hciAyNiwgMjAwOCA1OjAzIFBNIi4gTWF5IHRha2UgdGhlIHZhbHVlczogJ3N0cmluZycsCgkJICogJ251bWVyaWMnLCAnZGF0ZScgb3IgJ2h0bWwnIChieSBkZWZhdWx0KS4gRnVydGhlciB0eXBlcyBjYW4gYmUgYWRkaW5nCgkJICogdGhyb3VnaCBwbHVnLWlucy4KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IG51bGwgPGk+QXV0by1kZXRlY3RlZCBmcm9tIHJhdyBkYXRhPC9pPgoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4udHlwZQoJCSAqICBAZHRvcHQgQ29sdW1ucwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbkRlZnMiOiBbCgkJICogICAgICAgICAgeyAidHlwZSI6ICJodG1sIiwgInRhcmdldHMiOiBbIDAgXSB9CgkJICogICAgICAgIF0KCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9ICk7CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBVc2luZyBgY29sdW1uc2AKCQkgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7CgkJICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSggewoJCSAqICAgICAgICAiY29sdW1ucyI6IFsKCQkgKiAgICAgICAgICB7ICJ0eXBlIjogImh0bWwiIH0sCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbAoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqLwoJCSJzVHlwZSI6IG51bGwsCgkKCQoJCS8qKgoJCSAqIERlZmluaW5nIHRoZSB3aWR0aCBvZiB0aGUgY29sdW1uLCB0aGlzIHBhcmFtZXRlciBtYXkgdGFrZSBhbnkgQ1NTIHZhbHVlCgkJICogKDNlbSwgMjBweCBldGMpLiBEYXRhVGFibGVzIGFwcGxpZXMgJ3NtYXJ0JyB3aWR0aHMgdG8gY29sdW1ucyB3aGljaCBoYXZlIG5vdAoJCSAqIGJlZW4gZ2l2ZW4gYSBzcGVjaWZpYyB3aWR0aCB0aHJvdWdoIHRoaXMgaW50ZXJmYWNlIGVuc3VyaW5nIHRoYXQgdGhlIHRhYmxlCgkJICogcmVtYWlucyByZWFkYWJsZS4KCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IG51bGwgPGk+QXV0b21hdGljPC9pPgoJCSAqCgkJICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4ud2lkdGgKCQkgKiAgQGR0b3B0IENvbHVtbnMKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIFVzaW5nIGBjb2x1bW5EZWZzYAoJCSAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHsKCQkgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7CgkJICogICAgICAgICJjb2x1bW5EZWZzIjogWwoJCSAqICAgICAgICAgIHsgIndpZHRoIjogIjIwJSIsICJ0YXJnZXRzIjogWyAwIF0gfQoJCSAqICAgICAgICBdCgkJICogICAgICB9ICk7CgkJICogICAgfSApOwoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVXNpbmcgYGNvbHVtbnNgCgkJICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkgewoJCSAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHsKCQkgKiAgICAgICAgImNvbHVtbnMiOiBbCgkJICogICAgICAgICAgeyAid2lkdGgiOiAiMjAlIiB9LAoJCSAqICAgICAgICAgIG51bGwsCgkJICogICAgICAgICAgbnVsbCwKCQkgKiAgICAgICAgICBudWxsLAoJCSAqICAgICAgICAgIG51bGwKCQkgKiAgICAgICAgXQoJCSAqICAgICAgfSApOwoJCSAqICAgIH0gKTsKCQkgKi8KCQkic1dpZHRoIjogbnVsbAoJfTsKCQoJX2ZuSHVuZ2FyaWFuTWFwKCBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uICk7CgkKCQoJCgkvKioKCSAqIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0IC0gdGhpcyBob2xkcyBhbGwgdGhlIGluZm9ybWF0aW9uIG5lZWRlZCBmb3IgYQoJICogZ2l2ZW4gdGFibGUsIGluY2x1ZGluZyBjb25maWd1cmF0aW9uLCBkYXRhIGFuZCBjdXJyZW50IGFwcGxpY2F0aW9uIG9mIHRoZQoJICogdGFibGUgb3B0aW9ucy4gRGF0YVRhYmxlcyBkb2VzIG5vdCBoYXZlIGEgc2luZ2xlIGluc3RhbmNlIGZvciBlYWNoIERhdGFUYWJsZQoJICogd2l0aCB0aGUgc2V0dGluZ3MgYXR0YWNoZWQgdG8gdGhhdCBpbnN0YW5jZSwgYnV0IHJhdGhlciBpbnN0YW5jZXMgb2YgdGhlCgkgKiBEYXRhVGFibGUgImNsYXNzIiBhcmUgY3JlYXRlZCBvbi10aGUtZmx5IGFzIG5lZWRlZCAodHlwaWNhbGx5IGJ5IGEKCSAqICQoKS5kYXRhVGFibGUoKSBjYWxsKSBhbmQgdGhlIHNldHRpbmdzIG9iamVjdCBpcyB0aGVuIGFwcGxpZWQgdG8gdGhhdAoJICogaW5zdGFuY2UuCgkgKgoJICogTm90ZSB0aGF0IHRoaXMgb2JqZWN0IGlzIHJlbGF0ZWQgdG8ge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30gYnV0IHRoaXMKCSAqIG9uZSBpcyB0aGUgaW50ZXJuYWwgZGF0YSBzdG9yZSBmb3IgRGF0YVRhYmxlcydzIGNhY2hlIG9mIGNvbHVtbnMuIEl0IHNob3VsZAoJICogTk9UIGJlIG1hbmlwdWxhdGVkIG91dHNpZGUgb2YgRGF0YVRhYmxlcy4gQW55IGNvbmZpZ3VyYXRpb24gc2hvdWxkIGJlIGRvbmUKCSAqIHRocm91Z2ggdGhlIGluaXRpYWxpc2F0aW9uIG9wdGlvbnMuCgkgKiAgQG5hbWVzcGFjZQoJICogIEB0b2RvIFJlYWxseSBzaG91bGQgYXR0YWNoIHRoZSBzZXR0aW5ncyBvYmplY3QgdG8gaW5kaXZpZHVhbCBpbnN0YW5jZXMgc28gd2UKCSAqICAgIGRvbid0IG5lZWQgdG8gY3JlYXRlIG5ldyBpbnN0YW5jZXMgb24gZWFjaCAkKCkuZGF0YVRhYmxlKCkgY2FsbCAoaWYgdGhlCgkgKiAgICB0YWJsZSBhbHJlYWR5IGV4aXN0cykuIEl0IHdvdWxkIGFsc28gc2F2ZSBwYXNzaW5nIG9TZXR0aW5ncyBhcm91bmQgYW5kCgkgKiAgICBpbnRvIGV2ZXJ5IHNpbmdsZSBmdW5jdGlvbi4gSG93ZXZlciwgdGhpcyBpcyBhIHZlcnkgc2lnbmlmaWNhbnQKCSAqICAgIGFyY2hpdGVjdHVyZSBjaGFuZ2UgZm9yIERhdGFUYWJsZXMgYW5kIHdpbGwgYWxtb3N0IGNlcnRhaW5seSBicmVhawoJICogICAgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgd2l0aCBvbGRlciBpbnN0YWxsYXRpb25zLiBUaGlzIGlzIHNvbWV0aGluZyB0aGF0CgkgKiAgICB3aWxsIGJlIGRvbmUgaW4gMi4wLgoJICovCglEYXRhVGFibGUubW9kZWxzLm9TZXR0aW5ncyA9IHsKCQkvKioKCQkgKiBQcmltYXJ5IGZlYXR1cmVzIG9mIERhdGFUYWJsZXMgYW5kIHRoZWlyIGVuYWJsZW1lbnQgc3RhdGUuCgkJICogIEBuYW1lc3BhY2UKCQkgKi8KCQkib0ZlYXR1cmVzIjogewoJCgkJCS8qKgoJCQkgKiBGbGFnIHRvIHNheSBpZiBEYXRhVGFibGVzIHNob3VsZCBhdXRvbWF0aWNhbGx5IHRyeSB0byBjYWxjdWxhdGUgdGhlCgkJCSAqIG9wdGltdW0gdGFibGUgYW5kIGNvbHVtbnMgd2lkdGhzICh0cnVlKSBvciBub3QgKGZhbHNlKS4KCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIGJvb2xlYW4KCQkJICovCgkJCSJiQXV0b1dpZHRoIjogbnVsbCwKCQoJCQkvKioKCQkJICogRGVsYXkgdGhlIGNyZWF0aW9uIG9mIFRSIGFuZCBURCBlbGVtZW50cyB1bnRpbCB0aGV5IGFyZSBhY3R1YWxseQoJCQkgKiBuZWVkZWQgYnkgYSBkcml2ZW4gcGFnZSBkcmF3LiBUaGlzIGNhbiBnaXZlIGEgc2lnbmlmaWNhbnQgc3BlZWQKCQkJICogaW5jcmVhc2UgZm9yIEFqYXggc291cmNlIGFuZCBKYXZhc2NyaXB0IHNvdXJjZSBkYXRhLCBidXQgbWFrZXMgbm8KCQkJICogZGlmZmVyZW5jZSBhdCBhbGwgZm9yIERPTSBhbmQgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyB0YWJsZXMuCgkJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkJICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uCgkJCSAqICBAdHlwZSBib29sZWFuCgkJCSAqLwoJCQkiYkRlZmVyUmVuZGVyIjogbnVsbCwKCQoJCQkvKioKCQkJICogRW5hYmxlIGZpbHRlcmluZyBvbiB0aGUgdGFibGUgb3Igbm90LiBOb3RlIHRoYXQgaWYgdGhpcyBpcyBkaXNhYmxlZAoJCQkgKiB0aGVuIHRoZXJlIGlzIG5vIGZpbHRlcmluZyBhdCBhbGwgb24gdGhlIHRhYmxlLCBpbmNsdWRpbmcgZm5GaWx0ZXIuCgkJCSAqIFRvIGp1c3QgcmVtb3ZlIHRoZSBmaWx0ZXJpbmcgaW5wdXQgdXNlIHNEb20gYW5kIHJlbW92ZSB0aGUgJ2YnIG9wdGlvbi4KCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIGJvb2xlYW4KCQkJICovCgkJCSJiRmlsdGVyIjogbnVsbCwKCQoJCQkvKioKCQkJICogVGFibGUgaW5mb3JtYXRpb24gZWxlbWVudCAodGhlICdTaG93aW5nIHggb2YgeSByZWNvcmRzJyBkaXYpIGVuYWJsZQoJCQkgKiBmbGFnLgoJCQkgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvCgkJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCQkgKiAgQHR5cGUgYm9vbGVhbgoJCQkgKi8KCQkJImJJbmZvIjogbnVsbCwKCQoJCQkvKioKCQkJICogUHJlc2VudCBhIHVzZXIgY29udHJvbCBhbGxvd2luZyB0aGUgZW5kIHVzZXIgdG8gY2hhbmdlIHRoZSBwYWdlIHNpemUKCQkJICogd2hlbiBwYWdpbmF0aW9uIGlzIGVuYWJsZWQuCgkJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkJICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uCgkJCSAqICBAdHlwZSBib29sZWFuCgkJCSAqLwoJCQkiYkxlbmd0aENoYW5nZSI6IG51bGwsCgkKCQkJLyoqCgkJCSAqIFBhZ2luYXRpb24gZW5hYmxlZCBvciBub3QuIE5vdGUgdGhhdCBpZiB0aGlzIGlzIGRpc2FibGVkIHRoZW4gbGVuZ3RoCgkJCSAqIGNoYW5naW5nIG11c3QgYWxzbyBiZSBkaXNhYmxlZC4KCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIGJvb2xlYW4KCQkJICovCgkJCSJiUGFnaW5hdGUiOiBudWxsLAoJCgkJCS8qKgoJCQkgKiBQcm9jZXNzaW5nIGluZGljYXRvciBlbmFibGUgZmxhZyB3aGVuZXZlciBEYXRhVGFibGVzIGlzIGVuYWN0aW5nIGEKCQkJICogdXNlciByZXF1ZXN0IC0gdHlwaWNhbGx5IGFuIEFqYXggcmVxdWVzdCBmb3Igc2VydmVyLXNpZGUgcHJvY2Vzc2luZy4KCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIGJvb2xlYW4KCQkJICovCgkJCSJiUHJvY2Vzc2luZyI6IG51bGwsCgkKCQkJLyoqCgkJCSAqIFNlcnZlci1zaWRlIHByb2Nlc3NpbmcgZW5hYmxlZCBmbGFnIC0gd2hlbiBlbmFibGVkIERhdGFUYWJsZXMgd2lsbAoJCQkgKiBnZXQgYWxsIGRhdGEgZnJvbSB0aGUgc2VydmVyIGZvciBldmVyeSBkcmF3IC0gdGhlcmUgaXMgbm8gZmlsdGVyaW5nLAoJCQkgKiBzb3J0aW5nIG9yIHBhZ2luZyBkb25lIG9uIHRoZSBjbGllbnQtc2lkZS4KCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIGJvb2xlYW4KCQkJICovCgkJCSJiU2VydmVyU2lkZSI6IG51bGwsCgkKCQkJLyoqCgkJCSAqIFNvcnRpbmcgZW5hYmxlbWVudCBmbGFnLgoJCQkgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvCgkJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCQkgKiAgQHR5cGUgYm9vbGVhbgoJCQkgKi8KCQkJImJTb3J0IjogbnVsbCwKCQoJCQkvKioKCQkJICogTXVsdGktY29sdW1uIHNvcnRpbmcKCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIGJvb2xlYW4KCQkJICovCgkJCSJiU29ydE11bHRpIjogbnVsbCwKCQoJCQkvKioKCQkJICogQXBwbHkgYSBjbGFzcyB0byB0aGUgY29sdW1ucyB3aGljaCBhcmUgYmVpbmcgc29ydGVkIHRvIHByb3ZpZGUgYQoJCQkgKiB2aXN1YWwgaGlnaGxpZ2h0IG9yIG5vdC4gVGhpcyBjYW4gc2xvdyB0aGluZ3MgZG93biB3aGVuIGVuYWJsZWQgc2luY2UKCQkJICogdGhlcmUgaXMgYSBsb3Qgb2YgRE9NIGludGVyYWN0aW9uLgoJCQkgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvCgkJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCQkgKiAgQHR5cGUgYm9vbGVhbgoJCQkgKi8KCQkJImJTb3J0Q2xhc3NlcyI6IG51bGwsCgkKCQkJLyoqCgkJCSAqIFN0YXRlIHNhdmluZyBlbmFibGVtZW50IGZsYWcuCgkJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkJICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uCgkJCSAqICBAdHlwZSBib29sZWFuCgkJCSAqLwoJCQkiYlN0YXRlU2F2ZSI6IG51bGwKCQl9LAoJCgkKCQkvKioKCQkgKiBTY3JvbGxpbmcgc2V0dGluZ3MgZm9yIGEgdGFibGUuCgkJICogIEBuYW1lc3BhY2UKCQkgKi8KCQkib1Njcm9sbCI6IHsKCQkJLyoqCgkJCSAqIFdoZW4gdGhlIHRhYmxlIGlzIHNob3J0ZXIgaW4gaGVpZ2h0IHRoYW4gc1Njcm9sbFksIGNvbGxhcHNlIHRoZQoJCQkgKiB0YWJsZSBjb250YWluZXIgZG93biB0byB0aGUgaGVpZ2h0IG9mIHRoZSB0YWJsZSAod2hlbiB0cnVlKS4KCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIGJvb2xlYW4KCQkJICovCgkJCSJiQ29sbGFwc2UiOiBudWxsLAoJCgkJCS8qKgoJCQkgKiBXaWR0aCBvZiB0aGUgc2Nyb2xsYmFyIGZvciB0aGUgd2ViLWJyb3dzZXIncyBwbGF0Zm9ybS4gQ2FsY3VsYXRlZAoJCQkgKiBkdXJpbmcgdGFibGUgaW5pdGlhbGlzYXRpb24uCgkJCSAqICBAdHlwZSBpbnQKCQkJICogIEBkZWZhdWx0IDAKCQkJICovCgkJCSJpQmFyV2lkdGgiOiAwLAoJCgkJCS8qKgoJCQkgKiBWaWV3cG9ydCB3aWR0aCBmb3IgaG9yaXpvbnRhbCBzY3JvbGxpbmcuIEhvcml6b250YWwgc2Nyb2xsaW5nIGlzCgkJCSAqIGRpc2FibGVkIGlmIGFuIGVtcHR5IHN0cmluZy4KCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIHN0cmluZwoJCQkgKi8KCQkJInNYIjogbnVsbCwKCQoJCQkvKioKCQkJICogV2lkdGggdG8gZXhwYW5kIHRoZSB0YWJsZSB0byB3aGVuIHVzaW5nIHgtc2Nyb2xsaW5nLiBUeXBpY2FsbHkgeW91CgkJCSAqIHNob3VsZCBub3QgbmVlZCB0byB1c2UgdGhpcy4KCQkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkJICogIEB0eXBlIHN0cmluZwoJCQkgKiAgQGRlcHJlY2F0ZWQKCQkJICovCgkJCSJzWElubmVyIjogbnVsbCwKCQoJCQkvKioKCQkJICogVmlld3BvcnQgaGVpZ2h0IGZvciB2ZXJ0aWNhbCBzY3JvbGxpbmcuIFZlcnRpY2FsIHNjcm9sbGluZyBpcyBkaXNhYmxlZAoJCQkgKiBpZiBhbiBlbXB0eSBzdHJpbmcuCgkJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkJICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uCgkJCSAqICBAdHlwZSBzdHJpbmcKCQkJICovCgkJCSJzWSI6IG51bGwKCQl9LAoJCgkJLyoqCgkJICogTGFuZ3VhZ2UgaW5mb3JtYXRpb24gZm9yIHRoZSB0YWJsZS4KCQkgKiAgQG5hbWVzcGFjZQoJCSAqICBAZXh0ZW5kcyBEYXRhVGFibGUuZGVmYXVsdHMub0xhbmd1YWdlCgkJICovCgkJIm9MYW5ndWFnZSI6IHsKCQkJLyoqCgkJCSAqIEluZm9ybWF0aW9uIGNhbGxiYWNrIGZ1bmN0aW9uLiBTZWUKCQkJICoge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0cy5mbkluZm9DYWxsYmFja30KCQkJICogIEB0eXBlIGZ1bmN0aW9uCgkJCSAqICBAZGVmYXVsdCBudWxsCgkJCSAqLwoJCQkiZm5JbmZvQ2FsbGJhY2siOiBudWxsCgkJfSwKCQoJCS8qKgoJCSAqIEJyb3dzZXIgc3VwcG9ydCBwYXJhbWV0ZXJzCgkJICogIEBuYW1lc3BhY2UKCQkgKi8KCQkib0Jyb3dzZXIiOiB7CgkJCS8qKgoJCQkgKiBJbmRpY2F0ZSBpZiB0aGUgYnJvd3NlciBpbmNvcnJlY3RseSBjYWxjdWxhdGVzIHdpZHRoOjEwMCUgaW5zaWRlIGEKCQkJICogc2Nyb2xsaW5nIGVsZW1lbnQgKElFNi83KQoJCQkgKiAgQHR5cGUgYm9vbGVhbgoJCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkJICovCgkJCSJiU2Nyb2xsT3ZlcnNpemUiOiBmYWxzZSwKCQoJCQkvKioKCQkJICogRGV0ZXJtaW5lIGlmIHRoZSB2ZXJ0aWNhbCBzY3JvbGxiYXIgaXMgb24gdGhlIHJpZ2h0IG9yIGxlZnQgb2YgdGhlCgkJCSAqIHNjcm9sbGluZyBjb250YWluZXIgLSBuZWVkZWQgZm9yIHJ0bCBsYW5ndWFnZSBsYXlvdXQsIGFsdGhvdWdoIG5vdAoJCQkgKiBhbGwgYnJvd3NlcnMgbW92ZSB0aGUgc2Nyb2xsYmFyIChTYWZhcmkpLgoJCQkgKiAgQHR5cGUgYm9vbGVhbgoJCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkJICovCgkJCSJiU2Nyb2xsYmFyTGVmdCI6IGZhbHNlLAoJCgkJCS8qKgoJCQkgKiBGbGFnIGZvciBpZiBgZ2V0Qm91bmRpbmdDbGllbnRSZWN0YCBpcyBmdWxseSBzdXBwb3J0ZWQgb3Igbm90CgkJCSAqICBAdHlwZSBib29sZWFuCgkJCSAqICBAZGVmYXVsdCBmYWxzZQoJCQkgKi8KCQkJImJCb3VuZGluZyI6IGZhbHNlLAoJCgkJCS8qKgoJCQkgKiBCcm93c2VyIHNjcm9sbGJhciB3aWR0aAoJCQkgKiAgQHR5cGUgaW50ZWdlcgoJCQkgKiAgQGRlZmF1bHQgMAoJCQkgKi8KCQkJImJhcldpZHRoIjogMAoJCX0sCgkKCQoJCSJhamF4IjogbnVsbCwKCQoJCgkJLyoqCgkJICogQXJyYXkgcmVmZXJlbmNpbmcgdGhlIG5vZGVzIHdoaWNoIGFyZSB1c2VkIGZvciB0aGUgZmVhdHVyZXMuIFRoZQoJCSAqIHBhcmFtZXRlcnMgb2YgdGhpcyBvYmplY3QgbWF0Y2ggd2hhdCBpcyBhbGxvd2VkIGJ5IHNEb20gLSBpLmUuCgkJICogICA8dWw+CgkJICogICAgIDxsaT4nbCcgLSBMZW5ndGggY2hhbmdpbmc8L2xpPgoJCSAqICAgICA8bGk+J2YnIC0gRmlsdGVyaW5nIGlucHV0PC9saT4KCQkgKiAgICAgPGxpPid0JyAtIFRoZSB0YWJsZSE8L2xpPgoJCSAqICAgICA8bGk+J2knIC0gSW5mb3JtYXRpb248L2xpPgoJCSAqICAgICA8bGk+J3AnIC0gUGFnaW5hdGlvbjwvbGk+CgkJICogICAgIDxsaT4ncicgLSBwUm9jZXNzaW5nPC9saT4KCQkgKiAgIDwvdWw+CgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtdCgkJICovCgkJImFhbkZlYXR1cmVzIjogW10sCgkKCQkvKioKCQkgKiBTdG9yZSBkYXRhIGluZm9ybWF0aW9uIC0gc2VlIHtAbGluayBEYXRhVGFibGUubW9kZWxzLm9Sb3d9IGZvciBkZXRhaWxlZAoJCSAqIGluZm9ybWF0aW9uLgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhb0RhdGEiOiBbXSwKCQoJCS8qKgoJCSAqIEFycmF5IG9mIGluZGV4ZXMgd2hpY2ggYXJlIGluIHRoZSBjdXJyZW50IGRpc3BsYXkgKGFmdGVyIGZpbHRlcmluZyBldGMpCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtdCgkJICovCgkJImFpRGlzcGxheSI6IFtdLAoJCgkJLyoqCgkJICogQXJyYXkgb2YgaW5kZXhlcyBmb3IgZGlzcGxheSAtIG5vIGZpbHRlcmluZwoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhaURpc3BsYXlNYXN0ZXIiOiBbXSwKCQoJCS8qKgoJCSAqIE1hcCBvZiByb3cgaWRzIHRvIGRhdGEgaW5kZXhlcwoJCSAqICBAdHlwZSBvYmplY3QKCQkgKiAgQGRlZmF1bHQge30KCQkgKi8KCQkiYUlkcyI6IHt9LAoJCgkJLyoqCgkJICogU3RvcmUgaW5mb3JtYXRpb24gYWJvdXQgZWFjaCBjb2x1bW4gdGhhdCBpcyBpbiB1c2UKCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9Db2x1bW5zIjogW10sCgkKCQkvKioKCQkgKiBTdG9yZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdGFibGUncyBoZWFkZXIKCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9IZWFkZXIiOiBbXSwKCQoJCS8qKgoJCSAqIFN0b3JlIGluZm9ybWF0aW9uIGFib3V0IHRoZSB0YWJsZSdzIGZvb3RlcgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhb0Zvb3RlciI6IFtdLAoJCgkJLyoqCgkJICogU3RvcmUgdGhlIGFwcGxpZWQgZ2xvYmFsIHNlYXJjaCBpbmZvcm1hdGlvbiBpbiBjYXNlIHdlIHdhbnQgdG8gZm9yY2UgYQoJCSAqIHJlc2VhcmNoIG9yIGNvbXBhcmUgdGhlIG9sZCBzZWFyY2ggdG8gYSBuZXcgb25lLgoJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkgKiAgQG5hbWVzcGFjZQoJCSAqICBAZXh0ZW5kcyBEYXRhVGFibGUubW9kZWxzLm9TZWFyY2gKCQkgKi8KCQkib1ByZXZpb3VzU2VhcmNoIjoge30sCgkKCQkvKioKCQkgKiBTdG9yZSB0aGUgYXBwbGllZCBzZWFyY2ggZm9yIGVhY2ggY29sdW1uIC0gc2VlCgkJICoge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NlYXJjaH0gZm9yIHRoZSBmb3JtYXQgdGhhdCBpcyB1c2VkIGZvciB0aGUKCQkgKiBmaWx0ZXJpbmcgaW5mb3JtYXRpb24gZm9yIGVhY2ggY29sdW1uLgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhb1ByZVNlYXJjaENvbHMiOiBbXSwKCQoJCS8qKgoJCSAqIFNvcnRpbmcgdGhhdCBpcyBhcHBsaWVkIHRvIHRoZSB0YWJsZS4gTm90ZSB0aGF0IHRoZSBpbm5lciBhcnJheXMgYXJlCgkJICogdXNlZCBpbiB0aGUgZm9sbG93aW5nIG1hbm5lcjoKCQkgKiA8dWw+CgkJICogICA8bGk+SW5kZXggMCAtIGNvbHVtbiBudW1iZXI8L2xpPgoJCSAqICAgPGxpPkluZGV4IDEgLSBjdXJyZW50IHNvcnRpbmcgZGlyZWN0aW9uPC9saT4KCQkgKiA8L3VsPgoJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQHRvZG8gVGhlc2UgaW5uZXIgYXJyYXlzIHNob3VsZCByZWFsbHkgYmUgb2JqZWN0cwoJCSAqLwoJCSJhYVNvcnRpbmciOiBudWxsLAoJCgkJLyoqCgkJICogU29ydGluZyB0aGF0IGlzIGFsd2F5cyBhcHBsaWVkIHRvIHRoZSB0YWJsZSAoaS5lLiBwcmVmaXhlZCBpbiBmcm9udCBvZgoJCSAqIGFhU29ydGluZykuCgkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhYVNvcnRpbmdGaXhlZCI6IFtdLAoJCgkJLyoqCgkJICogQ2xhc3NlcyB0byB1c2UgZm9yIHRoZSBzdHJpcGluZyBvZiBhIHRhYmxlLgoJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYXNTdHJpcGVDbGFzc2VzIjogbnVsbCwKCQoJCS8qKgoJCSAqIElmIHJlc3RvcmluZyBhIHRhYmxlIC0gd2Ugc2hvdWxkIHJlc3RvcmUgaXRzIHN0cmlwaW5nIGNsYXNzZXMgYXMgd2VsbAoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhc0Rlc3Ryb3lTdHJpcGVzIjogW10sCgkKCQkvKioKCQkgKiBJZiByZXN0b3JpbmcgYSB0YWJsZSAtIHdlIHNob3VsZCByZXN0b3JlIGl0cyB3aWR0aAoJCSAqICBAdHlwZSBpbnQKCQkgKiAgQGRlZmF1bHQgMAoJCSAqLwoJCSJzRGVzdHJveVdpZHRoIjogMCwKCQoJCS8qKgoJCSAqIENhbGxiYWNrIGZ1bmN0aW9ucyBhcnJheSBmb3IgZXZlcnkgdGltZSBhIHJvdyBpcyBpbnNlcnRlZCAoaS5lLiBvbiBhIGRyYXcpLgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhb1Jvd0NhbGxiYWNrIjogW10sCgkKCQkvKioKCQkgKiBDYWxsYmFjayBmdW5jdGlvbnMgZm9yIHRoZSBoZWFkZXIgb24gZWFjaCBkcmF3LgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhb0hlYWRlckNhbGxiYWNrIjogW10sCgkKCQkvKioKCQkgKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgdGhlIGZvb3RlciBvbiBlYWNoIGRyYXcuCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtdCgkJICovCgkJImFvRm9vdGVyQ2FsbGJhY2siOiBbXSwKCQoJCS8qKgoJCSAqIEFycmF5IG9mIGNhbGxiYWNrIGZ1bmN0aW9ucyBmb3IgZHJhdyBjYWxsYmFjayBmdW5jdGlvbnMKCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9EcmF3Q2FsbGJhY2siOiBbXSwKCQoJCS8qKgoJCSAqIEFycmF5IG9mIGNhbGxiYWNrIGZ1bmN0aW9ucyBmb3Igcm93IGNyZWF0ZWQgZnVuY3Rpb24KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9Sb3dDcmVhdGVkQ2FsbGJhY2siOiBbXSwKCQoJCS8qKgoJCSAqIENhbGxiYWNrIGZ1bmN0aW9ucyBmb3IganVzdCBiZWZvcmUgdGhlIHRhYmxlIGlzIHJlZHJhd24uIEEgcmV0dXJuIG9mCgkJICogZmFsc2Ugd2lsbCBiZSB1c2VkIHRvIGNhbmNlbCB0aGUgZHJhdy4KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9QcmVEcmF3Q2FsbGJhY2siOiBbXSwKCQoJCS8qKgoJCSAqIENhbGxiYWNrIGZ1bmN0aW9ucyBmb3Igd2hlbiB0aGUgdGFibGUgaGFzIGJlZW4gaW5pdGlhbGlzZWQuCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtdCgkJICovCgkJImFvSW5pdENvbXBsZXRlIjogW10sCgkKCQoJCS8qKgoJCSAqIENhbGxiYWNrcyBmb3IgbW9kaWZ5aW5nIHRoZSBzZXR0aW5ncyB0byBiZSBzdG9yZWQgZm9yIHN0YXRlIHNhdmluZywgcHJpb3IgdG8KCQkgKiBzYXZpbmcgc3RhdGUuCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtdCgkJICovCgkJImFvU3RhdGVTYXZlUGFyYW1zIjogW10sCgkKCQkvKioKCQkgKiBDYWxsYmFja3MgZm9yIG1vZGlmeWluZyB0aGUgc2V0dGluZ3MgdGhhdCBoYXZlIGJlZW4gc3RvcmVkIGZvciBzdGF0ZSBzYXZpbmcKCQkgKiBwcmlvciB0byB1c2luZyB0aGUgc3RvcmVkIHZhbHVlcyB0byByZXN0b3JlIHRoZSBzdGF0ZS4KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9TdGF0ZUxvYWRQYXJhbXMiOiBbXSwKCQoJCS8qKgoJCSAqIENhbGxiYWNrcyBmb3Igb3BlcmF0aW5nIG9uIHRoZSBzZXR0aW5ncyBvYmplY3Qgb25jZSB0aGUgc2F2ZWQgc3RhdGUgaGFzIGJlZW4KCQkgKiBsb2FkZWQKCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9TdGF0ZUxvYWRlZCI6IFtdLAoJCgkJLyoqCgkJICogQ2FjaGUgdGhlIHRhYmxlIElEIGZvciBxdWljayBhY2Nlc3MKCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IDxpPkVtcHR5IHN0cmluZzwvaT4KCQkgKi8KCQkic1RhYmxlSWQiOiAiIiwKCQoJCS8qKgoJCSAqIFRoZSBUQUJMRSBub2RlIGZvciB0aGUgbWFpbiB0YWJsZQoJCSAqICBAdHlwZSBub2RlCgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkiblRhYmxlIjogbnVsbCwKCQoJCS8qKgoJCSAqIFBlcm1hbmVudCByZWYgdG8gdGhlIHRoZWFkIGVsZW1lbnQKCQkgKiAgQHR5cGUgbm9kZQoJCSAqICBAZGVmYXVsdCBudWxsCgkJICovCgkJIm5USGVhZCI6IG51bGwsCgkKCQkvKioKCQkgKiBQZXJtYW5lbnQgcmVmIHRvIHRoZSB0Zm9vdCBlbGVtZW50IC0gaWYgaXQgZXhpc3RzCgkJICogIEB0eXBlIG5vZGUKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJuVEZvb3QiOiBudWxsLAoJCgkJLyoqCgkJICogUGVybWFuZW50IHJlZiB0byB0aGUgdGJvZHkgZWxlbWVudAoJCSAqICBAdHlwZSBub2RlCgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkiblRCb2R5IjogbnVsbCwKCQoJCS8qKgoJCSAqIENhY2hlIHRoZSB3cmFwcGVyIG5vZGUgKGNvbnRhaW5zIGFsbCBEYXRhVGFibGVzIGNvbnRyb2xsZWQgZWxlbWVudHMpCgkJICogIEB0eXBlIG5vZGUKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJuVGFibGVXcmFwcGVyIjogbnVsbCwKCQoJCS8qKgoJCSAqIEluZGljYXRlIGlmIHdoZW4gdXNpbmcgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyB0aGUgbG9hZGluZyBvZiBkYXRhCgkJICogc2hvdWxkIGJlIGRlZmVycmVkIHVudGlsIHRoZSBzZWNvbmQgZHJhdy4KCQkgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvCgkJICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uCgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkgKi8KCQkiYkRlZmVyTG9hZGluZyI6IGZhbHNlLAoJCgkJLyoqCgkJICogSW5kaWNhdGUgaWYgYWxsIHJlcXVpcmVkIGluZm9ybWF0aW9uIGhhcyBiZWVuIHJlYWQgaW4KCQkgKiAgQHR5cGUgYm9vbGVhbgoJCSAqICBAZGVmYXVsdCBmYWxzZQoJCSAqLwoJCSJiSW5pdGlhbGlzZWQiOiBmYWxzZSwKCQoJCS8qKgoJCSAqIEluZm9ybWF0aW9uIGFib3V0IG9wZW4gcm93cy4gRWFjaCBvYmplY3QgaW4gdGhlIGFycmF5IGhhcyB0aGUgcGFyYW1ldGVycwoJCSAqICduVHInIGFuZCAnblBhcmVudCcKCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9PcGVuUm93cyI6IFtdLAoJCgkJLyoqCgkJICogRGljdGF0ZSB0aGUgcG9zaXRpb25pbmcgb2YgRGF0YVRhYmxlcycgY29udHJvbCBlbGVtZW50cyAtIHNlZQoJCSAqIHtAbGluayBEYXRhVGFibGUubW9kZWwub0luaXQuc0RvbX0uCgkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJzRG9tIjogbnVsbCwKCQoJCS8qKgoJCSAqIFNlYXJjaCBkZWxheSAoaW4gbVMpCgkJICogIEB0eXBlIGludGVnZXIKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJzZWFyY2hEZWxheSI6IG51bGwsCgkKCQkvKioKCQkgKiBXaGljaCB0eXBlIG9mIHBhZ2luYXRpb24gc2hvdWxkIGJlIHVzZWQuCgkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgdHdvX2J1dHRvbgoJCSAqLwoJCSJzUGFnaW5hdGlvblR5cGUiOiAidHdvX2J1dHRvbiIsCgkKCQkvKioKCQkgKiBUaGUgc3RhdGUgZHVyYXRpb24gKGZvciBgc3RhdGVTYXZlYCkgaW4gc2Vjb25kcy4KCQkgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvCgkJICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uCgkJICogIEB0eXBlIGludAoJCSAqICBAZGVmYXVsdCAwCgkJICovCgkJImlTdGF0ZUR1cmF0aW9uIjogMCwKCQoJCS8qKgoJCSAqIEFycmF5IG9mIGNhbGxiYWNrIGZ1bmN0aW9ucyBmb3Igc3RhdGUgc2F2aW5nLiBFYWNoIGFycmF5IGVsZW1lbnQgaXMgYW4KCQkgKiBvYmplY3Qgd2l0aCB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6CgkJICogICA8dWw+CgkJICogICAgIDxsaT5mdW5jdGlvbjpmbiAtIGZ1bmN0aW9uIHRvIGNhbGwuIFRha2VzIHR3byBwYXJhbWV0ZXJzLCBvU2V0dGluZ3MKCQkgKiAgICAgICBhbmQgdGhlIEpTT04gc3RyaW5nIHRvIHNhdmUgdGhhdCBoYXMgYmVlbiB0aHVzIGZhciBjcmVhdGVkLiBSZXR1cm5zCgkJICogICAgICAgYSBKU09OIHN0cmluZyB0byBiZSBpbnNlcnRlZCBpbnRvIGEganNvbiBvYmplY3QKCQkgKiAgICAgICAoaS5lLiAnInBhcmFtIjogWyAwLCAxLCAyXScpPC9saT4KCQkgKiAgICAgPGxpPnN0cmluZzpzTmFtZSAtIG5hbWUgb2YgY2FsbGJhY2s8L2xpPgoJCSAqICAgPC91bD4KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9TdGF0ZVNhdmUiOiBbXSwKCQoJCS8qKgoJCSAqIEFycmF5IG9mIGNhbGxiYWNrIGZ1bmN0aW9ucyBmb3Igc3RhdGUgbG9hZGluZy4gRWFjaCBhcnJheSBlbGVtZW50IGlzIGFuCgkJICogb2JqZWN0IHdpdGggdGhlIGZvbGxvd2luZyBwYXJhbWV0ZXJzOgoJCSAqICAgPHVsPgoJCSAqICAgICA8bGk+ZnVuY3Rpb246Zm4gLSBmdW5jdGlvbiB0byBjYWxsLiBUYWtlcyB0d28gcGFyYW1ldGVycywgb1NldHRpbmdzCgkJICogICAgICAgYW5kIHRoZSBvYmplY3Qgc3RvcmVkLiBNYXkgcmV0dXJuIGZhbHNlIHRvIGNhbmNlbCBzdGF0ZSBsb2FkaW5nPC9saT4KCQkgKiAgICAgPGxpPnN0cmluZzpzTmFtZSAtIG5hbWUgb2YgY2FsbGJhY2s8L2xpPgoJCSAqICAgPC91bD4KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYW9TdGF0ZUxvYWQiOiBbXSwKCQoJCS8qKgoJCSAqIFN0YXRlIHRoYXQgd2FzIHNhdmVkLiBVc2VmdWwgZm9yIGJhY2sgcmVmZXJlbmNlCgkJICogIEB0eXBlIG9iamVjdAoJCSAqICBAZGVmYXVsdCBudWxsCgkJICovCgkJIm9TYXZlZFN0YXRlIjogbnVsbCwKCQoJCS8qKgoJCSAqIFN0YXRlIHRoYXQgd2FzIGxvYWRlZC4gVXNlZnVsIGZvciBiYWNrIHJlZmVyZW5jZQoJCSAqICBAdHlwZSBvYmplY3QKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJvTG9hZGVkU3RhdGUiOiBudWxsLAoJCgkJLyoqCgkJICogU291cmNlIHVybCBmb3IgQUpBWCBkYXRhIGZvciB0aGUgdGFibGUuCgkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJzQWpheFNvdXJjZSI6IG51bGwsCgkKCQkvKioKCQkgKiBQcm9wZXJ0eSBmcm9tIGEgZ2l2ZW4gb2JqZWN0IGZyb20gd2hpY2ggdG8gcmVhZCB0aGUgdGFibGUgZGF0YSBmcm9tLiBUaGlzCgkJICogY2FuIGJlIGFuIGVtcHR5IHN0cmluZyAod2hlbiBub3Qgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyksIGluIHdoaWNoIGNhc2UKCQkgKiBpdCBpcyAgYXNzdW1lZCBhbiBhbiBhcnJheSBpcyBnaXZlbiBkaXJlY3RseS4KCQkgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvCgkJICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uCgkJICogIEB0eXBlIHN0cmluZwoJCSAqLwoJCSJzQWpheERhdGFQcm9wIjogbnVsbCwKCQoJCS8qKgoJCSAqIFRoZSBsYXN0IGpRdWVyeSBYSFIgb2JqZWN0IHRoYXQgd2FzIHVzZWQgZm9yIHNlcnZlci1zaWRlIGRhdGEgZ2F0aGVyaW5nLgoJCSAqIFRoaXMgY2FuIGJlIHVzZWQgZm9yIHdvcmtpbmcgd2l0aCB0aGUgWEhSIGluZm9ybWF0aW9uIGluIG9uZSBvZiB0aGUKCQkgKiBjYWxsYmFja3MKCQkgKiAgQHR5cGUgb2JqZWN0CgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkianFYSFIiOiBudWxsLAoJCgkJLyoqCgkJICogSlNPTiByZXR1cm5lZCBmcm9tIHRoZSBzZXJ2ZXIgaW4gdGhlIGxhc3QgQWpheCByZXF1ZXN0CgkJICogIEB0eXBlIG9iamVjdAoJCSAqICBAZGVmYXVsdCB1bmRlZmluZWQKCQkgKi8KCQkianNvbiI6IHVuZGVmaW5lZCwKCQoJCS8qKgoJCSAqIERhdGEgc3VibWl0dGVkIGFzIHBhcnQgb2YgdGhlIGxhc3QgQWpheCByZXF1ZXN0CgkJICogIEB0eXBlIG9iamVjdAoJCSAqICBAZGVmYXVsdCB1bmRlZmluZWQKCQkgKi8KCQkib0FqYXhEYXRhIjogdW5kZWZpbmVkLAoJCgkJLyoqCgkJICogRnVuY3Rpb24gdG8gZ2V0IHRoZSBzZXJ2ZXItc2lkZSBkYXRhLgoJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKi8KCQkiZm5TZXJ2ZXJEYXRhIjogbnVsbCwKCQoJCS8qKgoJCSAqIEZ1bmN0aW9ucyB3aGljaCBhcmUgY2FsbGVkIHByaW9yIHRvIHNlbmRpbmcgYW4gQWpheCByZXF1ZXN0IHNvIGV4dHJhCgkJICogcGFyYW1ldGVycyBjYW4gZWFzaWx5IGJlIHNlbnQgdG8gdGhlIHNlcnZlcgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqLwoJCSJhb1NlcnZlclBhcmFtcyI6IFtdLAoJCgkJLyoqCgkJICogU2VuZCB0aGUgWEhSIEhUVFAgbWV0aG9kIC0gR0VUIG9yIFBPU1QgKGNvdWxkIGJlIFBVVCBvciBERUxFVEUgaWYKCQkgKiByZXF1aXJlZCkuCgkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKi8KCQkic1NlcnZlck1ldGhvZCI6IG51bGwsCgkKCQkvKioKCQkgKiBGb3JtYXQgbnVtYmVycyBmb3IgZGlzcGxheS4KCQkgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvCgkJICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uCgkJICogIEB0eXBlIGZ1bmN0aW9uCgkJICovCgkJImZuRm9ybWF0TnVtYmVyIjogbnVsbCwKCQoJCS8qKgoJCSAqIExpc3Qgb2Ygb3B0aW9ucyB0aGF0IGNhbiBiZSB1c2VkIGZvciB0aGUgdXNlciBzZWxlY3RhYmxlIGxlbmd0aCBtZW51LgoJCSAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG8KCQkgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS4KCQkgKiAgQHR5cGUgYXJyYXkKCQkgKiAgQGRlZmF1bHQgW10KCQkgKi8KCQkiYUxlbmd0aE1lbnUiOiBudWxsLAoJCgkJLyoqCgkJICogQ291bnRlciBmb3IgdGhlIGRyYXdzIHRoYXQgdGhlIHRhYmxlIGRvZXMuIEFsc28gdXNlZCBhcyBhIHRyYWNrZXIgZm9yCgkJICogc2VydmVyLXNpZGUgcHJvY2Vzc2luZwoJCSAqICBAdHlwZSBpbnQKCQkgKiAgQGRlZmF1bHQgMAoJCSAqLwoJCSJpRHJhdyI6IDAsCgkKCQkvKioKCQkgKiBJbmRpY2F0ZSBpZiBhIHJlZHJhdyBpcyBiZWluZyBkb25lIC0gdXNlZnVsIGZvciBBamF4CgkJICogIEB0eXBlIGJvb2xlYW4KCQkgKiAgQGRlZmF1bHQgZmFsc2UKCQkgKi8KCQkiYkRyYXdpbmciOiBmYWxzZSwKCQoJCS8qKgoJCSAqIERyYXcgaW5kZXggKGlEcmF3KSBvZiB0aGUgbGFzdCBlcnJvciB3aGVuIHBhcnNpbmcgdGhlIHJldHVybmVkIGRhdGEKCQkgKiAgQHR5cGUgaW50CgkJICogIEBkZWZhdWx0IC0xCgkJICovCgkJImlEcmF3RXJyb3IiOiAtMSwKCQoJCS8qKgoJCSAqIFBhZ2luZyBkaXNwbGF5IGxlbmd0aAoJCSAqICBAdHlwZSBpbnQKCQkgKiAgQGRlZmF1bHQgMTAKCQkgKi8KCQkiX2lEaXNwbGF5TGVuZ3RoIjogMTAsCgkKCQkvKioKCQkgKiBQYWdpbmcgc3RhcnQgcG9pbnQgLSBhaURpc3BsYXkgaW5kZXgKCQkgKiAgQHR5cGUgaW50CgkJICogIEBkZWZhdWx0IDAKCQkgKi8KCQkiX2lEaXNwbGF5U3RhcnQiOiAwLAoJCgkJLyoqCgkJICogU2VydmVyLXNpZGUgcHJvY2Vzc2luZyAtIG51bWJlciBvZiByZWNvcmRzIGluIHRoZSByZXN1bHQgc2V0CgkJICogKGkuZS4gYmVmb3JlIGZpbHRlcmluZyksIFVzZSBmblJlY29yZHNUb3RhbCByYXRoZXIgdGhhbgoJCSAqIHRoaXMgcHJvcGVydHkgdG8gZ2V0IHRoZSB2YWx1ZSBvZiB0aGUgbnVtYmVyIG9mIHJlY29yZHMsIHJlZ2FyZGxlc3Mgb2YKCQkgKiB0aGUgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyBzZXR0aW5nLgoJCSAqICBAdHlwZSBpbnQKCQkgKiAgQGRlZmF1bHQgMAoJCSAqICBAcHJpdmF0ZQoJCSAqLwoJCSJfaVJlY29yZHNUb3RhbCI6IDAsCgkKCQkvKioKCQkgKiBTZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIC0gbnVtYmVyIG9mIHJlY29yZHMgaW4gdGhlIGN1cnJlbnQgZGlzcGxheSBzZXQKCQkgKiAoaS5lLiBhZnRlciBmaWx0ZXJpbmcpLiBVc2UgZm5SZWNvcmRzRGlzcGxheSByYXRoZXIgdGhhbgoJCSAqIHRoaXMgcHJvcGVydHkgdG8gZ2V0IHRoZSB2YWx1ZSBvZiB0aGUgbnVtYmVyIG9mIHJlY29yZHMsIHJlZ2FyZGxlc3Mgb2YKCQkgKiB0aGUgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyBzZXR0aW5nLgoJCSAqICBAdHlwZSBib29sZWFuCgkJICogIEBkZWZhdWx0IDAKCQkgKiAgQHByaXZhdGUKCQkgKi8KCQkiX2lSZWNvcmRzRGlzcGxheSI6IDAsCgkKCQkvKioKCQkgKiBUaGUgY2xhc3NlcyB0byB1c2UgZm9yIHRoZSB0YWJsZQoJCSAqICBAdHlwZSBvYmplY3QKCQkgKiAgQGRlZmF1bHQge30KCQkgKi8KCQkib0NsYXNzZXMiOiB7fSwKCQoJCS8qKgoJCSAqIEZsYWcgYXR0YWNoZWQgdG8gdGhlIHNldHRpbmdzIG9iamVjdCBzbyB5b3UgY2FuIGNoZWNrIGluIHRoZSBkcmF3CgkJICogY2FsbGJhY2sgaWYgZmlsdGVyaW5nIGhhcyBiZWVuIGRvbmUgaW4gdGhlIGRyYXcuIERlcHJlY2F0ZWQgaW4gZmF2b3VyIG9mCgkJICogZXZlbnRzLgoJCSAqICBAdHlwZSBib29sZWFuCgkJICogIEBkZWZhdWx0IGZhbHNlCgkJICogIEBkZXByZWNhdGVkCgkJICovCgkJImJGaWx0ZXJlZCI6IGZhbHNlLAoJCgkJLyoqCgkJICogRmxhZyBhdHRhY2hlZCB0byB0aGUgc2V0dGluZ3Mgb2JqZWN0IHNvIHlvdSBjYW4gY2hlY2sgaW4gdGhlIGRyYXcKCQkgKiBjYWxsYmFjayBpZiBzb3J0aW5nIGhhcyBiZWVuIGRvbmUgaW4gdGhlIGRyYXcuIERlcHJlY2F0ZWQgaW4gZmF2b3VyIG9mCgkJICogZXZlbnRzLgoJCSAqICBAdHlwZSBib29sZWFuCgkJICogIEBkZWZhdWx0IGZhbHNlCgkJICogIEBkZXByZWNhdGVkCgkJICovCgkJImJTb3J0ZWQiOiBmYWxzZSwKCQoJCS8qKgoJCSAqIEluZGljYXRlIHRoYXQgaWYgbXVsdGlwbGUgcm93cyBhcmUgaW4gdGhlIGhlYWRlciBhbmQgdGhlcmUgaXMgbW9yZSB0aGFuCgkJICogb25lIHVuaXF1ZSBjZWxsIHBlciBjb2x1bW4sIGlmIHRoZSB0b3Agb25lICh0cnVlKSBvciBib3R0b20gb25lIChmYWxzZSkKCQkgKiBzaG91bGQgYmUgdXNlZCBmb3Igc29ydGluZyAvIHRpdGxlIGJ5IERhdGFUYWJsZXMuCgkJICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUbwoJCSAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LgoJCSAqICBAdHlwZSBib29sZWFuCgkJICovCgkJImJTb3J0Q2VsbHNUb3AiOiBudWxsLAoJCgkJLyoqCgkJICogSW5pdGlhbGlzYXRpb24gb2JqZWN0IHRoYXQgaXMgdXNlZCBmb3IgdGhlIHRhYmxlCgkJICogIEB0eXBlIG9iamVjdAoJCSAqICBAZGVmYXVsdCBudWxsCgkJICovCgkJIm9Jbml0IjogbnVsbCwKCQoJCS8qKgoJCSAqIERlc3Ryb3kgY2FsbGJhY2sgZnVuY3Rpb25zIC0gZm9yIHBsdWctaW5zIHRvIGF0dGFjaCB0aGVtc2VsdmVzIHRvIHRoZQoJCSAqIGRlc3Ryb3kgc28gdGhleSBjYW4gY2xlYW4gdXAgbWFya3VwIGFuZCBldmVudHMuCgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtdCgkJICovCgkJImFvRGVzdHJveUNhbGxiYWNrIjogW10sCgkKCQoJCS8qKgoJCSAqIEdldCB0aGUgbnVtYmVyIG9mIHJlY29yZHMgaW4gdGhlIGN1cnJlbnQgcmVjb3JkIHNldCwgYmVmb3JlIGZpbHRlcmluZwoJCSAqICBAdHlwZSBmdW5jdGlvbgoJCSAqLwoJCSJmblJlY29yZHNUb3RhbCI6IGZ1bmN0aW9uICgpCgkJewoJCQlyZXR1cm4gX2ZuRGF0YVNvdXJjZSggdGhpcyApID09ICdzc3AnID8KCQkJCXRoaXMuX2lSZWNvcmRzVG90YWwgKiAxIDoKCQkJCXRoaXMuYWlEaXNwbGF5TWFzdGVyLmxlbmd0aDsKCQl9LAoJCgkJLyoqCgkJICogR2V0IHRoZSBudW1iZXIgb2YgcmVjb3JkcyBpbiB0aGUgY3VycmVudCByZWNvcmQgc2V0LCBhZnRlciBmaWx0ZXJpbmcKCQkgKiAgQHR5cGUgZnVuY3Rpb24KCQkgKi8KCQkiZm5SZWNvcmRzRGlzcGxheSI6IGZ1bmN0aW9uICgpCgkJewoJCQlyZXR1cm4gX2ZuRGF0YVNvdXJjZSggdGhpcyApID09ICdzc3AnID8KCQkJCXRoaXMuX2lSZWNvcmRzRGlzcGxheSAqIDEgOgoJCQkJdGhpcy5haURpc3BsYXkubGVuZ3RoOwoJCX0sCgkKCQkvKioKCQkgKiBHZXQgdGhlIGRpc3BsYXkgZW5kIHBvaW50IC0gYWlEaXNwbGF5IGluZGV4CgkJICogIEB0eXBlIGZ1bmN0aW9uCgkJICovCgkJImZuRGlzcGxheUVuZCI6IGZ1bmN0aW9uICgpCgkJewoJCQl2YXIKCQkJCWxlbiAgICAgID0gdGhpcy5faURpc3BsYXlMZW5ndGgsCgkJCQlzdGFydCAgICA9IHRoaXMuX2lEaXNwbGF5U3RhcnQsCgkJCQljYWxjICAgICA9IHN0YXJ0ICsgbGVuLAoJCQkJcmVjb3JkcyAgPSB0aGlzLmFpRGlzcGxheS5sZW5ndGgsCgkJCQlmZWF0dXJlcyA9IHRoaXMub0ZlYXR1cmVzLAoJCQkJcGFnaW5hdGUgPSBmZWF0dXJlcy5iUGFnaW5hdGU7CgkKCQkJaWYgKCBmZWF0dXJlcy5iU2VydmVyU2lkZSApIHsKCQkJCXJldHVybiBwYWdpbmF0ZSA9PT0gZmFsc2UgfHwgbGVuID09PSAtMSA/CgkJCQkJc3RhcnQgKyByZWNvcmRzIDoKCQkJCQlNYXRoLm1pbiggc3RhcnQrbGVuLCB0aGlzLl9pUmVjb3Jkc0Rpc3BsYXkgKTsKCQkJfQoJCQllbHNlIHsKCQkJCXJldHVybiAhIHBhZ2luYXRlIHx8IGNhbGM+cmVjb3JkcyB8fCBsZW49PT0tMSA/CgkJCQkJcmVjb3JkcyA6CgkJCQkJY2FsYzsKCQkJfQoJCX0sCgkKCQkvKioKCQkgKiBUaGUgRGF0YVRhYmxlcyBvYmplY3QgZm9yIHRoaXMgdGFibGUKCQkgKiAgQHR5cGUgb2JqZWN0CgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkib0luc3RhbmNlIjogbnVsbCwKCQoJCS8qKgoJCSAqIFVuaXF1ZSBpZGVudGlmaWVyIGZvciBlYWNoIGluc3RhbmNlIG9mIHRoZSBEYXRhVGFibGVzIG9iamVjdC4gSWYgdGhlcmUKCQkgKiBpcyBhbiBJRCBvbiB0aGUgdGFibGUgbm9kZSwgdGhlbiBpdCB0YWtlcyB0aGF0IHZhbHVlLCBvdGhlcndpc2UgYW4KCQkgKiBpbmNyZW1lbnRpbmcgaW50ZXJuYWwgY291bnRlciBpcyB1c2VkLgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlZmF1bHQgbnVsbAoJCSAqLwoJCSJzSW5zdGFuY2UiOiBudWxsLAoJCgkJLyoqCgkJICogdGFiaW5kZXggYXR0cmlidXRlIHZhbHVlIHRoYXQgaXMgYWRkZWQgdG8gRGF0YVRhYmxlcyBjb250cm9sIGVsZW1lbnRzLCBhbGxvd2luZwoJCSAqIGtleWJvYXJkIG5hdmlnYXRpb24gb2YgdGhlIHRhYmxlIGFuZCBpdHMgY29udHJvbHMuCgkJICovCgkJImlUYWJJbmRleCI6IDAsCgkKCQkvKioKCQkgKiBESVYgY29udGFpbmVyIGZvciB0aGUgZm9vdGVyIHNjcm9sbGluZyB0YWJsZSBpZiBzY3JvbGxpbmcKCQkgKi8KCQkiblNjcm9sbEhlYWQiOiBudWxsLAoJCgkJLyoqCgkJICogRElWIGNvbnRhaW5lciBmb3IgdGhlIGZvb3RlciBzY3JvbGxpbmcgdGFibGUgaWYgc2Nyb2xsaW5nCgkJICovCgkJIm5TY3JvbGxGb290IjogbnVsbCwKCQoJCS8qKgoJCSAqIExhc3QgYXBwbGllZCBzb3J0CgkJICogIEB0eXBlIGFycmF5CgkJICogIEBkZWZhdWx0IFtdCgkJICovCgkJImFMYXN0U29ydCI6IFtdLAoJCgkJLyoqCgkJICogU3RvcmVkIHBsdWctaW4gaW5zdGFuY2VzCgkJICogIEB0eXBlIG9iamVjdAoJCSAqICBAZGVmYXVsdCB7fQoJCSAqLwoJCSJvUGx1Z2lucyI6IHt9LAoJCgkJLyoqCgkJICogRnVuY3Rpb24gdXNlZCB0byBnZXQgYSByb3cncyBpZCBmcm9tIHRoZSByb3cncyBkYXRhCgkJICogIEB0eXBlIGZ1bmN0aW9uCgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkicm93SWRGbiI6IG51bGwsCgkKCQkvKioKCQkgKiBEYXRhIGxvY2F0aW9uIHdoZXJlIHRvIHN0b3JlIGEgcm93J3MgaWQKCQkgKiAgQHR5cGUgc3RyaW5nCgkJICogIEBkZWZhdWx0IG51bGwKCQkgKi8KCQkicm93SWQiOiBudWxsCgl9OwoJCgkvKioKCSAqIEV4dGVuc2lvbiBvYmplY3QgZm9yIERhdGFUYWJsZXMgdGhhdCBpcyB1c2VkIHRvIHByb3ZpZGUgYWxsIGV4dGVuc2lvbgoJICogb3B0aW9ucy4KCSAqCgkgKiBOb3RlIHRoYXQgdGhlIGBEYXRhVGFibGUuZXh0YCBvYmplY3QgaXMgYXZhaWxhYmxlIHRocm91Z2gKCSAqIGBqUXVlcnkuZm4uZGF0YVRhYmxlLmV4dGAgd2hlcmUgaXQgbWF5IGJlIGFjY2Vzc2VkIGFuZCBtYW5pcHVsYXRlZC4gSXQgaXMKCSAqIGFsc28gYWxpYXNlZCB0byBgalF1ZXJ5LmZuLmRhdGFUYWJsZUV4dGAgZm9yIGhpc3RvcmljIHJlYXNvbnMuCgkgKiAgQG5hbWVzcGFjZQoJICogIEBleHRlbmRzIERhdGFUYWJsZS5tb2RlbHMuZXh0CgkgKi8KCQoJCgkvKioKCSAqIERhdGFUYWJsZXMgZXh0ZW5zaW9ucwoJICogCgkgKiBUaGlzIG5hbWVzcGFjZSBhY3RzIGFzIGEgY29sbGVjdGlvbiBhcmVhIGZvciBwbHVnLWlucyB0aGF0IGNhbiBiZSB1c2VkIHRvCgkgKiBleHRlbmQgRGF0YVRhYmxlcyBjYXBhYmlsaXRpZXMuIEluZGVlZCBtYW55IG9mIHRoZSBidWlsZCBpbiBtZXRob2RzCgkgKiB1c2UgdGhpcyBtZXRob2QgdG8gcHJvdmlkZSB0aGVpciBvd24gY2FwYWJpbGl0aWVzIChzb3J0aW5nIG1ldGhvZHMgZm9yCgkgKiBleGFtcGxlKS4KCSAqCgkgKiBOb3RlIHRoYXQgdGhpcyBuYW1lc3BhY2UgaXMgYWxpYXNlZCB0byBgalF1ZXJ5LmZuLmRhdGFUYWJsZUV4dGAgZm9yIGxlZ2FjeQoJICogcmVhc29ucwoJICoKCSAqICBAbmFtZXNwYWNlCgkgKi8KCURhdGFUYWJsZS5leHQgPSBfZXh0ID0gewoJCS8qKgoJCSAqIEJ1dHRvbnMuIEZvciB1c2Ugd2l0aCB0aGUgQnV0dG9ucyBleHRlbnNpb24gZm9yIERhdGFUYWJsZXMuIFRoaXMgaXMKCQkgKiBkZWZpbmVkIGhlcmUgc28gb3RoZXIgZXh0ZW5zaW9ucyBjYW4gZGVmaW5lIGJ1dHRvbnMgcmVnYXJkbGVzcyBvZiBsb2FkCgkJICogb3JkZXIuIEl0IGlzIF9ub3RfIHVzZWQgYnkgRGF0YVRhYmxlcyBjb3JlLgoJCSAqCgkJICogIEB0eXBlIG9iamVjdAoJCSAqICBAZGVmYXVsdCB7fQoJCSAqLwoJCWJ1dHRvbnM6IHt9LAoJCgkKCQkvKioKCQkgKiBFbGVtZW50IGNsYXNzIG5hbWVzCgkJICoKCQkgKiAgQHR5cGUgb2JqZWN0CgkJICogIEBkZWZhdWx0IHt9CgkJICovCgkJY2xhc3Nlczoge30sCgkKCQoJCS8qKgoJCSAqIERhdGFUYWJsZXMgYnVpbGQgdHlwZSAoZXhwYW5kZWQgYnkgdGhlIGRvd25sb2FkIGJ1aWxkZXIpCgkJICoKCQkgKiAgQHR5cGUgc3RyaW5nCgkJICovCgkJYnVpbGRlcjogIi1zb3VyY2UtIiwKCQoJCgkJLyoqCgkJICogRXJyb3IgcmVwb3J0aW5nLgoJCSAqIAoJCSAqIEhvdyBzaG91bGQgRGF0YVRhYmxlcyByZXBvcnQgYW4gZXJyb3IuIENhbiB0YWtlIHRoZSB2YWx1ZSAnYWxlcnQnLAoJCSAqICd0aHJvdycsICdub25lJyBvciBhIGZ1bmN0aW9uLgoJCSAqCgkJICogIEB0eXBlIHN0cmluZ3xmdW5jdGlvbgoJCSAqICBAZGVmYXVsdCBhbGVydAoJCSAqLwoJCWVyck1vZGU6ICJhbGVydCIsCgkKCQoJCS8qKgoJCSAqIEZlYXR1cmUgcGx1Zy1pbnMuCgkJICogCgkJICogVGhpcyBpcyBhbiBhcnJheSBvZiBvYmplY3RzIHdoaWNoIGRlc2NyaWJlIHRoZSBmZWF0dXJlIHBsdWctaW5zIHRoYXQgYXJlCgkJICogYXZhaWxhYmxlIHRvIERhdGFUYWJsZXMuIFRoZXNlIGZlYXR1cmUgcGx1Zy1pbnMgYXJlIHRoZW4gYXZhaWxhYmxlIGZvcgoJCSAqIHVzZSB0aHJvdWdoIHRoZSBgZG9tYCBpbml0aWFsaXNhdGlvbiBvcHRpb24uCgkJICogCgkJICogRWFjaCBmZWF0dXJlIHBsdWctaW4gaXMgZGVzY3JpYmVkIGJ5IGFuIG9iamVjdCB3aGljaCBtdXN0IGhhdmUgdGhlCgkJICogZm9sbG93aW5nIHByb3BlcnRpZXM6CgkJICogCgkJICogKiBgZm5Jbml0YCAtIGZ1bmN0aW9uIHRoYXQgaXMgdXNlZCB0byBpbml0aWFsaXNlIHRoZSBwbHVnLWluLAoJCSAqICogYGNGZWF0dXJlYCAtIGEgY2hhcmFjdGVyIHNvIHRoZSBmZWF0dXJlIGNhbiBiZSBlbmFibGVkIGJ5IHRoZSBgZG9tYAoJCSAqICAgaW5zdGlsbGF0aW9uIG9wdGlvbi4gVGhpcyBpcyBjYXNlIHNlbnNpdGl2ZS4KCQkgKgoJCSAqIFRoZSBgZm5Jbml0YCBmdW5jdGlvbiBoYXMgdGhlIGZvbGxvd2luZyBpbnB1dCBwYXJhbWV0ZXJzOgoJCSAqCgkJICogMS4gYHtvYmplY3R9YCBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdDogc2VlCgkJICogICAge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfQoJCSAqCgkJICogQW5kIHRoZSBmb2xsb3dpbmcgcmV0dXJuIGlzIGV4cGVjdGVkOgoJCSAqIAoJCSAqICoge25vZGV8bnVsbH0gVGhlIGVsZW1lbnQgd2hpY2ggY29udGFpbnMgeW91ciBmZWF0dXJlLiBOb3RlIHRoYXQgdGhlCgkJICogICByZXR1cm4gbWF5IGFsc28gYmUgdm9pZCBpZiB5b3VyIHBsdWctaW4gZG9lcyBub3QgcmVxdWlyZSB0byBpbmplY3QgYW55CgkJICogICBET00gZWxlbWVudHMgaW50byBEYXRhVGFibGVzIGNvbnRyb2wgKGBkb21gKSAtIGZvciBleGFtcGxlIHRoaXMgbWlnaHQKCQkgKiAgIGJlIHVzZWZ1bCB3aGVuIGRldmVsb3BpbmcgYSBwbHVnLWluIHdoaWNoIGFsbG93cyB0YWJsZSBjb250cm9sIHZpYQoJCSAqICAga2V5Ym9hcmQgZW50cnkKCQkgKgoJCSAqICBAdHlwZSBhcnJheQoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgJC5mbi5kYXRhVGFibGUuZXh0LmZlYXR1cmVzLnB1c2goIHsKCQkgKiAgICAgICJmbkluaXQiOiBmdW5jdGlvbiggb1NldHRpbmdzICkgewoJCSAqICAgICAgICByZXR1cm4gbmV3IFRhYmxlVG9vbHMoIHsgIm9EVFNldHRpbmdzIjogb1NldHRpbmdzIH0gKTsKCQkgKiAgICAgIH0sCgkJICogICAgICAiY0ZlYXR1cmUiOiAiVCIKCQkgKiAgICB9ICk7CgkJICovCgkJZmVhdHVyZTogW10sCgkKCQoJCS8qKgoJCSAqIFJvdyBzZWFyY2hpbmcuCgkJICogCgkJICogVGhpcyBtZXRob2Qgb2Ygc2VhcmNoaW5nIGlzIGNvbXBsaW1lbnRhcnkgdG8gdGhlIGRlZmF1bHQgdHlwZSBiYXNlZAoJCSAqIHNlYXJjaGluZywgYW5kIGEgbG90IG1vcmUgY29tcHJlaGVuc2l2ZSBhcyBpdCBhbGxvd3MgeW91IGNvbXBsZXRlIGNvbnRyb2wKCQkgKiBvdmVyIHRoZSBzZWFyY2hpbmcgbG9naWMuIEVhY2ggZWxlbWVudCBpbiB0aGlzIGFycmF5IGlzIGEgZnVuY3Rpb24KCQkgKiAocGFyYW1ldGVycyBkZXNjcmliZWQgYmVsb3cpIHRoYXQgaXMgY2FsbGVkIGZvciBldmVyeSByb3cgaW4gdGhlIHRhYmxlLAoJCSAqIGFuZCB5b3VyIGxvZ2ljIGRlY2lkZXMgaWYgaXQgc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZSBzZWFyY2hpbmcgZGF0YSBzZXQKCQkgKiBvciBub3QuCgkJICoKCQkgKiBTZWFyY2hpbmcgZnVuY3Rpb25zIGhhdmUgdGhlIGZvbGxvd2luZyBpbnB1dCBwYXJhbWV0ZXJzOgoJCSAqCgkJICogMS4gYHtvYmplY3R9YCBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdDogc2VlCgkJICogICAge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfQoJCSAqIDIuIGB7YXJyYXl8b2JqZWN0fWAgRGF0YSBmb3IgdGhlIHJvdyB0byBiZSBwcm9jZXNzZWQgKHNhbWUgYXMgdGhlCgkJICogICAgb3JpZ2luYWwgZm9ybWF0IHRoYXQgd2FzIHBhc3NlZCBpbiBhcyB0aGUgZGF0YSBzb3VyY2UsIG9yIGFuIGFycmF5CgkJICogICAgZnJvbSBhIERPTSBkYXRhIHNvdXJjZQoJCSAqIDMuIGB7aW50fWAgUm93IGluZGV4ICh7QGxpbmsgRGF0YVRhYmxlLm1vZGVscy5vU2V0dGluZ3MuYW9EYXRhfSksIHdoaWNoCgkJICogICAgY2FuIGJlIHVzZWZ1bCB0byByZXRyaWV2ZSB0aGUgYFRSYCBlbGVtZW50IGlmIHlvdSBuZWVkIERPTSBpbnRlcmFjdGlvbi4KCQkgKgoJCSAqIEFuZCB0aGUgZm9sbG93aW5nIHJldHVybiBpcyBleHBlY3RlZDoKCQkgKgoJCSAqICoge2Jvb2xlYW59IEluY2x1ZGUgdGhlIHJvdyBpbiB0aGUgc2VhcmNoZWQgcmVzdWx0IHNldCAodHJ1ZSkgb3Igbm90CgkJICogICAoZmFsc2UpCgkJICoKCQkgKiBOb3RlIHRoYXQgYXMgd2l0aCB0aGUgbWFpbiBzZWFyY2ggYWJpbGl0eSBpbiBEYXRhVGFibGVzLCB0ZWNobmljYWxseSB0aGlzCgkJICogaXMgImZpbHRlcmluZyIsIHNpbmNlIGl0IGlzIHN1YnRyYWN0aXZlLiBIb3dldmVyLCBmb3IgY29uc2lzdGVuY3kgaW4KCQkgKiBuYW1pbmcgd2UgY2FsbCBpdCBzZWFyY2hpbmcgaGVyZS4KCQkgKgoJCSAqICBAdHlwZSBhcnJheQoJCSAqICBAZGVmYXVsdCBbXQoJCSAqCgkJICogIEBleGFtcGxlCgkJICogICAgLy8gVGhlIGZvbGxvd2luZyBleGFtcGxlIHNob3dzIGN1c3RvbSBzZWFyY2ggYmVpbmcgYXBwbGllZCB0byB0aGUKCQkgKiAgICAvLyBmb3VydGggY29sdW1uIChpLmUuIHRoZSBkYXRhWzNdIGluZGV4KSBiYXNlZCBvbiB0d28gaW5wdXQgdmFsdWVzCgkJICogICAgLy8gZnJvbSB0aGUgZW5kLXVzZXIsIG1hdGNoaW5nIHRoZSBkYXRhIGluIGEgY2VydGFpbiByYW5nZS4KCQkgKiAgICAkLmZuLmRhdGFUYWJsZS5leHQuc2VhcmNoLnB1c2goCgkJICogICAgICBmdW5jdGlvbiggc2V0dGluZ3MsIGRhdGEsIGRhdGFJbmRleCApIHsKCQkgKiAgICAgICAgdmFyIG1pbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtaW4nKS52YWx1ZSAqIDE7CgkJICogICAgICAgIHZhciBtYXggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbWF4JykudmFsdWUgKiAxOwoJCSAqICAgICAgICB2YXIgdmVyc2lvbiA9IGRhdGFbM10gPT0gIi0iID8gMCA6IGRhdGFbM10qMTsKCQkgKgoJCSAqICAgICAgICBpZiAoIG1pbiA9PSAiIiAmJiBtYXggPT0gIiIgKSB7CgkJICogICAgICAgICAgcmV0dXJuIHRydWU7CgkJICogICAgICAgIH0KCQkgKiAgICAgICAgZWxzZSBpZiAoIG1pbiA9PSAiIiAmJiB2ZXJzaW9uIDwgbWF4ICkgewoJCSAqICAgICAgICAgIHJldHVybiB0cnVlOwoJCSAqICAgICAgICB9CgkJICogICAgICAgIGVsc2UgaWYgKCBtaW4gPCB2ZXJzaW9uICYmICIiID09IG1heCApIHsKCQkgKiAgICAgICAgICByZXR1cm4gdHJ1ZTsKCQkgKiAgICAgICAgfQoJCSAqICAgICAgICBlbHNlIGlmICggbWluIDwgdmVyc2lvbiAmJiB2ZXJzaW9uIDwgbWF4ICkgewoJCSAqICAgICAgICAgIHJldHVybiB0cnVlOwoJCSAqICAgICAgICB9CgkJICogICAgICAgIHJldHVybiBmYWxzZTsKCQkgKiAgICAgIH0KCQkgKiAgICApOwoJCSAqLwoJCXNlYXJjaDogW10sCgkKCQoJCS8qKgoJCSAqIFNlbGVjdG9yIGV4dGVuc2lvbnMKCQkgKgoJCSAqIFRoZSBgc2VsZWN0b3JgIG9wdGlvbiBjYW4gYmUgdXNlZCB0byBleHRlbmQgdGhlIG9wdGlvbnMgYXZhaWxhYmxlIGZvciB0aGUKCQkgKiBzZWxlY3RvciBtb2RpZmllciBvcHRpb25zIChgc2VsZWN0b3ItbW9kaWZpZXJgIG9iamVjdCBkYXRhIHR5cGUpIHRoYXQKCQkgKiBlYWNoIG9mIHRoZSB0aHJlZSBidWlsdCBpbiBzZWxlY3RvciB0eXBlcyBvZmZlciAocm93LCBjb2x1bW4gYW5kIGNlbGwgKwoJCSAqIHRoZWlyIHBsdXJhbCBjb3VudGVycGFydHMpLiBGb3IgZXhhbXBsZSB0aGUgU2VsZWN0IGV4dGVuc2lvbiB1c2VzIHRoaXMKCQkgKiBtZWNoYW5pc20gdG8gcHJvdmlkZSBhbiBvcHRpb24gdG8gc2VsZWN0IG9ubHkgcm93cywgY29sdW1ucyBhbmQgY2VsbHMKCQkgKiB0aGF0IGhhdmUgYmVlbiBtYXJrZWQgYXMgc2VsZWN0ZWQgYnkgdGhlIGVuZCB1c2VyIChge3NlbGVjdGVkOiB0cnVlfWApLAoJCSAqIHdoaWNoIGNhbiBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggdGhlIGV4aXN0aW5nIGJ1aWx0IGluIHNlbGVjdG9yCgkJICogb3B0aW9ucy4KCQkgKgoJCSAqIEVhY2ggcHJvcGVydHkgaXMgYW4gYXJyYXkgdG8gd2hpY2ggZnVuY3Rpb25zIGNhbiBiZSBwdXNoZWQuIFRoZSBmdW5jdGlvbnMKCQkgKiB0YWtlIHRocmVlIGF0dHJpYnV0ZXM6CgkJICoKCQkgKiAqIFNldHRpbmdzIG9iamVjdCBmb3IgdGhlIGhvc3QgdGFibGUKCQkgKiAqIE9wdGlvbnMgb2JqZWN0IChgc2VsZWN0b3ItbW9kaWZpZXJgIG9iamVjdCB0eXBlKQoJCSAqICogQXJyYXkgb2Ygc2VsZWN0ZWQgaXRlbSBpbmRleGVzCgkJICoKCQkgKiBUaGUgcmV0dXJuIGlzIGFuIGFycmF5IG9mIHRoZSByZXN1bHRpbmcgaXRlbSBpbmRleGVzIGFmdGVyIHRoZSBjdXN0b20KCQkgKiBzZWxlY3RvciBoYXMgYmVlbiBhcHBsaWVkLgoJCSAqCgkJICogIEB0eXBlIG9iamVjdAoJCSAqLwoJCXNlbGVjdG9yOiB7CgkJCWNlbGw6IFtdLAoJCQljb2x1bW46IFtdLAoJCQlyb3c6IFtdCgkJfSwKCQoJCgkJLyoqCgkJICogSW50ZXJuYWwgZnVuY3Rpb25zLCBleHBvc2VkIGZvciB1c2VkIGluIHBsdWctaW5zLgoJCSAqIAoJCSAqIFBsZWFzZSBub3RlIHRoYXQgeW91IHNob3VsZCBub3QgbmVlZCB0byB1c2UgdGhlIGludGVybmFsIG1ldGhvZHMgZm9yCgkJICogYW55dGhpbmcgb3RoZXIgdGhhbiBhIHBsdWctaW4gKGFuZCBldmVuIHRoZW4sIHRyeSB0byBhdm9pZCBpZiBwb3NzaWJsZSkuCgkJICogVGhlIGludGVybmFsIGZ1bmN0aW9uIG1heSBjaGFuZ2UgYmV0d2VlbiByZWxlYXNlcy4KCQkgKgoJCSAqICBAdHlwZSBvYmplY3QKCQkgKiAgQGRlZmF1bHQge30KCQkgKi8KCQlpbnRlcm5hbDoge30sCgkKCQoJCS8qKgoJCSAqIExlZ2FjeSBjb25maWd1cmF0aW9uIG9wdGlvbnMuIEVuYWJsZSBhbmQgZGlzYWJsZSBsZWdhY3kgb3B0aW9ucyB0aGF0CgkJICogYXJlIGF2YWlsYWJsZSBpbiBEYXRhVGFibGVzLgoJCSAqCgkJICogIEB0eXBlIG9iamVjdAoJCSAqLwoJCWxlZ2FjeTogewoJCQkvKioKCQkJICogRW5hYmxlIC8gZGlzYWJsZSBEYXRhVGFibGVzIDEuOSBjb21wYXRpYmxlIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcKCQkJICogcmVxdWVzdHMKCQkJICoKCQkJICogIEB0eXBlIGJvb2xlYW4KCQkJICogIEBkZWZhdWx0IG51bGwKCQkJICovCgkJCWFqYXg6IG51bGwKCQl9LAoJCgkKCQkvKioKCQkgKiBQYWdpbmF0aW9uIHBsdWctaW4gbWV0aG9kcy4KCQkgKiAKCQkgKiBFYWNoIGVudHJ5IGluIHRoaXMgb2JqZWN0IGlzIGEgZnVuY3Rpb24gYW5kIGRlZmluZXMgd2hpY2ggYnV0dG9ucyBzaG91bGQKCQkgKiBiZSBzaG93biBieSB0aGUgcGFnaW5hdGlvbiByZW5kZXJpbmcgbWV0aG9kIHRoYXQgaXMgdXNlZCBmb3IgdGhlIHRhYmxlOgoJCSAqIHtAbGluayBEYXRhVGFibGUuZXh0LnJlbmRlcmVyLnBhZ2VCdXR0b259LiBUaGUgcmVuZGVyZXIgYWRkcmVzc2VzIGhvdyB0aGUKCQkgKiBidXR0b25zIGFyZSBkaXNwbGF5ZWQgaW4gdGhlIGRvY3VtZW50LCB3aGlsZSB0aGUgZnVuY3Rpb25zIGhlcmUgdGVsbCBpdAoJCSAqIHdoYXQgYnV0dG9ucyB0byBkaXNwbGF5LiBUaGlzIGlzIGRvbmUgYnkgcmV0dXJuaW5nIGFuIGFycmF5IG9mIGJ1dHRvbgoJCSAqIGRlc2NyaXB0aW9ucyAod2hhdCBlYWNoIGJ1dHRvbiB3aWxsIGRvKS4KCQkgKgoJCSAqIFBhZ2luYXRpb24gdHlwZXMgKHRoZSBmb3VyIGJ1aWx0IGluIG9wdGlvbnMgYW5kIGFueSBhZGRpdGlvbmFsIHBsdWctaW4KCQkgKiBvcHRpb25zIGRlZmluZWQgaGVyZSkgY2FuIGJlIHVzZWQgdGhyb3VnaCB0aGUgYHBhZ2luYXRpb25UeXBlYAoJCSAqIGluaXRpYWxpc2F0aW9uIHBhcmFtZXRlci4KCQkgKgoJCSAqIFRoZSBmdW5jdGlvbnMgZGVmaW5lZCB0YWtlIHR3byBwYXJhbWV0ZXJzOgoJCSAqCgkJICogMS4gYHtpbnR9IHBhZ2VgIFRoZSBjdXJyZW50IHBhZ2UgaW5kZXgKCQkgKiAyLiBge2ludH0gcGFnZXNgIFRoZSBudW1iZXIgb2YgcGFnZXMgaW4gdGhlIHRhYmxlCgkJICoKCQkgKiBFYWNoIGZ1bmN0aW9uIGlzIGV4cGVjdGVkIHRvIHJldHVybiBhbiBhcnJheSB3aGVyZSBlYWNoIGVsZW1lbnQgb2YgdGhlCgkJICogYXJyYXkgY2FuIGJlIG9uZSBvZjoKCQkgKgoJCSAqICogYGZpcnN0YCAtIEp1bXAgdG8gZmlyc3QgcGFnZSB3aGVuIGFjdGl2YXRlZAoJCSAqICogYGxhc3RgIC0gSnVtcCB0byBsYXN0IHBhZ2Ugd2hlbiBhY3RpdmF0ZWQKCQkgKiAqIGBwcmV2aW91c2AgLSBTaG93IHByZXZpb3VzIHBhZ2Ugd2hlbiBhY3RpdmF0ZWQKCQkgKiAqIGBuZXh0YCAtIFNob3cgbmV4dCBwYWdlIHdoZW4gYWN0aXZhdGVkCgkJICogKiBge2ludH1gIC0gU2hvdyBwYWdlIG9mIHRoZSBpbmRleCBnaXZlbgoJCSAqICogYHthcnJheX1gIC0gQSBuZXN0ZWQgYXJyYXkgY29udGFpbmluZyB0aGUgYWJvdmUgZWxlbWVudHMgdG8gYWRkIGEKCQkgKiAgIGNvbnRhaW5pbmcgJ0RJVicgZWxlbWVudCAobWlnaHQgYmUgdXNlZnVsIGZvciBzdHlsaW5nKS4KCQkgKgoJCSAqIE5vdGUgdGhhdCBEYXRhVGFibGVzIHYxLjktIHVzZWQgdGhpcyBvYmplY3Qgc2xpZ2h0bHkgZGlmZmVyZW50bHkgd2hlcmVieQoJCSAqIGFuIG9iamVjdCB3aXRoIHR3byBmdW5jdGlvbnMgd291bGQgYmUgZGVmaW5lZCBmb3IgZWFjaCBwbHVnLWluLiBUaGF0CgkJICogYWJpbGl0eSBpcyBzdGlsbCBzdXBwb3J0ZWQgYnkgRGF0YVRhYmxlcyAxLjEwKyB0byBwcm92aWRlIGJhY2t3YXJkcwoJCSAqIGNvbXBhdGliaWxpdHksIGJ1dCB0aGlzIG9wdGlvbiBvZiB1c2UgaXMgbm93IGRlY3JlbWVudGVkIGFuZCBubyBsb25nZXIKCQkgKiBkb2N1bWVudGVkIGluIERhdGFUYWJsZXMgMS4xMCsuCgkJICoKCQkgKiAgQHR5cGUgb2JqZWN0CgkJICogIEBkZWZhdWx0IHt9CgkJICoKCQkgKiAgQGV4YW1wbGUKCQkgKiAgICAvLyBTaG93IHByZXZpb3VzLCBuZXh0IGFuZCBjdXJyZW50IHBhZ2UgYnV0dG9ucyBvbmx5CgkJICogICAgJC5mbi5kYXRhVGFibGVFeHQub1BhZ2luYXRpb24uY3VycmVudCA9IGZ1bmN0aW9uICggcGFnZSwgcGFnZXMgKSB7CgkJICogICAgICByZXR1cm4gWyAncHJldmlvdXMnLCBwYWdlLCAnbmV4dCcgXTsKCQkgKiAgICB9OwoJCSAqLwoJCXBhZ2VyOiB7fSwKCQoJCgkJcmVuZGVyZXI6IHsKCQkJcGFnZUJ1dHRvbjoge30sCgkJCWhlYWRlcjoge30KCQl9LAoJCgkKCQkvKioKCQkgKiBPcmRlcmluZyBwbHVnLWlucyAtIGN1c3RvbSBkYXRhIHNvdXJjZQoJCSAqIAoJCSAqIFRoZSBleHRlbnNpb24gb3B0aW9ucyBmb3Igb3JkZXJpbmcgb2YgZGF0YSBhdmFpbGFibGUgaGVyZSBpcyBjb21wbGltZW50YXJ5CgkJICogdG8gdGhlIGRlZmF1bHQgdHlwZSBiYXNlZCBvcmRlcmluZyB0aGF0IERhdGFUYWJsZXMgdHlwaWNhbGx5IHVzZXMuIEl0CgkJICogYWxsb3dzIG11Y2ggZ3JlYXRlciBjb250cm9sIG92ZXIgdGhlIHRoZSBkYXRhIHRoYXQgaXMgYmVpbmcgdXNlZCB0bwoJCSAqIG9yZGVyIGEgY29sdW1uLCBidXQgaXMgbmVjZXNzYXJpbHkgdGhlcmVmb3JlIG1vcmUgY29tcGxleC4KCQkgKiAKCQkgKiBUaGlzIHR5cGUgb2Ygb3JkZXJpbmcgaXMgdXNlZnVsIGlmIHlvdSB3YW50IHRvIGRvIG9yZGVyaW5nIGJhc2VkIG9uIGRhdGEKCQkgKiBsaXZlIGZyb20gdGhlIERPTSAoZm9yIGV4YW1wbGUgdGhlIGNvbnRlbnRzIG9mIGFuICdpbnB1dCcgZWxlbWVudCkgcmF0aGVyCgkJICogdGhhbiBqdXN0IHRoZSBzdGF0aWMgc3RyaW5nIHRoYXQgRGF0YVRhYmxlcyBrbm93cyBvZi4KCQkgKiAKCQkgKiBUaGUgd2F5IHRoZXNlIHBsdWctaW5zIHdvcmsgaXMgdGhhdCB5b3UgY3JlYXRlIGFuIGFycmF5IG9mIHRoZSB2YWx1ZXMgeW91CgkJICogd2lzaCB0byBiZSBvcmRlcmluZyBmb3IgdGhlIGNvbHVtbiBpbiBxdWVzdGlvbiBhbmQgdGhlbiByZXR1cm4gdGhhdAoJCSAqIGFycmF5LiBUaGUgZGF0YSBpbiB0aGUgYXJyYXkgbXVjaCBiZSBpbiB0aGUgaW5kZXggb3JkZXIgb2YgdGhlIHJvd3MgaW4KCQkgKiB0aGUgdGFibGUgKG5vdCB0aGUgY3VycmVudGx5IG9yZGVyaW5nIG9yZGVyISkuIFdoaWNoIG9yZGVyIGRhdGEgZ2F0aGVyaW5nCgkJICogZnVuY3Rpb24gaXMgcnVuIGhlcmUgZGVwZW5kcyBvbiB0aGUgYGR0LWluaXQgY29sdW1ucy5vcmRlckRhdGFUeXBlYAoJCSAqIHBhcmFtZXRlciB0aGF0IGlzIHVzZWQgZm9yIHRoZSBjb2x1bW4gKGlmIGFueSkuCgkJICoKCQkgKiBUaGUgZnVuY3Rpb25zIGRlZmluZWQgdGFrZSB0d28gcGFyYW1ldGVyczoKCQkgKgoJCSAqIDEuIGB7b2JqZWN0fWAgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Q6IHNlZQoJCSAqICAgIHtAbGluayBEYXRhVGFibGUubW9kZWxzLm9TZXR0aW5nc30KCQkgKiAyLiBge2ludH1gIFRhcmdldCBjb2x1bW4gaW5kZXgKCQkgKgoJCSAqIEVhY2ggZnVuY3Rpb24gaXMgZXhwZWN0ZWQgdG8gcmV0dXJuIGFuIGFycmF5OgoJCSAqCgkJICogKiBge2FycmF5fWAgRGF0YSBmb3IgdGhlIGNvbHVtbiB0byBiZSBvcmRlcmluZyB1cG9uCgkJICoKCQkgKiAgQHR5cGUgYXJyYXkKCQkgKgoJCSAqICBAZXhhbXBsZQoJCSAqICAgIC8vIE9yZGVyaW5nIHVzaW5nIGBpbnB1dGAgbm9kZSB2YWx1ZXMKCQkgKiAgICAkLmZuLmRhdGFUYWJsZS5leHQub3JkZXJbJ2RvbS10ZXh0J10gPSBmdW5jdGlvbiAgKCBzZXR0aW5ncywgY29sICkKCQkgKiAgICB7CgkJICogICAgICByZXR1cm4gdGhpcy5hcGkoKS5jb2x1bW4oIGNvbCwge29yZGVyOidpbmRleCd9ICkubm9kZXMoKS5tYXAoIGZ1bmN0aW9uICggdGQsIGkgKSB7CgkJICogICAgICAgIHJldHVybiAkKCdpbnB1dCcsIHRkKS52YWwoKTsKCQkgKiAgICAgIH0gKTsKCQkgKiAgICB9CgkJICovCgkJb3JkZXI6IHt9LAoJCgkKCQkvKioKCQkgKiBUeXBlIGJhc2VkIHBsdWctaW5zLgoJCSAqCgkJICogRWFjaCBjb2x1bW4gaW4gRGF0YVRhYmxlcyBoYXMgYSB0eXBlIGFzc2lnbmVkIHRvIGl0LCBlaXRoZXIgYnkgYXV0b21hdGljCgkJICogZGV0ZWN0aW9uIG9yIGJ5IGRpcmVjdCBhc3NpZ25tZW50IHVzaW5nIHRoZSBgdHlwZWAgb3B0aW9uIGZvciB0aGUgY29sdW1uLgoJCSAqIFRoZSB0eXBlIG9mIGEgY29sdW1uIHdpbGwgZWZmZWN0IGhvdyBpdCBpcyBvcmRlcmluZyBhbmQgc2VhcmNoIChwbHVnLWlucwoJCSAqIGNhbiBhbHNvIG1ha2UgdXNlIG9mIHRoZSBjb2x1bW4gdHlwZSBpZiByZXF1aXJlZCkuCgkJICoKCQkgKiBAbmFtZXNwYWNlCgkJICovCgkJdHlwZTogewoJCQkvKioKCQkJICogVHlwZSBkZXRlY3Rpb24gZnVuY3Rpb25zLgoJCQkgKgoJCQkgKiBUaGUgZnVuY3Rpb25zIGRlZmluZWQgaW4gdGhpcyBvYmplY3QgYXJlIHVzZWQgdG8gYXV0b21hdGljYWxseSBkZXRlY3QKCQkJICogYSBjb2x1bW4ncyB0eXBlLCBtYWtpbmcgaW5pdGlhbGlzYXRpb24gb2YgRGF0YVRhYmxlcyBzdXBlciBlYXN5LCBldmVuCgkJCSAqIHdoZW4gY29tcGxleCBkYXRhIGlzIGluIHRoZSB0YWJsZS4KCQkJICoKCQkJICogVGhlIGZ1bmN0aW9ucyBkZWZpbmVkIHRha2UgdHdvIHBhcmFtZXRlcnM6CgkJCSAqCgkJICAgICAqICAxLiBgeyp9YCBEYXRhIGZyb20gdGhlIGNvbHVtbiBjZWxsIHRvIGJlIGFuYWx5c2VkCgkJICAgICAqICAyLiBge3NldHRpbmdzfWAgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QuIFRoaXMgY2FuIGJlIHVzZWQgdG8KCQkgICAgICogICAgIHBlcmZvcm0gY29udGV4dCBzcGVjaWZpYyB0eXBlIGRldGVjdGlvbiAtIGZvciBleGFtcGxlIGRldGVjdGlvbgoJCSAgICAgKiAgICAgYmFzZWQgb24gbGFuZ3VhZ2Ugc2V0dGluZ3Mgc3VjaCBhcyB1c2luZyBhIGNvbW1hIGZvciBhIGRlY2ltYWwKCQkgICAgICogICAgIHBsYWNlLiBHZW5lcmFsbHkgc3BlYWtpbmcgdGhlIG9wdGlvbnMgZnJvbSB0aGUgc2V0dGluZ3Mgd2lsbCBub3QKCQkgICAgICogICAgIGJlIHJlcXVpcmVkCgkJCSAqCgkJCSAqIEVhY2ggZnVuY3Rpb24gaXMgZXhwZWN0ZWQgdG8gcmV0dXJuOgoJCQkgKgoJCQkgKiAqIGB7c3RyaW5nfG51bGx9YCBEYXRhIHR5cGUgZGV0ZWN0ZWQsIG9yIG51bGwgaWYgdW5rbm93biAoYW5kIHRodXMKCQkJICogICBwYXNzIGl0IG9uIHRvIHRoZSBvdGhlciB0eXBlIGRldGVjdGlvbiBmdW5jdGlvbnMuCgkJCSAqCgkJCSAqICBAdHlwZSBhcnJheQoJCQkgKgoJCQkgKiAgQGV4YW1wbGUKCQkJICogICAgLy8gQ3VycmVuY3kgdHlwZSBkZXRlY3Rpb24gcGx1Zy1pbjoKCQkJICogICAgJC5mbi5kYXRhVGFibGUuZXh0LnR5cGUuZGV0ZWN0LnB1c2goCgkJCSAqICAgICAgZnVuY3Rpb24gKCBkYXRhLCBzZXR0aW5ncyApIHsKCQkJICogICAgICAgIC8vIENoZWNrIHRoZSBudW1lcmljIHBhcnQKCQkJICogICAgICAgIGlmICggISBkYXRhLnN1YnN0cmluZygxKS5tYXRjaCgvWzAtOV0vKSApIHsKCQkJICogICAgICAgICAgcmV0dXJuIG51bGw7CgkJCSAqICAgICAgICB9CgkJCSAqCgkJCSAqICAgICAgICAvLyBDaGVjayBwcmVmaXhlZCBieSBjdXJyZW5jeQoJCQkgKiAgICAgICAgaWYgKCBkYXRhLmNoYXJBdCgwKSA9PSAnJCcgfHwgZGF0YS5jaGFyQXQoMCkgPT0gJyZwb3VuZDsnICkgewoJCQkgKiAgICAgICAgICByZXR1cm4gJ2N1cnJlbmN5JzsKCQkJICogICAgICAgIH0KCQkJICogICAgICAgIHJldHVybiBudWxsOwoJCQkgKiAgICAgIH0KCQkJICogICAgKTsKCQkJICovCgkJCWRldGVjdDogW10sCgkKCQoJCQkvKioKCQkJICogVHlwZSBiYXNlZCBzZWFyY2ggZm9ybWF0dGluZy4KCQkJICoKCQkJICogVGhlIHR5cGUgYmFzZWQgc2VhcmNoaW5nIGZ1bmN0aW9ucyBjYW4gYmUgdXNlZCB0byBwcmUtZm9ybWF0IHRoZQoJCQkgKiBkYXRhIHRvIGJlIHNlYXJjaCBvbi4gRm9yIGV4YW1wbGUsIGl0IGNhbiBiZSB1c2VkIHRvIHN0cmlwIEhUTUwKCQkJICogdGFncyBvciB0byBkZS1mb3JtYXQgdGVsZXBob25lIG51bWJlcnMgZm9yIG51bWVyaWMgb25seSBzZWFyY2hpbmcuCgkJCSAqCgkJCSAqIE5vdGUgdGhhdCBpcyBhIHNlYXJjaCBpcyBub3QgZGVmaW5lZCBmb3IgYSBjb2x1bW4gb2YgYSBnaXZlbiB0eXBlLAoJCQkgKiBubyBzZWFyY2ggZm9ybWF0dGluZyB3aWxsIGJlIHBlcmZvcm1lZC4KCQkJICogCgkJCSAqIFByZS1wcm9jZXNzaW5nIG9mIHNlYXJjaGluZyBkYXRhIHBsdWctaW5zIC0gV2hlbiB5b3UgYXNzaWduIHRoZSBzVHlwZQoJCQkgKiBmb3IgYSBjb2x1bW4gKG9yIGhhdmUgaXQgYXV0b21hdGljYWxseSBkZXRlY3RlZCBmb3IgeW91IGJ5IERhdGFUYWJsZXMKCQkJICogb3IgYSB0eXBlIGRldGVjdGlvbiBwbHVnLWluKSwgeW91IHdpbGwgdHlwaWNhbGx5IGJlIHVzaW5nIHRoaXMgZm9yCgkJCSAqIGN1c3RvbSBzb3J0aW5nLCBidXQgaXQgY2FuIGFsc28gYmUgdXNlZCB0byBwcm92aWRlIGN1c3RvbSBzZWFyY2hpbmcKCQkJICogYnkgYWxsb3dpbmcgeW91IHRvIHByZS1wcm9jZXNzaW5nIHRoZSBkYXRhIGFuZCByZXR1cm5pbmcgdGhlIGRhdGEgaW4KCQkJICogdGhlIGZvcm1hdCB0aGF0IHNob3VsZCBiZSBzZWFyY2hlZCB1cG9uLiBUaGlzIGlzIGRvbmUgYnkgYWRkaW5nCgkJCSAqIGZ1bmN0aW9ucyB0aGlzIG9iamVjdCB3aXRoIGEgcGFyYW1ldGVyIG5hbWUgd2hpY2ggbWF0Y2hlcyB0aGUgc1R5cGUKCQkJICogZm9yIHRoYXQgdGFyZ2V0IGNvbHVtbi4gVGhpcyBpcyB0aGUgY29yb2xsYXJ5IG9mIDxpPmFmblNvcnREYXRhPC9pPgoJCQkgKiBmb3Igc2VhcmNoaW5nIGRhdGEuCgkJCSAqCgkJCSAqIFRoZSBmdW5jdGlvbnMgZGVmaW5lZCB0YWtlIGEgc2luZ2xlIHBhcmFtZXRlcjoKCQkJICoKCQkgICAgICogIDEuIGB7Kn1gIERhdGEgZnJvbSB0aGUgY29sdW1uIGNlbGwgdG8gYmUgcHJlcGFyZWQgZm9yIHNlYXJjaGluZwoJCQkgKgoJCQkgKiBFYWNoIGZ1bmN0aW9uIGlzIGV4cGVjdGVkIHRvIHJldHVybjoKCQkJICoKCQkJICogKiBge3N0cmluZ3xudWxsfWAgRm9ybWF0dGVkIHN0cmluZyB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgdGhlIHNlYXJjaGluZy4KCQkJICoKCQkJICogIEB0eXBlIG9iamVjdAoJCQkgKiAgQGRlZmF1bHQge30KCQkJICoKCQkJICogIEBleGFtcGxlCgkJCSAqICAgICQuZm4uZGF0YVRhYmxlLmV4dC50eXBlLnNlYXJjaFsndGl0bGUtbnVtZXJpYyddID0gZnVuY3Rpb24gKCBkICkgewoJCQkgKiAgICAgIHJldHVybiBkLnJlcGxhY2UoL1xuL2csIiAiKS5yZXBsYWNlKCAvPC4qPz4vZywgIiIgKTsKCQkJICogICAgfQoJCQkgKi8KCQkJc2VhcmNoOiB7fSwKCQoJCgkJCS8qKgoJCQkgKiBUeXBlIGJhc2VkIG9yZGVyaW5nLgoJCQkgKgoJCQkgKiBUaGUgY29sdW1uIHR5cGUgdGVsbHMgRGF0YVRhYmxlcyB3aGF0IG9yZGVyaW5nIHRvIGFwcGx5IHRvIHRoZSB0YWJsZQoJCQkgKiB3aGVuIGEgY29sdW1uIGlzIHNvcnRlZCB1cG9uLiBUaGUgb3JkZXIgZm9yIGVhY2ggdHlwZSB0aGF0IGlzIGRlZmluZWQsCgkJCSAqIGlzIGRlZmluZWQgYnkgdGhlIGZ1bmN0aW9ucyBhdmFpbGFibGUgaW4gdGhpcyBvYmplY3QuCgkJCSAqCgkJCSAqIEVhY2ggb3JkZXJpbmcgb3B0aW9uIGNhbiBiZSBkZXNjcmliZWQgYnkgdGhyZWUgcHJvcGVydGllcyBhZGRlZCB0bwoJCQkgKiB0aGlzIG9iamVjdDoKCQkJICoKCQkJICogKiBge3R5cGV9LXByZWAgLSBQcmUtZm9ybWF0dGluZyBmdW5jdGlvbgoJCQkgKiAqIGB7dHlwZX0tYXNjYCAtIEFzY2VuZGluZyBvcmRlciBmdW5jdGlvbgoJCQkgKiAqIGB7dHlwZX0tZGVzY2AgLSBEZXNjZW5kaW5nIG9yZGVyIGZ1bmN0aW9uCgkJCSAqCgkJCSAqIEFsbCB0aHJlZSBjYW4gYmUgdXNlZCB0b2dldGhlciwgb25seSBge3R5cGV9LXByZWAgb3Igb25seQoJCQkgKiBge3R5cGV9LWFzY2AgYW5kIGB7dHlwZX0tZGVzY2AgdG9nZXRoZXIuIEl0IGlzIGdlbmVyYWxseSByZWNvbW1lbmRlZAoJCQkgKiB0aGF0IG9ubHkgYHt0eXBlfS1wcmVgIGlzIHVzZWQsIGFzIHRoaXMgcHJvdmlkZXMgdGhlIG9wdGltYWwKCQkJICogaW1wbGVtZW50YXRpb24gaW4gdGVybXMgb2Ygc3BlZWQsIGFsdGhvdWdoIHRoZSBvdGhlcnMgYXJlIHByb3ZpZGVkCgkJCSAqIGZvciBjb21wYXRpYmlsaXR5IHdpdGggZXhpc3RpbmcgSmF2YXNjcmlwdCBzb3J0IGZ1bmN0aW9ucy4KCQkJICoKCQkJICogYHt0eXBlfS1wcmVgOiBGdW5jdGlvbnMgZGVmaW5lZCB0YWtlIGEgc2luZ2xlIHBhcmFtZXRlcjoKCQkJICoKCQkgICAgICogIDEuIGB7Kn1gIERhdGEgZnJvbSB0aGUgY29sdW1uIGNlbGwgdG8gYmUgcHJlcGFyZWQgZm9yIG9yZGVyaW5nCgkJCSAqCgkJCSAqIEFuZCByZXR1cm46CgkJCSAqCgkJCSAqICogYHsqfWAgRGF0YSB0byBiZSBzb3J0ZWQgdXBvbgoJCQkgKgoJCQkgKiBge3R5cGV9LWFzY2AgYW5kIGB7dHlwZX0tZGVzY2A6IEZ1bmN0aW9ucyBhcmUgdHlwaWNhbCBKYXZhc2NyaXB0IHNvcnQKCQkJICogZnVuY3Rpb25zLCB0YWtpbmcgdHdvIHBhcmFtZXRlcnM6CgkJCSAqCgkJICAgICAqICAxLiBgeyp9YCBEYXRhIHRvIGNvbXBhcmUgdG8gdGhlIHNlY29uZCBwYXJhbWV0ZXIKCQkgICAgICogIDIuIGB7Kn1gIERhdGEgdG8gY29tcGFyZSB0byB0aGUgZmlyc3QgcGFyYW1ldGVyCgkJCSAqCgkJCSAqIEFuZCByZXR1cm5pbmc6CgkJCSAqCgkJCSAqICogYHsqfWAgT3JkZXJpbmcgbWF0Y2g6IDwwIGlmIGZpcnN0IHBhcmFtZXRlciBzaG91bGQgYmUgc29ydGVkIGxvd2VyCgkJCSAqICAgdGhhbiB0aGUgc2Vjb25kIHBhcmFtZXRlciwgPT09MCBpZiB0aGUgdHdvIHBhcmFtZXRlcnMgYXJlIGVxdWFsIGFuZAoJCQkgKiAgID4wIGlmIHRoZSBmaXJzdCBwYXJhbWV0ZXIgc2hvdWxkIGJlIHNvcnRlZCBoZWlnaHQgdGhhbiB0aGUgc2Vjb25kCgkJCSAqICAgcGFyYW1ldGVyLgoJCQkgKiAKCQkJICogIEB0eXBlIG9iamVjdAoJCQkgKiAgQGRlZmF1bHQge30KCQkJICoKCQkJICogIEBleGFtcGxlCgkJCSAqICAgIC8vIE51bWVyaWMgb3JkZXJpbmcgb2YgZm9ybWF0dGVkIG51bWJlcnMgd2l0aCBhIHByZS1mb3JtYXR0ZXIKCQkJICogICAgJC5leHRlbmQoICQuZm4uZGF0YVRhYmxlLmV4dC50eXBlLm9yZGVyLCB7CgkJCSAqICAgICAgInN0cmluZy1wcmUiOiBmdW5jdGlvbih4KSB7CgkJCSAqICAgICAgICBhID0gKGEgPT09ICItIiB8fCBhID09PSAiIikgPyAwIDogYS5yZXBsYWNlKCAvW15cZFwtXC5dL2csICIiICk7CgkJCSAqICAgICAgICByZXR1cm4gcGFyc2VGbG9hdCggYSApOwoJCQkgKiAgICAgIH0KCQkJICogICAgfSApOwoJCQkgKgoJCQkgKiAgQGV4YW1wbGUKCQkJICogICAgLy8gQ2FzZS1zZW5zaXRpdmUgc3RyaW5nIG9yZGVyaW5nLCB3aXRoIG5vIHByZS1mb3JtYXR0aW5nIG1ldGhvZAoJCQkgKiAgICAkLmV4dGVuZCggJC5mbi5kYXRhVGFibGUuZXh0Lm9yZGVyLCB7CgkJCSAqICAgICAgInN0cmluZy1jYXNlLWFzYyI6IGZ1bmN0aW9uKHgseSkgewoJCQkgKiAgICAgICAgcmV0dXJuICgoeCA8IHkpID8gLTEgOiAoKHggPiB5KSA/IDEgOiAwKSk7CgkJCSAqICAgICAgfSwKCQkJICogICAgICAic3RyaW5nLWNhc2UtZGVzYyI6IGZ1bmN0aW9uKHgseSkgewoJCQkgKiAgICAgICAgcmV0dXJuICgoeCA8IHkpID8gMSA6ICgoeCA+IHkpID8gLTEgOiAwKSk7CgkJCSAqICAgICAgfQoJCQkgKiAgICB9ICk7CgkJCSAqLwoJCQlvcmRlcjoge30KCQl9LAoJCgkJLyoqCgkJICogVW5pcXVlIERhdGFUYWJsZXMgaW5zdGFuY2UgY291bnRlcgoJCSAqCgkJICogQHR5cGUgaW50CgkJICogQHByaXZhdGUKCQkgKi8KCQlfdW5pcXVlOiAwLAoJCgkKCQkvLwoJCS8vIERlcHJlY2lhdGVkCgkJLy8gVGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzIGFyZSByZXRhaW5lZCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgb25seS4KCQkvLyBUaGUgc2hvdWxkIG5vdCBiZSB1c2VkIGluIG5ldyBwcm9qZWN0cyBhbmQgd2lsbCBiZSByZW1vdmVkIGluIGEgZnV0dXJlCgkJLy8gdmVyc2lvbgoJCS8vCgkKCQkvKioKCQkgKiBWZXJzaW9uIGNoZWNrIGZ1bmN0aW9uLgoJCSAqICBAdHlwZSBmdW5jdGlvbgoJCSAqICBAZGVwcmVjaWF0ZWQgU2luY2UgMS4xMAoJCSAqLwoJCWZuVmVyc2lvbkNoZWNrOiBEYXRhVGFibGUuZm5WZXJzaW9uQ2hlY2ssCgkKCQoJCS8qKgoJCSAqIEluZGV4IGZvciB3aGF0ICd0aGlzJyBpbmRleCBBUEkgZnVuY3Rpb25zIHNob3VsZCB1c2UKCQkgKiAgQHR5cGUgaW50CgkJICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwCgkJICovCgkJaUFwaUluZGV4OiAwLAoJCgkKCQkvKioKCQkgKiBqUXVlcnkgVUkgY2xhc3MgY29udGFpbmVyCgkJICogIEB0eXBlIG9iamVjdAoJCSAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMAoJCSAqLwoJCW9KVUlDbGFzc2VzOiB7fSwKCQoJCgkJLyoqCgkJICogU29mdHdhcmUgdmVyc2lvbgoJCSAqICBAdHlwZSBzdHJpbmcKCQkgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTAKCQkgKi8KCQlzVmVyc2lvbjogRGF0YVRhYmxlLnZlcnNpb24KCX07CgkKCQoJLy8KCS8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LiBBbGlhcyB0byBwcmUgMS4xMCBIdW5nYXJpYW4gbm90YXRpb24gY291bnRlciBwYXJ0cwoJLy8KCSQuZXh0ZW5kKCBfZXh0LCB7CgkJYWZuRmlsdGVyaW5nOiBfZXh0LnNlYXJjaCwKCQlhVHlwZXM6ICAgICAgIF9leHQudHlwZS5kZXRlY3QsCgkJb2ZuU2VhcmNoOiAgICBfZXh0LnR5cGUuc2VhcmNoLAoJCW9Tb3J0OiAgICAgICAgX2V4dC50eXBlLm9yZGVyLAoJCWFmblNvcnREYXRhOiAgX2V4dC5vcmRlciwKCQlhb0ZlYXR1cmVzOiAgIF9leHQuZmVhdHVyZSwKCQlvQXBpOiAgICAgICAgIF9leHQuaW50ZXJuYWwsCgkJb1N0ZENsYXNzZXM6ICBfZXh0LmNsYXNzZXMsCgkJb1BhZ2luYXRpb246ICBfZXh0LnBhZ2VyCgl9ICk7CgkKCQoJJC5leHRlbmQoIERhdGFUYWJsZS5leHQuY2xhc3NlcywgewoJCSJzVGFibGUiOiAiZGF0YVRhYmxlIiwKCQkic05vRm9vdGVyIjogIm5vLWZvb3RlciIsCgkKCQkvKiBQYWdpbmcgYnV0dG9ucyAqLwoJCSJzUGFnZUJ1dHRvbiI6ICJwYWdpbmF0ZV9idXR0b24iLAoJCSJzUGFnZUJ1dHRvbkFjdGl2ZSI6ICJjdXJyZW50IiwKCQkic1BhZ2VCdXR0b25EaXNhYmxlZCI6ICJkaXNhYmxlZCIsCgkKCQkvKiBTdHJpcGluZyBjbGFzc2VzICovCgkJInNTdHJpcGVPZGQiOiAib2RkIiwKCQkic1N0cmlwZUV2ZW4iOiAiZXZlbiIsCgkKCQkvKiBFbXB0eSByb3cgKi8KCQkic1Jvd0VtcHR5IjogImRhdGFUYWJsZXNfZW1wdHkiLAoJCgkJLyogRmVhdHVyZXMgKi8KCQkic1dyYXBwZXIiOiAiZGF0YVRhYmxlc193cmFwcGVyIiwKCQkic0ZpbHRlciI6ICJkYXRhVGFibGVzX2ZpbHRlciIsCgkJInNJbmZvIjogImRhdGFUYWJsZXNfaW5mbyIsCgkJInNQYWdpbmciOiAiZGF0YVRhYmxlc19wYWdpbmF0ZSBwYWdpbmdfIiwgLyogTm90ZSB0aGF0IHRoZSB0eXBlIGlzIHBvc3RmaXhlZCAqLwoJCSJzTGVuZ3RoIjogImRhdGFUYWJsZXNfbGVuZ3RoIiwKCQkic1Byb2Nlc3NpbmciOiAiZGF0YVRhYmxlc19wcm9jZXNzaW5nIiwKCQoJCS8qIFNvcnRpbmcgKi8KCQkic1NvcnRBc2MiOiAic29ydGluZ19hc2MiLAoJCSJzU29ydERlc2MiOiAic29ydGluZ19kZXNjIiwKCQkic1NvcnRhYmxlIjogInNvcnRpbmciLCAvKiBTb3J0YWJsZSBpbiBib3RoIGRpcmVjdGlvbnMgKi8KCQkic1NvcnRhYmxlQXNjIjogInNvcnRpbmdfZGVzY19kaXNhYmxlZCIsCgkJInNTb3J0YWJsZURlc2MiOiAic29ydGluZ19hc2NfZGlzYWJsZWQiLAoJCSJzU29ydGFibGVOb25lIjogInNvcnRpbmdfZGlzYWJsZWQiLAoJCSJzU29ydENvbHVtbiI6ICJzb3J0aW5nXyIsIC8qIE5vdGUgdGhhdCBhbiBpbnQgaXMgcG9zdGZpeGVkIGZvciB0aGUgc29ydGluZyBvcmRlciAqLwoJCgkJLyogRmlsdGVyaW5nICovCgkJInNGaWx0ZXJJbnB1dCI6ICIiLAoJCgkJLyogUGFnZSBsZW5ndGggKi8KCQkic0xlbmd0aFNlbGVjdCI6ICIiLAoJCgkJLyogU2Nyb2xsaW5nICovCgkJInNTY3JvbGxXcmFwcGVyIjogImRhdGFUYWJsZXNfc2Nyb2xsIiwKCQkic1Njcm9sbEhlYWQiOiAiZGF0YVRhYmxlc19zY3JvbGxIZWFkIiwKCQkic1Njcm9sbEhlYWRJbm5lciI6ICJkYXRhVGFibGVzX3Njcm9sbEhlYWRJbm5lciIsCgkJInNTY3JvbGxCb2R5IjogImRhdGFUYWJsZXNfc2Nyb2xsQm9keSIsCgkJInNTY3JvbGxGb290IjogImRhdGFUYWJsZXNfc2Nyb2xsRm9vdCIsCgkJInNTY3JvbGxGb290SW5uZXIiOiAiZGF0YVRhYmxlc19zY3JvbGxGb290SW5uZXIiLAoJCgkJLyogTWlzYyAqLwoJCSJzSGVhZGVyVEgiOiAiIiwKCQkic0Zvb3RlclRIIjogIiIsCgkKCQkvLyBEZXByZWNhdGVkCgkJInNTb3J0SlVJQXNjIjogIiIsCgkJInNTb3J0SlVJRGVzYyI6ICIiLAoJCSJzU29ydEpVSSI6ICIiLAoJCSJzU29ydEpVSUFzY0FsbG93ZWQiOiAiIiwKCQkic1NvcnRKVUlEZXNjQWxsb3dlZCI6ICIiLAoJCSJzU29ydEpVSVdyYXBwZXIiOiAiIiwKCQkic1NvcnRJY29uIjogIiIsCgkJInNKVUlIZWFkZXIiOiAiIiwKCQkic0pVSUZvb3RlciI6ICIiCgl9ICk7CgkKCQoJdmFyIGV4dFBhZ2luYXRpb24gPSBEYXRhVGFibGUuZXh0LnBhZ2VyOwoJCglmdW5jdGlvbiBfbnVtYmVycyAoIHBhZ2UsIHBhZ2VzICkgewoJCXZhcgoJCQludW1iZXJzID0gW10sCgkJCWJ1dHRvbnMgPSBleHRQYWdpbmF0aW9uLm51bWJlcnNfbGVuZ3RoLAoJCQloYWxmID0gTWF0aC5mbG9vciggYnV0dG9ucyAvIDIgKSwKCQkJaSA9IDE7CgkKCQlpZiAoIHBhZ2VzIDw9IGJ1dHRvbnMgKSB7CgkJCW51bWJlcnMgPSBfcmFuZ2UoIDAsIHBhZ2VzICk7CgkJfQoJCWVsc2UgaWYgKCBwYWdlIDw9IGhhbGYgKSB7CgkJCW51bWJlcnMgPSBfcmFuZ2UoIDAsIGJ1dHRvbnMtMiApOwoJCQludW1iZXJzLnB1c2goICdlbGxpcHNpcycgKTsKCQkJbnVtYmVycy5wdXNoKCBwYWdlcy0xICk7CgkJfQoJCWVsc2UgaWYgKCBwYWdlID49IHBhZ2VzIC0gMSAtIGhhbGYgKSB7CgkJCW51bWJlcnMgPSBfcmFuZ2UoIHBhZ2VzLShidXR0b25zLTIpLCBwYWdlcyApOwoJCQludW1iZXJzLnNwbGljZSggMCwgMCwgJ2VsbGlwc2lzJyApOyAvLyBubyB1bnNoaWZ0IGluIGllNgoJCQludW1iZXJzLnNwbGljZSggMCwgMCwgMCApOwoJCX0KCQllbHNlIHsKCQkJbnVtYmVycyA9IF9yYW5nZSggcGFnZS1oYWxmKzIsIHBhZ2UraGFsZi0xICk7CgkJCW51bWJlcnMucHVzaCggJ2VsbGlwc2lzJyApOwoJCQludW1iZXJzLnB1c2goIHBhZ2VzLTEgKTsKCQkJbnVtYmVycy5zcGxpY2UoIDAsIDAsICdlbGxpcHNpcycgKTsKCQkJbnVtYmVycy5zcGxpY2UoIDAsIDAsIDAgKTsKCQl9CgkKCQludW1iZXJzLkRUX2VsID0gJ3NwYW4nOwoJCXJldHVybiBudW1iZXJzOwoJfQoJCgkKCSQuZXh0ZW5kKCBleHRQYWdpbmF0aW9uLCB7CgkJc2ltcGxlOiBmdW5jdGlvbiAoIHBhZ2UsIHBhZ2VzICkgewoJCQlyZXR1cm4gWyAncHJldmlvdXMnLCAnbmV4dCcgXTsKCQl9LAoJCgkJZnVsbDogZnVuY3Rpb24gKCBwYWdlLCBwYWdlcyApIHsKCQkJcmV0dXJuIFsgICdmaXJzdCcsICdwcmV2aW91cycsICduZXh0JywgJ2xhc3QnIF07CgkJfSwKCQoJCW51bWJlcnM6IGZ1bmN0aW9uICggcGFnZSwgcGFnZXMgKSB7CgkJCXJldHVybiBbIF9udW1iZXJzKHBhZ2UsIHBhZ2VzKSBdOwoJCX0sCgkKCQlzaW1wbGVfbnVtYmVyczogZnVuY3Rpb24gKCBwYWdlLCBwYWdlcyApIHsKCQkJcmV0dXJuIFsgJ3ByZXZpb3VzJywgX251bWJlcnMocGFnZSwgcGFnZXMpLCAnbmV4dCcgXTsKCQl9LAoJCgkJZnVsbF9udW1iZXJzOiBmdW5jdGlvbiAoIHBhZ2UsIHBhZ2VzICkgewoJCQlyZXR1cm4gWyAnZmlyc3QnLCAncHJldmlvdXMnLCBfbnVtYmVycyhwYWdlLCBwYWdlcyksICduZXh0JywgJ2xhc3QnIF07CgkJfSwKCQkKCQlmaXJzdF9sYXN0X251bWJlcnM6IGZ1bmN0aW9uIChwYWdlLCBwYWdlcykgewoJIAkJcmV0dXJuIFsnZmlyc3QnLCBfbnVtYmVycyhwYWdlLCBwYWdlcyksICdsYXN0J107CgkgCX0sCgkKCQkvLyBGb3IgdGVzdGluZyBhbmQgcGx1Zy1pbnMgdG8gdXNlCgkJX251bWJlcnM6IF9udW1iZXJzLAoJCgkJLy8gTnVtYmVyIG9mIG51bWJlciBidXR0b25zIChpbmNsdWRpbmcgZWxsaXBzaXMpIHRvIHNob3cuIF9NdXN0IGJlIG9kZCFfCgkJbnVtYmVyc19sZW5ndGg6IDcKCX0gKTsKCQoJCgkkLmV4dGVuZCggdHJ1ZSwgRGF0YVRhYmxlLmV4dC5yZW5kZXJlciwgewoJCXBhZ2VCdXR0b246IHsKCQkJXzogZnVuY3Rpb24gKCBzZXR0aW5ncywgaG9zdCwgaWR4LCBidXR0b25zLCBwYWdlLCBwYWdlcyApIHsKCQkJCXZhciBjbGFzc2VzID0gc2V0dGluZ3Mub0NsYXNzZXM7CgkJCQl2YXIgbGFuZyA9IHNldHRpbmdzLm9MYW5ndWFnZS5vUGFnaW5hdGU7CgkJCQl2YXIgYXJpYSA9IHNldHRpbmdzLm9MYW5ndWFnZS5vQXJpYS5wYWdpbmF0ZSB8fCB7fTsKCQkJCXZhciBidG5EaXNwbGF5LCBidG5DbGFzcywgY291bnRlcj0wOwoJCgkJCQl2YXIgYXR0YWNoID0gZnVuY3Rpb24oIGNvbnRhaW5lciwgYnV0dG9ucyApIHsKCQkJCQl2YXIgaSwgaWVuLCBub2RlLCBidXR0b24sIHRhYkluZGV4OwoJCQkJCXZhciBkaXNhYmxlZENsYXNzID0gY2xhc3Nlcy5zUGFnZUJ1dHRvbkRpc2FibGVkOwoJCQkJCXZhciBjbGlja0hhbmRsZXIgPSBmdW5jdGlvbiAoIGUgKSB7CgkJCQkJCV9mblBhZ2VDaGFuZ2UoIHNldHRpbmdzLCBlLmRhdGEuYWN0aW9uLCB0cnVlICk7CgkJCQkJfTsKCQoJCQkJCWZvciAoIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7CgkJCQkJCWJ1dHRvbiA9IGJ1dHRvbnNbaV07CgkKCQkJCQkJaWYgKCBBcnJheS5pc0FycmF5KCBidXR0b24gKSApIHsKCQkJCQkJCXZhciBpbm5lciA9ICQoICc8JysoYnV0dG9uLkRUX2VsIHx8ICdkaXYnKSsnLz4nICkKCQkJCQkJCQkuYXBwZW5kVG8oIGNvbnRhaW5lciApOwoJCQkJCQkJYXR0YWNoKCBpbm5lciwgYnV0dG9uICk7CgkJCQkJCX0KCQkJCQkJZWxzZSB7CgkJCQkJCQlidG5EaXNwbGF5ID0gbnVsbDsKCQkJCQkJCWJ0bkNsYXNzID0gYnV0dG9uOwoJCQkJCQkJdGFiSW5kZXggPSBzZXR0aW5ncy5pVGFiSW5kZXg7CgkKCQkJCQkJCXN3aXRjaCAoIGJ1dHRvbiApIHsKCQkJCQkJCQljYXNlICdlbGxpcHNpcyc6CgkJCQkJCQkJCWNvbnRhaW5lci5hcHBlbmQoJzxzcGFuIGNsYXNzPSJlbGxpcHNpcyI+JiN4MjAyNjs8L3NwYW4+Jyk7CgkJCQkJCQkJCWJyZWFrOwoJCgkJCQkJCQkJY2FzZSAnZmlyc3QnOgoJCQkJCQkJCQlidG5EaXNwbGF5ID0gbGFuZy5zRmlyc3Q7CgkKCQkJCQkJCQkJaWYgKCBwYWdlID09PSAwICkgewoJCQkJCQkJCQkJdGFiSW5kZXggPSAtMTsKCQkJCQkJCQkJCWJ0bkNsYXNzICs9ICcgJyArIGRpc2FibGVkQ2xhc3M7CgkJCQkJCQkJCX0KCQkJCQkJCQkJYnJlYWs7CgkKCQkJCQkJCQljYXNlICdwcmV2aW91cyc6CgkJCQkJCQkJCWJ0bkRpc3BsYXkgPSBsYW5nLnNQcmV2aW91czsKCQoJCQkJCQkJCQlpZiAoIHBhZ2UgPT09IDAgKSB7CgkJCQkJCQkJCQl0YWJJbmRleCA9IC0xOwoJCQkJCQkJCQkJYnRuQ2xhc3MgKz0gJyAnICsgZGlzYWJsZWRDbGFzczsKCQkJCQkJCQkJfQoJCQkJCQkJCQlicmVhazsKCQoJCQkJCQkJCWNhc2UgJ25leHQnOgoJCQkJCQkJCQlidG5EaXNwbGF5ID0gbGFuZy5zTmV4dDsKCQoJCQkJCQkJCQlpZiAoIHBhZ2VzID09PSAwIHx8IHBhZ2UgPT09IHBhZ2VzLTEgKSB7CgkJCQkJCQkJCQl0YWJJbmRleCA9IC0xOwoJCQkJCQkJCQkJYnRuQ2xhc3MgKz0gJyAnICsgZGlzYWJsZWRDbGFzczsKCQkJCQkJCQkJfQoJCQkJCQkJCQlicmVhazsKCQoJCQkJCQkJCWNhc2UgJ2xhc3QnOgoJCQkJCQkJCQlidG5EaXNwbGF5ID0gbGFuZy5zTGFzdDsKCQoJCQkJCQkJCQlpZiAoIHBhZ2VzID09PSAwIHx8IHBhZ2UgPT09IHBhZ2VzLTEgKSB7CgkJCQkJCQkJCQl0YWJJbmRleCA9IC0xOwoJCQkJCQkJCQkJYnRuQ2xhc3MgKz0gJyAnICsgZGlzYWJsZWRDbGFzczsKCQkJCQkJCQkJfQoJCQkJCQkJCQlicmVhazsKCQoJCQkJCQkJCWRlZmF1bHQ6CgkJCQkJCQkJCWJ0bkRpc3BsYXkgPSBzZXR0aW5ncy5mbkZvcm1hdE51bWJlciggYnV0dG9uICsgMSApOwoJCQkJCQkJCQlidG5DbGFzcyA9IHBhZ2UgPT09IGJ1dHRvbiA/CgkJCQkJCQkJCQljbGFzc2VzLnNQYWdlQnV0dG9uQWN0aXZlIDogJyc7CgkJCQkJCQkJCWJyZWFrOwoJCQkJCQkJfQoJCgkJCQkJCQlpZiAoIGJ0bkRpc3BsYXkgIT09IG51bGwgKSB7CgkJCQkJCQkJbm9kZSA9ICQoJzxhPicsIHsKCQkJCQkJCQkJCSdjbGFzcyc6IGNsYXNzZXMuc1BhZ2VCdXR0b24rJyAnK2J0bkNsYXNzLAoJCQkJCQkJCQkJJ2FyaWEtY29udHJvbHMnOiBzZXR0aW5ncy5zVGFibGVJZCwKCQkJCQkJCQkJCSdhcmlhLWxhYmVsJzogYXJpYVsgYnV0dG9uIF0sCgkJCQkJCQkJCQknZGF0YS1kdC1pZHgnOiBjb3VudGVyLAoJCQkJCQkJCQkJJ3RhYmluZGV4JzogdGFiSW5kZXgsCgkJCQkJCQkJCQknaWQnOiBpZHggPT09IDAgJiYgdHlwZW9mIGJ1dHRvbiA9PT0gJ3N0cmluZycgPwoJCQkJCQkJCQkJCXNldHRpbmdzLnNUYWJsZUlkICsnXycrIGJ1dHRvbiA6CgkJCQkJCQkJCQkJbnVsbAoJCQkJCQkJCQl9ICkKCQkJCQkJCQkJLmh0bWwoIGJ0bkRpc3BsYXkgKQoJCQkJCQkJCQkuYXBwZW5kVG8oIGNvbnRhaW5lciApOwoJCgkJCQkJCQkJX2ZuQmluZEFjdGlvbigKCQkJCQkJCQkJbm9kZSwge2FjdGlvbjogYnV0dG9ufSwgY2xpY2tIYW5kbGVyCgkJCQkJCQkJKTsKCQoJCQkJCQkJCWNvdW50ZXIrKzsKCQkJCQkJCX0KCQkJCQkJfQoJCQkJCX0KCQkJCX07CgkKCQkJCS8vIElFOSB0aHJvd3MgYW4gJ3Vua25vd24gZXJyb3InIGlmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgaXMgdXNlZAoJCQkJLy8gaW5zaWRlIGFuIGlmcmFtZSBvciBmcmFtZS4gVHJ5IC8gY2F0Y2ggdGhlIGVycm9yLiBOb3QgZ29vZCBmb3IKCQkJCS8vIGFjY2Vzc2liaWxpdHksIGJ1dCBuZWl0aGVyIGFyZSBmcmFtZXMuCgkJCQl2YXIgYWN0aXZlRWw7CgkKCQkJCXRyeSB7CgkJCQkJLy8gQmVjYXVzZSB0aGlzIGFwcHJvYWNoIGlzIGRlc3Ryb3lpbmcgYW5kIHJlY3JlYXRpbmcgdGhlIHBhZ2luZwoJCQkJCS8vIGVsZW1lbnRzLCBmb2N1cyBpcyBsb3N0IG9uIHRoZSBzZWxlY3QgYnV0dG9uIHdoaWNoIGlzIGJhZCBmb3IKCQkJCQkvLyBhY2Nlc3NpYmlsaXR5LiBTbyB3ZSB3YW50IHRvIHJlc3RvcmUgZm9jdXMgb25jZSB0aGUgZHJhdyBoYXMKCQkJCQkvLyBjb21wbGV0ZWQKCQkJCQlhY3RpdmVFbCA9ICQoaG9zdCkuZmluZChkb2N1bWVudC5hY3RpdmVFbGVtZW50KS5kYXRhKCdkdC1pZHgnKTsKCQkJCX0KCQkJCWNhdGNoIChlKSB7fQoJCgkJCQlhdHRhY2goICQoaG9zdCkuZW1wdHkoKSwgYnV0dG9ucyApOwoJCgkJCQlpZiAoIGFjdGl2ZUVsICE9PSB1bmRlZmluZWQgKSB7CgkJCQkJJChob3N0KS5maW5kKCAnW2RhdGEtZHQtaWR4PScrYWN0aXZlRWwrJ10nICkudHJpZ2dlcignZm9jdXMnKTsKCQkJCX0KCQkJfQoJCX0KCX0gKTsKCQoJCgkKCS8vIEJ1aWx0IGluIHR5cGUgZGV0ZWN0aW9uLiBTZWUgbW9kZWwuZXh0LmFUeXBlcyBmb3IgaW5mb3JtYXRpb24gYWJvdXQKCS8vIHdoYXQgaXMgcmVxdWlyZWQgZnJvbSB0aGlzIG1ldGhvZHMuCgkkLmV4dGVuZCggRGF0YVRhYmxlLmV4dC50eXBlLmRldGVjdCwgWwoJCS8vIFBsYWluIG51bWJlcnMgLSBmaXJzdCBzaW5jZSBWOCBkZXRlY3RzIHNvbWUgcGxhaW4gbnVtYmVycyBhcyBkYXRlcwoJCS8vIGUuZy4gRGF0ZS5wYXJzZSgnNTUnKSAoYnV0IG5vdCBhbGwsIGUuZy4gRGF0ZS5wYXJzZSgnMjInKS4uLikuCgkJZnVuY3Rpb24gKCBkLCBzZXR0aW5ncyApCgkJewoJCQl2YXIgZGVjaW1hbCA9IHNldHRpbmdzLm9MYW5ndWFnZS5zRGVjaW1hbDsKCQkJcmV0dXJuIF9pc051bWJlciggZCwgZGVjaW1hbCApID8gJ251bScrZGVjaW1hbCA6IG51bGw7CgkJfSwKCQoJCS8vIERhdGVzIChvbmx5IHRob3NlIHJlY29nbmlzZWQgYnkgdGhlIGJyb3dzZXIncyBEYXRlLnBhcnNlKQoJCWZ1bmN0aW9uICggZCwgc2V0dGluZ3MgKQoJCXsKCQkJLy8gVjggdHJpZXMgX3ZlcnlfIGhhcmQgdG8gbWFrZSBhIHN0cmluZyBwYXNzZWQgaW50byBgRGF0ZS5wYXJzZSgpYAoJCQkvLyB2YWxpZCwgc28gd2UgbmVlZCB0byB1c2UgYSByZWdleCB0byByZXN0cmljdCBkYXRlIGZvcm1hdHMuIFVzZSBhCgkJCS8vIHBsdWctaW4gZm9yIGFueXRoaW5nIG90aGVyIHRoYW4gSVNPODYwMSBzdHlsZSBzdHJpbmdzCgkJCWlmICggZCAmJiAhKGQgaW5zdGFuY2VvZiBEYXRlKSAmJiAhIF9yZV9kYXRlLnRlc3QoZCkgKSB7CgkJCQlyZXR1cm4gbnVsbDsKCQkJfQoJCQl2YXIgcGFyc2VkID0gRGF0ZS5wYXJzZShkKTsKCQkJcmV0dXJuIChwYXJzZWQgIT09IG51bGwgJiYgIWlzTmFOKHBhcnNlZCkpIHx8IF9lbXB0eShkKSA/ICdkYXRlJyA6IG51bGw7CgkJfSwKCQoJCS8vIEZvcm1hdHRlZCBudW1iZXJzCgkJZnVuY3Rpb24gKCBkLCBzZXR0aW5ncyApCgkJewoJCQl2YXIgZGVjaW1hbCA9IHNldHRpbmdzLm9MYW5ndWFnZS5zRGVjaW1hbDsKCQkJcmV0dXJuIF9pc051bWJlciggZCwgZGVjaW1hbCwgdHJ1ZSApID8gJ251bS1mbXQnK2RlY2ltYWwgOiBudWxsOwoJCX0sCgkKCQkvLyBIVE1MIG51bWVyaWMKCQlmdW5jdGlvbiAoIGQsIHNldHRpbmdzICkKCQl7CgkJCXZhciBkZWNpbWFsID0gc2V0dGluZ3Mub0xhbmd1YWdlLnNEZWNpbWFsOwoJCQlyZXR1cm4gX2h0bWxOdW1lcmljKCBkLCBkZWNpbWFsICkgPyAnaHRtbC1udW0nK2RlY2ltYWwgOiBudWxsOwoJCX0sCgkKCQkvLyBIVE1MIG51bWVyaWMsIGZvcm1hdHRlZAoJCWZ1bmN0aW9uICggZCwgc2V0dGluZ3MgKQoJCXsKCQkJdmFyIGRlY2ltYWwgPSBzZXR0aW5ncy5vTGFuZ3VhZ2Uuc0RlY2ltYWw7CgkJCXJldHVybiBfaHRtbE51bWVyaWMoIGQsIGRlY2ltYWwsIHRydWUgKSA/ICdodG1sLW51bS1mbXQnK2RlY2ltYWwgOiBudWxsOwoJCX0sCgkKCQkvLyBIVE1MICh0aGlzIGlzIHN0cmljdCBjaGVja2luZyAtIHRoZXJlIG11c3QgYmUgaHRtbCkKCQlmdW5jdGlvbiAoIGQsIHNldHRpbmdzICkKCQl7CgkJCXJldHVybiBfZW1wdHkoIGQgKSB8fCAodHlwZW9mIGQgPT09ICdzdHJpbmcnICYmIGQuaW5kZXhPZignPCcpICE9PSAtMSkgPwoJCQkJJ2h0bWwnIDogbnVsbDsKCQl9CgldICk7CgkKCQoJCgkvLyBGaWx0ZXIgZm9ybWF0dGluZyBmdW5jdGlvbnMuIFNlZSBtb2RlbC5leHQub2ZuU2VhcmNoIGZvciBpbmZvcm1hdGlvbiBhYm91dAoJLy8gd2hhdCBpcyByZXF1aXJlZCBmcm9tIHRoZXNlIG1ldGhvZHMuCgkvLyAKCS8vIE5vdGUgdGhhdCBhZGRpdGlvbmFsIHNlYXJjaCBtZXRob2RzIGFyZSBhZGRlZCBmb3IgdGhlIGh0bWwgbnVtYmVycyBhbmQKCS8vIGh0bWwgZm9ybWF0dGVkIG51bWJlcnMgYnkgYF9hZGROdW1lcmljU29ydCgpYCB3aGVuIHdlIGtub3cgd2hhdCB0aGUgZGVjaW1hbAoJLy8gcGxhY2UgaXMKCQoJCgkkLmV4dGVuZCggRGF0YVRhYmxlLmV4dC50eXBlLnNlYXJjaCwgewoJCWh0bWw6IGZ1bmN0aW9uICggZGF0YSApIHsKCQkJcmV0dXJuIF9lbXB0eShkYXRhKSA/CgkJCQlkYXRhIDoKCQkJCXR5cGVvZiBkYXRhID09PSAnc3RyaW5nJyA/CgkJCQkJZGF0YQoJCQkJCQkucmVwbGFjZSggX3JlX25ld19saW5lcywgIiAiICkKCQkJCQkJLnJlcGxhY2UoIF9yZV9odG1sLCAiIiApIDoKCQkJCQknJzsKCQl9LAoJCgkJc3RyaW5nOiBmdW5jdGlvbiAoIGRhdGEgKSB7CgkJCXJldHVybiBfZW1wdHkoZGF0YSkgPwoJCQkJZGF0YSA6CgkJCQl0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycgPwoJCQkJCWRhdGEucmVwbGFjZSggX3JlX25ld19saW5lcywgIiAiICkgOgoJCQkJCWRhdGE7CgkJfQoJfSApOwoJCgkKCQoJdmFyIF9fbnVtZXJpY1JlcGxhY2UgPSBmdW5jdGlvbiAoIGQsIGRlY2ltYWxQbGFjZSwgcmUxLCByZTIgKSB7CgkJaWYgKCBkICE9PSAwICYmICghZCB8fCBkID09PSAnLScpICkgewoJCQlyZXR1cm4gLUluZmluaXR5OwoJCX0KCQoJCS8vIElmIGEgZGVjaW1hbCBwbGFjZSBvdGhlciB0aGFuIGAuYCBpcyB1c2VkLCBpdCBuZWVkcyB0byBiZSBnaXZlbiB0byB0aGUKCQkvLyBmdW5jdGlvbiBzbyB3ZSBjYW4gZGV0ZWN0IGl0IGFuZCByZXBsYWNlIHdpdGggYSBgLmAgd2hpY2ggaXMgdGhlIG9ubHkKCQkvLyBkZWNpbWFsIHBsYWNlIEphdmFzY3JpcHQgcmVjb2duaXNlcyAtIGl0IGlzIG5vdCBsb2NhbGUgYXdhcmUuCgkJaWYgKCBkZWNpbWFsUGxhY2UgKSB7CgkJCWQgPSBfbnVtVG9EZWNpbWFsKCBkLCBkZWNpbWFsUGxhY2UgKTsKCQl9CgkKCQlpZiAoIGQucmVwbGFjZSApIHsKCQkJaWYgKCByZTEgKSB7CgkJCQlkID0gZC5yZXBsYWNlKCByZTEsICcnICk7CgkJCX0KCQoJCQlpZiAoIHJlMiApIHsKCQkJCWQgPSBkLnJlcGxhY2UoIHJlMiwgJycgKTsKCQkJfQoJCX0KCQoJCXJldHVybiBkICogMTsKCX07CgkKCQoJLy8gQWRkIHRoZSBudW1lcmljICdkZWZvcm1hdHRpbmcnIGZ1bmN0aW9ucyBmb3Igc29ydGluZyBhbmQgc2VhcmNoLiBUaGlzIGlzIGRvbmUKCS8vIGluIGEgZnVuY3Rpb24gdG8gcHJvdmlkZSBhbiBlYXN5IGFiaWxpdHkgZm9yIHRoZSBsYW5ndWFnZSBvcHRpb25zIHRvIGFkZAoJLy8gYWRkaXRpb25hbCBtZXRob2RzIGlmIGEgbm9uLXBlcmlvZCBkZWNpbWFsIHBsYWNlIGlzIHVzZWQuCglmdW5jdGlvbiBfYWRkTnVtZXJpY1NvcnQgKCBkZWNpbWFsUGxhY2UgKSB7CgkJJC5lYWNoKAoJCQl7CgkJCQkvLyBQbGFpbiBudW1iZXJzCgkJCQkibnVtIjogZnVuY3Rpb24gKCBkICkgewoJCQkJCXJldHVybiBfX251bWVyaWNSZXBsYWNlKCBkLCBkZWNpbWFsUGxhY2UgKTsKCQkJCX0sCgkKCQkJCS8vIEZvcm1hdHRlZCBudW1iZXJzCgkJCQkibnVtLWZtdCI6IGZ1bmN0aW9uICggZCApIHsKCQkJCQlyZXR1cm4gX19udW1lcmljUmVwbGFjZSggZCwgZGVjaW1hbFBsYWNlLCBfcmVfZm9ybWF0dGVkX251bWVyaWMgKTsKCQkJCX0sCgkKCQkJCS8vIEhUTUwgbnVtZXJpYwoJCQkJImh0bWwtbnVtIjogZnVuY3Rpb24gKCBkICkgewoJCQkJCXJldHVybiBfX251bWVyaWNSZXBsYWNlKCBkLCBkZWNpbWFsUGxhY2UsIF9yZV9odG1sICk7CgkJCQl9LAoJCgkJCQkvLyBIVE1MIG51bWVyaWMsIGZvcm1hdHRlZAoJCQkJImh0bWwtbnVtLWZtdCI6IGZ1bmN0aW9uICggZCApIHsKCQkJCQlyZXR1cm4gX19udW1lcmljUmVwbGFjZSggZCwgZGVjaW1hbFBsYWNlLCBfcmVfaHRtbCwgX3JlX2Zvcm1hdHRlZF9udW1lcmljICk7CgkJCQl9CgkJCX0sCgkJCWZ1bmN0aW9uICgga2V5LCBmbiApIHsKCQkJCS8vIEFkZCB0aGUgb3JkZXJpbmcgbWV0aG9kCgkJCQlfZXh0LnR5cGUub3JkZXJbIGtleStkZWNpbWFsUGxhY2UrJy1wcmUnIF0gPSBmbjsKCQoJCQkJLy8gRm9yIEhUTUwgdHlwZXMgYWRkIGEgc2VhcmNoIGZvcm1hdHRlciB0aGF0IHdpbGwgc3RyaXAgdGhlIEhUTUwKCQkJCWlmICgga2V5Lm1hdGNoKC9eaHRtbFwtLykgKSB7CgkJCQkJX2V4dC50eXBlLnNlYXJjaFsga2V5K2RlY2ltYWxQbGFjZSBdID0gX2V4dC50eXBlLnNlYXJjaC5odG1sOwoJCQkJfQoJCQl9CgkJKTsKCX0KCQoJCgkvLyBEZWZhdWx0IHNvcnQgbWV0aG9kcwoJJC5leHRlbmQoIF9leHQudHlwZS5vcmRlciwgewoJCS8vIERhdGVzCgkJImRhdGUtcHJlIjogZnVuY3Rpb24gKCBkICkgewoJCQl2YXIgdHMgPSBEYXRlLnBhcnNlKCBkICk7CgkJCXJldHVybiBpc05hTih0cykgPyAtSW5maW5pdHkgOiB0czsKCQl9LAoJCgkJLy8gaHRtbAoJCSJodG1sLXByZSI6IGZ1bmN0aW9uICggYSApIHsKCQkJcmV0dXJuIF9lbXB0eShhKSA/CgkJCQknJyA6CgkJCQlhLnJlcGxhY2UgPwoJCQkJCWEucmVwbGFjZSggLzwuKj8+L2csICIiICkudG9Mb3dlckNhc2UoKSA6CgkJCQkJYSsnJzsKCQl9LAoJCgkJLy8gc3RyaW5nCgkJInN0cmluZy1wcmUiOiBmdW5jdGlvbiAoIGEgKSB7CgkJCS8vIFRoaXMgaXMgYSBsaXR0bGUgY29tcGxleCwgYnV0IGZhc3RlciB0aGFuIGFsd2F5cyBjYWxsaW5nIHRvU3RyaW5nLAoJCQkvLyBodHRwOi8vanNwZXJmLmNvbS90b3N0cmluZy12LWNoZWNrCgkJCXJldHVybiBfZW1wdHkoYSkgPwoJCQkJJycgOgoJCQkJdHlwZW9mIGEgPT09ICdzdHJpbmcnID8KCQkJCQlhLnRvTG93ZXJDYXNlKCkgOgoJCQkJCSEgYS50b1N0cmluZyA/CgkJCQkJCScnIDoKCQkJCQkJYS50b1N0cmluZygpOwoJCX0sCgkKCQkvLyBzdHJpbmctYXNjIGFuZCAtZGVzYyBhcmUgcmV0YWluZWQgb25seSBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIHRoZSBvbGQKCQkvLyBzb3J0IG1ldGhvZHMKCQkic3RyaW5nLWFzYyI6IGZ1bmN0aW9uICggeCwgeSApIHsKCQkJcmV0dXJuICgoeCA8IHkpID8gLTEgOiAoKHggPiB5KSA/IDEgOiAwKSk7CgkJfSwKCQoJCSJzdHJpbmctZGVzYyI6IGZ1bmN0aW9uICggeCwgeSApIHsKCQkJcmV0dXJuICgoeCA8IHkpID8gMSA6ICgoeCA+IHkpID8gLTEgOiAwKSk7CgkJfQoJfSApOwoJCgkKCS8vIE51bWVyaWMgc29ydGluZyB0eXBlcyAtIG9yZGVyIGRvZXNuJ3QgbWF0dGVyIGhlcmUKCV9hZGROdW1lcmljU29ydCggJycgKTsKCQoJCgkkLmV4dGVuZCggdHJ1ZSwgRGF0YVRhYmxlLmV4dC5yZW5kZXJlciwgewoJCWhlYWRlcjogewoJCQlfOiBmdW5jdGlvbiAoIHNldHRpbmdzLCBjZWxsLCBjb2x1bW4sIGNsYXNzZXMgKSB7CgkJCQkvLyBObyBhZGRpdGlvbmFsIG1hcmstdXAgcmVxdWlyZWQKCQkJCS8vIEF0dGFjaCBhIHNvcnQgbGlzdGVuZXIgdG8gdXBkYXRlIG9uIHNvcnQgLSBub3RlIHRoYXQgdXNpbmcgdGhlCgkJCQkvLyBgRFRgIG5hbWVzcGFjZSB3aWxsIGFsbG93IHRoZSBldmVudCB0byBiZSByZW1vdmVkIGF1dG9tYXRpY2FsbHkKCQkJCS8vIG9uIGRlc3Ryb3ksIHdoaWxlIHRoZSBgZHRgIG5hbWVzcGFjZWQgZXZlbnQgaXMgdGhlIG9uZSB3ZSBhcmUKCQkJCS8vIGxpc3RlbmluZyBmb3IKCQkJCSQoc2V0dGluZ3MublRhYmxlKS5vbiggJ29yZGVyLmR0LkRUJywgZnVuY3Rpb24gKCBlLCBjdHgsIHNvcnRpbmcsIGNvbHVtbnMgKSB7CgkJCQkJaWYgKCBzZXR0aW5ncyAhPT0gY3R4ICkgeyAvLyBuZWVkIHRvIGNoZWNrIHRoaXMgdGhpcyBpcyB0aGUgaG9zdAoJCQkJCQlyZXR1cm47ICAgICAgICAgICAgICAgLy8gdGFibGUsIG5vdCBhIG5lc3RlZCBvbmUKCQkJCQl9CgkKCQkJCQl2YXIgY29sSWR4ID0gY29sdW1uLmlkeDsKCQoJCQkJCWNlbGwKCQkJCQkJLnJlbW92ZUNsYXNzKAoJCQkJCQkJY2xhc3Nlcy5zU29ydEFzYyArJyAnKwoJCQkJCQkJY2xhc3Nlcy5zU29ydERlc2MKCQkJCQkJKQoJCQkJCQkuYWRkQ2xhc3MoIGNvbHVtbnNbIGNvbElkeCBdID09ICdhc2MnID8KCQkJCQkJCWNsYXNzZXMuc1NvcnRBc2MgOiBjb2x1bW5zWyBjb2xJZHggXSA9PSAnZGVzYycgPwoJCQkJCQkJCWNsYXNzZXMuc1NvcnREZXNjIDoKCQkJCQkJCQljb2x1bW4uc1NvcnRpbmdDbGFzcwoJCQkJCQkpOwoJCQkJfSApOwoJCQl9LAoJCgkJCWpxdWVyeXVpOiBmdW5jdGlvbiAoIHNldHRpbmdzLCBjZWxsLCBjb2x1bW4sIGNsYXNzZXMgKSB7CgkJCQkkKCc8ZGl2Lz4nKQoJCQkJCS5hZGRDbGFzcyggY2xhc3Nlcy5zU29ydEpVSVdyYXBwZXIgKQoJCQkJCS5hcHBlbmQoIGNlbGwuY29udGVudHMoKSApCgkJCQkJLmFwcGVuZCggJCgnPHNwYW4vPicpCgkJCQkJCS5hZGRDbGFzcyggY2xhc3Nlcy5zU29ydEljb24rJyAnK2NvbHVtbi5zU29ydGluZ0NsYXNzSlVJICkKCQkJCQkpCgkJCQkJLmFwcGVuZFRvKCBjZWxsICk7CgkKCQkJCS8vIEF0dGFjaCBhIHNvcnQgbGlzdGVuZXIgdG8gdXBkYXRlIG9uIHNvcnQKCQkJCSQoc2V0dGluZ3MublRhYmxlKS5vbiggJ29yZGVyLmR0LkRUJywgZnVuY3Rpb24gKCBlLCBjdHgsIHNvcnRpbmcsIGNvbHVtbnMgKSB7CgkJCQkJaWYgKCBzZXR0aW5ncyAhPT0gY3R4ICkgewoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCgkJCQkJdmFyIGNvbElkeCA9IGNvbHVtbi5pZHg7CgkKCQkJCQljZWxsCgkJCQkJCS5yZW1vdmVDbGFzcyggY2xhc3Nlcy5zU29ydEFzYyArIiAiK2NsYXNzZXMuc1NvcnREZXNjICkKCQkJCQkJLmFkZENsYXNzKCBjb2x1bW5zWyBjb2xJZHggXSA9PSAnYXNjJyA/CgkJCQkJCQljbGFzc2VzLnNTb3J0QXNjIDogY29sdW1uc1sgY29sSWR4IF0gPT0gJ2Rlc2MnID8KCQkJCQkJCQljbGFzc2VzLnNTb3J0RGVzYyA6CgkJCQkJCQkJY29sdW1uLnNTb3J0aW5nQ2xhc3MKCQkJCQkJKTsKCQoJCQkJCWNlbGwKCQkJCQkJLmZpbmQoICdzcGFuLicrY2xhc3Nlcy5zU29ydEljb24gKQoJCQkJCQkucmVtb3ZlQ2xhc3MoCgkJCQkJCQljbGFzc2VzLnNTb3J0SlVJQXNjICsiICIrCgkJCQkJCQljbGFzc2VzLnNTb3J0SlVJRGVzYyArIiAiKwoJCQkJCQkJY2xhc3Nlcy5zU29ydEpVSSArIiAiKwoJCQkJCQkJY2xhc3Nlcy5zU29ydEpVSUFzY0FsbG93ZWQgKyIgIisKCQkJCQkJCWNsYXNzZXMuc1NvcnRKVUlEZXNjQWxsb3dlZAoJCQkJCQkpCgkJCQkJCS5hZGRDbGFzcyggY29sdW1uc1sgY29sSWR4IF0gPT0gJ2FzYycgPwoJCQkJCQkJY2xhc3Nlcy5zU29ydEpVSUFzYyA6IGNvbHVtbnNbIGNvbElkeCBdID09ICdkZXNjJyA/CgkJCQkJCQkJY2xhc3Nlcy5zU29ydEpVSURlc2MgOgoJCQkJCQkJCWNvbHVtbi5zU29ydGluZ0NsYXNzSlVJCgkJCQkJCSk7CgkJCQl9ICk7CgkJCX0KCQl9Cgl9ICk7CgkKCS8qCgkgKiBQdWJsaWMgaGVscGVyIGZ1bmN0aW9ucy4gVGhlc2UgYXJlbid0IHVzZWQgaW50ZXJuYWxseSBieSBEYXRhVGFibGVzLCBvcgoJICogY2FsbGVkIGJ5IGFueSBvZiB0aGUgb3B0aW9ucyBwYXNzZWQgaW50byBEYXRhVGFibGVzLCBidXQgdGhleSBjYW4gYmUgdXNlZAoJICogZXh0ZXJuYWxseSBieSBkZXZlbG9wZXJzIHdvcmtpbmcgd2l0aCBEYXRhVGFibGVzLiBUaGV5IGFyZSBoZWxwZXIgZnVuY3Rpb25zCgkgKiB0byBtYWtlIHdvcmtpbmcgd2l0aCBEYXRhVGFibGVzIGEgbGl0dGxlIGJpdCBlYXNpZXIuCgkgKi8KCQoJdmFyIF9faHRtbEVzY2FwZUVudGl0aWVzID0gZnVuY3Rpb24gKCBkICkgewoJCWlmIChBcnJheS5pc0FycmF5KGQpKSB7CgkJCWQgPSBkLmpvaW4oJywnKTsKCQl9CgkKCQlyZXR1cm4gdHlwZW9mIGQgPT09ICdzdHJpbmcnID8KCQkJZAoJCQkJLnJlcGxhY2UoLyYvZywgJyZhbXA7JykKCQkJCS5yZXBsYWNlKC88L2csICcmbHQ7JykKCQkJCS5yZXBsYWNlKC8+L2csICcmZ3Q7JykKCQkJCS5yZXBsYWNlKC8iL2csICcmcXVvdDsnKSA6CgkJCWQ7Cgl9OwoJCgkvLyBDb21tb24gbG9naWMgZm9yIG1vbWVudCwgbHV4b24gb3IgYSBkYXRlIGFjdGlvbgoJZnVuY3Rpb24gX19tbGQoIGR0LCBtb21lbnRGbiwgbHV4b25GbiwgZGF0ZUZuLCBhcmcxICkgewoJCWlmICh3aW5kb3cubW9tZW50KSB7CgkJCXJldHVybiBkdFttb21lbnRGbl0oIGFyZzEgKTsKCQl9CgkJZWxzZSBpZiAod2luZG93Lmx1eG9uKSB7CgkJCXJldHVybiBkdFtsdXhvbkZuXSggYXJnMSApOwoJCX0KCQkKCQlyZXR1cm4gZGF0ZUZuID8gZHRbZGF0ZUZuXSggYXJnMSApIDogZHQ7Cgl9CgkKCQoJdmFyIF9fbWxXYXJuaW5nID0gZmFsc2U7CglmdW5jdGlvbiBfX21sZE9iaiAoZCwgZm9ybWF0LCBsb2NhbGUpIHsKCQl2YXIgZHQ7CgkKCQlpZiAod2luZG93Lm1vbWVudCkgewoJCQlkdCA9IHdpbmRvdy5tb21lbnQudXRjKCBkLCBmb3JtYXQsIGxvY2FsZSwgdHJ1ZSApOwoJCgkJCWlmICghIGR0LmlzVmFsaWQoKSkgewoJCQkJcmV0dXJuIG51bGw7CgkJCX0KCQl9CgkJZWxzZSBpZiAod2luZG93Lmx1eG9uKSB7CgkJCWR0ID0gZm9ybWF0CgkJCQk/IHdpbmRvdy5sdXhvbi5EYXRlVGltZS5mcm9tRm9ybWF0KCBkLCBmb3JtYXQgKQoJCQkJOiB3aW5kb3cubHV4b24uRGF0ZVRpbWUuZnJvbUlTTyggZCApOwoJCgkJCWlmICghIGR0LmlzVmFsaWQpIHsKCQkJCXJldHVybiBudWxsOwoJCQl9CgkKCQkJZHQuc2V0TG9jYWxlKGxvY2FsZSk7CgkJfQoJCWVsc2UgaWYgKCEgZm9ybWF0KSB7CgkJCS8vIE5vIGZvcm1hdCBnaXZlbiwgbXVzdCBiZSBJU08KCQkJZHQgPSBuZXcgRGF0ZShkKTsKCQl9CgkJZWxzZSB7CgkJCWlmICghIF9fbWxXYXJuaW5nKSB7CgkJCQlhbGVydCgnRGF0YVRhYmxlcyB3YXJuaW5nOiBGb3JtYXR0ZWQgZGF0ZSB3aXRob3V0IE1vbWVudC5qcyBvciBMdXhvbiAtIGh0dHBzOi8vZGF0YXRhYmxlcy5uZXQvdG4vMTcnKTsKCQkJfQoJCgkJCV9fbWxXYXJuaW5nID0gdHJ1ZTsKCQl9CgkKCQlyZXR1cm4gZHQ7Cgl9CgkKCS8vIFdyYXBwZXIgZm9yIGRhdGUsIGRhdGV0aW1lIGFuZCB0aW1lIHdoaWNoIGFsbCBvcGVyYXRlIHRoZSBzYW1lIHdheSB3aXRoIHRoZSBleGNlcHRpb24gb2YKCS8vIHRoZSBvdXRwdXQgc3RyaW5nIGZvciBhdXRvIGxvY2FsZSBzdXBwb3J0CglmdW5jdGlvbiBfX21sSGVscGVyIChsb2NhbGVTdHJpbmcpIHsKCQlyZXR1cm4gZnVuY3Rpb24gKCBmcm9tLCB0bywgbG9jYWxlLCBkZWYgKSB7CgkJCS8vIEx1eG9uIGFuZCBNb21lbnQgc3VwcG9ydAoJCQkvLyBBcmd1bWVudCBzaGlmdGluZwoJCQlpZiAoIGFyZ3VtZW50cy5sZW5ndGggPT09IDAgKSB7CgkJCQlsb2NhbGUgPSAnZW4nOwoJCQkJdG8gPSBudWxsOyAvLyBtZWFucyB0b0xvY2FsZVN0cmluZwoJCQkJZnJvbSA9IG51bGw7IC8vIG1lYW5zIGlzbzg2MDEKCQkJfQoJCQllbHNlIGlmICggYXJndW1lbnRzLmxlbmd0aCA9PT0gMSApIHsKCQkJCWxvY2FsZSA9ICdlbic7CgkJCQl0byA9IGZyb207CgkJCQlmcm9tID0gbnVsbDsKCQkJfQoJCQllbHNlIGlmICggYXJndW1lbnRzLmxlbmd0aCA9PT0gMiApIHsKCQkJCWxvY2FsZSA9IHRvOwoJCQkJdG8gPSBmcm9tOwoJCQkJZnJvbSA9IG51bGw7CgkJCX0KCQoJCQl2YXIgdHlwZU5hbWUgPSAnZGF0ZXRpbWUtJyArIHRvOwoJCgkJCS8vIEFkZCB0eXBlIGRldGVjdGlvbiBhbmQgc29ydGluZyBzcGVjaWZpYyB0byB0aGlzIGRhdGUgZm9ybWF0IC0gd2UgbmVlZCB0byBiZSBhYmxlIHRvIGlkZW50aWZ5CgkJCS8vIGRhdGUgdHlwZSBjb2x1bW5zIGFzIHN1Y2gsIHJhdGhlciB0aGFuIGFzIG51bWJlcnMgaW4gZXh0ZW5zaW9ucy4gSGVuY2UgdGhlIG5lZWQgZm9yIHRoaXMuCgkJCWlmICghIERhdGFUYWJsZS5leHQudHlwZS5vcmRlclt0eXBlTmFtZV0pIHsKCQkJCS8vIFRoZSByZW5kZXJlciB3aWxsIGdpdmUgdGhlIHZhbHVlIHRvIHR5cGUgZGV0ZWN0IGFzIHRoZSB0eXBlIQoJCQkJRGF0YVRhYmxlLmV4dC50eXBlLmRldGVjdC51bnNoaWZ0KGZ1bmN0aW9uIChkKSB7CgkJCQkJcmV0dXJuIGQgPT09IHR5cGVOYW1lID8gdHlwZU5hbWUgOiBmYWxzZTsKCQkJCX0pOwoJCgkJCQkvLyBUaGUgcmVuZGVyZXIgZ2l2ZXMgdXMgTW9tZW50LCBMdXhvbiBvciBEYXRlIG9iZWN0cyBmb3IgdGhlIHNvcnRpbmcsIGFsbCBvZiB3aGljaCBoYXZlIGEKCQkJCS8vIGB2YWx1ZU9mYCB3aGljaCBnaXZlcyBtaWxsaXNlY29uZHMgZXBvY2gKCQkJCURhdGFUYWJsZS5leHQudHlwZS5vcmRlclt0eXBlTmFtZSArICctYXNjJ10gPSBmdW5jdGlvbiAoYSwgYikgewoJCQkJCXZhciB4ID0gYS52YWx1ZU9mKCk7CgkJCQkJdmFyIHkgPSBiLnZhbHVlT2YoKTsKCQoJCQkJCXJldHVybiB4ID09PSB5CgkJCQkJCT8gMAoJCQkJCQk6IHggPCB5CgkJCQkJCQk/IC0xCgkJCQkJCQk6IDE7CgkJCQl9CgkKCQkJCURhdGFUYWJsZS5leHQudHlwZS5vcmRlclt0eXBlTmFtZSArICctZGVzYyddID0gZnVuY3Rpb24gKGEsIGIpIHsKCQkJCQl2YXIgeCA9IGEudmFsdWVPZigpOwoJCQkJCXZhciB5ID0gYi52YWx1ZU9mKCk7CgkKCQkJCQlyZXR1cm4geCA9PT0geQoJCQkJCQk/IDAKCQkJCQkJOiB4ID4geQoJCQkJCQkJPyAtMQoJCQkJCQkJOiAxOwoJCQkJfQoJCQl9CgkJCgkJCXJldHVybiBmdW5jdGlvbiAoIGQsIHR5cGUgKSB7CgkJCQkvLyBBbGxvdyBmb3IgYSBkZWZhdWx0IHZhbHVlCgkJCQlpZiAoZCA9PT0gbnVsbCB8fCBkID09PSB1bmRlZmluZWQpIHsKCQkJCQlpZiAoZGVmID09PSAnLS1ub3cnKSB7CgkJCQkJCS8vIFdlIHRyZWF0IGV2ZXJ5dGhpbmcgYXMgVVRDIGZ1cnRoZXIgZG93biwgc28gbm8gY2hhbmdlcyBhcmUKCQkJCQkJLy8gbWFkZSwgYXMgc3VjaCBuZWVkIHRvIGdldCB0aGUgbG9jYWwgZGF0ZSAvIHRpbWUgYXMgaWYgaXQgd2VyZQoJCQkJCQkvLyBVVEMKCQkJCQkJdmFyIGxvY2FsID0gbmV3IERhdGUoKTsKCQkJCQkJZCA9IG5ldyBEYXRlKCBEYXRlLlVUQygKCQkJCQkJCWxvY2FsLmdldEZ1bGxZZWFyKCksIGxvY2FsLmdldE1vbnRoKCksIGxvY2FsLmdldERhdGUoKSwKCQkJCQkJCWxvY2FsLmdldEhvdXJzKCksIGxvY2FsLmdldE1pbnV0ZXMoKSwgbG9jYWwuZ2V0U2Vjb25kcygpCgkJCQkJCSkgKTsKCQkJCQl9CgkJCQkJZWxzZSB7CgkJCQkJCWQgPSAnJzsKCQkJCQl9CgkJCQl9CgkKCQkJCWlmICh0eXBlID09PSAndHlwZScpIHsKCQkJCQkvLyBUeXBpbmcgdXNlcyB0aGUgdHlwZSBuYW1lIGZvciBmYXN0IG1hdGNoaW5nCgkJCQkJcmV0dXJuIHR5cGVOYW1lOwoJCQkJfQoJCgkJCQlpZiAoZCA9PT0gJycpIHsKCQkJCQlyZXR1cm4gdHlwZSAhPT0gJ3NvcnQnCgkJCQkJCT8gJycKCQkJCQkJOiBfX21sZE9iaignMDAwMC0wMS0wMSAwMDowMDowMCcsIG51bGwsIGxvY2FsZSk7CgkJCQl9CgkKCQkJCS8vIFNob3J0Y3V0LiBJZiBgZnJvbWAgYW5kIGB0b2AgYXJlIHRoZSBzYW1lLCB3ZSBhcmUgdXNpbmcgdGhlIHJlbmRlcmVyIHRvCgkJCQkvLyBmb3JtYXQgZm9yIG9yZGVyaW5nLCBub3QgZGlzcGxheSAtIGl0cyBhbHJlYWR5IGluIHRoZSBkaXNwbGF5IGZvcm1hdC4KCQkJCWlmICggdG8gIT09IG51bGwgJiYgZnJvbSA9PT0gdG8gJiYgdHlwZSAhPT0gJ3NvcnQnICYmIHR5cGUgIT09ICd0eXBlJyAmJiAhIChkIGluc3RhbmNlb2YgRGF0ZSkgKSB7CgkJCQkJcmV0dXJuIGQ7CgkJCQl9CgkKCQkJCXZhciBkdCA9IF9fbWxkT2JqKGQsIGZyb20sIGxvY2FsZSk7CgkKCQkJCWlmIChkdCA9PT0gbnVsbCkgewoJCQkJCXJldHVybiBkOwoJCQkJfQoJCgkJCQlpZiAodHlwZSA9PT0gJ3NvcnQnKSB7CgkJCQkJcmV0dXJuIGR0OwoJCQkJfQoJCQkJCgkJCQl2YXIgZm9ybWF0dGVkID0gdG8gPT09IG51bGwKCQkJCQk/IF9fbWxkKGR0LCAndG9EYXRlJywgJ3RvSlNEYXRlJywgJycpW2xvY2FsZVN0cmluZ10oKQoJCQkJCTogX19tbGQoZHQsICdmb3JtYXQnLCAndG9Gb3JtYXQnLCAndG9JU09TdHJpbmcnLCB0byk7CgkKCQkJCS8vIFhTUyBwcm90ZWN0aW9uCgkJCQlyZXR1cm4gdHlwZSA9PT0gJ2Rpc3BsYXknID8KCQkJCQlfX2h0bWxFc2NhcGVFbnRpdGllcyggZm9ybWF0dGVkICkgOgoJCQkJCWZvcm1hdHRlZDsKCQkJfTsKCQl9Cgl9CgkKCS8vIEJhc2VkIG9uIGxvY2FsZSwgZGV0ZXJtaW5lIHN0YW5kYXJkIG51bWJlciBmb3JtYXR0aW5nCgkvLyBGYWxsYmFjayBmb3IgbGVnYWN5IGJyb3dzZXJzIGlzIFVTIEVuZ2xpc2gKCXZhciBfX3Rob3VzYW5kcyA9ICcsJzsKCXZhciBfX2RlY2ltYWwgPSAnLic7CgkKCWlmIChJbnRsKSB7CgkJdHJ5IHsKCQkJdmFyIG51bSA9IG5ldyBJbnRsLk51bWJlckZvcm1hdCgpLmZvcm1hdFRvUGFydHMoMTAwMDAwLjEpOwoJCQoJCQlmb3IgKHZhciBpPTAgOyBpPG51bS5sZW5ndGggOyBpKyspIHsKCQkJCWlmIChudW1baV0udHlwZSA9PT0gJ2dyb3VwJykgewoJCQkJCV9fdGhvdXNhbmRzID0gbnVtW2ldLnZhbHVlOwoJCQkJfQoJCQkJZWxzZSBpZiAobnVtW2ldLnR5cGUgPT09ICdkZWNpbWFsJykgewoJCQkJCV9fZGVjaW1hbCA9IG51bVtpXS52YWx1ZTsKCQkJCX0KCQkJfQoJCX0KCQljYXRjaCAoZSkgewoJCQkvLyBub29wCgkJfQoJfQoJCgkvLyBGb3JtYXR0ZWQgZGF0ZSB0aW1lIGRldGVjdGlvbiAtIHVzZSBieSBkZWNsYXJpbmcgdGhlIGZvcm1hdHMgeW91IGFyZSBnb2luZyB0byB1c2UKCURhdGFUYWJsZS5kYXRldGltZSA9IGZ1bmN0aW9uICggZm9ybWF0LCBsb2NhbGUgKSB7CgkJdmFyIHR5cGVOYW1lID0gJ2RhdGV0aW1lLWRldGVjdC0nICsgZm9ybWF0OwoJCgkJaWYgKCEgbG9jYWxlKSB7CgkJCWxvY2FsZSA9ICdlbic7CgkJfQoJCgkJaWYgKCEgRGF0YVRhYmxlLmV4dC50eXBlLm9yZGVyW3R5cGVOYW1lXSkgewoJCQlEYXRhVGFibGUuZXh0LnR5cGUuZGV0ZWN0LnVuc2hpZnQoZnVuY3Rpb24gKGQpIHsKCQkJCXZhciBkdCA9IF9fbWxkT2JqKGQsIGZvcm1hdCwgbG9jYWxlKTsKCQkJCXJldHVybiBkID09PSAnJyB8fCBkdCA/IHR5cGVOYW1lIDogZmFsc2U7CgkJCX0pOwoJCgkJCURhdGFUYWJsZS5leHQudHlwZS5vcmRlclt0eXBlTmFtZSArICctcHJlJ10gPSBmdW5jdGlvbiAoZCkgewoJCQkJcmV0dXJuIF9fbWxkT2JqKGQsIGZvcm1hdCwgbG9jYWxlKSB8fCAwOwoJCQl9CgkJfQoJfQoJCgkvKioKCSAqIEhlbHBlcnMgZm9yIGBjb2x1bW5zLnJlbmRlcmAuCgkgKgoJICogVGhlIG9wdGlvbnMgZGVmaW5lZCBoZXJlIGNhbiBiZSB1c2VkIHdpdGggdGhlIGBjb2x1bW5zLnJlbmRlcmAgaW5pdGlhbGlzYXRpb24KCSAqIG9wdGlvbiB0byBwcm92aWRlIGEgZGlzcGxheSByZW5kZXJlci4gVGhlIGZvbGxvd2luZyBmdW5jdGlvbnMgYXJlIGRlZmluZWQ6CgkgKgoJICogKiBgbnVtYmVyYCAtIFdpbGwgZm9ybWF0IG51bWVyaWMgZGF0YSAoZGVmaW5lZCBieSBgY29sdW1ucy5kYXRhYCkgZm9yCgkgKiAgIGRpc3BsYXksIHJldGFpbmluZyB0aGUgb3JpZ2luYWwgdW5mb3JtYXR0ZWQgZGF0YSBmb3Igc29ydGluZyBhbmQgZmlsdGVyaW5nLgoJICogICBJdCB0YWtlcyA1IHBhcmFtZXRlcnM6CgkgKiAgICogYHN0cmluZ2AgLSBUaG91c2FuZHMgZ3JvdXBpbmcgc2VwYXJhdG9yCgkgKiAgICogYHN0cmluZ2AgLSBEZWNpbWFsIHBvaW50IGluZGljYXRvcgoJICogICAqIGBpbnRlZ2VyYCAtIE51bWJlciBvZiBkZWNpbWFsIHBvaW50cyB0byBzaG93CgkgKiAgICogYHN0cmluZ2AgKG9wdGlvbmFsKSAtIFByZWZpeC4KCSAqICAgKiBgc3RyaW5nYCAob3B0aW9uYWwpIC0gUG9zdGZpeCAoL3N1ZmZpeCkuCgkgKiAqIGB0ZXh0YCAtIEVzY2FwZSBIVE1MIHRvIGhlbHAgcHJldmVudCBYU1MgYXR0YWNrcy4gSXQgaGFzIG5vIG9wdGlvbmFsCgkgKiAgIHBhcmFtZXRlcnMuCgkgKgoJICogQGV4YW1wbGUKCSAqICAgLy8gQ29sdW1uIGRlZmluaXRpb24gdXNpbmcgdGhlIG51bWJlciByZW5kZXJlcgoJICogICB7CgkgKiAgICAgZGF0YTogInNhbGFyeSIsCgkgKiAgICAgcmVuZGVyOiAkLmZuLmRhdGFUYWJsZS5yZW5kZXIubnVtYmVyKCAnXCcnLCAnLicsIDAsICckJyApCgkgKiAgIH0KCSAqCgkgKiBAbmFtZXNwYWNlCgkgKi8KCURhdGFUYWJsZS5yZW5kZXIgPSB7CgkJZGF0ZTogX19tbEhlbHBlcigndG9Mb2NhbGVEYXRlU3RyaW5nJyksCgkJZGF0ZXRpbWU6IF9fbWxIZWxwZXIoJ3RvTG9jYWxlU3RyaW5nJyksCgkJdGltZTogX19tbEhlbHBlcigndG9Mb2NhbGVUaW1lU3RyaW5nJyksCgkJbnVtYmVyOiBmdW5jdGlvbiAoIHRob3VzYW5kcywgZGVjaW1hbCwgcHJlY2lzaW9uLCBwcmVmaXgsIHBvc3RmaXggKSB7CgkJCS8vIEF1dG8gbG9jYWxlIGRldGVjdGlvbgoJCQlpZiAodGhvdXNhbmRzID09PSBudWxsIHx8IHRob3VzYW5kcyA9PT0gdW5kZWZpbmVkKSB7CgkJCQl0aG91c2FuZHMgPSBfX3Rob3VzYW5kczsKCQkJfQoJCgkJCWlmIChkZWNpbWFsID09PSBudWxsIHx8IGRlY2ltYWwgPT09IHVuZGVmaW5lZCkgewoJCQkJZGVjaW1hbCA9IF9fZGVjaW1hbDsKCQkJfQoJCgkJCXJldHVybiB7CgkJCQlkaXNwbGF5OiBmdW5jdGlvbiAoIGQgKSB7CgkJCQkJaWYgKCB0eXBlb2YgZCAhPT0gJ251bWJlcicgJiYgdHlwZW9mIGQgIT09ICdzdHJpbmcnICkgewoJCQkJCQlyZXR1cm4gZDsKCQkJCQl9CgkKCQkJCQlpZiAoZCA9PT0gJycgfHwgZCA9PT0gbnVsbCkgewoJCQkJCQlyZXR1cm4gZDsKCQkJCQl9CgkKCQkJCQl2YXIgbmVnYXRpdmUgPSBkIDwgMCA/ICctJyA6ICcnOwoJCQkJCXZhciBmbG8gPSBwYXJzZUZsb2F0KCBkICk7CgkKCQkJCQkvLyBJZiBOYU4gdGhlbiB0aGVyZSBpc24ndCBtdWNoIGZvcm1hdHRpbmcgdGhhdCB3ZSBjYW4gZG8gLSBqdXN0CgkJCQkJLy8gcmV0dXJuIGltbWVkaWF0ZWx5LCBlc2NhcGluZyBhbnkgSFRNTCAodGhpcyB3YXMgc3VwcG9zZWQgdG8KCQkJCQkvLyBiZSBhIG51bWJlciBhZnRlciBhbGwpCgkJCQkJaWYgKCBpc05hTiggZmxvICkgKSB7CgkJCQkJCXJldHVybiBfX2h0bWxFc2NhcGVFbnRpdGllcyggZCApOwoJCQkJCX0KCQoJCQkJCWZsbyA9IGZsby50b0ZpeGVkKCBwcmVjaXNpb24gKTsKCQkJCQlkID0gTWF0aC5hYnMoIGZsbyApOwoJCgkJCQkJdmFyIGludFBhcnQgPSBwYXJzZUludCggZCwgMTAgKTsKCQkJCQl2YXIgZmxvYXRQYXJ0ID0gcHJlY2lzaW9uID8KCQkJCQkJZGVjaW1hbCsoZCAtIGludFBhcnQpLnRvRml4ZWQoIHByZWNpc2lvbiApLnN1YnN0cmluZyggMiApOgoJCQkJCQknJzsKCQoJCQkJCS8vIElmIHplcm8sIHRoZW4gY2FuJ3QgaGF2ZSBhIG5lZ2F0aXZlIHByZWZpeAoJCQkJCWlmIChpbnRQYXJ0ID09PSAwICYmIHBhcnNlRmxvYXQoZmxvYXRQYXJ0KSA9PT0gMCkgewoJCQkJCQluZWdhdGl2ZSA9ICcnOwoJCQkJCX0KCQoJCQkJCXJldHVybiBuZWdhdGl2ZSArIChwcmVmaXh8fCcnKSArCgkJCQkJCWludFBhcnQudG9TdHJpbmcoKS5yZXBsYWNlKAoJCQkJCQkJL1xCKD89KFxkezN9KSsoPyFcZCkpL2csIHRob3VzYW5kcwoJCQkJCQkpICsKCQkJCQkJZmxvYXRQYXJ0ICsKCQkJCQkJKHBvc3RmaXh8fCcnKTsKCQkJCX0KCQkJfTsKCQl9LAoJCgkJdGV4dDogZnVuY3Rpb24gKCkgewoJCQlyZXR1cm4gewoJCQkJZGlzcGxheTogX19odG1sRXNjYXBlRW50aXRpZXMsCgkJCQlmaWx0ZXI6IF9faHRtbEVzY2FwZUVudGl0aWVzCgkJCX07CgkJfQoJfTsKCQoJCgkvKgoJICogVGhpcyBpcyByZWFsbHkgYSBnb29kIGJpdCBydWJiaXNoIHRoaXMgbWV0aG9kIG9mIGV4cG9zaW5nIHRoZSBpbnRlcm5hbCBtZXRob2RzCgkgKiBwdWJsaWNseS4uLiAtIFRvIGJlIGZpeGVkIGluIDIuMCB1c2luZyBtZXRob2RzIG9uIHRoZSBwcm90b3R5cGUKCSAqLwoJCgkKCS8qKgoJICogQ3JlYXRlIGEgd3JhcHBlciBmdW5jdGlvbiBmb3IgZXhwb3J0aW5nIGFuIGludGVybmFsIGZ1bmN0aW9ucyB0byBhbiBleHRlcm5hbCBBUEkuCgkgKiAgQHBhcmFtIHtzdHJpbmd9IGZuIEFQSSBmdW5jdGlvbiBuYW1lCgkgKiAgQHJldHVybnMge2Z1bmN0aW9ufSB3cmFwcGVkIGZ1bmN0aW9uCgkgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNpbnRlcm5hbAoJICovCglmdW5jdGlvbiBfZm5FeHRlcm5BcGlGdW5jIChmbikKCXsKCQlyZXR1cm4gZnVuY3Rpb24oKSB7CgkJCXZhciBhcmdzID0gW19mblNldHRpbmdzRnJvbU5vZGUoIHRoaXNbRGF0YVRhYmxlLmV4dC5pQXBpSW5kZXhdICldLmNvbmNhdCgKCQkJCUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cykKCQkJKTsKCQkJcmV0dXJuIERhdGFUYWJsZS5leHQuaW50ZXJuYWxbZm5dLmFwcGx5KCB0aGlzLCBhcmdzICk7CgkJfTsKCX0KCQoJCgkvKioKCSAqIFJlZmVyZW5jZSB0byBpbnRlcm5hbCBmdW5jdGlvbnMgZm9yIHVzZSBieSBwbHVnLWluIGRldmVsb3BlcnMuIE5vdGUgdGhhdAoJICogdGhlc2UgbWV0aG9kcyBhcmUgcmVmZXJlbmNlcyB0byBpbnRlcm5hbCBmdW5jdGlvbnMgYW5kIGFyZSBjb25zaWRlcmVkIHRvIGJlCgkgKiBwcml2YXRlLiBJZiB5b3UgdXNlIHRoZXNlIG1ldGhvZHMsIGJlIGF3YXJlIHRoYXQgdGhleSBhcmUgbGlhYmxlIHRvIGNoYW5nZQoJICogYmV0d2VlbiB2ZXJzaW9ucy4KCSAqICBAbmFtZXNwYWNlCgkgKi8KCSQuZXh0ZW5kKCBEYXRhVGFibGUuZXh0LmludGVybmFsLCB7CgkJX2ZuRXh0ZXJuQXBpRnVuYzogX2ZuRXh0ZXJuQXBpRnVuYywKCQlfZm5CdWlsZEFqYXg6IF9mbkJ1aWxkQWpheCwKCQlfZm5BamF4VXBkYXRlOiBfZm5BamF4VXBkYXRlLAoJCV9mbkFqYXhQYXJhbWV0ZXJzOiBfZm5BamF4UGFyYW1ldGVycywKCQlfZm5BamF4VXBkYXRlRHJhdzogX2ZuQWpheFVwZGF0ZURyYXcsCgkJX2ZuQWpheERhdGFTcmM6IF9mbkFqYXhEYXRhU3JjLAoJCV9mbkFkZENvbHVtbjogX2ZuQWRkQ29sdW1uLAoJCV9mbkNvbHVtbk9wdGlvbnM6IF9mbkNvbHVtbk9wdGlvbnMsCgkJX2ZuQWRqdXN0Q29sdW1uU2l6aW5nOiBfZm5BZGp1c3RDb2x1bW5TaXppbmcsCgkJX2ZuVmlzaWJsZVRvQ29sdW1uSW5kZXg6IF9mblZpc2libGVUb0NvbHVtbkluZGV4LAoJCV9mbkNvbHVtbkluZGV4VG9WaXNpYmxlOiBfZm5Db2x1bW5JbmRleFRvVmlzaWJsZSwKCQlfZm5WaXNibGVDb2x1bW5zOiBfZm5WaXNibGVDb2x1bW5zLAoJCV9mbkdldENvbHVtbnM6IF9mbkdldENvbHVtbnMsCgkJX2ZuQ29sdW1uVHlwZXM6IF9mbkNvbHVtblR5cGVzLAoJCV9mbkFwcGx5Q29sdW1uRGVmczogX2ZuQXBwbHlDb2x1bW5EZWZzLAoJCV9mbkh1bmdhcmlhbk1hcDogX2ZuSHVuZ2FyaWFuTWFwLAoJCV9mbkNhbWVsVG9IdW5nYXJpYW46IF9mbkNhbWVsVG9IdW5nYXJpYW4sCgkJX2ZuTGFuZ3VhZ2VDb21wYXQ6IF9mbkxhbmd1YWdlQ29tcGF0LAoJCV9mbkJyb3dzZXJEZXRlY3Q6IF9mbkJyb3dzZXJEZXRlY3QsCgkJX2ZuQWRkRGF0YTogX2ZuQWRkRGF0YSwKCQlfZm5BZGRUcjogX2ZuQWRkVHIsCgkJX2ZuTm9kZVRvRGF0YUluZGV4OiBfZm5Ob2RlVG9EYXRhSW5kZXgsCgkJX2ZuTm9kZVRvQ29sdW1uSW5kZXg6IF9mbk5vZGVUb0NvbHVtbkluZGV4LAoJCV9mbkdldENlbGxEYXRhOiBfZm5HZXRDZWxsRGF0YSwKCQlfZm5TZXRDZWxsRGF0YTogX2ZuU2V0Q2VsbERhdGEsCgkJX2ZuU3BsaXRPYmpOb3RhdGlvbjogX2ZuU3BsaXRPYmpOb3RhdGlvbiwKCQlfZm5HZXRPYmplY3REYXRhRm46IF9mbkdldE9iamVjdERhdGFGbiwKCQlfZm5TZXRPYmplY3REYXRhRm46IF9mblNldE9iamVjdERhdGFGbiwKCQlfZm5HZXREYXRhTWFzdGVyOiBfZm5HZXREYXRhTWFzdGVyLAoJCV9mbkNsZWFyVGFibGU6IF9mbkNsZWFyVGFibGUsCgkJX2ZuRGVsZXRlSW5kZXg6IF9mbkRlbGV0ZUluZGV4LAoJCV9mbkludmFsaWRhdGU6IF9mbkludmFsaWRhdGUsCgkJX2ZuR2V0Um93RWxlbWVudHM6IF9mbkdldFJvd0VsZW1lbnRzLAoJCV9mbkNyZWF0ZVRyOiBfZm5DcmVhdGVUciwKCQlfZm5CdWlsZEhlYWQ6IF9mbkJ1aWxkSGVhZCwKCQlfZm5EcmF3SGVhZDogX2ZuRHJhd0hlYWQsCgkJX2ZuRHJhdzogX2ZuRHJhdywKCQlfZm5SZURyYXc6IF9mblJlRHJhdywKCQlfZm5BZGRPcHRpb25zSHRtbDogX2ZuQWRkT3B0aW9uc0h0bWwsCgkJX2ZuRGV0ZWN0SGVhZGVyOiBfZm5EZXRlY3RIZWFkZXIsCgkJX2ZuR2V0VW5pcXVlVGhzOiBfZm5HZXRVbmlxdWVUaHMsCgkJX2ZuRmVhdHVyZUh0bWxGaWx0ZXI6IF9mbkZlYXR1cmVIdG1sRmlsdGVyLAoJCV9mbkZpbHRlckNvbXBsZXRlOiBfZm5GaWx0ZXJDb21wbGV0ZSwKCQlfZm5GaWx0ZXJDdXN0b206IF9mbkZpbHRlckN1c3RvbSwKCQlfZm5GaWx0ZXJDb2x1bW46IF9mbkZpbHRlckNvbHVtbiwKCQlfZm5GaWx0ZXI6IF9mbkZpbHRlciwKCQlfZm5GaWx0ZXJDcmVhdGVTZWFyY2g6IF9mbkZpbHRlckNyZWF0ZVNlYXJjaCwKCQlfZm5Fc2NhcGVSZWdleDogX2ZuRXNjYXBlUmVnZXgsCgkJX2ZuRmlsdGVyRGF0YTogX2ZuRmlsdGVyRGF0YSwKCQlfZm5GZWF0dXJlSHRtbEluZm86IF9mbkZlYXR1cmVIdG1sSW5mbywKCQlfZm5VcGRhdGVJbmZvOiBfZm5VcGRhdGVJbmZvLAoJCV9mbkluZm9NYWNyb3M6IF9mbkluZm9NYWNyb3MsCgkJX2ZuSW5pdGlhbGlzZTogX2ZuSW5pdGlhbGlzZSwKCQlfZm5Jbml0Q29tcGxldGU6IF9mbkluaXRDb21wbGV0ZSwKCQlfZm5MZW5ndGhDaGFuZ2U6IF9mbkxlbmd0aENoYW5nZSwKCQlfZm5GZWF0dXJlSHRtbExlbmd0aDogX2ZuRmVhdHVyZUh0bWxMZW5ndGgsCgkJX2ZuRmVhdHVyZUh0bWxQYWdpbmF0ZTogX2ZuRmVhdHVyZUh0bWxQYWdpbmF0ZSwKCQlfZm5QYWdlQ2hhbmdlOiBfZm5QYWdlQ2hhbmdlLAoJCV9mbkZlYXR1cmVIdG1sUHJvY2Vzc2luZzogX2ZuRmVhdHVyZUh0bWxQcm9jZXNzaW5nLAoJCV9mblByb2Nlc3NpbmdEaXNwbGF5OiBfZm5Qcm9jZXNzaW5nRGlzcGxheSwKCQlfZm5GZWF0dXJlSHRtbFRhYmxlOiBfZm5GZWF0dXJlSHRtbFRhYmxlLAoJCV9mblNjcm9sbERyYXc6IF9mblNjcm9sbERyYXcsCgkJX2ZuQXBwbHlUb0NoaWxkcmVuOiBfZm5BcHBseVRvQ2hpbGRyZW4sCgkJX2ZuQ2FsY3VsYXRlQ29sdW1uV2lkdGhzOiBfZm5DYWxjdWxhdGVDb2x1bW5XaWR0aHMsCgkJX2ZuVGhyb3R0bGU6IF9mblRocm90dGxlLAoJCV9mbkNvbnZlcnRUb1dpZHRoOiBfZm5Db252ZXJ0VG9XaWR0aCwKCQlfZm5HZXRXaWRlc3ROb2RlOiBfZm5HZXRXaWRlc3ROb2RlLAoJCV9mbkdldE1heExlblN0cmluZzogX2ZuR2V0TWF4TGVuU3RyaW5nLAoJCV9mblN0cmluZ1RvQ3NzOiBfZm5TdHJpbmdUb0NzcywKCQlfZm5Tb3J0RmxhdHRlbjogX2ZuU29ydEZsYXR0ZW4sCgkJX2ZuU29ydDogX2ZuU29ydCwKCQlfZm5Tb3J0QXJpYTogX2ZuU29ydEFyaWEsCgkJX2ZuU29ydExpc3RlbmVyOiBfZm5Tb3J0TGlzdGVuZXIsCgkJX2ZuU29ydEF0dGFjaExpc3RlbmVyOiBfZm5Tb3J0QXR0YWNoTGlzdGVuZXIsCgkJX2ZuU29ydGluZ0NsYXNzZXM6IF9mblNvcnRpbmdDbGFzc2VzLAoJCV9mblNvcnREYXRhOiBfZm5Tb3J0RGF0YSwKCQlfZm5TYXZlU3RhdGU6IF9mblNhdmVTdGF0ZSwKCQlfZm5Mb2FkU3RhdGU6IF9mbkxvYWRTdGF0ZSwKCQlfZm5JbXBsZW1lbnRTdGF0ZTogX2ZuSW1wbGVtZW50U3RhdGUsCgkJX2ZuU2V0dGluZ3NGcm9tTm9kZTogX2ZuU2V0dGluZ3NGcm9tTm9kZSwKCQlfZm5Mb2c6IF9mbkxvZywKCQlfZm5NYXA6IF9mbk1hcCwKCQlfZm5CaW5kQWN0aW9uOiBfZm5CaW5kQWN0aW9uLAoJCV9mbkNhbGxiYWNrUmVnOiBfZm5DYWxsYmFja1JlZywKCQlfZm5DYWxsYmFja0ZpcmU6IF9mbkNhbGxiYWNrRmlyZSwKCQlfZm5MZW5ndGhPdmVyZmxvdzogX2ZuTGVuZ3RoT3ZlcmZsb3csCgkJX2ZuUmVuZGVyZXI6IF9mblJlbmRlcmVyLAoJCV9mbkRhdGFTb3VyY2U6IF9mbkRhdGFTb3VyY2UsCgkJX2ZuUm93QXR0cmlidXRlczogX2ZuUm93QXR0cmlidXRlcywKCQlfZm5FeHRlbmQ6IF9mbkV4dGVuZCwKCQlfZm5DYWxjdWxhdGVFbmQ6IGZ1bmN0aW9uICgpIHt9IC8vIFVzZWQgYnkgYSBsb3Qgb2YgcGx1Zy1pbnMsIGJ1dCByZWR1bmRhbnQKCQkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIDEuMTAsIHNvIHRoaXMgZGVhZC1lbmQgZnVuY3Rpb24gaXMKCQkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZGVkIHRvIHByZXZlbnQgZXJyb3JzCgl9ICk7CgkKCQoJLy8galF1ZXJ5IGFjY2VzcwoJJC5mbi5kYXRhVGFibGUgPSBEYXRhVGFibGU7CgkKCS8vIFByb3ZpZGUgYWNjZXNzIHRvIHRoZSBob3N0IGpRdWVyeSBvYmplY3QgKGNpcmN1bGFyIHJlZmVyZW5jZSkKCURhdGFUYWJsZS4kID0gJDsKCQoJLy8gTGVnYWN5IGFsaWFzZXMKCSQuZm4uZGF0YVRhYmxlU2V0dGluZ3MgPSBEYXRhVGFibGUuc2V0dGluZ3M7CgkkLmZuLmRhdGFUYWJsZUV4dCA9IERhdGFUYWJsZS5leHQ7CgkKCS8vIFdpdGggYSBjYXBpdGFsIGBEYCB3ZSByZXR1cm4gYSBEYXRhVGFibGVzIEFQSSBpbnN0YW5jZSByYXRoZXIgdGhhbiBhCgkvLyBqUXVlcnkgb2JqZWN0CgkkLmZuLkRhdGFUYWJsZSA9IGZ1bmN0aW9uICggb3B0cyApIHsKCQlyZXR1cm4gJCh0aGlzKS5kYXRhVGFibGUoIG9wdHMgKS5hcGkoKTsKCX07CgkKCS8vIEFsbCBwcm9wZXJ0aWVzIHRoYXQgYXJlIGF2YWlsYWJsZSB0byAkLmZuLmRhdGFUYWJsZSBzaG91bGQgYWxzbyBiZQoJLy8gYXZhaWxhYmxlIG9uICQuZm4uRGF0YVRhYmxlCgkkLmVhY2goIERhdGFUYWJsZSwgZnVuY3Rpb24gKCBwcm9wLCB2YWwgKSB7CgkJJC5mbi5EYXRhVGFibGVbIHByb3AgXSA9IHZhbDsKCX0gKTsKCQoJcmV0dXJuIERhdGFUYWJsZTsKfQo=\")).default;\n",
       "    dt(window.$);\n",
       "  }\n",
       "</script>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style>table.dataTable td.dt-control{text-align:center;cursor:pointer}table.dataTable td.dt-control:before{height:1em;width:1em;margin-top:-9px;display:inline-block;color:white;border:.15em solid white;border-radius:1em;box-shadow:0 0 .2em #444;box-sizing:content-box;text-align:center;text-indent:0 !important;font-family:\"Courier New\",Courier,monospace;line-height:1em;content:\"+\";background-color:#31b131}table.dataTable tr.dt-hasChild td.dt-control:before{content:\"-\";background-color:#d33333}table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting_asc_disabled,table.dataTable thead>tr>th.sorting_desc_disabled,table.dataTable thead>tr>td.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting_asc_disabled,table.dataTable thead>tr>td.sorting_desc_disabled{cursor:pointer;position:relative;padding-right:26px}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after{position:absolute;display:block;opacity:.125;right:10px;line-height:9px;font-size:.9em}table.dataTable thead>tr>th.sorting:before,table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:before,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>th.sorting_desc_disabled:before,table.dataTable thead>tr>td.sorting:before,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:before,table.dataTable thead>tr>td.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:before{bottom:50%;content:\"▴\"}table.dataTable thead>tr>th.sorting:after,table.dataTable thead>tr>th.sorting_asc:after,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>th.sorting_asc_disabled:after,table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting:after,table.dataTable thead>tr>td.sorting_asc:after,table.dataTable thead>tr>td.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc_disabled:after,table.dataTable thead>tr>td.sorting_desc_disabled:after{top:50%;content:\"▾\"}table.dataTable thead>tr>th.sorting_asc:before,table.dataTable thead>tr>th.sorting_desc:after,table.dataTable thead>tr>td.sorting_asc:before,table.dataTable thead>tr>td.sorting_desc:after{opacity:.6}table.dataTable thead>tr>th.sorting_desc_disabled:after,table.dataTable thead>tr>th.sorting_asc_disabled:before,table.dataTable thead>tr>td.sorting_desc_disabled:after,table.dataTable thead>tr>td.sorting_asc_disabled:before{display:none}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}div.dataTables_scrollBody table.dataTable thead>tr>th:before,div.dataTables_scrollBody table.dataTable thead>tr>th:after,div.dataTables_scrollBody table.dataTable thead>tr>td:before,div.dataTables_scrollBody table.dataTable thead>tr>td:after{display:none}div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:2px}div.dataTables_processing>div:last-child{position:relative;width:80px;height:15px;margin:1em auto}div.dataTables_processing>div:last-child>div{position:absolute;top:0;width:13px;height:13px;border-radius:50%;background:rgba(13, 110, 253, 0.9);animation-timing-function:cubic-bezier(0, 1, 1, 0)}div.dataTables_processing>div:last-child>div:nth-child(1){left:8px;animation:datatables-loader-1 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(2){left:8px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(3){left:32px;animation:datatables-loader-2 .6s infinite}div.dataTables_processing>div:last-child>div:nth-child(4){left:56px;animation:datatables-loader-3 .6s infinite}@keyframes datatables-loader-1{0%{transform:scale(0)}100%{transform:scale(1)}}@keyframes datatables-loader-3{0%{transform:scale(1)}100%{transform:scale(0)}}@keyframes datatables-loader-2{0%{transform:translate(0, 0)}100%{transform:translate(24px, 0)}}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th,table.dataTable thead td,table.dataTable tfoot th,table.dataTable tfoot td{text-align:left}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable{width:100%;margin:0 auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead th,table.dataTable tfoot th{font-weight:bold}table.dataTable thead th,table.dataTable thead td{padding:10px;border-bottom:1px solid rgba(0, 0, 0, 0.3)}table.dataTable thead th:active,table.dataTable thead td:active{outline:none}table.dataTable tfoot th,table.dataTable tfoot td{padding:10px 10px 6px 10px;border-top:1px solid rgba(0, 0, 0, 0.3)}table.dataTable tbody tr{background-color:transparent}table.dataTable tbody tr.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.9);color:white}table.dataTable tbody th,table.dataTable tbody td{padding:8px 10px}table.dataTable.row-border tbody th,table.dataTable.row-border tbody td,table.dataTable.display tbody th,table.dataTable.display tbody td{border-top:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.row-border tbody tr:first-child th,table.dataTable.row-border tbody tr:first-child td,table.dataTable.display tbody tr:first-child th,table.dataTable.display tbody tr:first-child td{border-top:none}table.dataTable.cell-border tbody th,table.dataTable.cell-border tbody td{border-top:1px solid rgba(0, 0, 0, 0.15);border-right:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.cell-border tbody tr th:first-child,table.dataTable.cell-border tbody tr td:first-child{border-left:1px solid rgba(0, 0, 0, 0.15)}table.dataTable.cell-border tbody tr:first-child th,table.dataTable.cell-border tbody tr:first-child td{border-top:none}table.dataTable.stripe>tbody>tr.odd>*,table.dataTable.display>tbody>tr.odd>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.023)}table.dataTable.stripe>tbody>tr.odd.selected>*,table.dataTable.display>tbody>tr.odd.selected>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.923)}table.dataTable.hover>tbody>tr:hover>*,table.dataTable.display>tbody>tr:hover>*{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.035)}table.dataTable.hover>tbody>tr.selected:hover>*,table.dataTable.display>tbody>tr.selected:hover>*{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.935)}table.dataTable.order-column>tbody tr>.sorting_1,table.dataTable.order-column>tbody tr>.sorting_2,table.dataTable.order-column>tbody tr>.sorting_3,table.dataTable.display>tbody tr>.sorting_1,table.dataTable.display>tbody tr>.sorting_2,table.dataTable.display>tbody tr>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.019)}table.dataTable.order-column>tbody tr.selected>.sorting_1,table.dataTable.order-column>tbody tr.selected>.sorting_2,table.dataTable.order-column>tbody tr.selected>.sorting_3,table.dataTable.display>tbody tr.selected>.sorting_1,table.dataTable.display>tbody tr.selected>.sorting_2,table.dataTable.display>tbody tr.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.919)}table.dataTable.display>tbody>tr.odd>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.054)}table.dataTable.display>tbody>tr.odd>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.047)}table.dataTable.display>tbody>tr.odd>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.odd>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.039)}table.dataTable.display>tbody>tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.954)}table.dataTable.display>tbody>tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.947)}table.dataTable.display>tbody>tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.odd.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.939)}table.dataTable.display>tbody>tr.even>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.019)}table.dataTable.display>tbody>tr.even>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.011)}table.dataTable.display>tbody>tr.even>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.even>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.003)}table.dataTable.display>tbody>tr.even.selected>.sorting_1,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.919)}table.dataTable.display>tbody>tr.even.selected>.sorting_2,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.911)}table.dataTable.display>tbody>tr.even.selected>.sorting_3,table.dataTable.order-column.stripe>tbody>tr.even.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.903)}table.dataTable.display tbody tr:hover>.sorting_1,table.dataTable.order-column.hover tbody tr:hover>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.082)}table.dataTable.display tbody tr:hover>.sorting_2,table.dataTable.order-column.hover tbody tr:hover>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.074)}table.dataTable.display tbody tr:hover>.sorting_3,table.dataTable.order-column.hover tbody tr:hover>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(0, 0, 0, 0.062)}table.dataTable.display tbody tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.982)}table.dataTable.display tbody tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.974)}table.dataTable.display tbody tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3{box-shadow:inset 0 0 0 9999px rgba(13, 110, 253, 0.962)}table.dataTable.no-footer{border-bottom:1px solid rgba(0, 0, 0, 0.3)}table.dataTable.compact thead th,table.dataTable.compact thead td{padding:4px 17px}table.dataTable.compact tfoot th,table.dataTable.compact tfoot td{padding:4px}table.dataTable.compact tbody th,table.dataTable.compact tbody td{padding:4px}table.dataTable th,table.dataTable td{box-sizing:content-box}.dataTables_wrapper{position:relative;clear:both}.dataTables_wrapper .dataTables_length{float:left}.dataTables_wrapper .dataTables_length select{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;padding:4px}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter input{border:1px solid #aaa;border-radius:3px;padding:5px;background-color:transparent;margin-left:3px}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:.755em}.dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:.25em}.dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;color:#333 !important;border:1px solid transparent;border-radius:2px}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:#333 !important;border:1px solid rgba(0, 0, 0, 0.3);background-color:rgba(230, 230, 230, 0.1);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(230, 230, 230, 0.1)), color-stop(100%, rgba(0, 0, 0, 0.1)));background:-webkit-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-moz-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-ms-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:-o-linear-gradient(top, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%);background:linear-gradient(to bottom, rgba(230, 230, 230, 0.1) 0%, rgba(0, 0, 0, 0.1) 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#585858;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));background:-webkit-linear-gradient(top, #585858 0%, #111 100%);background:-moz-linear-gradient(top, #585858 0%, #111 100%);background:-ms-linear-gradient(top, #585858 0%, #111 100%);background:-o-linear-gradient(top, #585858 0%, #111 100%);background:linear-gradient(to bottom, #585858 0%, #111 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:none;background-color:#2b2b2b;background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));background:-webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:-o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);background:linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper .dataTables_paginate .ellipsis{padding:0 1em}.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_wrapper .dataTables_paginate{color:#333}.dataTables_wrapper .dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{-webkit-overflow-scrolling:touch}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td{vertical-align:middle}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid rgba(0, 0, 0, 0.3)}.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,.dataTables_wrapper.no-footer div.dataTables_scrollBody>table{border-bottom:none}.dataTables_wrapper:after{visibility:hidden;display:block;content:\"\";clear:both;height:0}@media screen and (max-width: 767px){.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.dataTables_wrapper .dataTables_paginate{margin-top:.5em}}@media screen and (max-width: 640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter{float:none;text-align:center}.dataTables_wrapper .dataTables_filter{margin-top:.5em}}\n",
       "</style>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2022.10</span>.<span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">24</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[1;36m2022.10\u001b[0m.\u001b[1;36m24\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from cdapython import Q, columns, unique_terms, query\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from itables import init_notebook_mode, show\n",
    "init_notebook_mode(all_interactive=True)\n",
    "import itables.options as opt\n",
    "opt.maxBytes=0\n",
    "opt.scrollX=\"200px\"\n",
    "opt.scrollCollapse=True\n",
    "opt.paging=True\n",
    "opt.maxColumns=0\n",
    "print(Q.get_version())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d538da92",
   "metadata": {},
   "source": [
    "<div class=\"cdanote\" style=\"background-color:#b3e5d5;color:black;padding:20px;\">\n",
    "    \n",
    "CDA data comes from three sources:\n",
    "<ul>\n",
    "<li><b>The <a href=\"https://proteomic.datacommons.cancer.gov/pdc/\"> Proteomic Data Commons</a> (PDC)</b></li>\n",
    "<li><b>The <a href=\"https://gdc.cancer.gov/\">Genomic Data Commons</a> (GDC)</b></li>\n",
    "<li><b>The <a href=\"https://datacommons.cancer.gov/repository/imaging-data-commons\">Imaging Data Commons</a> (IDC)</b></li>\n",
    "</ul> \n",
    "    \n",
    "The CDA makes this data searchable in four main endpoints:\n",
    "\n",
    "<ul>\n",
    "<li><b>subject:</b> A patient entity captures the study-independent metadata for research subjects. Human research subjects are usually not traceable to a particular person to protect the subjects privacy.</li>\n",
    "<li><b>researchsubject:</b> A research subject is the entity of interest in a specific research study or project, typically a human being or an animal, but can also be a device, group of humans or animals, or a tissue sample. Human research subjects are usually not traceable to a particular person to protect the subjects privacy. This entity plays the role of the case_id in existing data. A subject who participates in 3 studies will have 3 researchsubject IDs.</li>\n",
    "<li><b>specimen:</b> Any material taken as a sample from a biological entity (living or dead), or from a physical object or the environment. Specimens are usually collected as an example of their kind, often for use in some investigation.</li>\n",
    "<li><b>mutation:</b> Molecular data about specific mutations, currently limited to the TCGA-READ project from GDC.</li>\n",
    "</ul>\n",
    "one endpoint that can be added to the subject, researchsubject, or specimen to get the relevant files:    \n",
    "<ul>\n",
    "<li><b>file:</b> A unit of data about subjects, researchsubjects, specimens, or their associated information.</li>\n",
    "</ul>\n",
    "and two endpoints that offer deeper information about data in the researchsubject endpoint:\n",
    "<ul>\n",
    "<li><b>diagnosis:</b> A collection of characteristics that describe an abnormal condition of the body as assessed at a point in time. May be used to capture information about neoplastic and non-neoplastic conditions.</li>\n",
    "<li><b>treatment:</b> Represent medication administration or other treatment types.</li>\n",
    "</ul>\n",
    "</div>\n",
    "\n",
    "\n",
    "If you are looking to build a cohort of distinct individuals who meet some criteria, search by `subject`. If you want to build a cohort, but are particularly interested in studies rather than the participates per se, search by `researchsubject`. If you are looking for biosamples that can be ordered or a specific format of information (for e.g. histological slides) start with `specimen`. If you are primarily looking for files you can reuse for your own analysis, add `.file` to your call.\n",
    "\n",
    "In the subject, researchsubject, or specimen tables, all of the rows will have one or more files associated with them that can be directly found by chaining, as in `specimen.files`. Diagnosis and treatment do not have files directly associated with them, so a query statemet of `diagnosis.files` or `treatment.file` will not work. The mutation table does have files associated with it, but currently they cannot be accessed with `mutation.file`. Look for this feature in a later release.\n",
    "\n",
    "Any metadata field can be searched from any endpoint, the only difference between search types is what type of data is returned by default. This means that you can think of the CDA as a really, really enormous spreadsheet full of data. To search this enormous spreadsheet, you'd want select columns, and then filter rows.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f76026a3",
   "metadata": {},
   "source": [
    "## Getting simple summary data\n",
    "\n",
    "Let's try a broad search of the CDA to see what information exists about cancers that were first diagnosed in the brain. To run this simple search, we would first construct a query in `Q` and save it to a variable `myquery`. This is the same query we ran in the <a href=\"../BasicSearch\">Basic Search</a> notebook:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c92a98ba",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "myquery = Q('primary_diagnosis_site = \"brain\"')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e855573",
   "metadata": {
    "tags": [
     "Help!"
    ]
   },
   "source": [
    "\n",
    "<div class=\"cdawarn\" style=\"background-color:#f9cfbf;color:black;padding:20px;\">\n",
    "<h3>Where did those terms come from?</h3>\n",
    "    \n",
    "If you aren't sure how we knew what terms to put in our search, please refer back to the <a href=\"../SearchTerms\">What search terms are available?</a> notebook. \n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e492876",
   "metadata": {},
   "source": [
    "### Overall summary\n",
    "\n",
    "You can get a quick summary of how many unique specimens, treatments, diagnoses, researchsubjects and subjects meet your search criteria by chaining a `count` command into the basic `run` call. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c8e3599f",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">10.88</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">10880</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m10.88\u001b[0m sec \u001b[1;36m10880\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">specimen_count : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">39220</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "specimen_count : \u001b[1;36m39220\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">treatment_count : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2396</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "treatment_count : \u001b[1;36m2396\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">diagnosis_count : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1757</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "diagnosis_count : \u001b[1;36m1757\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">mutation_count : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">904</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "mutation_count : \u001b[1;36m904\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">researchsubject_count : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4347</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "researchsubject_count : \u001b[1;36m4347\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">subject_count : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">3015</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "subject_count : \u001b[1;36m3015\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": []
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myquery.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d483e944",
   "metadata": {},
   "source": [
    "These numbers are how many total rows of data will come back when querying the various endpoints.\n",
    "\n",
    "\n",
    "\n",
    "### subject summary\n",
    "\n",
    "We can also add `count`to the other run calls we did in the <a href=\"../BasicSearch\">Basic Search</a> notebook to get more detailed summaries:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "6d9137aa",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">13.584</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">13584</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m13.584\u001b[0m sec \u001b[1;36m13584\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "subjectresults = myquery.subject.count.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "4d0501a2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">3.911</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">3911</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m3.911\u001b[0m sec \u001b[1;36m3911\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">  files : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4924982</span>   \n",
       "</pre>\n"
      ],
      "text/plain": [
       "  files : \u001b[1;36m4924982\u001b[0m   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">    total : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">3015</span>    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "    total : \u001b[1;36m3015\u001b[0m    \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_95174_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_95174_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_95174_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >sex</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_95174_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_95174_row0_col1\" class=\"data row0 col1\" >1378</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_95174_row1_col0\" class=\"data row1 col0\" >female</td>\n",
       "      <td id=\"T_95174_row1_col1\" class=\"data row1 col1\" >653</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_95174_row2_col0\" class=\"data row2 col0\" >male</td>\n",
       "      <td id=\"T_95174_row2_col1\" class=\"data row2 col1\" >981</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_95174_row3_col0\" class=\"data row3 col0\" >not reported</td>\n",
       "      <td id=\"T_95174_row3_col1\" class=\"data row3 col1\" >3</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_b8ffb_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_b8ffb_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_b8ffb_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >race</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_b8ffb_row0_col1\" class=\"data row0 col1\" >1378</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row1_col0\" class=\"data row1 col0\" >not reported</td>\n",
       "      <td id=\"T_b8ffb_row1_col1\" class=\"data row1 col1\" >136</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row2_col0\" class=\"data row2 col0\" >white</td>\n",
       "      <td id=\"T_b8ffb_row2_col1\" class=\"data row2 col1\" >1312</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row3_col0\" class=\"data row3 col0\" >black or african american</td>\n",
       "      <td id=\"T_b8ffb_row3_col1\" class=\"data row3 col1\" >96</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row4_col0\" class=\"data row4 col0\" >asian</td>\n",
       "      <td id=\"T_b8ffb_row4_col1\" class=\"data row4 col1\" >33</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row5_col0\" class=\"data row5 col0\" >american indian or alaska native</td>\n",
       "      <td id=\"T_b8ffb_row5_col1\" class=\"data row5 col1\" >4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row6_col0\" class=\"data row6 col0\" >not allowed to collect</td>\n",
       "      <td id=\"T_b8ffb_row6_col1\" class=\"data row6 col1\" >25</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row7_col0\" class=\"data row7 col0\" >other</td>\n",
       "      <td id=\"T_b8ffb_row7_col1\" class=\"data row7 col1\" >9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row8_col0\" class=\"data row8 col0\" >Unknown</td>\n",
       "      <td id=\"T_b8ffb_row8_col1\" class=\"data row8 col1\" >21</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b8ffb_row9_col0\" class=\"data row9 col0\" >native hawaiian or other pacific islander</td>\n",
       "      <td id=\"T_b8ffb_row9_col1\" class=\"data row9 col1\" >1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_5711d_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_5711d_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_5711d_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >ethnicity</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_5711d_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_5711d_row0_col1\" class=\"data row0 col1\" >1378</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5711d_row1_col0\" class=\"data row1 col0\" >not hispanic or latino</td>\n",
       "      <td id=\"T_5711d_row1_col1\" class=\"data row1 col1\" >1286</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5711d_row2_col0\" class=\"data row2 col0\" >not reported</td>\n",
       "      <td id=\"T_5711d_row2_col1\" class=\"data row2 col1\" >219</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5711d_row3_col0\" class=\"data row3 col0\" >hispanic or latino</td>\n",
       "      <td id=\"T_5711d_row3_col1\" class=\"data row3 col1\" >85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5711d_row4_col0\" class=\"data row4 col0\" >Unknown</td>\n",
       "      <td id=\"T_5711d_row4_col1\" class=\"data row4 col1\" >22</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5711d_row5_col0\" class=\"data row5 col0\" >not allowed to collect</td>\n",
       "      <td id=\"T_5711d_row5_col1\" class=\"data row5 col1\" >25</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_6c655_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_6c655_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_6c655_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >cause_of_death</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_6c655_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_6c655_row0_col1\" class=\"data row0 col1\" >2746</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_6c655_row1_col0\" class=\"data row1 col0\" >Not Reported</td>\n",
       "      <td id=\"T_6c655_row1_col1\" class=\"data row1 col1\" >199</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_6c655_row2_col0\" class=\"data row2 col0\" >Not Cancer Related</td>\n",
       "      <td id=\"T_6c655_row2_col1\" class=\"data row2 col1\" >9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_6c655_row3_col0\" class=\"data row3 col0\" >Cancer Related</td>\n",
       "      <td id=\"T_6c655_row3_col1\" class=\"data row3 col1\" >48</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_6c655_row4_col0\" class=\"data row4 col0\" >Unknown</td>\n",
       "      <td id=\"T_6c655_row4_col1\" class=\"data row4 col1\" >8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_6c655_row5_col0\" class=\"data row5 col0\" >Infection</td>\n",
       "      <td id=\"T_6c655_row5_col1\" class=\"data row5 col1\" >3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_6c655_row6_col0\" class=\"data row6 col0\" >Surgical Complications</td>\n",
       "      <td id=\"T_6c655_row6_col1\" class=\"data row6 col1\" >2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_7ce57_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_7ce57_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_7ce57_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >subject_identifier_system</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_7ce57_row0_col0\" class=\"data row0 col0\" >IDC</td>\n",
       "      <td id=\"T_7ce57_row0_col1\" class=\"data row0 col1\" >2585</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7ce57_row1_col0\" class=\"data row1 col0\" >PDC</td>\n",
       "      <td id=\"T_7ce57_row1_col1\" class=\"data row1 col1\" >309</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7ce57_row2_col0\" class=\"data row2 col0\" >GDC</td>\n",
       "      <td id=\"T_7ce57_row2_col1\" class=\"data row2 col1\" >1455</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myquery.subject.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dff2da08",
   "metadata": {},
   "source": [
    "Since we save the output as a variable, we need to look at the variable to see the results:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "993479db",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">  files : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4924982</span>   \n",
       "</pre>\n"
      ],
      "text/plain": [
       "  files : \u001b[1;36m4924982\u001b[0m   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">    total : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">3015</span>    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "    total : \u001b[1;36m3015\u001b[0m    \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_ec543_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_ec543_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_ec543_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >sex</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_ec543_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_ec543_row0_col1\" class=\"data row0 col1\" >1378</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_ec543_row1_col0\" class=\"data row1 col0\" >female</td>\n",
       "      <td id=\"T_ec543_row1_col1\" class=\"data row1 col1\" >653</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_ec543_row2_col0\" class=\"data row2 col0\" >male</td>\n",
       "      <td id=\"T_ec543_row2_col1\" class=\"data row2 col1\" >981</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_ec543_row3_col0\" class=\"data row3 col0\" >not reported</td>\n",
       "      <td id=\"T_ec543_row3_col1\" class=\"data row3 col1\" >3</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_cc10c_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_cc10c_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_cc10c_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >race</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_cc10c_row0_col1\" class=\"data row0 col1\" >1378</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row1_col0\" class=\"data row1 col0\" >not reported</td>\n",
       "      <td id=\"T_cc10c_row1_col1\" class=\"data row1 col1\" >136</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row2_col0\" class=\"data row2 col0\" >white</td>\n",
       "      <td id=\"T_cc10c_row2_col1\" class=\"data row2 col1\" >1312</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row3_col0\" class=\"data row3 col0\" >black or african american</td>\n",
       "      <td id=\"T_cc10c_row3_col1\" class=\"data row3 col1\" >96</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row4_col0\" class=\"data row4 col0\" >asian</td>\n",
       "      <td id=\"T_cc10c_row4_col1\" class=\"data row4 col1\" >33</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row5_col0\" class=\"data row5 col0\" >american indian or alaska native</td>\n",
       "      <td id=\"T_cc10c_row5_col1\" class=\"data row5 col1\" >4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row6_col0\" class=\"data row6 col0\" >not allowed to collect</td>\n",
       "      <td id=\"T_cc10c_row6_col1\" class=\"data row6 col1\" >25</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row7_col0\" class=\"data row7 col0\" >other</td>\n",
       "      <td id=\"T_cc10c_row7_col1\" class=\"data row7 col1\" >9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row8_col0\" class=\"data row8 col0\" >Unknown</td>\n",
       "      <td id=\"T_cc10c_row8_col1\" class=\"data row8 col1\" >21</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_cc10c_row9_col0\" class=\"data row9 col0\" >native hawaiian or other pacific islander</td>\n",
       "      <td id=\"T_cc10c_row9_col1\" class=\"data row9 col1\" >1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_b6f53_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_b6f53_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_b6f53_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >ethnicity</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_b6f53_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_b6f53_row0_col1\" class=\"data row0 col1\" >1378</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b6f53_row1_col0\" class=\"data row1 col0\" >not hispanic or latino</td>\n",
       "      <td id=\"T_b6f53_row1_col1\" class=\"data row1 col1\" >1286</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b6f53_row2_col0\" class=\"data row2 col0\" >not reported</td>\n",
       "      <td id=\"T_b6f53_row2_col1\" class=\"data row2 col1\" >219</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b6f53_row3_col0\" class=\"data row3 col0\" >hispanic or latino</td>\n",
       "      <td id=\"T_b6f53_row3_col1\" class=\"data row3 col1\" >85</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b6f53_row4_col0\" class=\"data row4 col0\" >Unknown</td>\n",
       "      <td id=\"T_b6f53_row4_col1\" class=\"data row4 col1\" >22</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_b6f53_row5_col0\" class=\"data row5 col0\" >not allowed to collect</td>\n",
       "      <td id=\"T_b6f53_row5_col1\" class=\"data row5 col1\" >25</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_56c0d_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_56c0d_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_56c0d_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >cause_of_death</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_56c0d_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_56c0d_row0_col1\" class=\"data row0 col1\" >2746</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_56c0d_row1_col0\" class=\"data row1 col0\" >Not Reported</td>\n",
       "      <td id=\"T_56c0d_row1_col1\" class=\"data row1 col1\" >199</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_56c0d_row2_col0\" class=\"data row2 col0\" >Not Cancer Related</td>\n",
       "      <td id=\"T_56c0d_row2_col1\" class=\"data row2 col1\" >9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_56c0d_row3_col0\" class=\"data row3 col0\" >Cancer Related</td>\n",
       "      <td id=\"T_56c0d_row3_col1\" class=\"data row3 col1\" >48</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_56c0d_row4_col0\" class=\"data row4 col0\" >Unknown</td>\n",
       "      <td id=\"T_56c0d_row4_col1\" class=\"data row4 col1\" >8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_56c0d_row5_col0\" class=\"data row5 col0\" >Infection</td>\n",
       "      <td id=\"T_56c0d_row5_col1\" class=\"data row5 col1\" >3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_56c0d_row6_col0\" class=\"data row6 col0\" >Surgical Complications</td>\n",
       "      <td id=\"T_56c0d_row6_col1\" class=\"data row6 col1\" >2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_5e668_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_5e668_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_5e668_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >subject_identifier_system</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_5e668_row0_col0\" class=\"data row0 col0\" >IDC</td>\n",
       "      <td id=\"T_5e668_row0_col1\" class=\"data row0 col1\" >2585</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5e668_row1_col0\" class=\"data row1 col0\" >PDC</td>\n",
       "      <td id=\"T_5e668_row1_col1\" class=\"data row1 col1\" >309</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5e668_row2_col0\" class=\"data row2 col0\" >GDC</td>\n",
       "      <td id=\"T_5e668_row2_col1\" class=\"data row2 col1\" >1455</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "subjectresults"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7e6d522",
   "metadata": {},
   "source": [
    "By default, the results are displayed as a table for easy previewing of the data. Since we queried the `subject` endpoint, our default results tell us `subject` level information, that is, information about unique individuals: their sex, race, age, species, etc. Using counts gives us back a nice pivot table type summary of the countable fields for Subjects. Note that above the table it also tells you the total subject count, as well as how many files are associated with those subjects."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05e52f3f",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "<div class=\"cdadefine\" style=\"background-color:#add9e5;color:black;padding:20px;\">\n",
    "\n",
    "<h3>Subject Field Definitions</h3>\n",
    "\n",
    "<i>A patient entity captures the study-independent metadata for research subjects. Human research subjects are usually not traceable to a particular person to protect the subjects privacy.</i>\n",
    "    \n",
    "    \n",
    "    \n",
    "<style type=\"text/css\">\n",
    ".tg  {border-collapse:collapse;border-spacing:0;margin:0px auto;}\n",
    ".tg td{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg th{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg .tg-7zrl{text-align:left;vertical-align:bottom}\n",
    ".tg .tg-0lax{text-align:left;vertical-align:top}\n",
    "</style>\n",
    "<table class=\"tg\">\n",
    "<tbody>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> id (`total`)</td>\n",
    "    <td class=\"tg-0lax\"> The overall number of subjects returned.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> files</td>\n",
    "    <td class=\"tg-0lax\"> The number of files that match this search.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">identifier.value(`system`)</td>\n",
    "    <td class=\"tg-0lax\"> The identifier for the data provider.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">species</td>\n",
    "    <td class=\"tg-0lax\"> The taxonomic group (e.g. species) of the subject.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">sex</td>\n",
    "    <td class=\"tg-0lax\">  The biologic character or quality that distinguishes male and female from one another as expressed by analysis of the person's gonadal, morphologic (internal and external), chromosomal, and hormonal characteristics. </td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">race</td>\n",
    "    <td class=\"tg-0lax\"> An arbitrary classification of a taxonomic group that is a division of a species.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">ethnicity</td>\n",
    "    <td class=\"tg-0lax\"> An individual's self-described social and cultural grouping.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> cause_of_death</td>\n",
    "    <td class=\"tg-0lax\"> The cause of death, if known</td>\n",
    "  </tr>\n",
    "</tbody>\n",
    "</table>\n",
    "\n",
    "</div>\n",
    "    \n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5356bf41",
   "metadata": {},
   "source": [
    "This gives you a quick way to assess whether the full search results will have the data fields you require. But if you want to get the underlying data for your own downstream applications, you can also get the raw numbers by calling the zeroth value of the variable:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "869dfd5d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'files': 4924982,\n",
       " 'total': 3015,\n",
       " 'sex': [{'sex': 'NULL', 'count': 1378},\n",
       "  {'sex': 'female', 'count': 653},\n",
       "  {'sex': 'male', 'count': 981},\n",
       "  {'sex': 'not reported', 'count': 3}],\n",
       " 'race': [{'race': 'NULL', 'count': 1378},\n",
       "  {'race': 'not reported', 'count': 136},\n",
       "  {'race': 'white', 'count': 1312},\n",
       "  {'race': 'black or african american', 'count': 96},\n",
       "  {'race': 'asian', 'count': 33},\n",
       "  {'race': 'american indian or alaska native', 'count': 4},\n",
       "  {'race': 'not allowed to collect', 'count': 25},\n",
       "  {'race': 'other', 'count': 9},\n",
       "  {'race': 'Unknown', 'count': 21},\n",
       "  {'race': 'native hawaiian or other pacific islander', 'count': 1}],\n",
       " 'ethnicity': [{'ethnicity': 'NULL', 'count': 1378},\n",
       "  {'ethnicity': 'not hispanic or latino', 'count': 1286},\n",
       "  {'ethnicity': 'not reported', 'count': 219},\n",
       "  {'ethnicity': 'hispanic or latino', 'count': 85},\n",
       "  {'ethnicity': 'Unknown', 'count': 22},\n",
       "  {'ethnicity': 'not allowed to collect', 'count': 25}],\n",
       " 'cause_of_death': [{'cause_of_death': 'NULL', 'count': 2746},\n",
       "  {'cause_of_death': 'Not Reported', 'count': 199},\n",
       "  {'cause_of_death': 'Not Cancer Related', 'count': 9},\n",
       "  {'cause_of_death': 'Cancer Related', 'count': 48},\n",
       "  {'cause_of_death': 'Unknown', 'count': 8},\n",
       "  {'cause_of_death': 'Infection', 'count': 3},\n",
       "  {'cause_of_death': 'Surgical Complications', 'count': 2}],\n",
       " 'subject_identifier_system': [{'subject_identifier_system': 'IDC',\n",
       "   'count': 2585},\n",
       "  {'subject_identifier_system': 'PDC', 'count': 309},\n",
       "  {'subject_identifier_system': 'GDC', 'count': 1455}]}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "subjectresults[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73745aa6",
   "metadata": {},
   "source": [
    "### researchsubject\n",
    "\n",
    "If we're interested in what researchsubjects meet our criteria, we can also run our query against the researchsubject endpoint. Lets run it without saving to a variable this time to make it a bit quicker:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a2d8c874",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">11.082</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">11082</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m11.082\u001b[0m sec \u001b[1;36m11082\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">  files : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4924962</span>   \n",
       "</pre>\n"
      ],
      "text/plain": [
       "  files : \u001b[1;36m4924962\u001b[0m   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">    total : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4347</span>    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "    total : \u001b[1;36m4347\u001b[0m    \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_e4e4e_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_e4e4e_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_e4e4e_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >primary_diagnosis_condition</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row0_col0\" class=\"data row0 col0\" >Gliomas</td>\n",
       "      <td id=\"T_e4e4e_row0_col1\" class=\"data row0 col1\" >1247</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row1_col0\" class=\"data row1 col0\" >Glioblastoma</td>\n",
       "      <td id=\"T_e4e4e_row1_col1\" class=\"data row1 col1\" >100</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row2_col0\" class=\"data row2 col0\" >Germ Cell Neoplasms</td>\n",
       "      <td id=\"T_e4e4e_row2_col1\" class=\"data row2 col1\" >104</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row3_col0\" class=\"data row3 col0\" >None</td>\n",
       "      <td id=\"T_e4e4e_row3_col1\" class=\"data row3 col1\" >2583</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row4_col0\" class=\"data row4 col0\" >Pediatric/AYA Brain Tumors</td>\n",
       "      <td id=\"T_e4e4e_row4_col1\" class=\"data row4 col1\" >199</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row5_col0\" class=\"data row5 col0\" >Not Applicable</td>\n",
       "      <td id=\"T_e4e4e_row5_col1\" class=\"data row5 col1\" >9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row6_col0\" class=\"data row6 col0\" >Not Reported</td>\n",
       "      <td id=\"T_e4e4e_row6_col1\" class=\"data row6 col1\" >11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row7_col0\" class=\"data row7 col0\" >Malignant Lymphomas, NOS or Diffuse</td>\n",
       "      <td id=\"T_e4e4e_row7_col1\" class=\"data row7 col1\" >14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row8_col0\" class=\"data row8 col0\" >Neoplasms, NOS</td>\n",
       "      <td id=\"T_e4e4e_row8_col1\" class=\"data row8 col1\" >66</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row9_col0\" class=\"data row9 col0\" >Other</td>\n",
       "      <td id=\"T_e4e4e_row9_col1\" class=\"data row9 col1\" >10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row10_col0\" class=\"data row10 col0\" >Neuroepitheliomatous Neoplasms</td>\n",
       "      <td id=\"T_e4e4e_row10_col1\" class=\"data row10 col1\" >2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e4e4e_row11_col0\" class=\"data row11 col0\" >Mature B-Cell Lymphomas</td>\n",
       "      <td id=\"T_e4e4e_row11_col1\" class=\"data row11 col1\" >2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_8d96a_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_8d96a_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_8d96a_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >primary_diagnosis_site</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_8d96a_row0_col0\" class=\"data row0 col0\" >Brain</td>\n",
       "      <td id=\"T_8d96a_row0_col1\" class=\"data row0 col1\" >4347</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_4f875_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_4f875_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_4f875_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >researchsubject_identifier_system</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_4f875_row0_col0\" class=\"data row0 col0\" >GDC</td>\n",
       "      <td id=\"T_4f875_row0_col1\" class=\"data row0 col1\" >1455</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_4f875_row1_col0\" class=\"data row1 col0\" >PDC</td>\n",
       "      <td id=\"T_4f875_row1_col1\" class=\"data row1 col1\" >309</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_4f875_row2_col0\" class=\"data row2 col0\" >IDC</td>\n",
       "      <td id=\"T_4f875_row2_col1\" class=\"data row2 col1\" >2583</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myquery.researchsubject.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4564beee",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "\n",
    "---\n",
    "\n",
    "<div class=\"cdadefine\" style=\"background-color:#add9e5;color:black;padding:20px;\">\n",
    "\n",
    "<h3>ResearchSubject Field Definitions</h3>\n",
    "\n",
    "<i>A research subject is the entity of interest in a specific research study or project, typically a human being or an animal, but can also be a device, group of humans or animals, or a tissue sample. Human research subjects are usually not traceable to a particular person to protect the subjects privacy. This entity plays the role of the case_id in existing data. An individual who participates in 3 studies will have 3 researchsubject IDs</i>\n",
    "    \n",
    "<style type=\"text/css\">\n",
    ".tg  {border-collapse:collapse;border-spacing:0;margin:0px auto;}\n",
    ".tg td{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg th{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg .tg-7zrl{text-align:left;vertical-align:bottom}\n",
    ".tg .tg-0lax{text-align:left;vertical-align:top}\n",
    "</style>\n",
    "<table class=\"tg\">\n",
    "<tbody>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> id (`total`)</td>\n",
    "    <td class=\"tg-0lax\"> The overall number of researchsubjects returned.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> files</td>\n",
    "    <td class=\"tg-0lax\"> The number of files that match this search.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">identifier.value(`system`)</td>\n",
    "    <td class=\"tg-0lax\"> The identifier for the data provider.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">primary_diagnosis_condition</td>\n",
    "    <td class=\"tg-0lax\"> The text term used to describe the type of malignant disease.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">primary_diagnosis_site</td>\n",
    "    <td class=\"tg-0lax\"> The text term used to describe the primary site of disease.</td>\n",
    "  </tr>\n",
    "</tbody>\n",
    "</table>\n",
    "</div>\n",
    "    \n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a67cf09",
   "metadata": {},
   "source": [
    "### diagnosis\n",
    "\n",
    "The diagnosis endpoint is an extension of the researchsubject endpoint, and returns information about researchsubjects that have a diagnosis that meets our search criteria. :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "7770d68c",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4.961</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4961</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m4.961\u001b[0m sec \u001b[1;36m4961\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">    total : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1757</span>    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "    total : \u001b[1;36m1757\u001b[0m    \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_f52aa_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_f52aa_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_f52aa_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >primary_diagnosis</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row0_col0\" class=\"data row0 col0\" >Glioblastoma</td>\n",
       "      <td id=\"T_f52aa_row0_col1\" class=\"data row0 col1\" >822</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row1_col0\" class=\"data row1 col0\" >Mixed glioma</td>\n",
       "      <td id=\"T_f52aa_row1_col1\" class=\"data row1 col1\" >131</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row2_col0\" class=\"data row2 col0\" >Oligodendroglioma, NOS</td>\n",
       "      <td id=\"T_f52aa_row2_col1\" class=\"data row2 col1\" >112</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row3_col0\" class=\"data row3 col0\" >Astrocytoma, anaplastic</td>\n",
       "      <td id=\"T_f52aa_row3_col1\" class=\"data row3 col1\" >130</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row4_col0\" class=\"data row4 col0\" >Ganglioglioma, NOS</td>\n",
       "      <td id=\"T_f52aa_row4_col1\" class=\"data row4 col1\" >18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row5_col0\" class=\"data row5 col0\" >Astrocytoma, NOS</td>\n",
       "      <td id=\"T_f52aa_row5_col1\" class=\"data row5 col1\" >64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row6_col0\" class=\"data row6 col0\" >Ependymoma, NOS</td>\n",
       "      <td id=\"T_f52aa_row6_col1\" class=\"data row6 col1\" >32</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row7_col0\" class=\"data row7 col0\" >Mixed germ cell tumor</td>\n",
       "      <td id=\"T_f52aa_row7_col1\" class=\"data row7 col1\" >79</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row8_col0\" class=\"data row8 col0\" >Glioma, NOS</td>\n",
       "      <td id=\"T_f52aa_row8_col1\" class=\"data row8 col1\" >93</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row9_col0\" class=\"data row9 col0\" >Neoplasm, uncertain whether benign or malignant</td>\n",
       "      <td id=\"T_f52aa_row9_col1\" class=\"data row9 col1\" >13</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row10_col0\" class=\"data row10 col0\" >Oligodendroglioma, anaplastic</td>\n",
       "      <td id=\"T_f52aa_row10_col1\" class=\"data row10 col1\" >78</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row11_col0\" class=\"data row11 col0\" >Malignant lymphoma, NOS</td>\n",
       "      <td id=\"T_f52aa_row11_col1\" class=\"data row11 col1\" >14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row12_col0\" class=\"data row12 col0\" >Teratoma, benign</td>\n",
       "      <td id=\"T_f52aa_row12_col1\" class=\"data row12 col1\" >3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row13_col0\" class=\"data row13 col0\" >Neoplasm, malignant</td>\n",
       "      <td id=\"T_f52aa_row13_col1\" class=\"data row13 col1\" >50</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row14_col0\" class=\"data row14 col0\" >Embryonal carcinoma, NOS</td>\n",
       "      <td id=\"T_f52aa_row14_col1\" class=\"data row14 col1\" >8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row15_col0\" class=\"data row15 col0\" >Not Reported</td>\n",
       "      <td id=\"T_f52aa_row15_col1\" class=\"data row15 col1\" >10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row16_col0\" class=\"data row16 col0\" >Craniopharyngioma</td>\n",
       "      <td id=\"T_f52aa_row16_col1\" class=\"data row16 col1\" >16</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row17_col0\" class=\"data row17 col0\" >Germinoma</td>\n",
       "      <td id=\"T_f52aa_row17_col1\" class=\"data row17 col1\" >4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row18_col0\" class=\"data row18 col0\" >Glioma, malignant</td>\n",
       "      <td id=\"T_f52aa_row18_col1\" class=\"data row18 col1\" >26</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row19_col0\" class=\"data row19 col0\" >Medulloblastoma, NOS</td>\n",
       "      <td id=\"T_f52aa_row19_col1\" class=\"data row19 col1\" >22</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row20_col0\" class=\"data row20 col0\" >Yolk sac tumor</td>\n",
       "      <td id=\"T_f52aa_row20_col1\" class=\"data row20 col1\" >8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row21_col0\" class=\"data row21 col0\" >Malignant lymphoma, large B-cell, diffuse, NOS</td>\n",
       "      <td id=\"T_f52aa_row21_col1\" class=\"data row21 col1\" >2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row22_col0\" class=\"data row22 col0\" >Atypical teratoid/rhabdoid tumor</td>\n",
       "      <td id=\"T_f52aa_row22_col1\" class=\"data row22 col1\" >12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row23_col0\" class=\"data row23 col0\" >Glioblastoma multiforme</td>\n",
       "      <td id=\"T_f52aa_row23_col1\" class=\"data row23 col1\" >4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row24_col0\" class=\"data row24 col0\" >Teratoma, malignant, NOS</td>\n",
       "      <td id=\"T_f52aa_row24_col1\" class=\"data row24 col1\" >2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row25_col0\" class=\"data row25 col0\" >Gliosarcoma</td>\n",
       "      <td id=\"T_f52aa_row25_col1\" class=\"data row25 col1\" >1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row26_col0\" class=\"data row26 col0\" >Oligoastrocytoma</td>\n",
       "      <td id=\"T_f52aa_row26_col1\" class=\"data row26 col1\" >1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_f52aa_row27_col0\" class=\"data row27 col0\" >Papillary glioneuronal tumor</td>\n",
       "      <td id=\"T_f52aa_row27_col1\" class=\"data row27 col1\" >2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_e47b9_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_e47b9_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_e47b9_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >stage</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_e47b9_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_e47b9_row0_col1\" class=\"data row0 col1\" >1428</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e47b9_row1_col0\" class=\"data row1 col0\" >Not Reported</td>\n",
       "      <td id=\"T_e47b9_row1_col1\" class=\"data row1 col1\" >110</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e47b9_row2_col0\" class=\"data row2 col0\" >Unknown</td>\n",
       "      <td id=\"T_e47b9_row2_col1\" class=\"data row2 col1\" >219</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_e2dc7_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_e2dc7_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_e2dc7_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >grade</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_e2dc7_row0_col0\" class=\"data row0 col0\" >not reported</td>\n",
       "      <td id=\"T_e2dc7_row0_col1\" class=\"data row0 col1\" >1116</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e2dc7_row1_col0\" class=\"data row1 col0\" >Not Reported</td>\n",
       "      <td id=\"T_e2dc7_row1_col1\" class=\"data row1 col1\" >392</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e2dc7_row2_col0\" class=\"data row2 col0\" >None</td>\n",
       "      <td id=\"T_e2dc7_row2_col1\" class=\"data row2 col1\" >28</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e2dc7_row3_col0\" class=\"data row3 col0\" >High Grade</td>\n",
       "      <td id=\"T_e2dc7_row3_col1\" class=\"data row3 col1\" >26</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e2dc7_row4_col0\" class=\"data row4 col0\" >G1</td>\n",
       "      <td id=\"T_e2dc7_row4_col1\" class=\"data row4 col1\" >98</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e2dc7_row5_col0\" class=\"data row5 col0\" >G4</td>\n",
       "      <td id=\"T_e2dc7_row5_col1\" class=\"data row5 col1\" >36</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e2dc7_row6_col0\" class=\"data row6 col0\" >G2</td>\n",
       "      <td id=\"T_e2dc7_row6_col1\" class=\"data row6 col1\" >52</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e2dc7_row7_col0\" class=\"data row7 col0\" >Low Grade</td>\n",
       "      <td id=\"T_e2dc7_row7_col1\" class=\"data row7 col1\" >9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_bcdf7_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_bcdf7_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_bcdf7_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >diagnosis_identifier_system</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_bcdf7_row0_col0\" class=\"data row0 col0\" >GDC</td>\n",
       "      <td id=\"T_bcdf7_row0_col1\" class=\"data row0 col1\" >1428</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_bcdf7_row1_col0\" class=\"data row1 col0\" >PDC</td>\n",
       "      <td id=\"T_bcdf7_row1_col1\" class=\"data row1 col1\" >329</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myquery.diagnosis.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb73357c",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "<div class=\"cdadefine\" style=\"background-color:#add9e5;color:black;padding:20px;\">\n",
    "\n",
    "<h3>Diagnosis Field Definitions</h3>\n",
    "\n",
    "<i>A collection of characteristics that describe an abnormal condition of the body as assessed at a point in time. May be used to capture information about neoplastic and non-neoplastic conditions.</i>\n",
    "\n",
    "<style type=\"text/css\">\n",
    ".tg  {border-collapse:collapse;border-spacing:0;margin:0px auto;}\n",
    ".tg td{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg th{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg .tg-za14{border-color:inherit;text-align:left;vertical-align:bottom}\n",
    ".tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top}\n",
    ".tg .tg-7zrl{text-align:left;vertical-align:bottom}\n",
    ".tg .tg-0lax{text-align:left;vertical-align:top}\n",
    "</style>\n",
    "<table class=\"tg\">\n",
    "<tbody>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> id (`total`)</td>\n",
    "    <td class=\"tg-0lax\"> The overall number of diagnoses returned.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">identifier.value(`system`)</td>\n",
    "    <td class=\"tg-0lax\"> The identifier for the data provider.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-za14\">primary_diagnosis</td>\n",
    "    <td class=\"tg-0pky\"> The diagnosis instance that qualified a subject for inclusion on a ResearchProject.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-za14\">stage</td>\n",
    "    <td class=\"tg-0pky\"> The extent of a cancer in the body.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">grade</td>\n",
    "    <td class=\"tg-0lax\"> The degree of abnormality of cancer cells.</td>\n",
    "  </tr>\n",
    "</tbody>\n",
    "</table>\n",
    "\n",
    "\n",
    "</div>\n",
    "    \n",
    "---\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97442718",
   "metadata": {},
   "source": [
    "### treatment\n",
    "\n",
    "The treatment endpoint is an extension of diagnosis and returns information about treatments undertaken on research subjects that have a given diagnosis that meets our search criteria:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "be1ac64f",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4.906</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4906</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m4.906\u001b[0m sec \u001b[1;36m4906\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">    total : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">2396</span>    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "    total : \u001b[1;36m2396\u001b[0m    \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_76a34_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_76a34_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_76a34_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >treatment_type</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_76a34_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_76a34_row0_col1\" class=\"data row0 col1\" >2396</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_85a1a_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_85a1a_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_85a1a_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >treatment_effect</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_85a1a_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_85a1a_row0_col1\" class=\"data row0 col1\" >2396</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_9e2f5_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_9e2f5_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_9e2f5_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >treatment_identifier_system</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_9e2f5_row0_col0\" class=\"data row0 col0\" >GDC</td>\n",
       "      <td id=\"T_9e2f5_row0_col1\" class=\"data row0 col1\" >2396</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myquery.treatment.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec5dda7f",
   "metadata": {},
   "source": [
    "\n",
    "---\n",
    "\n",
    "<div class=\"cdadefine\" style=\"background-color:#add9e5;color:black;padding:20px;\">\n",
    "\n",
    "<h3>Treatment Field Definitions</h3>\n",
    "\n",
    "<i><i> Medication administration or other treatment types. A single research subject may have multiple treatments for a single diagnosis, and/or different diagnoses, and different treatments, across different studies</i></i>\n",
    "    \n",
    "<style type=\"text/css\">\n",
    ".tg  {border-collapse:collapse;border-spacing:0;margin:0px auto;}\n",
    ".tg td{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg th{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg .tg-za14{border-color:inherit;text-align:left;vertical-align:bottom}\n",
    ".tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top}\n",
    ".tg .tg-7zrl{text-align:left;vertical-align:bottom}\n",
    ".tg .tg-0lax{text-align:left;vertical-align:top}\n",
    "</style>\n",
    "<table class=\"tg\">\n",
    "<tbody>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> id (`total`)</td>\n",
    "    <td class=\"tg-0lax\"> The overall number of treatments returned.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">identifier.value(`system`)</td>\n",
    "    <td class=\"tg-0lax\"> The identifier for the data provider.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-za14\">treatment_type</td>\n",
    "    <td class=\"tg-0pky\"> The treatment type including medication/therapeutics or other procedures.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">treatment_effect</td>\n",
    "    <td class=\"tg-0lax\">The effect of a treatment on the diagnosis or tumor. </td>\n",
    "  </tr>\n",
    "</tbody>\n",
    "</table>\n",
    " \n",
    "\n",
    "</div>\n",
    "    \n",
    "---\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c00bec8",
   "metadata": {},
   "source": [
    "### specimens\n",
    "\n",
    "We can use this same query to see what specimens are available for brain tissue at the CDA:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "51960eed",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">11.052</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">11052</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m11.052\u001b[0m sec \u001b[1;36m11052\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">   files : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">47327</span>    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "   files : \u001b[1;36m47327\u001b[0m    \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">   total : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">39220</span>    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "   total : \u001b[1;36m39220\u001b[0m    \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_7a407_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_7a407_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_7a407_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >primary_disease_type</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row0_col0\" class=\"data row0 col0\" >Gliomas</td>\n",
       "      <td id=\"T_7a407_row0_col1\" class=\"data row0 col1\" >37586</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row1_col0\" class=\"data row1 col0\" >Glioblastoma</td>\n",
       "      <td id=\"T_7a407_row1_col1\" class=\"data row1 col1\" >200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row2_col0\" class=\"data row2 col0\" >Not Applicable</td>\n",
       "      <td id=\"T_7a407_row2_col1\" class=\"data row2 col1\" >36</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row3_col0\" class=\"data row3 col0\" >Germ Cell Neoplasms</td>\n",
       "      <td id=\"T_7a407_row3_col1\" class=\"data row3 col1\" >416</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row4_col0\" class=\"data row4 col0\" >Pediatric/AYA Brain Tumors</td>\n",
       "      <td id=\"T_7a407_row4_col1\" class=\"data row4 col1\" >438</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row5_col0\" class=\"data row5 col0\" >Neoplasms, NOS</td>\n",
       "      <td id=\"T_7a407_row5_col1\" class=\"data row5 col1\" >285</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row6_col0\" class=\"data row6 col0\" >Not Reported</td>\n",
       "      <td id=\"T_7a407_row6_col1\" class=\"data row6 col1\" >121</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row7_col0\" class=\"data row7 col0\" >Mature B-Cell Lymphomas</td>\n",
       "      <td id=\"T_7a407_row7_col1\" class=\"data row7 col1\" >54</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row8_col0\" class=\"data row8 col0\" >Malignant Lymphomas, NOS or Diffuse</td>\n",
       "      <td id=\"T_7a407_row8_col1\" class=\"data row8 col1\" >56</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row9_col0\" class=\"data row9 col0\" >Other</td>\n",
       "      <td id=\"T_7a407_row9_col1\" class=\"data row9 col1\" >20</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_7a407_row10_col0\" class=\"data row10 col0\" >Neuroepitheliomatous Neoplasms</td>\n",
       "      <td id=\"T_7a407_row10_col1\" class=\"data row10 col1\" >8</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_5a032_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_5a032_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_5a032_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >source_material_type</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row0_col0\" class=\"data row0 col0\" >Primary Tumor</td>\n",
       "      <td id=\"T_5a032_row0_col1\" class=\"data row0 col1\" >27578</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row1_col0\" class=\"data row1 col0\" >Metastatic</td>\n",
       "      <td id=\"T_5a032_row1_col1\" class=\"data row1 col1\" >252</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row2_col0\" class=\"data row2 col0\" >Solid Tissue Normal</td>\n",
       "      <td id=\"T_5a032_row2_col1\" class=\"data row2 col1\" >538</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row3_col0\" class=\"data row3 col0\" >Blood Derived Normal</td>\n",
       "      <td id=\"T_5a032_row3_col1\" class=\"data row3 col1\" >10078</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row4_col0\" class=\"data row4 col0\" >Recurrent Tumor</td>\n",
       "      <td id=\"T_5a032_row4_col1\" class=\"data row4 col1\" >513</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row5_col0\" class=\"data row5 col0\" >Buccal Cell Normal</td>\n",
       "      <td id=\"T_5a032_row5_col1\" class=\"data row5 col1\" >14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row6_col0\" class=\"data row6 col0\" >Next Generation Cancer Model</td>\n",
       "      <td id=\"T_5a032_row6_col1\" class=\"data row6 col1\" >176</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row7_col0\" class=\"data row7 col0\" >Expanded Next Generation Cancer Model</td>\n",
       "      <td id=\"T_5a032_row7_col1\" class=\"data row7 col1\" >35</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_5a032_row8_col0\" class=\"data row8 col0\" >Not Reported</td>\n",
       "      <td id=\"T_5a032_row8_col1\" class=\"data row8 col1\" >36</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_be866_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_be866_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_be866_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >specimen_type</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_be866_row0_col0\" class=\"data row0 col0\" >aliquot</td>\n",
       "      <td id=\"T_be866_row0_col1\" class=\"data row0 col1\" >18701</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_be866_row1_col0\" class=\"data row1 col0\" >analyte</td>\n",
       "      <td id=\"T_be866_row1_col1\" class=\"data row1 col1\" >6676</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_be866_row2_col0\" class=\"data row2 col0\" >portion</td>\n",
       "      <td id=\"T_be866_row2_col1\" class=\"data row2 col1\" >5996</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_be866_row3_col0\" class=\"data row3 col0\" >slide</td>\n",
       "      <td id=\"T_be866_row3_col1\" class=\"data row3 col1\" >3754</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_be866_row4_col0\" class=\"data row4 col0\" >sample</td>\n",
       "      <td id=\"T_be866_row4_col1\" class=\"data row4 col1\" >4093</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_8febe_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_8febe_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_8febe_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >specimen_identifier_system</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_8febe_row0_col0\" class=\"data row0 col0\" >GDC</td>\n",
       "      <td id=\"T_8febe_row0_col1\" class=\"data row0 col1\" >38562</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_8febe_row1_col0\" class=\"data row1 col0\" >PDC</td>\n",
       "      <td id=\"T_8febe_row1_col1\" class=\"data row1 col1\" >658</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myquery.specimen.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f254547",
   "metadata": {},
   "source": [
    "Nearly 40,000 specimens with over 50,000 files meet our search criteria! We would typically expect this number to be much larger than our number of subjects or research_subjects. First because studies will often take more than one sample per subject, and second because any given specimen might be aliquoted out to be used in multiple tests. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3ed75e5",
   "metadata": {},
   "source": [
    "<div class=\"cdadefine\" style=\"background-color:#add9e5;color:black;padding:20px;\">\n",
    "\n",
    "<h3>Specimen Field Definitions</h3>\n",
    "\n",
    "<i><i>Any material taken as a sample from a biological entity (living or dead), or from a physical object or the environment. Specimens are usually collected as an example of their kind, often for use in some investigation.</i>\n",
    " A given specimen will have only a single subject ID and a single research subject ID</i>\n",
    "    \n",
    "    \n",
    "<style type=\"text/css\">\n",
    ".tg  {border-collapse:collapse;border-spacing:0;margin:0px auto;}\n",
    ".tg td{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg th{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg .tg-za14{border-color:inherit;text-align:left;vertical-align:bottom}\n",
    ".tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top}\n",
    ".tg .tg-7zrl{text-align:left;vertical-align:bottom}\n",
    ".tg .tg-0lax{text-align:left;vertical-align:top}\n",
    "</style>\n",
    "    \n",
    "<table class=\"tg\">\n",
    "<tbody>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> id (`total`)</td>\n",
    "    <td class=\"tg-0lax\"> The overall number of specimens returned.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> files</td>\n",
    "    <td class=\"tg-0lax\"> The number of files that match this search.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">identifier.value(`system`)</td>\n",
    "    <td class=\"tg-0lax\"> The identifier for the data provider.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-za14\">primary_disease_type</td>\n",
    "    <td class=\"tg-0pky\"> The text term used to describe the type of malignant disease.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">source_material_type</td>\n",
    "    <td class=\"tg-0lax\"> The general kind of material from which the specimen was derived.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">specimen_type</td>\n",
    "    <td class=\"tg-0lax\"> The high-level type of the specimen, based on its how it has been derived from the original extracted sample. One of: analyte, aliquot, portion, sample, or slide.</td>\n",
    "  </tr>\n",
    "</tbody>\n",
    "</table>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ccb0f1c",
   "metadata": {},
   "source": [
    "### file\n",
    "\n",
    "The file endpoint returns all files that match our query:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "d6e0639a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">13.645</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">13645</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m13.645\u001b[0m sec \u001b[1;36m13645\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">  total : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">4924982</span>   \n",
       "</pre>\n"
      ],
      "text/plain": [
       "  total : \u001b[1;36m4924982\u001b[0m   \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_30b67_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_30b67_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_30b67_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >data_category</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row0_col0\" class=\"data row0 col0\" >Imaging</td>\n",
       "      <td id=\"T_30b67_row0_col1\" class=\"data row0 col1\" >4874560</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row1_col0\" class=\"data row1 col0\" >Simple Nucleotide Variation</td>\n",
       "      <td id=\"T_30b67_row1_col1\" class=\"data row1 col1\" >16970</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row2_col0\" class=\"data row2 col0\" >Peptide Spectral Matches</td>\n",
       "      <td id=\"T_30b67_row2_col1\" class=\"data row2 col1\" >1524</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row3_col0\" class=\"data row3 col0\" >DNA Methylation</td>\n",
       "      <td id=\"T_30b67_row3_col1\" class=\"data row3 col1\" >3342</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row4_col0\" class=\"data row4 col0\" >Copy Number Variation</td>\n",
       "      <td id=\"T_30b67_row4_col1\" class=\"data row4 col1\" >6913</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row5_col0\" class=\"data row5 col0\" >Structural Variation</td>\n",
       "      <td id=\"T_30b67_row5_col1\" class=\"data row5 col1\" >3384</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row6_col0\" class=\"data row6 col0\" >Sequencing Reads</td>\n",
       "      <td id=\"T_30b67_row6_col1\" class=\"data row6 col1\" >5897</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row7_col0\" class=\"data row7 col0\" >Raw Mass Spectra</td>\n",
       "      <td id=\"T_30b67_row7_col1\" class=\"data row7 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row8_col0\" class=\"data row8 col0\" >Processed Mass Spectra</td>\n",
       "      <td id=\"T_30b67_row8_col1\" class=\"data row8 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row9_col0\" class=\"data row9 col0\" >Biospecimen</td>\n",
       "      <td id=\"T_30b67_row9_col1\" class=\"data row9 col1\" >5583</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row10_col0\" class=\"data row10 col0\" >Proteome Profiling</td>\n",
       "      <td id=\"T_30b67_row10_col1\" class=\"data row10 col1\" >679</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row11_col0\" class=\"data row11 col0\" >Transcriptome Profiling</td>\n",
       "      <td id=\"T_30b67_row11_col1\" class=\"data row11 col1\" >3116</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row12_col0\" class=\"data row12 col0\" >Clinical</td>\n",
       "      <td id=\"T_30b67_row12_col1\" class=\"data row12 col1\" >1187</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_30b67_row13_col0\" class=\"data row13 col0\" >Somatic Structural Variation</td>\n",
       "      <td id=\"T_30b67_row13_col1\" class=\"data row13 col1\" >303</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_0006a_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_0006a_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_0006a_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >data_type</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row0_col0\" class=\"data row0 col0\" >None</td>\n",
       "      <td id=\"T_0006a_row0_col1\" class=\"data row0 col1\" >4874560</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row1_col0\" class=\"data row1 col0\" >Aligned Reads</td>\n",
       "      <td id=\"T_0006a_row1_col1\" class=\"data row1 col1\" >5897</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row2_col0\" class=\"data row2 col0\" >Text</td>\n",
       "      <td id=\"T_0006a_row2_col1\" class=\"data row2 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row3_col0\" class=\"data row3 col0\" >Raw Simple Somatic Mutation</td>\n",
       "      <td id=\"T_0006a_row3_col1\" class=\"data row3 col1\" >5033</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row4_col0\" class=\"data row4 col0\" >Clinical Supplement</td>\n",
       "      <td id=\"T_0006a_row4_col1\" class=\"data row4 col1\" >1182</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row5_col0\" class=\"data row5 col0\" >Transcript Fusion</td>\n",
       "      <td id=\"T_0006a_row5_col1\" class=\"data row5 col1\" >3385</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row6_col0\" class=\"data row6 col0\" >Slide Image</td>\n",
       "      <td id=\"T_0006a_row6_col1\" class=\"data row6 col1\" >3629</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row7_col0\" class=\"data row7 col0\" >Masked Somatic Mutation</td>\n",
       "      <td id=\"T_0006a_row7_col1\" class=\"data row7 col1\" >1146</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row8_col0\" class=\"data row8 col0\" >Gene Level Copy Number</td>\n",
       "      <td id=\"T_0006a_row8_col1\" class=\"data row8 col1\" >1222</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row9_col0\" class=\"data row9 col0\" >Masked Copy Number Segment</td>\n",
       "      <td id=\"T_0006a_row9_col1\" class=\"data row9 col1\" >2185</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row10_col0\" class=\"data row10 col0\" >Proprietary</td>\n",
       "      <td id=\"T_0006a_row10_col1\" class=\"data row10 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row11_col0\" class=\"data row11 col0\" >Annotated Somatic Mutation</td>\n",
       "      <td id=\"T_0006a_row11_col1\" class=\"data row11 col1\" >9462</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row12_col0\" class=\"data row12 col0\" >Biospecimen Supplement</td>\n",
       "      <td id=\"T_0006a_row12_col1\" class=\"data row12 col1\" >1954</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row13_col0\" class=\"data row13 col0\" >Aggregated Somatic Mutation</td>\n",
       "      <td id=\"T_0006a_row13_col1\" class=\"data row13 col1\" >1146</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row14_col0\" class=\"data row14 col0\" >Open Standard</td>\n",
       "      <td id=\"T_0006a_row14_col1\" class=\"data row14 col1\" >1524</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row15_col0\" class=\"data row15 col0\" >Copy Number Segment</td>\n",
       "      <td id=\"T_0006a_row15_col1\" class=\"data row15 col1\" >2336</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row16_col0\" class=\"data row16 col0\" >Masked Intensities</td>\n",
       "      <td id=\"T_0006a_row16_col1\" class=\"data row16 col1\" >2228</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row17_col0\" class=\"data row17 col0\" >Allele-specific Copy Number Segment</td>\n",
       "      <td id=\"T_0006a_row17_col1\" class=\"data row17 col1\" >1071</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row18_col0\" class=\"data row18 col0\" >Methylation Beta Value</td>\n",
       "      <td id=\"T_0006a_row18_col1\" class=\"data row18 col1\" >1114</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row19_col0\" class=\"data row19 col0\" >Gene Expression Quantification</td>\n",
       "      <td id=\"T_0006a_row19_col1\" class=\"data row19 col1\" >906</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row20_col0\" class=\"data row20 col0\" >Structural Rearrangement</td>\n",
       "      <td id=\"T_0006a_row20_col1\" class=\"data row20 col1\" >302</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row21_col0\" class=\"data row21 col0\" >Splice Junction Quantification</td>\n",
       "      <td id=\"T_0006a_row21_col1\" class=\"data row21 col1\" >870</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row22_col0\" class=\"data row22 col0\" >Protein Expression Quantification</td>\n",
       "      <td id=\"T_0006a_row22_col1\" class=\"data row22 col1\" >679</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row23_col0\" class=\"data row23 col0\" >miRNA Expression Quantification</td>\n",
       "      <td id=\"T_0006a_row23_col1\" class=\"data row23 col1\" >643</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row24_col0\" class=\"data row24 col0\" >Gene Level Copy Number Scores</td>\n",
       "      <td id=\"T_0006a_row24_col1\" class=\"data row24 col1\" >99</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row25_col0\" class=\"data row25 col0\" >Isoform Expression Quantification</td>\n",
       "      <td id=\"T_0006a_row25_col1\" class=\"data row25 col1\" >643</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row26_col0\" class=\"data row26 col0\" >Masked Annotated Somatic Mutation</td>\n",
       "      <td id=\"T_0006a_row26_col1\" class=\"data row26 col1\" >183</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row27_col0\" class=\"data row27 col0\" >Single Cell Analysis</td>\n",
       "      <td id=\"T_0006a_row27_col1\" class=\"data row27 col1\" >36</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row28_col0\" class=\"data row28 col0\" >Differential Gene Expression</td>\n",
       "      <td id=\"T_0006a_row28_col1\" class=\"data row28 col1\" >18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_0006a_row29_col0\" class=\"data row29 col0\" >Pathology Report</td>\n",
       "      <td id=\"T_0006a_row29_col1\" class=\"data row29 col1\" >5</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_3670f_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_3670f_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_3670f_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >file_format</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row0_col0\" class=\"data row0 col0\" >DICOM</td>\n",
       "      <td id=\"T_3670f_row0_col1\" class=\"data row0 col1\" >4874560</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row1_col0\" class=\"data row1 col0\" >vendor-specific</td>\n",
       "      <td id=\"T_3670f_row1_col1\" class=\"data row1 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row2_col0\" class=\"data row2 col0\" >mzML</td>\n",
       "      <td id=\"T_3670f_row2_col1\" class=\"data row2 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row3_col0\" class=\"data row3 col0\" >BAM</td>\n",
       "      <td id=\"T_3670f_row3_col1\" class=\"data row3 col1\" >5897</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row4_col0\" class=\"data row4 col0\" >BCR Biotab</td>\n",
       "      <td id=\"T_3670f_row4_col1\" class=\"data row4 col1\" >49</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row5_col0\" class=\"data row5 col0\" >TXT</td>\n",
       "      <td id=\"T_3670f_row5_col1\" class=\"data row5 col1\" >8851</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row6_col0\" class=\"data row6 col0\" >tsv</td>\n",
       "      <td id=\"T_3670f_row6_col1\" class=\"data row6 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row7_col0\" class=\"data row7 col0\" >VCF</td>\n",
       "      <td id=\"T_3670f_row7_col1\" class=\"data row7 col1\" >9915</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row8_col0\" class=\"data row8 col0\" >TSV</td>\n",
       "      <td id=\"T_3670f_row8_col1\" class=\"data row8 col1\" >4561</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row9_col0\" class=\"data row9 col0\" >MAF</td>\n",
       "      <td id=\"T_3670f_row9_col1\" class=\"data row9 col1\" >7206</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row10_col0\" class=\"data row10 col0\" >mzIdentML</td>\n",
       "      <td id=\"T_3670f_row10_col1\" class=\"data row10 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row11_col0\" class=\"data row11 col0\" >IDAT</td>\n",
       "      <td id=\"T_3670f_row11_col1\" class=\"data row11 col1\" >2228</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row12_col0\" class=\"data row12 col0\" >BCR XML</td>\n",
       "      <td id=\"T_3670f_row12_col1\" class=\"data row12 col1\" >2282</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row13_col0\" class=\"data row13 col0\" >SVS</td>\n",
       "      <td id=\"T_3670f_row13_col1\" class=\"data row13 col1\" >3629</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row14_col0\" class=\"data row14 col0\" >BEDPE</td>\n",
       "      <td id=\"T_3670f_row14_col1\" class=\"data row14 col1\" >1892</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row15_col0\" class=\"data row15 col0\" >MEX</td>\n",
       "      <td id=\"T_3670f_row15_col1\" class=\"data row15 col1\" >36</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row16_col0\" class=\"data row16 col0\" >BCR SSF XML</td>\n",
       "      <td id=\"T_3670f_row16_col1\" class=\"data row16 col1\" >758</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row17_col0\" class=\"data row17 col0\" >HDF5</td>\n",
       "      <td id=\"T_3670f_row17_col1\" class=\"data row17 col1\" >18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row18_col0\" class=\"data row18 col0\" >BCR OMF XML</td>\n",
       "      <td id=\"T_3670f_row18_col1\" class=\"data row18 col1\" >19</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row19_col0\" class=\"data row19 col0\" >CDC JSON</td>\n",
       "      <td id=\"T_3670f_row19_col1\" class=\"data row19 col1\" >28</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_3670f_row20_col0\" class=\"data row20 col0\" >PDF</td>\n",
       "      <td id=\"T_3670f_row20_col1\" class=\"data row20 col1\" >5</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_e6e86_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_e6e86_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_e6e86_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >file_identifier_system</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_e6e86_row0_col0\" class=\"data row0 col0\" >IDC</td>\n",
       "      <td id=\"T_e6e86_row0_col1\" class=\"data row0 col1\" >4874560</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e6e86_row1_col0\" class=\"data row1 col0\" >PDC</td>\n",
       "      <td id=\"T_e6e86_row1_col1\" class=\"data row1 col1\" >3048</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e6e86_row2_col0\" class=\"data row2 col0\" >GDC</td>\n",
       "      <td id=\"T_e6e86_row2_col1\" class=\"data row2 col1\" >47374</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myquery.file.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e34044c9",
   "metadata": {},
   "source": [
    "There are a huge number of files (4099497) that match our search. Likely we would want to additionally filter the results by file format or data type to get only files we can use. See all the ways you can filter and refine searches  with more search terms in the <a href=\"../Operators\">Operators</a> notebook.\n",
    "\n",
    "\n",
    "<div class=\"cdadefine\" style=\"background-color:#add9e5;color:black;padding:20px;\">\n",
    "\n",
    "<h3>File Field Definitions</h3>\n",
    "\n",
    "<i>A file is an information-bearing electronic object that contains a physical embodiment of some information using a particular character encoding.</i>\n",
    "\n",
    "    \n",
    "<style type=\"text/css\">\n",
    ".tg  {border-collapse:collapse;border-spacing:0;}\n",
    ".tg td{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg th{border-color:black;border-style:solid;border-width:1px;font-family:noto sans, sans-serif;font-size:14px;\n",
    "  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n",
    ".tg .tg-7zrl{text-align:left;vertical-align:bottom}\n",
    "</style>\n",
    "<table class=\"tg\">\n",
    "<tbody>\n",
    "  <tr>\n",
    "    <td class=\"tg-0lax\"> id (`total`)</td>\n",
    "    <td class=\"tg-0lax\"> The overall number of files returned.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">identifier.value(`system`)</td>\n",
    "    <td class=\"tg-0lax\"> The identifier for the data provider.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">data_catagory</td>\n",
    "    <td class=\"tg-7zrl\">Broad categorization of the contents of the data file.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">data_type</td>\n",
    "    <td class=\"tg-7zrl\">Specific content type of the data file.</td>\n",
    "  </tr>\n",
    "  <tr>\n",
    "    <td class=\"tg-7zrl\">file_format</td>\n",
    "    <td class=\"tg-7zrl\">Format of the data files.</td>\n",
    "  </tr>\n",
    "</tbody>\n",
    "</table>\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3de2391",
   "metadata": {},
   "source": [
    "### mutation\n",
    "\n",
    "The mutation endpoint returns all mutations that match our query:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "c89ac53f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                Http Status: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">500</span>\n",
       "                Error Message: Unrecognized name: case_barcode at <span style=\"font-weight: bold\">[</span><span style=\"color: #00ff00; text-decoration-color: #00ff00; font-weight: bold\">1:770</span><span style=\"font-weight: bold\">]</span>\n",
       "                \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                Http Status: \u001b[1;36m500\u001b[0m\n",
       "                Error Message: Unrecognized name: case_barcode at \u001b[1m[\u001b[0m\u001b[1;92m1:770\u001b[0m\u001b[1m]\u001b[0m\n",
       "                \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1.129</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">1129</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m1.129\u001b[0m sec \u001b[1;36m1129\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "myquery.mutation.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a4fd46e",
   "metadata": {},
   "source": [
    "## Files from a single endpoint (endpoint chaining)\n",
    "\n",
    "If you want all file formats and data types, but only from a specific endpoint, you can also filter the file results by chaining endpoints together. This will return all the files that match our search AND that are specifically from specimens:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2cfb2582",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Getting results from database\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "Getting results from database\n",
       "\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "                        Total execution time: <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">0</span>\n",
       "                        min <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">10.612</span> sec <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">10612</span> ms\n",
       "                        \n",
       "</pre>\n"
      ],
      "text/plain": [
       "\n",
       "                        Total execution time: \u001b[1;36m0\u001b[0m\n",
       "                        min \u001b[1;36m10.612\u001b[0m sec \u001b[1;36m10612\u001b[0m ms\n",
       "                        \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">   total : <span style=\"color: #008080; text-decoration-color: #008080; font-weight: bold\">47327</span>    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "   total : \u001b[1;36m47327\u001b[0m    \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "#T_80636_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_80636_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_80636_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >data_category</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row0_col0\" class=\"data row0 col0\" >Simple Nucleotide Variation</td>\n",
       "      <td id=\"T_80636_row0_col1\" class=\"data row0 col1\" >16970</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row1_col0\" class=\"data row1 col0\" >Copy Number Variation</td>\n",
       "      <td id=\"T_80636_row1_col1\" class=\"data row1 col1\" >6959</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row2_col0\" class=\"data row2 col0\" >Processed Mass Spectra</td>\n",
       "      <td id=\"T_80636_row2_col1\" class=\"data row2 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row3_col0\" class=\"data row3 col0\" >DNA Methylation</td>\n",
       "      <td id=\"T_80636_row3_col1\" class=\"data row3 col1\" >3342</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row4_col0\" class=\"data row4 col0\" >Peptide Spectral Matches</td>\n",
       "      <td id=\"T_80636_row4_col1\" class=\"data row4 col1\" >1524</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row5_col0\" class=\"data row5 col0\" >Biospecimen</td>\n",
       "      <td id=\"T_80636_row5_col1\" class=\"data row5 col1\" >3629</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row6_col0\" class=\"data row6 col0\" >Transcriptome Profiling</td>\n",
       "      <td id=\"T_80636_row6_col1\" class=\"data row6 col1\" >3116</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row7_col0\" class=\"data row7 col0\" >Raw Mass Spectra</td>\n",
       "      <td id=\"T_80636_row7_col1\" class=\"data row7 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row8_col0\" class=\"data row8 col0\" >Sequencing Reads</td>\n",
       "      <td id=\"T_80636_row8_col1\" class=\"data row8 col1\" >5897</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row9_col0\" class=\"data row9 col0\" >Structural Variation</td>\n",
       "      <td id=\"T_80636_row9_col1\" class=\"data row9 col1\" >3384</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row10_col0\" class=\"data row10 col0\" >Proteome Profiling</td>\n",
       "      <td id=\"T_80636_row10_col1\" class=\"data row10 col1\" >679</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_80636_row11_col0\" class=\"data row11 col0\" >Somatic Structural Variation</td>\n",
       "      <td id=\"T_80636_row11_col1\" class=\"data row11 col1\" >303</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_e9cba_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_e9cba_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_e9cba_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >data_type</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row0_col0\" class=\"data row0 col0\" >Masked Copy Number Segment</td>\n",
       "      <td id=\"T_e9cba_row0_col1\" class=\"data row0 col1\" >2231</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row1_col0\" class=\"data row1 col0\" >Slide Image</td>\n",
       "      <td id=\"T_e9cba_row1_col1\" class=\"data row1 col1\" >3629</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row2_col0\" class=\"data row2 col0\" >Open Standard</td>\n",
       "      <td id=\"T_e9cba_row2_col1\" class=\"data row2 col1\" >1524</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row3_col0\" class=\"data row3 col0\" >Text</td>\n",
       "      <td id=\"T_e9cba_row3_col1\" class=\"data row3 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row4_col0\" class=\"data row4 col0\" >Aggregated Somatic Mutation</td>\n",
       "      <td id=\"T_e9cba_row4_col1\" class=\"data row4 col1\" >1146</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row5_col0\" class=\"data row5 col0\" >Proprietary</td>\n",
       "      <td id=\"T_e9cba_row5_col1\" class=\"data row5 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row6_col0\" class=\"data row6 col0\" >Raw Simple Somatic Mutation</td>\n",
       "      <td id=\"T_e9cba_row6_col1\" class=\"data row6 col1\" >5033</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row7_col0\" class=\"data row7 col0\" >Masked Intensities</td>\n",
       "      <td id=\"T_e9cba_row7_col1\" class=\"data row7 col1\" >2228</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row8_col0\" class=\"data row8 col0\" >Transcript Fusion</td>\n",
       "      <td id=\"T_e9cba_row8_col1\" class=\"data row8 col1\" >3385</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row9_col0\" class=\"data row9 col0\" >Aligned Reads</td>\n",
       "      <td id=\"T_e9cba_row9_col1\" class=\"data row9 col1\" >5897</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row10_col0\" class=\"data row10 col0\" >Masked Somatic Mutation</td>\n",
       "      <td id=\"T_e9cba_row10_col1\" class=\"data row10 col1\" >1146</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row11_col0\" class=\"data row11 col0\" >Copy Number Segment</td>\n",
       "      <td id=\"T_e9cba_row11_col1\" class=\"data row11 col1\" >2336</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row12_col0\" class=\"data row12 col0\" >Annotated Somatic Mutation</td>\n",
       "      <td id=\"T_e9cba_row12_col1\" class=\"data row12 col1\" >9462</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row13_col0\" class=\"data row13 col0\" >Methylation Beta Value</td>\n",
       "      <td id=\"T_e9cba_row13_col1\" class=\"data row13 col1\" >1114</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row14_col0\" class=\"data row14 col0\" >Gene Level Copy Number</td>\n",
       "      <td id=\"T_e9cba_row14_col1\" class=\"data row14 col1\" >1222</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row15_col0\" class=\"data row15 col0\" >Isoform Expression Quantification</td>\n",
       "      <td id=\"T_e9cba_row15_col1\" class=\"data row15 col1\" >643</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row16_col0\" class=\"data row16 col0\" >Gene Expression Quantification</td>\n",
       "      <td id=\"T_e9cba_row16_col1\" class=\"data row16 col1\" >906</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row17_col0\" class=\"data row17 col0\" >miRNA Expression Quantification</td>\n",
       "      <td id=\"T_e9cba_row17_col1\" class=\"data row17 col1\" >643</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row18_col0\" class=\"data row18 col0\" >Masked Annotated Somatic Mutation</td>\n",
       "      <td id=\"T_e9cba_row18_col1\" class=\"data row18 col1\" >183</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row19_col0\" class=\"data row19 col0\" >Gene Level Copy Number Scores</td>\n",
       "      <td id=\"T_e9cba_row19_col1\" class=\"data row19 col1\" >99</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row20_col0\" class=\"data row20 col0\" >Splice Junction Quantification</td>\n",
       "      <td id=\"T_e9cba_row20_col1\" class=\"data row20 col1\" >870</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row21_col0\" class=\"data row21 col0\" >Allele-specific Copy Number Segment</td>\n",
       "      <td id=\"T_e9cba_row21_col1\" class=\"data row21 col1\" >1071</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row22_col0\" class=\"data row22 col0\" >Protein Expression Quantification</td>\n",
       "      <td id=\"T_e9cba_row22_col1\" class=\"data row22 col1\" >679</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row23_col0\" class=\"data row23 col0\" >Structural Rearrangement</td>\n",
       "      <td id=\"T_e9cba_row23_col1\" class=\"data row23 col1\" >302</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row24_col0\" class=\"data row24 col0\" >Single Cell Analysis</td>\n",
       "      <td id=\"T_e9cba_row24_col1\" class=\"data row24 col1\" >36</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_e9cba_row25_col0\" class=\"data row25 col0\" >Differential Gene Expression</td>\n",
       "      <td id=\"T_e9cba_row25_col1\" class=\"data row25 col1\" >18</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_86adb_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_86adb_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_86adb_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >file_format</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row0_col0\" class=\"data row0 col0\" >TXT</td>\n",
       "      <td id=\"T_86adb_row0_col1\" class=\"data row0 col1\" >8897</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row1_col0\" class=\"data row1 col0\" >MAF</td>\n",
       "      <td id=\"T_86adb_row1_col1\" class=\"data row1 col1\" >7206</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row2_col0\" class=\"data row2 col0\" >tsv</td>\n",
       "      <td id=\"T_86adb_row2_col1\" class=\"data row2 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row3_col0\" class=\"data row3 col0\" >SVS</td>\n",
       "      <td id=\"T_86adb_row3_col1\" class=\"data row3 col1\" >3629</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row4_col0\" class=\"data row4 col0\" >TSV</td>\n",
       "      <td id=\"T_86adb_row4_col1\" class=\"data row4 col1\" >4561</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row5_col0\" class=\"data row5 col0\" >VCF</td>\n",
       "      <td id=\"T_86adb_row5_col1\" class=\"data row5 col1\" >9915</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row6_col0\" class=\"data row6 col0\" >mzIdentML</td>\n",
       "      <td id=\"T_86adb_row6_col1\" class=\"data row6 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row7_col0\" class=\"data row7 col0\" >BAM</td>\n",
       "      <td id=\"T_86adb_row7_col1\" class=\"data row7 col1\" >5897</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row8_col0\" class=\"data row8 col0\" >vendor-specific</td>\n",
       "      <td id=\"T_86adb_row8_col1\" class=\"data row8 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row9_col0\" class=\"data row9 col0\" >mzML</td>\n",
       "      <td id=\"T_86adb_row9_col1\" class=\"data row9 col1\" >762</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row10_col0\" class=\"data row10 col0\" >BEDPE</td>\n",
       "      <td id=\"T_86adb_row10_col1\" class=\"data row10 col1\" >1892</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row11_col0\" class=\"data row11 col0\" >IDAT</td>\n",
       "      <td id=\"T_86adb_row11_col1\" class=\"data row11 col1\" >2228</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row12_col0\" class=\"data row12 col0\" >MEX</td>\n",
       "      <td id=\"T_86adb_row12_col1\" class=\"data row12 col1\" >36</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_86adb_row13_col0\" class=\"data row13 col0\" >HDF5</td>\n",
       "      <td id=\"T_86adb_row13_col1\" class=\"data row13 col1\" >18</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<style type=\"text/css\">\n",
       "#T_17be3_ th {\n",
       "  background-color: #000066;\n",
       "  color: white;\n",
       "  text-align: left;\n",
       "}\n",
       "#T_17be3_ td {\n",
       "  text-align: left;\n",
       "  border-bottom: 1px solid black;\n",
       "}\n",
       "</style>\n",
       "<table id=\"T_17be3_\" style='display:inline'>\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"col_heading level0 col0\" >file_identifier_system</th>\n",
       "      <th class=\"col_heading level0 col1\" >count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td id=\"T_17be3_row0_col0\" class=\"data row0 col0\" >GDC</td>\n",
       "      <td id=\"T_17be3_row0_col1\" class=\"data row0 col1\" >44279</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td id=\"T_17be3_row1_col0\" class=\"data row1 col0\" >PDC</td>\n",
       "      <td id=\"T_17be3_row1_col1\" class=\"data row1 col1\" >3048</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myquery.specimen.file.count.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6994e312",
   "metadata": {},
   "source": [
    "Learn more about chaining endpoints in the [Chaining endpoints](\"../AdvancedSearch-Chaining\") notebook."
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "5c867d1980d5b66d2bfc8a5903dcee074b4b68f3917a4f27f8a310cab24e9f1b"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  },
  "metadata": {
   "interpreter": {
    "hash": "5c867d1980d5b66d2bfc8a5903dcee074b4b68f3917a4f27f8a310cab24e9f1b"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
