Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 349B3200C62 for ; Wed, 26 Apr 2017 13:23:14 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 32EA1160BA8; Wed, 26 Apr 2017 11:23:14 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 7F4AF160B95 for ; Wed, 26 Apr 2017 13:23:12 +0200 (CEST) Received: (qmail 43044 invoked by uid 500); 26 Apr 2017 11:23:11 -0000 Mailing-List: contact user-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: user@ignite.apache.org Delivered-To: mailing list user@ignite.apache.org Received: (qmail 43034 invoked by uid 99); 26 Apr 2017 11:23:11 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Apr 2017 11:23:11 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id 2960EC0787 for ; Wed, 26 Apr 2017 11:23:11 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 3.88 X-Spam-Level: *** X-Spam-Status: No, score=3.88 tagged_above=-999 required=6.31 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=2, KAM_BADIPHTTP=2, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001, WEIRD_PORT=0.001] autolearn=disabled Authentication-Results: spamd4-us-west.apache.org (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com Received: from mx1-lw-us.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id p-Qhnu3cuHIF for ; Wed, 26 Apr 2017 11:23:06 +0000 (UTC) Received: from mail-ua0-f173.google.com (mail-ua0-f173.google.com [209.85.217.173]) by mx1-lw-us.apache.org (ASF Mail Server at mx1-lw-us.apache.org) with ESMTPS id 794705F36B for ; Wed, 26 Apr 2017 11:23:06 +0000 (UTC) Received: by mail-ua0-f173.google.com with SMTP id 110so49648673uas.3 for ; Wed, 26 Apr 2017 04:23:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to; bh=8ddaPksCYjpHQnSY/WUgx8l+aP70B7as1bPlwg5dHJ8=; b=Lx8M0NZREoZ4TSn6fpIYW/zCsdWFhrovMdVps3KB5T7+JQ4aseFIWSJZwYw0ByxB3t qkINhinVVlgLlCizUQym9uzmcfLjkncH9WBkpo23ZlMCjYZ53bMi9XAyiTLogmRBJLUB TdNsB8qV3oIqoPveOP18+mjJjVqVEfd18Zo84TjZ1SqwYcUlcXnych1IqaYT+BYm5lzk /yiFmllzYs4aFuNk0vJXE+yK2kjq4AjgP6IUma6oN8hxQbDFS3jYADo7W7f+5vS0RF9Z 2BzPyHXnC7/R7wCay3Mecw3+TvaZxj8JotVpXCl/fPr5bi/hrYO9U0kqNVYvFjvxQH+W FPTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to; bh=8ddaPksCYjpHQnSY/WUgx8l+aP70B7as1bPlwg5dHJ8=; b=h/TkyJoJv6T75DpM3CgixnuM2y76dXaP4kkMz6W3wQWDQ2316eST75LVT8Ih/SKT+M cIgcx66QWwRFppQn23/13+AWj6pxNf7V6Kw0+1D5VV8wDem7zrbmujaM6/ogQaN6xxHu VEsGxDgMjVz7ATNHEBwI0ech0Y++FDuQ8ieFc+nmsQbLcZhxC30xRktKmjtlBZR/ZPxb QlqvN4nS5EIrHbYa0rf3b0yFUtH6UfqZO0nb0pzds7/HgKk0zjFaS5wgiLFxWL782SDc Lb5vHgKnsRs90+ozj7DCBLpiZApqigdSRa9orbYHQ23BRZbw9QqIu0mqXv6KICHWfNnN 0BAw== X-Gm-Message-State: AN3rC/6PHc8+Uuxk4+E8V2EwEqEiEZ5KIwr05Xa6frMIZU5XyM/H4dQU 6hvqzqSP+nFVbgvs7S9wX42hvaOkrMu3 X-Received: by 10.176.9.196 with SMTP id e4mr19151829uah.34.1493205780180; Wed, 26 Apr 2017 04:23:00 -0700 (PDT) MIME-Version: 1.0 Received: by 10.176.7.136 with HTTP; Wed, 26 Apr 2017 04:22:59 -0700 (PDT) In-Reply-To: <1493103777807-12216.post@n6.nabble.com> References: <1493103777807-12216.post@n6.nabble.com> From: Andrey Mashenkov Date: Wed, 26 Apr 2017 14:22:59 +0300 Message-ID: Subject: Re: How to do write-behind caching? To: user@ignite.apache.org Content-Type: multipart/alternative; boundary=f403043ed32c1ab9a7054e1010aa archived-at: Wed, 26 Apr 2017 11:23:14 -0000 --f403043ed32c1ab9a7054e1010aa Content-Type: text/plain; charset=UTF-8 Hi Ricky, I see no property *writeBehindEnabled=true* in your config. On Tue, Apr 25, 2017 at 10:02 AM, Ricky Nauvaldy Ruliputra < ricky.nauvaldy@sci.ui.ac.id> wrote: > I've tried it again but the write behind still doesn't work. Like I said > before, if I only use write through, I'm able to write the data to my > database, but when I enable write behind, it just won't write even if I > wait > until 5 seconds (writeBehindFlushFrequency default value). I've read the > documentation but couldn't figure it out what's wrong. Would you mind to > take a look to my program and see what's wrong in it? I'm afraid that I did > something wrong in my configuration. > > My table looks like this, in learnignite database, with the table name of > transaction. > +------------+------------+ > | idNumber | amount | > +------------+------------+ > | 1 | 300 | > | 2 | 100 | > | 3 | 100 | > +------------+------------+ > > Config file: ignite-jdbc.xml > > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > xmlns:util="http://www.springframework.org/schema/util" > xsi:schemaLocation=" > http://www.springframework.org/schema/beans > http://www.springframework.org/schema/beans/spring-beans.xsd > http://www.springframework.org/schema/util > http://www.springframework.org/schema/util/spring-util.xsd"> > Main Spring file for ignite configuration. > > class="org.springframework.jdbc.datasource.DriverManagerDataSource" > id="dataSource"> > value="com.mysql.jdbc.Driver"> > value="jdbc:mysql://localhost:3306/learnignite"> > > > > id="ignite.cfg"> > > > class="org.apache.ignite.configuration.CacheConfiguration"> > value="transactionCache"> > > > value="true"> > value="true"> > > > > > > class="org.apache.ignite.cache.QueryEntity"> > value="java.lang.Long"> > value="ignite.myexamples.model.Store"> > > > > > value="java.lang.Integer"> > > > > > > > > > class="javax.cache.configuration.FactoryBuilder" > factory-method="factoryOf"> > value="myexamples.store.TransactionStore"> > > > > > > > > class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi"> > > class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast. > TcpDiscoveryMulticastIpFinder"> > value="228.10.10.157"/> > > > > > localhost/127.0.0.1:3306 > > > > > > > > > > Model file: Store.java > > package ignite.myexamples.model; > public class Store { > private int idNumber; > private int amount; > public void update(double deposit) { > amount += deposit; > } > public Store(int idNumber, int amount) { > super(); > this.idNumber = idNumber; > this.amount = amount; > } > public long getIdNumber() { > return idNumber; > } > public void setIdNumber(int idNumber) { > this.idNumber = idNumber; > } > public long getAmount() { > return amount; > } > public void setAmount(int amount) { > this.amount = amount; > } > @Override > public String toString() { > return "Transaction [idNumber=" + idNumber + ", amount=" + > amount + "]"; > } > } > > TransactionStore.java > > package myexamples.store; > import java.sql.Connection; > import java.sql.PreparedStatement; > import java.sql.ResultSet; > import java.sql.SQLException; > import java.util.Collection; > import java.util.Map; > > import javax.cache.Cache.Entry; > import javax.cache.integration.CacheLoaderException; > import javax.cache.integration.CacheWriterException; > import javax.sql.DataSource; > > import org.apache.ignite.cache.store.CacheStore; > import org.apache.ignite.lang.IgniteBiInClosure; > import org.apache.ignite.resources.SpringResource; > import org.jetbrains.annotations.Nullable; > > import ignite.myexamples.model.Store; > > public class TransactionStore implements CacheStore { > @SpringResource(resourceName = "dataSource") > private DataSource dataSource; > // This method is called whenever IgniteCache.loadCache() method is > called. > @Override > public void loadCache(IgniteBiInClosure clo, > @Nullable > Object... objects) throws CacheLoaderException { > System.out.println(">> Loading cache from store..."); > try (Connection conn = dataSource.getConnection()) { > try (PreparedStatement st = > conn.prepareStatement("select * from TRANSACTION")) { // dari tabel mysql > try (ResultSet rs = st.executeQuery()) { > while (rs.next()) { > Store transaksi = new > Store(rs.getInt(1), rs.getInt(2)); > > clo.apply(transaksi.getIdNumber(), transaksi); > } > } > } > } > catch (SQLException e) { > throw new CacheLoaderException("Failed to load > values from cache store.", e); > } > } > // This method is called whenever IgniteCache.get() method is > called. > @Override > public Store load(Long key) throws CacheLoaderException { > System.out.println("Loading Transaction from Store ..."); > try (Connection conn = dataSource.getConnection()) { > try (PreparedStatement st = > conn.prepareStatement("select * from TRANSACTION where id = ?")) { > st.setString(1, key.toString()); > ResultSet rs = st.executeQuery(); > return rs.next() ? new Store(rs.getInt(1), > rs.getInt(2)) : null; > } > } > catch (SQLException e) { > throw new CacheLoaderException("Failed to load > values from cache store.", e); > } > } > @Override > public Map loadAll(Iterable arg0) > throws CacheLoaderException { > // TODO Auto-generated method stub > return null; > } > @Override > public void delete(Object arg0) throws CacheWriterException { > // TODO Auto-generated method stub > > } > @Override > public void deleteAll(Collection arg0) throws > CacheWriterException { > // TODO Auto-generated method stub > > } > @Override > public void write(Entry arg0) > throws CacheWriterException { > // TODO Auto-generated method stub > Long key = arg0.getKey(); > Store val = arg0.getValue(); > > System.out.println(">>> Store write "); > System.out.println("[key=" + key + ", val=" + val + ']'); > > try { > Connection conn = dataSource.getConnection(); > int updated; > // Try update first. If it does not work, then try > insert. > // Some databases would allow these to be done in > one 'upsert' operation. > try (PreparedStatement st = conn.prepareStatement( > "update TRANSACTION set amount = ? > where idNumber = ?")) { > st.setLong(1, val.getAmount()); > st.setLong(2, val.getIdNumber()); > > updated = st.executeUpdate(); > System.out.println("update success"); > } > if (updated == 0) { > try (PreparedStatement st = > conn.prepareStatement( > "insert into TRANSACTION > (id, amount) values (?, ?)")) { > st.setLong(1, val.getIdNumber()); > st.setLong(2, val.getAmount()); > st.executeUpdate(); > System.out.println("insertion > success"); > } > } > > } > catch (SQLException e) { > throw new CacheWriterException("Failed to write > object [key=" + key + ", val=" + val + ']', e); > } > } > @Override > public void writeAll(Collection Store>> arg0) throws CacheWriterException { > // TODO Auto-generated method stub > > } > @Override > public void sessionEnd(boolean commit) throws CacheWriterException > { > // TODO Auto-generated method stub > > } > > } > > Server node: TransactionServer.java > package myexamples.store; > import java.util.List; > import org.apache.ignite.Ignite; > import org.apache.ignite.IgniteCache; > import org.apache.ignite.IgniteException; > import org.apache.ignite.Ignition; > import org.apache.ignite.cache.query.QueryCursor; > import org.apache.ignite.cache.query.SqlFieldsQuery; > import ignite.myexamples.model.Store; > > public class TransactionServer { > public static void main(String[] args) throws IgniteException { > // Start Ignite node. > Ignite ignite = > Ignition.start("path/to/my/ignite-jdbc.xml"); > IgniteCache cache = > ignite.getOrCreateCache("transactionCache"); > // Load cache with data from the database. > cache.loadCache(null); > // Execute query on cache. > QueryCursor> cursor = cache.query(new > SqlFieldsQuery( > "select idNumber, amount from Store")); > System.out.println(cursor.getAll()); > } > > } > > Client node: TransactionStoreExample.java > package myexamples.store; > > import static > org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC; > import static > org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ; > > import org.apache.ignite.Ignite; > import org.apache.ignite.IgniteCache; > import org.apache.ignite.IgniteException; > import org.apache.ignite.Ignition; > import org.apache.ignite.transactions.Transaction; > > import ignite.myexamples.model.Store; > > public class TransactionStoreExample { > public static void main(String[] args) throws IgniteException { > // In this case, I just try the number 1 and add it with > the > amount of 100 > long id = 1; > long amount = 100; > > // Set it as a client > Ignition.setClientMode(true); > > // Start Ignite node. > try (Ignite ignite = > Ignition.start("path/to/my/ignite-jdbc.xml")) { > try (IgniteCache igniteCache = > ignite.getOrCreateCache("transactionCache")) { > try (Transaction tx = > ignite.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) { > Store account = > igniteCache.get((long) id); > assert account != null; > > // update amount > account.update(amount); > > // Store updated account in cache. > igniteCache.put(id, account); > > tx.commit(); > > System.out.println(igniteCache.get(id)); > } > } > } > } > } > > Thanks for any help that you can provide. > -- Ricky > > > > -- > View this message in context: http://apache-ignite-users. > 70518.x6.nabble.com/How-to-do-write-behind-caching-tp12138p12216.html > Sent from the Apache Ignite Users mailing list archive at Nabble.com. > -- Best regards, Andrey V. Mashenkov --f403043ed32c1ab9a7054e1010aa Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+SGkgUmlja3ksPGRpdj48YnI+PC9kaXY+PGRpdj5JIHNlZSBubyBwcm9w ZXJ0ecKgPGk+d3JpdGVCZWhpbmRFbmFibGVkPXRydWU8L2k+PGI+wqA8L2I+aW4geW91ciBjb25m aWcuPGJyPjwvZGl2PjwvZGl2PjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj48YnI+PGRpdiBjbGFz cz0iZ21haWxfcXVvdGUiPk9uIFR1ZSwgQXByIDI1LCAyMDE3IGF0IDEwOjAyIEFNLCBSaWNreSBO YXV2YWxkeSBSdWxpcHV0cmEgPHNwYW4gZGlyPSJsdHIiPiZsdDs8YSBocmVmPSJtYWlsdG86cmlj a3kubmF1dmFsZHlAc2NpLnVpLmFjLmlkIiB0YXJnZXQ9Il9ibGFuayI+cmlja3kubmF1dmFsZHlA c2NpLnVpLmFjLmlkPC9hPiZndDs8L3NwYW4+IHdyb3RlOjxicj48YmxvY2txdW90ZSBjbGFzcz0i Z21haWxfcXVvdGUiIHN0eWxlPSJtYXJnaW46MCAwIDAgLjhleDtib3JkZXItbGVmdDoxcHggI2Nj YyBzb2xpZDtwYWRkaW5nLWxlZnQ6MWV4Ij48c3BhbiBjbGFzcz0iIj5JJiMzOTt2ZSB0cmllZCBp dCBhZ2FpbiBidXQgdGhlIHdyaXRlIGJlaGluZCBzdGlsbCBkb2VzbiYjMzk7dCB3b3JrLiBMaWtl IEkgc2FpZDxicj4NCmJlZm9yZSwgaWYgSSBvbmx5IHVzZSB3cml0ZSB0aHJvdWdoLCBJJiMzOTtt IGFibGUgdG8gd3JpdGUgdGhlIGRhdGEgdG8gbXk8YnI+DQpkYXRhYmFzZSwgYnV0IHdoZW4gSSBl bmFibGUgd3JpdGUgYmVoaW5kLCBpdCBqdXN0IHdvbiYjMzk7dCB3cml0ZSBldmVuIGlmIEkgd2Fp dDxicj4NCnVudGlsIDUgc2Vjb25kcyAod3JpdGVCZWhpbmRGbHVzaEZyZXF1ZW5jeSBkZWZhdWx0 IHZhbHVlKS4gSSYjMzk7dmUgcmVhZCB0aGU8YnI+DQpkb2N1bWVudGF0aW9uIGJ1dCBjb3VsZG4m IzM5O3QgZmlndXJlIGl0IG91dCB3aGF0JiMzOTtzIHdyb25nLiBXb3VsZCB5b3UgbWluZCB0bzxi cj4NCnRha2UgYSBsb29rIHRvIG15IHByb2dyYW0gYW5kIHNlZSB3aGF0JiMzOTtzIHdyb25nIGlu IGl0PyBJJiMzOTttIGFmcmFpZCB0aGF0IEkgZGlkPGJyPg0Kc29tZXRoaW5nIHdyb25nIGluIG15 IGNvbmZpZ3VyYXRpb24uPGJyPg0KPGJyPg0KPC9zcGFuPk15IHRhYmxlIGxvb2tzIGxpa2UgdGhp cywgaW4gbGVhcm5pZ25pdGUgZGF0YWJhc2UsIHdpdGggdGhlIHRhYmxlIG5hbWUgb2Y8YnI+DQp0 cmFuc2FjdGlvbi48YnI+DQo8c3BhbiBjbGFzcz0iIj4rLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0t LSs8YnI+DQp8IGlkTnVtYmVywqAgfCBhbW91bnTCoCDCoCB8PGJyPg0KKy0tLS0tLS0tLS0tLSst LS0tLS0tLS0tLS0rPGJyPg0KfMKgIMKgIMKgIMKgIMKgIMKgIMKgMSB8wqAgwqAgMzAwwqAgwqAg wqAgfDxicj4NCnzCoCDCoCDCoCDCoCDCoCDCoCDCoDIgfMKgIMKgIDEwMMKgIMKgIMKgIHw8YnI+ DQp8wqAgwqAgwqAgwqAgwqAgwqAgwqAzIHzCoCDCoCAxMDDCoCDCoCDCoCB8PGJyPg0KKy0tLS0t LS0tLS0tLSstLS0tLS0tLS0tLS0rPGJyPg0KPGJyPg0KPC9zcGFuPkNvbmZpZyBmaWxlOiBpZ25p dGUtamRiYy54bWw8YnI+DQo8ZGl2PjxkaXYgY2xhc3M9Img1Ij48YnI+DQombHQ7YmVhbnMgeG1s bnM9JnF1b3Q7PGEgaHJlZj0iaHR0cDovL3d3dy5zcHJpbmdmcmFtZXdvcmsub3JnL3NjaGVtYS9i ZWFucyIgcmVsPSJub3JlZmVycmVyIiB0YXJnZXQ9Il9ibGFuayI+aHR0cDovL3d3dy48d2JyPnNw cmluZ2ZyYW1ld29yay5vcmcvc2NoZW1hLzx3YnI+YmVhbnM8L2E+JnF1b3Q7PGJyPg0KwqAgwqAg wqAgwqB4bWxuczp4c2k9JnF1b3Q7PGEgaHJlZj0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxT Y2hlbWEtaW5zdGFuY2UiIHJlbD0ibm9yZWZlcnJlciIgdGFyZ2V0PSJfYmxhbmsiPmh0dHA6Ly93 d3cudzMub3JnLzx3YnI+MjAwMS9YTUxTY2hlbWEtaW5zdGFuY2U8L2E+JnF1b3Q7PGJyPg0KwqAg wqAgwqAgwqB4bWxuczp1dGlsPSZxdW90OzxhIGhyZWY9Imh0dHA6Ly93d3cuc3ByaW5nZnJhbWV3 b3JrLm9yZy9zY2hlbWEvdXRpbCIgcmVsPSJub3JlZmVycmVyIiB0YXJnZXQ9Il9ibGFuayI+aHR0 cDovL3d3dy48d2JyPnNwcmluZ2ZyYW1ld29yay5vcmcvc2NoZW1hLzx3YnI+dXRpbDwvYT4mcXVv dDs8YnI+DQrCoCDCoCDCoCDCoHhzaTpzY2hlbWFMb2NhdGlvbj0mcXVvdDs8YnI+DQrCoCDCoCDC oCDCoCA8YSBocmVmPSJodHRwOi8vd3d3LnNwcmluZ2ZyYW1ld29yay5vcmcvc2NoZW1hL2JlYW5z IiByZWw9Im5vcmVmZXJyZXIiIHRhcmdldD0iX2JsYW5rIj5odHRwOi8vd3d3LnNwcmluZ2ZyYW1l d29yay48d2JyPm9yZy9zY2hlbWEvYmVhbnM8L2E+PGJyPg0KPGEgaHJlZj0iaHR0cDovL3d3dy5z cHJpbmdmcmFtZXdvcmsub3JnL3NjaGVtYS9iZWFucy9zcHJpbmctYmVhbnMueHNkIiByZWw9Im5v cmVmZXJyZXIiIHRhcmdldD0iX2JsYW5rIj5odHRwOi8vd3d3LnNwcmluZ2ZyYW1ld29yay48d2Jy Pm9yZy9zY2hlbWEvYmVhbnMvc3ByaW5nLWJlYW5zLjx3YnI+eHNkPC9hPjxicj4NCsKgIMKgIMKg IMKgIDxhIGhyZWY9Imh0dHA6Ly93d3cuc3ByaW5nZnJhbWV3b3JrLm9yZy9zY2hlbWEvdXRpbCIg cmVsPSJub3JlZmVycmVyIiB0YXJnZXQ9Il9ibGFuayI+aHR0cDovL3d3dy5zcHJpbmdmcmFtZXdv cmsuPHdicj5vcmcvc2NoZW1hL3V0aWw8L2E+PGJyPg0KPGEgaHJlZj0iaHR0cDovL3d3dy5zcHJp bmdmcmFtZXdvcmsub3JnL3NjaGVtYS91dGlsL3NwcmluZy11dGlsLnhzZCIgcmVsPSJub3JlZmVy cmVyIiB0YXJnZXQ9Il9ibGFuayI+aHR0cDovL3d3dy5zcHJpbmdmcmFtZXdvcmsuPHdicj5vcmcv c2NoZW1hL3V0aWwvc3ByaW5nLXV0aWwuPHdicj54c2Q8L2E+JnF1b3Q7Jmd0Ozxicj4NCsKgIMKg ICZsdDtkZXNjcmlwdGlvbiZndDtNYWluIFNwcmluZyBmaWxlIGZvciBpZ25pdGUgY29uZmlndXJh dGlvbi4mbHQ7L2Rlc2NyaXB0aW9uJmd0Ozxicj4NCjxicj4NCsKgIMKgICZsdDtiZWFuPGJyPg0K Y2xhc3M9JnF1b3Q7b3JnLnNwcmluZ2ZyYW1ld29yay48d2JyPmpkYmMuZGF0YXNvdXJjZS48d2Jy PkRyaXZlck1hbmFnZXJEYXRhU291cmNlJnF1b3Q7PGJyPg0KaWQ9JnF1b3Q7ZGF0YVNvdXJjZSZx dW90OyZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7cHJvcGVydHkgbmFtZT0mcXVvdDtk cml2ZXJDbGFzc05hbWUmcXVvdDs8YnI+DQp2YWx1ZT0mcXVvdDtjb20ubXlzcWwuamRiYy5Ecml2 ZXImcXVvdDsmZ3Q7PHdicj4mbHQ7L3Byb3BlcnR5Jmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKg ICZsdDtwcm9wZXJ0eSBuYW1lPSZxdW90O3VybCZxdW90Ozxicj4NCnZhbHVlPSZxdW90O2pkYmM6 bXlzcWw6Ly9sb2NhbGhvc3Q6PHdicj4zMzA2L2xlYXJuaWduaXRlJnF1b3Q7Jmd0OyZsdDsvcHJv cGVydHkmZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgJmx0O3Byb3BlcnR5IG5hbWU9JnF1b3Q7 dXNlcm5hbWUmcXVvdDsgdmFsdWU9JnF1b3Q7cm9vdCZxdW90OyZndDsmbHQ7L3Byb3BlcnR5Jmd0 Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgICZsdDtwcm9wZXJ0eSBuYW1lPSZxdW90O3Bhc3N3b3Jk JnF1b3Q7IHZhbHVlPSZxdW90OyZxdW90OyZndDsmbHQ7L3Byb3BlcnR5Jmd0Ozxicj4NCsKgIMKg IMKgIMKgICZsdDsvYmVhbiZndDs8YnI+DQrCoCDCoCDCoCDCoCAmbHQ7YmVhbiBjbGFzcz0mcXVv dDtvcmcuYXBhY2hlLmlnbml0ZS48d2JyPmNvbmZpZ3VyYXRpb24uPHdicj5JZ25pdGVDb25maWd1 cmF0aW9uJnF1b3Q7PGJyPg0KaWQ9JnF1b3Q7aWduaXRlLmNmZyZxdW90OyZndDs8YnI+DQrCoCDC oCDCoCDCoCDCoCDCoCAmbHQ7cHJvcGVydHkgbmFtZT0mcXVvdDtjYWNoZUNvbmZpZ3VyYXRpb24m cXVvdDsmZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJmx0O2xpc3QmZ3Q7PGJyPg0K wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJmx0O2JlYW48YnI+DQpjbGFzcz0mcXVvdDtv cmcuYXBhY2hlLmlnbml0ZS48d2JyPmNvbmZpZ3VyYXRpb24uPHdicj5DYWNoZUNvbmZpZ3VyYXRp b24mcXVvdDsmZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJmx0 O3Byb3BlcnR5IG5hbWU9JnF1b3Q7bmFtZSZxdW90Ozxicj4NCnZhbHVlPSZxdW90O3RyYW5zYWN0 aW9uQ2FjaGUmcXVvdDsmZ3Q7Jmx0Oy88d2JyPnByb3BlcnR5Jmd0Ozxicj4NCjxicj4NCjxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZsdDtwcm9wZXJ0eSBuYW1lPSZx dW90O3JlYWRUaHJvdWdoJnF1b3Q7PGJyPg0KdmFsdWU9JnF1b3Q7dHJ1ZSZxdW90OyZndDsmbHQ7 L3Byb3BlcnR5Jmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZs dDtwcm9wZXJ0eSBuYW1lPSZxdW90O3dyaXRlVGhyb3VnaCZxdW90Ozxicj4NCnZhbHVlPSZxdW90 O3RydWUmcXVvdDsmZ3Q7Jmx0Oy9wcm9wZXJ0eSZndDs8YnI+DQo8YnI+DQo8YnI+DQo8YnI+DQrC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7cHJvcGVydHkgbmFtZT0mcXVv dDtxdWVyeUVudGl0aWVzJnF1b3Q7Jmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgICZsdDtsaXN0Jmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZsdDtiZWFuPGJyPg0KY2xhc3M9JnF1b3Q7b3JnLmFw YWNoZS5pZ25pdGUuPHdicj5jYWNoZS5RdWVyeUVudGl0eSZxdW90OyZndDs8YnI+DQrCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7cHJvcGVy dHkgbmFtZT0mcXVvdDtrZXlUeXBlJnF1b3Q7PGJyPg0KdmFsdWU9JnF1b3Q7amF2YS5sYW5nLkxv bmcmcXVvdDsmZ3Q7Jmx0Oy88d2JyPnByb3BlcnR5Jmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZsdDtwcm9wZXJ0eSBuYW1lPSZx dW90O3ZhbHVlVHlwZSZxdW90Ozxicj4NCnZhbHVlPSZxdW90O2lnbml0ZS5teWV4YW1wbGVzLjx3 YnI+bW9kZWwuU3RvcmUmcXVvdDsmZ3Q7Jmx0Oy9wcm9wZXJ0eSZndDs8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7cHJvcGVydHkg bmFtZT0mcXVvdDtmaWVsZHMmcXVvdDsmZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJmx0O21hcCZndDs8YnI+DQo8YnI+ DQombHQ7ZW50cnkga2V5PSZxdW90O2lkTnVtYmVyJnF1b3Q7IHZhbHVlPSZxdW90O2phdmEubGFu Zy5JbnRlZ2VyJnF1b3Q7Jmd0OyZsdDsvPHdicj5lbnRyeSZndDs8YnI+DQrCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7 ZW50cnkga2V5PSZxdW90O2Ftb3VudCZxdW90Ozxicj4NCnZhbHVlPSZxdW90O2phdmEubGFuZy5J bnRlZ2VyJnF1b3Q7Jmd0OyZsdDsvPHdicj5lbnRyeSZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7L21hcCZndDs8 YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCAmbHQ7L3Byb3BlcnR5Jmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgICZsdDsvYmVhbiZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7L2xpc3QmZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgJmx0Oy9wcm9wZXJ0eSZndDs8YnI+DQo8YnI+DQo8YnI+DQrCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7cHJvcGVydHkgbmFtZT0mcXVvdDtj YWNoZVN0b3JlRmFjdG9yeSZxdW90OyZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCAmbHQ7YmVhbjxicj4NCmNsYXNzPSZxdW90O2phdmF4LmNhY2hlLjx3 YnI+Y29uZmlndXJhdGlvbi5GYWN0b3J5QnVpbGRlciZxdW90OyBmYWN0b3J5LW1ldGhvZD0mcXVv dDtmYWN0b3J5T2YmcXVvdDsmZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgJmx0O2NvbnN0cnVjdG9yLWFyZzxicj4NCnZhbHVlPSZxdW90O215 ZXhhbXBsZXMuc3RvcmUuPHdicj5UcmFuc2FjdGlvblN0b3JlJnF1b3Q7Jmd0OyZsdDsvPHdicj5j b25zdHJ1Y3Rvci1hcmcmZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgJmx0Oy9iZWFuJmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgICZsdDsvcHJvcGVydHkmZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgJmx0Oy9iZWFuJmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZsdDsvbGlzdCZn dDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7L3Byb3BlcnR5Jmd0Ozxicj4NCjxicj4NCsKg IMKgIMKgIMKgIMKgIMKgICZsdDtwcm9wZXJ0eSBuYW1lPSZxdW90O2Rpc2NvdmVyeVNwaSZxdW90 OyZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7YmVhbjxicj4NCmNs YXNzPSZxdW90O29yZy5hcGFjaGUuaWduaXRlLnNwaS48d2JyPmRpc2NvdmVyeS50Y3AuVGNwRGlz Y292ZXJ5U3BpJnF1b3Q7PHdicj4mZ3Q7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgJmx0O3Byb3BlcnR5IG5hbWU9JnF1b3Q7aXBGaW5kZXImcXVvdDsmZ3Q7PGJyPg0KwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgJmx0O2JlYW48YnI+DQpjbGFzcz0mcXVv dDtvcmcuYXBhY2hlLmlnbml0ZS5zcGkuPHdicj5kaXNjb3ZlcnkudGNwLmlwZmluZGVyLjx3YnI+ bXVsdGljYXN0Ljx3YnI+VGNwRGlzY292ZXJ5TXVsdGljYXN0SXBGaW5kZXImcXVvdDs8d2JyPiZn dDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7cHJvcGVy dHkgbmFtZT0mcXVvdDttdWx0aWNhc3RHcm91cCZxdW90Ozxicj4NCnZhbHVlPSZxdW90OzIyOC4x MC4xMC4xNTcmcXVvdDsvJmd0Ozxicj4NCjxicj4NCjxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgICZsdDtwcm9wZXJ0eSBuYW1lPSZxdW90O2FkZHJlc3NlcyZxdW90 OyZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7 bGlzdCZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCAmbHQ7dmFsdWUmZ3Q7bG9jYWxob3N0LzxhIGhyZWY9Imh0dHA6Ly8xMjcuMC4wLjE6MzMwNiIg cmVsPSJub3JlZmVycmVyIiB0YXJnZXQ9Il9ibGFuayI+MTI3LjAuMC4xOjx3YnI+MzMwNjwvYT4m bHQ7L3ZhbHVlJmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgICZsdDsvbGlzdCZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCAmbHQ7L3Byb3BlcnR5Jmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgICZsdDsvYmVhbiZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCAmbHQ7L3Byb3BlcnR5Jmd0Ozxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZs dDsvYmVhbiZndDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmbHQ7L3Byb3BlcnR5 Jmd0Ozxicj4NCsKgIMKgICZsdDsvYmVhbiZndDs8YnI+DQombHQ7L2JlYW5zJmd0Ozxicj4NCjxi cj4NCjwvZGl2PjwvZGl2Pk1vZGVsIGZpbGU6IFN0b3JlLmphdmE8YnI+DQo8c3BhbiBjbGFzcz0i Ij48YnI+DQpwYWNrYWdlIGlnbml0ZS5teWV4YW1wbGVzLm1vZGVsOzxicj4NCnB1YmxpYyBjbGFz cyBTdG9yZSB7PGJyPg0KwqAgwqAgwqAgwqAgcHJpdmF0ZSBpbnQgaWROdW1iZXI7PGJyPg0KwqAg wqAgwqAgwqAgcHJpdmF0ZSBpbnQgYW1vdW50Ozxicj4NCsKgIMKgIMKgIMKgIHB1YmxpYyB2b2lk IHVwZGF0ZShkb3VibGUgZGVwb3NpdCkgezxicj4NCsKgIMKgIMKgIMKgIGFtb3VudCArPSBkZXBv c2l0Ozxicj4NCsKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgU3RvcmUoaW50IGlkTnVt YmVyLCBpbnQgYW1vdW50KSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3VwZXIoKTs8 YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB0aGlzLmlkTnVtYmVyID0gaWROdW1iZXI7PGJy Pg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdGhpcy5hbW91bnQgPSBhbW91bnQ7PGJyPg0KwqAg wqAgwqAgwqAgfTxicj4NCsKgIMKgIMKgIMKgIHB1YmxpYyBsb25nIGdldElkTnVtYmVyKCkgezxi cj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHJldHVybiBpZE51bWJlcjs8YnI+DQrCoCDCoCDC oCDCoCB9PGJyPg0KwqAgwqAgwqAgwqAgcHVibGljIHZvaWQgc2V0SWROdW1iZXIoaW50IGlkTnVt YmVyKSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdGhpcy5pZE51bWJlciA9IGlkTnVt YmVyOzxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgbG9uZyBnZXRB bW91bnQoKSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIGFtb3VudDs8YnI+ DQrCoCDCoCDCoCDCoCB9PGJyPg0KwqAgwqAgwqAgwqAgcHVibGljIHZvaWQgc2V0QW1vdW50KGlu dCBhbW91bnQpIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB0aGlzLmFtb3VudCA9IGFt b3VudDs8YnI+DQrCoCDCoCDCoCDCoCB9PGJyPg0KwqAgwqAgwqAgwqAgQE92ZXJyaWRlPGJyPg0K wqAgwqAgwqAgwqAgcHVibGljIFN0cmluZyB0b1N0cmluZygpIHs8YnI+DQrCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCByZXR1cm4gJnF1b3Q7VHJhbnNhY3Rpb24gW2lkTnVtYmVyPSZxdW90OyArIGlk TnVtYmVyICsgJnF1b3Q7LCBhbW91bnQ9JnF1b3Q7ICs8YnI+DQphbW91bnQgKyAmcXVvdDtdJnF1 b3Q7Ozxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQp9PGJyPg0KPGJyPg0KPC9zcGFuPlRyYW5zYWN0 aW9uU3RvcmUuamF2YTxicj4NCjxkaXY+PGRpdiBjbGFzcz0iaDUiPjxicj4NCnBhY2thZ2UgbXll eGFtcGxlcy5zdG9yZTs8YnI+DQppbXBvcnQgamF2YS5zcWwuQ29ubmVjdGlvbjs8YnI+DQppbXBv cnQgamF2YS5zcWwuUHJlcGFyZWRTdGF0ZW1lbnQ7PGJyPg0KaW1wb3J0IGphdmEuc3FsLlJlc3Vs dFNldDs8YnI+DQppbXBvcnQgamF2YS5zcWwuU1FMRXhjZXB0aW9uOzxicj4NCmltcG9ydCBqYXZh LnV0aWwuQ29sbGVjdGlvbjs8YnI+DQppbXBvcnQgamF2YS51dGlsLk1hcDs8YnI+DQo8YnI+DQpp bXBvcnQgamF2YXguY2FjaGUuQ2FjaGUuRW50cnk7PGJyPg0KaW1wb3J0IGphdmF4LmNhY2hlLmlu dGVncmF0aW9uLjx3YnI+Q2FjaGVMb2FkZXJFeGNlcHRpb247PGJyPg0KaW1wb3J0IGphdmF4LmNh Y2hlLmludGVncmF0aW9uLjx3YnI+Q2FjaGVXcml0ZXJFeGNlcHRpb247PGJyPg0KaW1wb3J0IGph dmF4LnNxbC5EYXRhU291cmNlOzxicj4NCjxicj4NCmltcG9ydCBvcmcuYXBhY2hlLmlnbml0ZS5j YWNoZS5zdG9yZS48d2JyPkNhY2hlU3RvcmU7PGJyPg0KaW1wb3J0IG9yZy5hcGFjaGUuaWduaXRl LmxhbmcuPHdicj5JZ25pdGVCaUluQ2xvc3VyZTs8YnI+DQppbXBvcnQgb3JnLmFwYWNoZS5pZ25p dGUucmVzb3VyY2VzLjx3YnI+U3ByaW5nUmVzb3VyY2U7PGJyPg0KaW1wb3J0IG9yZy5qZXRicmFp bnMuYW5ub3RhdGlvbnMuPHdicj5OdWxsYWJsZTs8YnI+DQo8YnI+DQppbXBvcnQgaWduaXRlLm15 ZXhhbXBsZXMubW9kZWwuU3RvcmU7PGJyPg0KPGJyPg0KcHVibGljIGNsYXNzIFRyYW5zYWN0aW9u U3RvcmUgaW1wbGVtZW50cyBDYWNoZVN0b3JlJmx0O0xvbmcsIFN0b3JlJmd0OyB7PGJyPg0KwqAg wqAgwqAgwqAgQFNwcmluZ1Jlc291cmNlKHJlc291cmNlTmFtZSA9ICZxdW90O2RhdGFTb3VyY2Um cXVvdDspPGJyPg0KwqAgwqAgwqAgwqAgcHJpdmF0ZSBEYXRhU291cmNlIGRhdGFTb3VyY2U7PGJy Pg0KwqAgwqAgwqAgwqAgLy8gVGhpcyBtZXRob2QgaXMgY2FsbGVkIHdoZW5ldmVyIElnbml0ZUNh Y2hlLmxvYWRDYWNoZSgpIG1ldGhvZCBpczxicj4NCmNhbGxlZC48YnI+DQrCoCDCoCDCoCDCoCBA T3ZlcnJpZGU8YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgdm9pZCBsb2FkQ2FjaGUoSWduaXRlQmlJ bkNsb3N1cmUmbHQ7PHdicj5Mb25nLCBTdG9yZSZndDsgY2xvLCBATnVsbGFibGU8YnI+DQpPYmpl Y3QuLi4gb2JqZWN0cykgdGhyb3dzIENhY2hlTG9hZGVyRXhjZXB0aW9uIHs8YnI+DQrCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBTeXN0ZW0ub3V0LnByaW50bG4oJnF1b3Q7Jmd0OyZndDsgTG9hZGlu ZyBjYWNoZSBmcm9tIHN0b3JlLi4uJnF1b3Q7KTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCB0cnkgKENvbm5lY3Rpb24gY29ubiA9IGRhdGFTb3VyY2UuZ2V0Q29ubmVjdGlvbigpKSB7PGJy Pg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdHJ5IChQcmVwYXJlZFN0YXRl bWVudCBzdCA9PGJyPg0KY29ubi5wcmVwYXJlU3RhdGVtZW50KCZxdW90O3NlbGVjdCAqIGZyb20g VFJBTlNBQ1RJT04mcXVvdDspKSB7IC8vIGRhcmkgdGFiZWwgbXlzcWw8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB0cnkgKFJlc3VsdFNldCBycyA9 IHN0LmV4ZWN1dGVRdWVyeSgpKSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgd2hpbGUgKHJzLm5leHQoKSkgezxicj4NCsKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIFN0b3JlIHRyYW5zYWtzaSA9IG5ldzxicj4NClN0b3JlKHJzLmdldEludCgx KSwgcnMuZ2V0SW50KDIpKTs8YnI+DQo8YnI+DQpjbG8uYXBwbHkodHJhbnNha3NpLjx3YnI+Z2V0 SWROdW1iZXIoKSwgdHJhbnNha3NpKTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgY2F0Y2ggKFNRTEV4Y2VwdGlvbiBlKSB7PGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdGhyb3cgbmV3IENhY2hlTG9hZGVyRXhjZXB0 aW9uKCZxdW90O0ZhaWxlZCB0byBsb2FkPGJyPg0KdmFsdWVzIGZyb20gY2FjaGUgc3RvcmUuJnF1 b3Q7LCBlKTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KwqAgwqAgwqAgwqAg fTxicj4NCsKgIMKgIMKgIMKgIC8vIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB3aGVuZXZlciBJZ25p dGVDYWNoZS5nZXQoKSBtZXRob2QgaXM8YnI+DQpjYWxsZWQuPGJyPg0KwqAgwqAgwqAgwqAgQE92 ZXJyaWRlPGJyPg0KwqAgwqAgwqAgwqAgcHVibGljIFN0b3JlIGxvYWQoTG9uZyBrZXkpIHRocm93 cyBDYWNoZUxvYWRlckV4Y2VwdGlvbiB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgU3lz dGVtLm91dC5wcmludGxuKCZxdW90O0xvYWRpbmcgVHJhbnNhY3Rpb24gZnJvbSBTdG9yZSAuLi4m cXVvdDspOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHRyeSAoQ29ubmVjdGlvbiBjb25u ID0gZGF0YVNvdXJjZS5nZXRDb25uZWN0aW9uKCkpIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCB0cnkgKFByZXBhcmVkU3RhdGVtZW50IHN0ID08YnI+DQpjb25uLnBy ZXBhcmVTdGF0ZW1lbnQoJnF1b3Q7c2VsZWN0ICogZnJvbSBUUkFOU0FDVElPTiB3aGVyZSBpZCA9 ID8mcXVvdDspKSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgc3Quc2V0U3RyaW5nKDEsIGtleS50b1N0cmluZygpKTs8YnI+DQrCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBSZXN1bHRTZXQgcnMgPSBzdC5l eGVjdXRlUXVlcnkoKTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCByZXR1cm4gcnMubmV4dCgpID8gbmV3IFN0b3JlKHJzLmdldEludCgxKSw8YnI+ DQpycy5nZXRJbnQoMikpIDogbnVsbDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCB9PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIGNhdGNoIChTUUxFeGNlcHRpb24gZSkgezxicj4NCsKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIHRocm93IG5ldyBDYWNoZUxvYWRlckV4Y2VwdGlvbigmcXVv dDtGYWlsZWQgdG8gbG9hZDxicj4NCnZhbHVlcyBmcm9tIGNhY2hlIHN0b3JlLiZxdW90OywgZSk7 PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQrC oCDCoCDCoCDCoCBAT3ZlcnJpZGU8YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgTWFwJmx0O0xvbmcs IFN0b3JlJmd0OyBsb2FkQWxsKEl0ZXJhYmxlJmx0Oz8gZXh0ZW5kcyBMb25nJmd0OyBhcmcwKTxi cj4NCnRocm93cyBDYWNoZUxvYWRlckV4Y2VwdGlvbiB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgLy8gVE9ETyBBdXRvLWdlbmVyYXRlZCBtZXRob2Qgc3R1Yjxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIHJldHVybiBudWxsOzxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDC oCDCoCBAT3ZlcnJpZGU8YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgdm9pZCBkZWxldGUoT2JqZWN0 IGFyZzApIHRocm93cyBDYWNoZVdyaXRlckV4Y2VwdGlvbiB7PGJyPg0KwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgLy8gVE9ETyBBdXRvLWdlbmVyYXRlZCBtZXRob2Qgc3R1Yjxicj4NCjxicj4NCsKg IMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCBAT3ZlcnJpZGU8YnI+DQrCoCDCoCDCoCDCoCBw dWJsaWMgdm9pZCBkZWxldGVBbGwoQ29sbGVjdGlvbiZsdDs/Jmd0OyBhcmcwKSB0aHJvd3M8YnI+ DQpDYWNoZVdyaXRlckV4Y2VwdGlvbiB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgLy8g VE9ETyBBdXRvLWdlbmVyYXRlZCBtZXRob2Qgc3R1Yjxicj4NCjxicj4NCsKgIMKgIMKgIMKgIH08 YnI+DQrCoCDCoCDCoCDCoCBAT3ZlcnJpZGU8YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgdm9pZCB3 cml0ZShFbnRyeSZsdDs/IGV4dGVuZHMgTG9uZywgPyBleHRlbmRzIFN0b3JlJmd0OyBhcmcwKTxi cj4NCnRocm93cyBDYWNoZVdyaXRlckV4Y2VwdGlvbiB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgLy8gVE9ETyBBdXRvLWdlbmVyYXRlZCBtZXRob2Qgc3R1Yjxicj4NCsKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIExvbmcga2V5ID0gYXJnMC5nZXRLZXkoKTs8YnI+DQrCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCBTdG9yZSB2YWwgPSBhcmcwLmdldFZhbHVlKCk7PGJyPg0KPGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgU3lzdGVtLm91dC5wcmludGxuKCZxdW90OyZndDsmZ3Q7Jmd0OyBT dG9yZSB3cml0ZSAmcXVvdDspOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIFN5c3RlbS5v dXQucHJpbnRsbigmcXVvdDtba2V5PSZxdW90OyArIGtleSArICZxdW90OywgdmFsPSZxdW90OyAr IHZhbCArICYjMzk7XSYjMzk7KTs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB0 cnkgezxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIENvbm5lY3Rpb24g Y29ubiA9IGRhdGFTb3VyY2UuZ2V0Q29ubmVjdGlvbigpOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIGludCB1cGRhdGVkOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIC8vIFRyeSB1cGRhdGUgZmlyc3QuIElmIGl0IGRvZXMgbm90IHdvcmss IHRoZW4gdHJ5PGJyPg0KaW5zZXJ0Ljxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIC8vIFNvbWUgZGF0YWJhc2VzIHdvdWxkIGFsbG93IHRoZXNlIHRvIGJlIGRvbmUgaW48 YnI+DQpvbmUgJiMzOTt1cHNlcnQmIzM5OyBvcGVyYXRpb24uPGJyPg0KwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgdHJ5IChQcmVwYXJlZFN0YXRlbWVudCBzdCA9IGNvbm4ucHJl cGFyZVN0YXRlbWVudCg8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmcXVvdDt1cGRhdGUgVFJBTlNBQ1RJT04gc2V0IGFtb3Vu dCA9ID88YnI+DQp3aGVyZSBpZE51bWJlciA9ID8mcXVvdDspKSB7PGJyPg0KwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgc3Quc2V0TG9uZygxLCB2YWwuZ2V0 QW1vdW50KCkpOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIHN0LnNldExvbmcoMiwgdmFsLmdldElkTnVtYmVyKCkpOzxicj4NCjxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHVwZGF0ZWQgPSBzdC5l eGVjdXRlVXBkYXRlKCk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgU3lzdGVtLm91dC5wcmludGxuKCZxdW90O3VwZGF0ZSBzdWNjZXNzJnF1b3Q7 KTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9PGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHVwZGF0ZWQgPT0gMCkgezxicj4NCsKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHRyeSAoUHJlcGFy ZWRTdGF0ZW1lbnQgc3QgPTxicj4NCmNvbm4ucHJlcGFyZVN0YXRlbWVudCg8YnI+DQrCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCAmcXVvdDtpbnNlcnQgaW50byBUUkFOU0FDVElPTjxicj4NCihpZCwgYW1vdW50KSB2 YWx1ZXMgKD8sID8pJnF1b3Q7KSkgezxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHN0LnNldExvbmcoMSwgdmFsLmdldElkTnVt YmVyKCkpOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIHN0LnNldExvbmcoMiwgdmFsLmdldEFtb3VudCgpKTs8YnI+DQrCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBz dC5leGVjdXRlVXBkYXRlKCk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgU3lzdGVtLm91dC5wcmludGxuKCZxdW90O2luc2Vy dGlvbjxicj4NCnN1Y2Nlc3MmcXVvdDspOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCB9PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIGNhdGNoIChTUUxFeGNlcHRpb24gZSkgezxicj4NCsKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHRocm93IG5ldyBDYWNoZVdyaXRlckV4Y2VwdGlv bigmcXVvdDtGYWlsZWQgdG8gd3JpdGU8YnI+DQpvYmplY3QgW2tleT0mcXVvdDsgKyBrZXkgKyAm cXVvdDssIHZhbD0mcXVvdDsgKyB2YWwgKyAmIzM5O10mIzM5OywgZSk7PGJyPg0KwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgfTxicj4NCsKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCBAT3Zl cnJpZGU8YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgdm9pZCB3cml0ZUFsbChDb2xsZWN0aW9uJmx0 O0VudHJ5JmFtcDtsdDs/IGV4dGVuZHMgTG9uZywgPyBleHRlbmRzPGJyPg0KU3RvcmUmZ3Q7Jmd0 OyBhcmcwKSB0aHJvd3MgQ2FjaGVXcml0ZXJFeGNlcHRpb24gezxicj4NCsKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIC8vIFRPRE8gQXV0by1nZW5lcmF0ZWQgbWV0aG9kIHN0dWI8YnI+DQo8YnI+DQrC oCDCoCDCoCDCoCB9PGJyPg0KwqAgwqAgwqAgwqAgQE92ZXJyaWRlPGJyPg0KwqAgwqAgwqAgwqAg cHVibGljIHZvaWQgc2Vzc2lvbkVuZChib29sZWFuIGNvbW1pdCkgdGhyb3dzIENhY2hlV3JpdGVy RXhjZXB0aW9uIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAvLyBUT0RPIEF1dG8tZ2Vu ZXJhdGVkIG1ldGhvZCBzdHViPGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgfTxicj4NCjxicj4NCn08 YnI+DQo8YnI+DQo8L2Rpdj48L2Rpdj5TZXJ2ZXIgbm9kZTogVHJhbnNhY3Rpb25TZXJ2ZXIuamF2 YTxicj4NCjxzcGFuIGNsYXNzPSIiPnBhY2thZ2UgbXlleGFtcGxlcy5zdG9yZTs8YnI+DQppbXBv cnQgamF2YS51dGlsLkxpc3Q7PGJyPg0KaW1wb3J0IG9yZy5hcGFjaGUuaWduaXRlLklnbml0ZTs8 YnI+DQppbXBvcnQgb3JnLmFwYWNoZS5pZ25pdGUuSWduaXRlQ2FjaGU7PGJyPg0KaW1wb3J0IG9y Zy5hcGFjaGUuaWduaXRlLjx3YnI+SWduaXRlRXhjZXB0aW9uOzxicj4NCmltcG9ydCBvcmcuYXBh Y2hlLmlnbml0ZS5JZ25pdGlvbjs8YnI+DQppbXBvcnQgb3JnLmFwYWNoZS5pZ25pdGUuY2FjaGUu cXVlcnkuPHdicj5RdWVyeUN1cnNvcjs8YnI+DQppbXBvcnQgb3JnLmFwYWNoZS5pZ25pdGUuY2Fj aGUucXVlcnkuPHdicj5TcWxGaWVsZHNRdWVyeTs8YnI+DQppbXBvcnQgaWduaXRlLm15ZXhhbXBs ZXMubW9kZWwuU3RvcmU7PGJyPg0KPGJyPg0KcHVibGljIGNsYXNzIFRyYW5zYWN0aW9uU2VydmVy IHs8YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdz KSB0aHJvd3MgSWduaXRlRXhjZXB0aW9uIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAv LyBTdGFydCBJZ25pdGUgbm9kZS48YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBJZ25pdGUg aWduaXRlID08YnI+DQpJZ25pdGlvbi5zdGFydCgmcXVvdDtwYXRoL3RvL215Lzx3YnI+aWduaXRl LWpkYmMueG1sJnF1b3Q7KTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBJZ25pdGVDYWNo ZSZsdDtMb25nLCBTdG9yZSZndDsgY2FjaGUgPTxicj4NCmlnbml0ZS5nZXRPckNyZWF0ZUNhY2hl KCZxdW90Ozx3YnI+dHJhbnNhY3Rpb25DYWNoZSZxdW90Oyk7PGJyPg0KwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgLy8gTG9hZCBjYWNoZSB3aXRoIGRhdGEgZnJvbSB0aGUgZGF0YWJhc2UuPGJyPg0K wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY2FjaGUubG9hZENhY2hlKG51bGwpOzxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIC8vIEV4ZWN1dGUgcXVlcnkgb24gY2FjaGUuPGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgUXVlcnlDdXJzb3ImbHQ7TGlzdCZhbXA7bHQ7PyZndDsmZ3Q7IGN1 cnNvciA9IGNhY2hlLnF1ZXJ5KG5ldzxicj4NClNxbEZpZWxkc1F1ZXJ5KDxicj4NCsKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICZxdW90O3NlbGVjdCBpZE51 bWJlciwgYW1vdW50IGZyb20gU3RvcmUmcXVvdDspKTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCBTeXN0ZW0ub3V0LnByaW50bG4oY3Vyc29yLjx3YnI+Z2V0QWxsKCkpOzxicj4NCsKgIMKg IMKgIMKgIH08YnI+DQo8YnI+DQp9PGJyPg0KPGJyPg0KPC9zcGFuPkNsaWVudCBub2RlOiBUcmFu c2FjdGlvblN0b3JlRXhhbXBsZS5qYXZhPGJyPg0KPGRpdj48ZGl2IGNsYXNzPSJoNSI+cGFja2Fn ZSBteWV4YW1wbGVzLnN0b3JlOzxicj4NCjxicj4NCmltcG9ydCBzdGF0aWM8YnI+DQpvcmcuYXBh Y2hlLmlnbml0ZS48d2JyPnRyYW5zYWN0aW9ucy48d2JyPlRyYW5zYWN0aW9uQ29uY3VycmVuY3ku PHdicj5QRVNTSU1JU1RJQzs8YnI+DQppbXBvcnQgc3RhdGljPGJyPg0Kb3JnLmFwYWNoZS5pZ25p dGUuPHdicj50cmFuc2FjdGlvbnMuPHdicj5UcmFuc2FjdGlvbklzb2xhdGlvbi48d2JyPlJFUEVB VEFCTEVfUkVBRDs8YnI+DQo8YnI+DQppbXBvcnQgb3JnLmFwYWNoZS5pZ25pdGUuSWduaXRlOzxi cj4NCmltcG9ydCBvcmcuYXBhY2hlLmlnbml0ZS5JZ25pdGVDYWNoZTs8YnI+DQppbXBvcnQgb3Jn LmFwYWNoZS5pZ25pdGUuPHdicj5JZ25pdGVFeGNlcHRpb247PGJyPg0KaW1wb3J0IG9yZy5hcGFj aGUuaWduaXRlLklnbml0aW9uOzxicj4NCmltcG9ydCBvcmcuYXBhY2hlLmlnbml0ZS48d2JyPnRy YW5zYWN0aW9ucy5UcmFuc2FjdGlvbjs8YnI+DQo8YnI+DQppbXBvcnQgaWduaXRlLm15ZXhhbXBs ZXMubW9kZWwuU3RvcmU7PGJyPg0KPGJyPg0KcHVibGljIGNsYXNzIFRyYW5zYWN0aW9uU3RvcmVF eGFtcGxlIHs8YnI+DQrCoCDCoCDCoCDCoCBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdb XSBhcmdzKSB0aHJvd3MgSWduaXRlRXhjZXB0aW9uIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCAvLyBJbiB0aGlzIGNhc2UsIEkganVzdCB0cnkgdGhlIG51bWJlciAxIGFuZCBhZGQgaXQg d2l0aCB0aGU8YnI+DQphbW91bnQgb2YgMTAwPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg bG9uZyBpZCA9IDE7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgbG9uZyBhbW91bnQgPSAx MDA7PGJyPg0KPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgLy8gU2V0IGl0IGFzIGEgY2xp ZW50PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgSWduaXRpb24uc2V0Q2xpZW50TW9kZSh0 cnVlKTs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAvLyBTdGFydCBJZ25pdGUg bm9kZS48YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB0cnkgKElnbml0ZSBpZ25pdGUgPTxi cj4NCklnbml0aW9uLnN0YXJ0KCZxdW90O3BhdGgvdG8vbXkvPHdicj5pZ25pdGUtamRiYy54bWwm cXVvdDspKSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgdHJ5IChJ Z25pdGVDYWNoZSZsdDtMb25nLCBTdG9yZSZndDsgaWduaXRlQ2FjaGUgPTxicj4NCmlnbml0ZS5n ZXRPckNyZWF0ZUNhY2hlKCZxdW90Ozx3YnI+dHJhbnNhY3Rpb25DYWNoZSZxdW90OykpIHs8YnI+ DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB0cnkgKFRy YW5zYWN0aW9uIHR4ID08YnI+DQppZ25pdGUudHJhbnNhY3Rpb25zKCkudHhTdGFydCg8d2JyPlBF U1NJTUlTVElDLCBSRVBFQVRBQkxFX1JFQUQpKSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgU3RvcmUgYWNjb3VudCA9PGJy Pg0KaWduaXRlQ2FjaGUuZ2V0KChsb25nKSBpZCk7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYXNzZXJ0IGFjY291bnQgIT0g bnVsbDs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCAvLyB1cGRhdGUgYW1vdW50PGJyPg0KwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYWNjb3VudC51cGRh dGUoYW1vdW50KTs8YnI+DQo8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAvLyBTdG9yZSB1cGRhdGVkIGFjY291bnQgaW4gY2Fj aGUuPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgaWduaXRlQ2FjaGUucHV0KGlkLCBhY2NvdW50KTs8YnI+DQo8YnI+DQrCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB0 eC5jb21taXQoKTs8YnI+DQo8YnI+DQpTeXN0ZW0ub3V0LnByaW50bG4oPHdicj5pZ25pdGVDYWNo ZS5nZXQoaWQpKTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCB9PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQrCoCDCoCDCoCDCoCB9PGJyPg0KfTxicj4N Cjxicj4NClRoYW5rcyBmb3IgYW55IGhlbHAgdGhhdCB5b3UgY2FuIHByb3ZpZGUuPGJyPg0KLS0g Umlja3k8YnI+DQo8YnI+DQo8YnI+DQo8YnI+DQotLTxicj4NCjwvZGl2PjwvZGl2PlZpZXcgdGhp cyBtZXNzYWdlIGluIGNvbnRleHQ6IDxhIGhyZWY9Imh0dHA6Ly9hcGFjaGUtaWduaXRlLXVzZXJz LjcwNTE4Lng2Lm5hYmJsZS5jb20vSG93LXRvLWRvLXdyaXRlLWJlaGluZC1jYWNoaW5nLXRwMTIx MzhwMTIyMTYuaHRtbCIgcmVsPSJub3JlZmVycmVyIiB0YXJnZXQ9Il9ibGFuayI+aHR0cDovL2Fw YWNoZS1pZ25pdGUtdXNlcnMuPHdicj43MDUxOC54Ni5uYWJibGUuY29tL0hvdy10by1kby08d2Jy PndyaXRlLWJlaGluZC1jYWNoaW5nLTx3YnI+dHAxMjEzOHAxMjIxNi5odG1sPC9hPjxicj4NCjxk aXYgY2xhc3M9IkhPRW5aYiI+PGRpdiBjbGFzcz0iaDUiPlNlbnQgZnJvbSB0aGUgQXBhY2hlIEln bml0ZSBVc2VycyBtYWlsaW5nIGxpc3QgYXJjaGl2ZSBhdCBOYWJibGUuY29tLjxicj4NCjwvZGl2 PjwvZGl2PjwvYmxvY2txdW90ZT48L2Rpdj48YnI+PGJyIGNsZWFyPSJhbGwiPjxkaXY+PGJyPjwv ZGl2Pi0tIDxicj48ZGl2IGNsYXNzPSJnbWFpbF9zaWduYXR1cmUiIGRhdGEtc21hcnRtYWlsPSJn bWFpbF9zaWduYXR1cmUiPjxkaXYgZGlyPSJsdHIiPjxkaXY+QmVzdCByZWdhcmRzLDxicj5BbmRy ZXkgVi4gTWFzaGVua292PGJyPjwvZGl2PjwvZGl2PjwvZGl2Pg0KPC9kaXY+DQo= --f403043ed32c1ab9a7054e1010aa--