From ffe4b47d2053e08db86975d9176a68251b184685 Mon Sep 17 00:00:00 2001
From: Jaroslav Bachorik
Date: Fri, 3 Apr 2015 15:39:38 +0200
Subject: [PATCH 01/36] 8075926: Add a sun.management.JMXConnectorServer perf
counter to track its state
Reviewed-by: duke
---
.../share/classes/sun/management/Agent.java | 1 +
.../sun/management/ConnectorAddressLink.java | 43 +++-
.../bootstrap/JvmstatCountersTest.java | 13 +-
.../startstop/JMXStatusPerfCountersTest.java | 188 ++++++++++++++++++
.../startstop/ManagementAgentJcmd.java | 36 ++++
5 files changed, 274 insertions(+), 7 deletions(-)
create mode 100644 jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java
diff --git a/jdk/src/java.management/share/classes/sun/management/Agent.java b/jdk/src/java.management/share/classes/sun/management/Agent.java
index ffb3105255e..e0b781dc71c 100644
--- a/jdk/src/java.management/share/classes/sun/management/Agent.java
+++ b/jdk/src/java.management/share/classes/sun/management/Agent.java
@@ -345,6 +345,7 @@ public class Agent {
if (jmxServer != null) {
ConnectorBootstrap.unexportRegistry();
+ ConnectorAddressLink.unexportRemote();
// Attempt to stop already stopped agent
// Don't cause any errors.
diff --git a/jdk/src/java.management/share/classes/sun/management/ConnectorAddressLink.java b/jdk/src/java.management/share/classes/sun/management/ConnectorAddressLink.java
index 893f11c1f46..4ec5ec799cc 100644
--- a/jdk/src/java.management/share/classes/sun/management/ConnectorAddressLink.java
+++ b/jdk/src/java.management/share/classes/sun/management/ConnectorAddressLink.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@ package sun.management;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -45,9 +46,26 @@ import sun.management.counter.perf.PerfInstrumentation;
* @since 1.5
*/
public class ConnectorAddressLink {
+ /**
+ * A simple wrapper for the perf-counter backing {@linkplain ByteBuffer}
+ */
+ private static final class PerfHandle {
+ private ByteBuffer bb;
+
+ private PerfHandle(ByteBuffer bb) {
+ this.bb = bb.order(ByteOrder.nativeOrder());
+ }
+
+ private void putLong(long l) {
+ this.bb = bb.clear();
+ this.bb.asLongBuffer().put(l);
+ }
+ }
private static final String CONNECTOR_ADDRESS_COUNTER =
"sun.management.JMXConnectorServer.address";
+ private static final String REMOTE_CONNECTOR_STATE_COUNTER =
+ "sun.management.JMXConnectorServer.remote.enabled";
/*
* The format of the jvmstat counters representing the properties of
@@ -78,7 +96,9 @@ public class ConnectorAddressLink {
* JMX remote connector counter (it will be incremented every
* time a new out-of-the-box JMX remote connector is created).
*/
- private static AtomicInteger counter = new AtomicInteger();
+ private static final AtomicInteger counter = new AtomicInteger();
+
+ private static PerfHandle remotePerfHandle = null;
/**
* Exports the specified connector address to the instrumentation buffer
@@ -93,7 +113,17 @@ public class ConnectorAddressLink {
}
Perf perf = Perf.getPerf();
perf.createString(
- CONNECTOR_ADDRESS_COUNTER, 1, Units.STRING.intValue(), address);
+ CONNECTOR_ADDRESS_COUNTER, 1, Units.STRING.intValue(), address);
+ }
+
+ public static void unexportRemote() {
+ unexport(remotePerfHandle);
+ }
+
+ private static void unexport(PerfHandle ph) {
+ if (ph != null) {
+ ph.putLong(-1L);
+ }
}
/**
@@ -143,6 +173,13 @@ public class ConnectorAddressLink {
perf.createString(REMOTE_CONNECTOR_COUNTER_PREFIX + index + "." +
entry.getKey(), 1, Units.STRING.intValue(), entry.getValue());
}
+ if (remotePerfHandle != null) {
+ remotePerfHandle.putLong(index);
+ } else {
+ remotePerfHandle = new PerfHandle(
+ perf.createLong(REMOTE_CONNECTOR_STATE_COUNTER, 1, Units.NONE.intValue(), (long)index)
+ );
+ }
}
/**
diff --git a/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java
index 277edb33e5f..80f74b37ce3 100644
--- a/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java
@@ -116,10 +116,10 @@ public class JvmstatCountersTest {
throw new IllegalArgumentException("Test case 3 failed");
}
for (String key : remoteData.keySet()) {
- if (!key.startsWith("sun.management.JMXConnectorServer.0.")) {
+ if (!isKeyAcceptable(key)) {
System.out.println("Test FAILED! The OOTB management " +
"agent shouldn't publish anything which isn't " +
- "related to the remote connector.");
+ "related to the remote connector (" + key + ").");
throw new IllegalArgumentException("Test case 3 failed");
}
}
@@ -165,10 +165,10 @@ public class JvmstatCountersTest {
throw new IllegalArgumentException("Test case 4 failed");
}
for (String key : remoteData2.keySet()) {
- if (!key.startsWith("sun.management.JMXConnectorServer.0.")) {
+ if (!isKeyAcceptable(key)) {
System.out.println("Test FAILED! The OOTB management " +
"agent shouldn't publish anything which isn't " +
- "related to the remote connector.");
+ "related to the remote connector (" + key + ").");
throw new IllegalArgumentException("Test case 4 failed");
}
}
@@ -184,4 +184,9 @@ public class JvmstatCountersTest {
}
System.out.println("Bye! Bye!");
}
+
+ private static boolean isKeyAcceptable(String key) {
+ return key.startsWith("sun.management.JMXConnectorServer.0.") ||
+ key.startsWith("sun.management.JMXConnectorServer.remote.enabled");
+ }
}
diff --git a/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java b/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java
new file mode 100644
index 00000000000..4d1eef69f50
--- /dev/null
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.net.BindException;
+import java.util.Properties;
+import java.util.function.Predicate;
+import static org.testng.Assert.*;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import jdk.testlibrary.ProcessTools;
+
+
+/**
+ * @test
+ * @bug 8075926
+ * @summary Makes sure that the current management agent status is reflected
+ * in the related performance counters.
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.* PortAllocator TestApp ManagementAgentJcmd
+ * @run testng/othervm -XX:+UsePerfData JMXStatusPerfCountersTest
+ */
+public class JMXStatusPerfCountersTest {
+ private final static String TEST_APP_NAME = "TestApp";
+
+ private final static String REMOTE_STATUS_KEY = "sun.management.JMXConnectorServer.remote.enabled";
+
+ private static ProcessBuilder testAppPb;
+ private Process testApp;
+
+ private ManagementAgentJcmd jcmd;
+
+ @BeforeClass
+ public static void setupClass() throws Exception {
+ testAppPb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UsePerfData",
+ "-cp", System.getProperty("test.class.path"),
+ TEST_APP_NAME
+ );
+ }
+
+ @BeforeTest
+ public void setup() {
+ jcmd = new ManagementAgentJcmd(TEST_APP_NAME, false);
+ }
+
+ @BeforeMethod
+ public void startTestApp() throws Exception {
+ testApp = ProcessTools.startProcess(
+ TEST_APP_NAME, testAppPb,
+ (Predicate)l->l.trim().equals("main enter")
+ );
+ }
+
+ @AfterMethod
+ public void stopTestApp() throws Exception {
+ testApp.getOutputStream().write(1);
+ testApp.getOutputStream().flush();
+ testApp.waitFor();
+ testApp = null;
+ }
+
+ /**
+ * The 'sun.management.JMXConnectorServer.remote.enabled' counter must not be
+ * exported if the remote agent is not enabled.
+ * @throws Exception
+ */
+ @Test
+ public void testNotInitializedRemote() throws Exception {
+ assertFalse(
+ getCounters().containsKey(REMOTE_STATUS_KEY),
+ "Unexpected occurrence of " + REMOTE_STATUS_KEY + " in perf counters"
+ );
+ }
+
+ /**
+ * After enabling the remote agent the 'sun.management.JMXConnectorServer.remote.enabled'
+ * counter will be exported with value of '0' - corresponding to the actual
+ * version of the associated remote connector perf counters.
+ * @throws Exception
+ */
+ @Test
+ public void testRemoteEnabled() throws Exception {
+ while (true) {
+ try {
+ int[] ports = PortAllocator.allocatePorts(1);
+ jcmd.start(
+ "jmxremote.port=" + ports[0],
+ "jmxremote.authenticate=false",
+ "jmxremote.ssl=false"
+ );
+ String v = getCounters().getProperty(REMOTE_STATUS_KEY);
+ assertNotNull(v);
+ assertEquals("0", v);
+ return;
+ } catch (BindException e) {
+ System.out.println("Failed to allocate ports. Retrying ...");
+ }
+ }
+ }
+
+ /**
+ * After disabling the remote agent the value of 'sun.management.JMXConnectorServer.remote.enabled'
+ * counter will become '-1'.
+ * @throws Exception
+ */
+ @Test
+ public void testRemoteDisabled() throws Exception {
+ while (true) {
+ try {
+ int[] ports = PortAllocator.allocatePorts(1);
+ jcmd.start(
+ "jmxremote.port=" + ports[0],
+ "jmxremote.authenticate=false",
+ "jmxremote.ssl=false"
+ );
+ jcmd.stop();
+ String v = getCounters().getProperty(REMOTE_STATUS_KEY);
+ assertNotNull(v);
+ assertEquals("-1", v);
+ return;
+ } catch (BindException e) {
+ System.out.println("Failed to allocate ports. Retrying ...");
+ }
+ }
+ }
+
+ /**
+ * Each subsequent re-enablement of the remote agent must keep the value of
+ * 'sun.management.JMXConnectorServer.remote.enabled' counter in sync with
+ * the actual version of the associated remote connector perf counters.
+ * @throws Exception
+ */
+ @Test
+ public void testRemoteReEnabled() throws Exception {
+ while (true) {
+ try {
+ int[] ports = PortAllocator.allocatePorts(1);
+ jcmd.start(
+ "jmxremote.port=" + ports[0],
+ "jmxremote.authenticate=false",
+ "jmxremote.ssl=false"
+ );
+ jcmd.stop();
+ jcmd.start(
+ "jmxremote.port=" + ports[0],
+ "jmxremote.authenticate=false",
+ "jmxremote.ssl=false"
+ );
+
+ String v = getCounters().getProperty(REMOTE_STATUS_KEY);
+ assertNotNull(v);
+ assertEquals("1", v);
+ return;
+ } catch (BindException e) {
+ System.out.println("Failed to allocate ports. Retrying ...");
+ }
+ }
+ }
+
+ private Properties getCounters() throws IOException, InterruptedException {
+ return jcmd.perfCounters("sun\\.management\\.JMXConnectorServer\\..*");
+ }
+}
\ No newline at end of file
diff --git a/jdk/test/sun/management/jmxremote/startstop/ManagementAgentJcmd.java b/jdk/test/sun/management/jmxremote/startstop/ManagementAgentJcmd.java
index efee771cf4a..f273cd2ce4b 100644
--- a/jdk/test/sun/management/jmxremote/startstop/ManagementAgentJcmd.java
+++ b/jdk/test/sun/management/jmxremote/startstop/ManagementAgentJcmd.java
@@ -25,8 +25,10 @@ import java.net.BindException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import sun.management.Agent;
import sun.management.AgentConfigurationError;
@@ -43,6 +45,7 @@ final class ManagementAgentJcmd {
private static final String CMD_START = "ManagementAgent.start";
private static final String CMD_START_LOCAL = "ManagementAgent.start_local";
private static final String CMD_STATUS = "ManagementAgent.status";
+ private static final String CMD_PRINTPERF = "PerfCounter.print";
private final String id;
private final boolean verbose;
@@ -62,6 +65,39 @@ final class ManagementAgentJcmd {
return jcmd();
}
+ /**
+ * `jcmd PerfCounter.print`
+ * @return Returns the available performance counters with their values as
+ * {@linkplain Properties} instance
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public Properties perfCounters() throws IOException, InterruptedException {
+ return perfCounters(".*");
+ }
+
+ /**
+ * `jcmd PerfCounter.print | grep {exp}>`
+ * @param regex Regular expression for including perf counters in the result
+ * @return Returns the matching performance counters with their values
+ * as {@linkplain Properties} instance
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public Properties perfCounters(String regex) throws IOException, InterruptedException {
+ Pattern pat = Pattern.compile(regex);
+ Properties p = new Properties();
+ for(String l : jcmd(CMD_PRINTPERF).split("\\n")) {
+ String[] kv = l.split("=");
+ if (kv.length > 1) {
+ if (pat.matcher(kv[0]).matches()) {
+ p.setProperty(kv[0], kv[1].replace("\"", ""));
+ }
+ }
+ }
+ return p;
+ }
+
/**
* `jcmd ManagementAgent.stop`
* @return The JCMD output
From 15fffb90d7af3ef665886c0fcc6f777004e91971 Mon Sep 17 00:00:00 2001
From: Jaroslav Bachorik
Date: Wed, 13 May 2015 10:17:38 +0200
Subject: [PATCH 02/36] 8046869: Several java/lang/instrument/PremainClass/*
tests fail due to timeout
Reviewed-by: sla
---
.../java/lang/instrument/PremainClass/NoPremainAgentTest.java | 2 +-
.../lang/instrument/PremainClass/ZeroArgPremainAgentTest.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/jdk/test/java/lang/instrument/PremainClass/NoPremainAgentTest.java b/jdk/test/java/lang/instrument/PremainClass/NoPremainAgentTest.java
index 29bf5623352..bd64239320a 100644
--- a/jdk/test/java/lang/instrument/PremainClass/NoPremainAgentTest.java
+++ b/jdk/test/java/lang/instrument/PremainClass/NoPremainAgentTest.java
@@ -33,7 +33,7 @@ import jdk.testlibrary.Utils;
* @modules java.management
* @run build jdk.testlibrary.* DummyMain
* @run shell ../MakeJAR3.sh NoPremainAgent
- * @run main NoPremainAgentTest
+ * @run main/othervm -XX:-CreateCoredumpOnCrash NoPremainAgentTest
*/
public class NoPremainAgentTest {
// Use a javaagent without the premain() function.
diff --git a/jdk/test/java/lang/instrument/PremainClass/ZeroArgPremainAgentTest.java b/jdk/test/java/lang/instrument/PremainClass/ZeroArgPremainAgentTest.java
index b879aa10f23..66633ea12d3 100644
--- a/jdk/test/java/lang/instrument/PremainClass/ZeroArgPremainAgentTest.java
+++ b/jdk/test/java/lang/instrument/PremainClass/ZeroArgPremainAgentTest.java
@@ -33,7 +33,7 @@ import jdk.testlibrary.Utils;
* @modules java.management
* @run build jdk.testlibrary.* DummyMain
* @run shell ../MakeJAR3.sh ZeroArgPremainAgent
- * @run main ZeroArgPremainAgentTest
+ * @run main/othervm -XX:-CreateCoredumpOnCrash ZeroArgPremainAgentTest
*/
public class ZeroArgPremainAgentTest {
// Use a javaagent with a zero argument premain() function.
From d7f44658949034f81aa01ab16c107be1a27be0ad Mon Sep 17 00:00:00 2001
From: Jaroslav Bachorik
Date: Wed, 13 May 2015 10:17:49 +0200
Subject: [PATCH 03/36] 8029098: Exclude
javax/management/remote/mandatory/notif/ListenerScaleTest.java from running
on fastdebug builds
Reviewed-by: sla, sjiang
---
.../remote/mandatory/notif/ListenerScaleTest.java | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java b/jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java
index efebce3b365..0d7080e6b7d 100644
--- a/jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java
+++ b/jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java
@@ -21,12 +21,16 @@
* questions.
*/
-/*
+/**
* @test
* @bug 6338874
* @summary Check that notification dispatch is not linear in number of MBeans.
* @author Eamonn McManus
* @modules java.management
+ *
+ * @library /lib/testlibrary
+ * @run build jdk.testlibrary.* ListenerScaleTest
+ * @run main ListenerScaleTest
*/
/*
@@ -67,6 +71,8 @@ import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
+import jdk.testlibrary.Platform;
+
public class ListenerScaleTest {
private static final int WARMUP_WITH_ONE_MBEAN = 1000;
private static final int NOTIFS_TO_TIME = 100;
@@ -126,6 +132,10 @@ public class ListenerScaleTest {
};
public static void main(String[] args) throws Exception {
+ if (Platform.isDebugBuild()) {
+ System.out.println("Running on a debug build. Performance test not applicable. Skipping.");
+ return;
+ }
MBeanServer mbs = MBeanServerFactory.newMBeanServer();
Sender sender = new Sender();
mbs.registerMBean(sender, testObjectName);
From 3e2a1f00e54b94ee9ed515881dd772334fb230c5 Mon Sep 17 00:00:00 2001
From: Jaroslav Bachorik
Date: Thu, 14 May 2015 11:41:11 +0200
Subject: [PATCH 04/36] 8078143:
java/lang/management/ThreadMXBean/AllThreadIds.java fails intermittently
Reviewed-by: dholmes, martin
---
.../management/ThreadMXBean/AllThreadIds.java | 220 +++++++++++++-----
1 file changed, 160 insertions(+), 60 deletions(-)
diff --git a/jdk/test/java/lang/management/ThreadMXBean/AllThreadIds.java b/jdk/test/java/lang/management/ThreadMXBean/AllThreadIds.java
index 3ecacae2569..9de573c3851 100644
--- a/jdk/test/java/lang/management/ThreadMXBean/AllThreadIds.java
+++ b/jdk/test/java/lang/management/ThreadMXBean/AllThreadIds.java
@@ -32,9 +32,30 @@
*/
import java.lang.management.*;
+import java.time.Instant;
import java.util.concurrent.Phaser;
+import java.util.function.Supplier;
public class AllThreadIds {
+ /**
+ * A supplier wrapper for the delayed format printing.
+ * The supplied value will have to be formatted as $s
+ * @param The wrapped type
+ */
+ private static final class ArgWrapper {
+ private final Supplier val;
+
+ public ArgWrapper(Supplier val) {
+ this.val = val;
+ }
+
+ @Override
+ public String toString() {
+ T resolved = val.get();
+ return resolved != null ? resolved.toString() : null;
+ }
+ }
+
final static int DAEMON_THREADS = 20;
final static int USER_THREADS = 5;
final static int ALL_THREADS = DAEMON_THREADS + USER_THREADS;
@@ -47,15 +68,10 @@ public class AllThreadIds {
private static long prevTotalThreadCount = 0;
private static int prevLiveThreadCount = 0;
private static int prevPeakThreadCount = 0;
- private static long curTotalThreadCount = 0;
- private static int curLiveThreadCount = 0;
- private static int curPeakThreadCount = 0;
private static final Phaser startupCheck = new Phaser(ALL_THREADS + 1);
private static void printThreadList() {
- if (!trace) return;
-
long[] list = mbean.getAllThreadIds();
for (int i = 1; i <= list.length; i++) {
System.out.println(i + ": Thread id = " + list[i-1]);
@@ -68,59 +84,13 @@ public class AllThreadIds {
}
}
- private static void fail(String msg) {
- trace = true;
- printThreadList();
- throw new RuntimeException(msg);
- }
-
- private static void checkThreadCount(int numNewThreads,
- int numTerminatedThreads)
- throws Exception {
- prevTotalThreadCount = curTotalThreadCount;
- prevLiveThreadCount = curLiveThreadCount;
- prevPeakThreadCount = curPeakThreadCount;
- curTotalThreadCount = mbean.getTotalStartedThreadCount();
- curLiveThreadCount = mbean.getThreadCount();
- curPeakThreadCount = mbean.getPeakThreadCount();
-
- if ((curLiveThreadCount - prevLiveThreadCount) !=
- (numNewThreads - numTerminatedThreads)) {
- fail("Unexpected number of live threads: " +
- " Prev live = " + prevLiveThreadCount +
- " Current live = " + curLiveThreadCount +
- " Threads added = " + numNewThreads +
- " Threads terminated = " + numTerminatedThreads);
- }
- if (curPeakThreadCount - prevPeakThreadCount != numNewThreads) {
- fail("Unexpected number of peak threads: " +
- " Prev peak = " + prevPeakThreadCount +
- " Current peak = " + curPeakThreadCount +
- " Threads added = " + numNewThreads);
- }
- if (curTotalThreadCount - prevTotalThreadCount != numNewThreads) {
- fail("Unexpected number of total threads: " +
- " Prev Total = " + prevTotalThreadCount +
- " Current Total = " + curTotalThreadCount +
- " Threads added = " + numNewThreads);
- }
- long[] list = mbean.getAllThreadIds();
- if (list.length != curLiveThreadCount) {
- fail("Array length returned by " +
- "getAllThreadIds() = " + list.length +
- " not matched count = " + curLiveThreadCount);
- }
- }
-
- public static void main(String args[]) throws Exception {
- if (args.length > 0 && args[0].equals("trace")) {
- trace = true;
- }
-
- curTotalThreadCount = mbean.getTotalStartedThreadCount();
- curLiveThreadCount = mbean.getThreadCount();
- curPeakThreadCount = mbean.getPeakThreadCount();
+ private static void checkInitialState() throws Exception {
+ updateCounters();
checkThreadCount(0, 0);
+ }
+
+ private static void checkAllThreadsAlive() throws Exception {
+ updateCounters();
// Start all threads and wait to be sure they all are alive
for (int i = 0; i < ALL_THREADS; i++) {
@@ -133,8 +103,9 @@ public class AllThreadIds {
startupCheck.arriveAndAwaitAdvance();
checkThreadCount(ALL_THREADS, 0);
- printThreadList();
-
+ if (trace) {
+ printThreadList();
+ }
// Check mbean now. All threads must appear in getAllThreadIds() list
long[] list = mbean.getAllThreadIds();
@@ -165,6 +136,10 @@ public class AllThreadIds {
if (trace) {
System.out.println();
}
+ }
+
+ private static void checkDaemonThreadsDead() throws Exception {
+ updateCounters();
// Stop daemon threads, wait to be sure they all are dead, and check
// that they disappeared from getAllThreadIds() list
@@ -179,7 +154,7 @@ public class AllThreadIds {
checkThreadCount(0, DAEMON_THREADS);
// Check mbean now
- list = mbean.getAllThreadIds();
+ long[] list = mbean.getAllThreadIds();
for (int i = 0; i < ALL_THREADS; i++) {
long expectedId = allThreads[i].getId();
@@ -208,6 +183,10 @@ public class AllThreadIds {
}
}
}
+ }
+
+ private static void checkAllThreadsDead() throws Exception {
+ updateCounters();
// Stop all threads and wait to be sure they all are dead
for (int i = DAEMON_THREADS; i < ALL_THREADS; i++) {
@@ -219,6 +198,127 @@ public class AllThreadIds {
// and check the thread count
checkThreadCount(0, ALL_THREADS - DAEMON_THREADS);
+ }
+
+ private static void checkThreadCount(int numNewThreads,
+ int numTerminatedThreads)
+ throws Exception {
+
+ checkLiveThreads(numNewThreads, numTerminatedThreads);
+ checkPeakThreads(numNewThreads);
+ checkTotalThreads(numNewThreads);
+ checkThreadIds();
+ }
+
+ private static void checkLiveThreads(int numNewThreads,
+ int numTerminatedThreads)
+ throws InterruptedException {
+ int diff = numNewThreads - numTerminatedThreads;
+
+ waitTillEquals(
+ diff + prevLiveThreadCount,
+ ()->(long)mbean.getThreadCount(),
+ "Unexpected number of live threads: " +
+ " Prev live = %1$d Current live = ${provided} Threads added = %2$d" +
+ " Threads terminated = %3$d",
+ ()->prevLiveThreadCount,
+ ()->numNewThreads,
+ ()->numTerminatedThreads
+ );
+ }
+
+ private static void checkPeakThreads(int numNewThreads)
+ throws InterruptedException {
+
+ waitTillEquals(numNewThreads + prevPeakThreadCount,
+ ()->(long)mbean.getPeakThreadCount(),
+ "Unexpected number of peak threads: " +
+ " Prev peak = %1$d Current peak = ${provided} Threads added = %2$d",
+ ()->prevPeakThreadCount,
+ ()->numNewThreads
+ );
+ }
+
+ private static void checkTotalThreads(int numNewThreads)
+ throws InterruptedException {
+
+ waitTillEquals(numNewThreads + prevTotalThreadCount,
+ ()->mbean.getTotalStartedThreadCount(),
+ "Unexpected number of total threads: " +
+ " Prev Total = %1$d Current Total = ${provided} Threads added = %2$d",
+ ()->prevTotalThreadCount,
+ ()->numNewThreads
+ );
+ }
+
+ private static void checkThreadIds() throws InterruptedException {
+ long[] list = mbean.getAllThreadIds();
+
+ waitTillEquals(
+ list.length,
+ ()->(long)mbean.getThreadCount(),
+ "Array length returned by " +
+ "getAllThreadIds() = %1$d not matched count = ${provided}",
+ ()->list.length
+ );
+ }
+
+ /**
+ * Waits till the expectedVal equals to the retrievedVal.
+ * It will report a status message on the first occasion of the value mismatch
+ * and then, subsequently, when the retrievedVal value changes.
+ * @param expectedVal The value to wait for
+ * @param retrievedVal The supplier of the value to check against the expectedVal
+ * @param msgFormat The formatted message to be printed in case of mismatch
+ * @param msgArgs The parameters to the formatted message
+ * @throws InterruptedException
+ */
+ private static void waitTillEquals(long expectedVal, Supplier retrievedVal,
+ String msgFormat, Supplier
-
-
-The following changes were discovered to be necessary for backward
-compatibility with certain applications (see bug 4474172):
-
-
-
-
The existing JVM entry point JVM_LatestUserDefinedLoader
-(typically used in applications which rely on the 1.1 security
-framework) must skip reflection-related frames in its stack walk:
-specifically all frames associated with subclasses of
-sun.reflect.MethodAccessorImpl and
-sun.reflect.ConstructorAccessorImpl.
-
-
The new reflection implementation can cause class loading to
-occur in previously-unexpected places (namely during reflective
-calls). This can cause class loaders which contain subtle bugs to
-break. In general it is not possible to guarantee complete backward
-bug compatibility, but one kind of bug has been observed more than
-once: the inability of a user-defined loader to handle delegation to
-it for a class it has already loaded. The new reflection
-implementation is predicated on delegation working properly, as it
-loads stub classes into newly-fabricated class loaders of type
-sun.reflect.DelegatingClassLoader, one stub class per loader, to allow
-unloading of the stub classes to occur more quickly. To handle this
-kind of bug, the JVM's internal class lookup mechanism must be
-slightly modified to check for instances of
-sun.reflect.DelegatingClassLoader as the incoming class loader and
-silently traverse the "parent" field once for such loaders before
-entering the bulk of the resolution code. This avoids an upcall to
-Java programming language code which certain loaders can not handle.
-
-
-
-
-
-
-The following JVM entry points may be deleted:
-
-
-
JVM_GetClassFields
-
JVM_GetClassMethods
-
JVM_GetClassConstructors
-
JVM_GetClassField
-
JVM_GetClassMethod
-
JVM_GetClassConstructor
-
JVM_NewInstance
-
JVM_GetField
-
JVM_GetPrimitiveField
-
JVM_SetField
-
JVM_SetPrimitiveField
-
-
-
-
-
-To keep using the previous reflection implementation, licensees should
-not take changes from Sun's JDK 1.4 relating specifically to the
-implementation of reflection in the following classes/methods and
-any associated native code:
-
-
-
java.lang.Class.newInstance0
-
java.lang.Class.getClassLoader0
-
java.lang.Class.getFields
-
java.lang.Class.getMethods
-
java.lang.Class.getDeclaredFields
-
java.lang.Class.getDeclaredMethods
-
java.lang.Class.getFields0
-
java.lang.Class.getMethods0
-
java.lang.Class.getConstructors0
-
java.lang.Class.getField0
-
java.lang.Class.getMethod0
-
java.lang.Class.getConstructor0
-
java.lang.ClassLoader.getCallerClassLoader
-
java.lang.System.getCallerClass
-
java.lang.reflect.AccessibleObject
-
java.lang.reflect.Constructor
-
java.lang.reflect.Field
-
java.lang.reflect.Method
-
java.lang.reflect.Modifier
-
sun.misc.ClassReflector
-
-
-
-
From efeb942f9fbfe6a5f411c026d57e18bb4a6fb3c4 Mon Sep 17 00:00:00 2001
From: Mandy Chung
Date: Fri, 22 May 2015 16:43:39 -0700
Subject: [PATCH 12/36] 8074431: Remove native2ascii tool
Reviewed-by: erikj, alanb, okutsu, mfang, naoto
---
jdk/make/launcher/Launcher-jdk.dev.gmk | 4 -
jdk/src/bsd/doc/man/ja/native2ascii.1 | 24 --
jdk/src/bsd/doc/man/native2ascii.1 | 87 ----
.../share/classes/java/util/Properties.java | 6 +-
.../java/util/prefs/WindowsPreferences.java | 4 +-
.../sun/tools/native2ascii/A2NFilter.java | 144 -------
.../classes/sun/tools/native2ascii/Main.java | 375 ------------------
.../sun/tools/native2ascii/N2AFilter.java | 74 ----
.../resources/MsgNative2ascii.java | 43 --
.../tools/javac/resources/javac.properties | 2 +-
jdk/test/TEST.groups | 2 -
jdk/test/sun/tools/native2ascii/A2N_4630463 | 1 -
.../tools/native2ascii/A2N_4630463.expected | 1 -
jdk/test/sun/tools/native2ascii/A2N_4630971 | 4 -
jdk/test/sun/tools/native2ascii/A2N_4701617 | 11 -
.../tools/native2ascii/A2N_4701617.expected | 11 -
jdk/test/sun/tools/native2ascii/A2N_6247817 | 1 -
jdk/test/sun/tools/native2ascii/N2A_4636448 | 1 -
.../tools/native2ascii/N2A_4636448.expected | 1 -
.../tools/native2ascii/Native2AsciiTests.sh | 129 ------
.../sun/tools/native2ascii/NativeErrors.java | 117 ------
.../sun/tools/native2ascii/Permission.java | 85 ----
.../resources/ImmutableResourceTest.java | 68 ----
jdk/test/sun/tools/native2ascii/test1 | 1 -
jdk/test/sun/tools/native2ascii/test3 | 1 -
jdk/test/tools/launcher/VersionCheck.java | 1 -
26 files changed, 3 insertions(+), 1195 deletions(-)
delete mode 100644 jdk/src/bsd/doc/man/ja/native2ascii.1
delete mode 100644 jdk/src/bsd/doc/man/native2ascii.1
delete mode 100644 jdk/src/jdk.dev/share/classes/sun/tools/native2ascii/A2NFilter.java
delete mode 100644 jdk/src/jdk.dev/share/classes/sun/tools/native2ascii/Main.java
delete mode 100644 jdk/src/jdk.dev/share/classes/sun/tools/native2ascii/N2AFilter.java
delete mode 100644 jdk/src/jdk.dev/share/classes/sun/tools/native2ascii/resources/MsgNative2ascii.java
delete mode 100644 jdk/test/sun/tools/native2ascii/A2N_4630463
delete mode 100644 jdk/test/sun/tools/native2ascii/A2N_4630463.expected
delete mode 100644 jdk/test/sun/tools/native2ascii/A2N_4630971
delete mode 100644 jdk/test/sun/tools/native2ascii/A2N_4701617
delete mode 100644 jdk/test/sun/tools/native2ascii/A2N_4701617.expected
delete mode 100644 jdk/test/sun/tools/native2ascii/A2N_6247817
delete mode 100644 jdk/test/sun/tools/native2ascii/N2A_4636448
delete mode 100644 jdk/test/sun/tools/native2ascii/N2A_4636448.expected
delete mode 100644 jdk/test/sun/tools/native2ascii/Native2AsciiTests.sh
delete mode 100644 jdk/test/sun/tools/native2ascii/NativeErrors.java
delete mode 100644 jdk/test/sun/tools/native2ascii/Permission.java
delete mode 100644 jdk/test/sun/tools/native2ascii/resources/ImmutableResourceTest.java
delete mode 100644 jdk/test/sun/tools/native2ascii/test1
delete mode 100644 jdk/test/sun/tools/native2ascii/test3
diff --git a/jdk/make/launcher/Launcher-jdk.dev.gmk b/jdk/make/launcher/Launcher-jdk.dev.gmk
index 7d3781707cb..5c01b4fb498 100644
--- a/jdk/make/launcher/Launcher-jdk.dev.gmk
+++ b/jdk/make/launcher/Launcher-jdk.dev.gmk
@@ -32,7 +32,3 @@ $(eval $(call SetupLauncher,jdeps, \
$(eval $(call SetupLauncher,jimage,\
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.tools.jimage.Main"$(COMMA) }'))
-
-$(eval $(call SetupLauncher,native2ascii, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.native2ascii.Main"$(COMMA) }'))
-
diff --git a/jdk/src/bsd/doc/man/ja/native2ascii.1 b/jdk/src/bsd/doc/man/ja/native2ascii.1
deleted file mode 100644
index c7232ea9b2f..00000000000
--- a/jdk/src/bsd/doc/man/ja/native2ascii.1
+++ /dev/null
@@ -1,24 +0,0 @@
-." Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
-." DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-."
-." This code is free software; you can redistribute it and/or modify it
-." under the terms of the GNU General Public License version 2 only, as
-." published by the Free Software Foundation.
-."
-." This code is distributed in the hope that it will be useful, but WITHOUT
-." ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-." FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-." version 2 for more details (a copy is included in the LICENSE file that
-." accompanied this code).
-."
-." You should have received a copy of the GNU General Public License version
-." 2 along with this work; if not, write to the Free Software Foundation,
-." Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-."
-." Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-." or visit www.oracle.com if you need additional information or have any
-." questions.
-."
-.TH native2ascii 1 "07 May 2011"
-
-.LP
diff --git a/jdk/src/bsd/doc/man/native2ascii.1 b/jdk/src/bsd/doc/man/native2ascii.1
deleted file mode 100644
index 7e7ec7cfaa9..00000000000
--- a/jdk/src/bsd/doc/man/native2ascii.1
+++ /dev/null
@@ -1,87 +0,0 @@
-'\" t
-.\" Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
-.\"
-.\" DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-.\"
-.\" This code is free software; you can redistribute it and/or modify it
-.\" under the terms of the GNU General Public License version 2 only, as
-.\" published by the Free Software Foundation.
-.\"
-.\" This code is distributed in the hope that it will be useful, but WITHOUT
-.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-.\" version 2 for more details (a copy is included in the LICENSE file that
-.\" accompanied this code).
-.\"
-.\" You should have received a copy of the GNU General Public License version
-.\" 2 along with this work; if not, write to the Free Software Foundation,
-.\" Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-.\"
-.\" Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-.\" or visit www.oracle.com if you need additional information or have any
-.\" questions.
-.\"
-.\" Arch: generic
-.\" Software: JDK 8
-.\" Date: 21 November 2013
-.\" SectDesc: Internationalization Tools
-.\" Title: native2ascii.1
-.\"
-.if n .pl 99999
-.TH native2ascii 1 "21 November 2013" "JDK 8" "Internationalization Tools"
-.\" -----------------------------------------------------------------
-.\" * Define some portability stuff
-.\" -----------------------------------------------------------------
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.\" http://bugs.debian.org/507673
-.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\" -----------------------------------------------------------------
-.\" * set default formatting
-.\" -----------------------------------------------------------------
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.\" -----------------------------------------------------------------
-.\" * MAIN CONTENT STARTS HERE *
-.\" -----------------------------------------------------------------
-
-.SH NAME
-native2ascii \- Creates localizable applications by converting a file with characters in any supported character encoding to one with ASCII and/or Unicode escapes or vice versa\&.
-.SH SYNOPSIS
-.sp
-.nf
-
-\fBnative2ascii\fR [ \fIinputfile\fR ] [ \fIoutputfile\fR ]
-.fi
-.sp
-.TP
-\fIinputfile\fR
-The encoded file to be converted to ASCII\&.
-.TP
-\fIoutputfile\fR
-The converted ASCII file\&.
-.SH DESCRIPTION
-The \f3native2ascii\fR command converts encoded files supported by the Java Runtime Environment (JRE) to files encoded in ASCII, using Unicode escapes (\f3\eu\fR\fIxxxx\fR) notation for all characters that are not part of the ASCII character set\&. This process is required for properties files that contain characters not in ISO-8859-1 character sets\&. The tool can also perform the reverse conversion\&.
-.PP
-If the \f3outputfile\fR value is omitted, then standard output is used for output\&. If, in addition, the \f3inputfile\fR value is omitted, then standard input is used for input\&.
-.SH OPTIONS
-.TP
--reverse
-.br
-Perform the reverse operation: Converts a file encoded in ISO-8859-1 with Unicode escapes to a file in any character encoding supported by the JRE\&.
-.TP
--encoding \fIencoding_name\fR
-.br
-Specifies the name of the character encoding to be used by the conversion procedure\&. If this option is not present, then the default character encoding (as determined by the \f3java\&.nio\&.charset\&.Charset\&.defaultCharset\fR method) is used\&. The \f3encoding_name\fR string must be the name of a character encoding that is supported by the JRE\&. See Supported Encodings at http://docs\&.oracle\&.com/javase/8/docs/technotes/guides/intl/encoding\&.doc\&.html
-.TP
--J\fIoption\fR
-.br
-Passes \f3option\fR to the Java Virtual Machine (JVM), where option is one of the options described on the reference page for the Java application launcher\&. For example, \f3-J-Xms48m\fR sets the startup memory to 48 MB\&. See java(1)\&.
-.RE
-.br
-'pl 8.5i
-'bp
diff --git a/jdk/src/java.base/share/classes/java/util/Properties.java b/jdk/src/java.base/share/classes/java/util/Properties.java
index a075da67d1c..0d983e52f96 100644
--- a/jdk/src/java.base/share/classes/java/util/Properties.java
+++ b/jdk/src/java.base/share/classes/java/util/Properties.java
@@ -73,8 +73,7 @@ import jdk.internal.util.xml.PropertiesDefaultHandler;
* Unicode escapes as defined in section 3.3 of
* The Java™ Language Specification;
* only a single 'u' character is allowed in an escape
- * sequence. The native2ascii tool can be used to convert property files to and
- * from other character encodings.
+ * sequence.
*
*
The {@link #loadFromXML(InputStream)} and {@link
* #storeToXML(OutputStream, String, String)} methods load and store properties
@@ -108,9 +107,6 @@ import jdk.internal.util.xml.PropertiesDefaultHandler;
*
@@ -2282,10 +2243,6 @@ public class PolicyFile extends java.security.Policy {
// Stores grant entries in the policy
final List policyEntries;
- // Stores grant entries gotten from identity database
- // Use separate lists to avoid sync on policyEntries
- final List identityPolicyEntries;
-
// Maps aliases to certs
final Map aliasMapping;
@@ -2295,8 +2252,6 @@ public class PolicyFile extends java.security.Policy {
PolicyInfo(int numCaches) {
policyEntries = new ArrayList<>();
- identityPolicyEntries =
- Collections.synchronizedList(new ArrayList(2));
aliasMapping = Collections.synchronizedMap(new HashMap<>(11));
pdMapping = new ProtectionDomainCache[numCaches];
diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security
index be33f832a36..0f1fe1f5e27 100644
--- a/jdk/src/java.base/share/conf/security/java.security
+++ b/jdk/src/java.base/share/conf/security/java.security
@@ -179,7 +179,8 @@ policy.allowSystemProperty=true
# whether or not we look into the IdentityScope for trusted Identities
# when encountering a 1.1 signed JAR file. If the identity is found
-# and is trusted, we grant it AllPermission.
+# and is trusted, we grant it AllPermission. Note: the default policy
+# provider (sun.security.provider.PolicyFile) does not support this property.
policy.ignoreIdentityScope=false
#
From 6b7bbd4884767e23093635b3c165737e7a89ec91 Mon Sep 17 00:00:00 2001
From: Artem Smotrakov
Date: Mon, 25 May 2015 11:47:41 +0300
Subject: [PATCH 14/36] 8050374: More Signature tests
Reviewed-by: valeriep
---
jdk/test/java/security/Signature/Offsets.java | 251 ++++++++++++++++++
.../java/security/SignedObject/Chain.java | 216 +++++++++++++++
jdk/test/java/security/SignedObject/Copy.java | 123 +++++++++
.../sun/security/ec/SignatureOffsets.java | 52 ++++
.../sun/security/ec/SignedObjectChain.java | 57 ++++
.../sun/security/mscapi/SignatureOffsets.java | 53 ++++
.../security/mscapi/SignedObjectChain.java | 58 ++++
.../sun/security/rsa/SignatureOffsets.java | 53 ++++
.../sun/security/rsa/SignedObjectChain.java | 59 ++++
.../security/ssl/rsa/SignatureOffsets.java | 50 ++++
.../security/ssl/rsa/SignedObjectChain.java | 56 ++++
11 files changed, 1028 insertions(+)
create mode 100644 jdk/test/java/security/Signature/Offsets.java
create mode 100644 jdk/test/java/security/SignedObject/Chain.java
create mode 100644 jdk/test/java/security/SignedObject/Copy.java
create mode 100644 jdk/test/sun/security/ec/SignatureOffsets.java
create mode 100644 jdk/test/sun/security/ec/SignedObjectChain.java
create mode 100644 jdk/test/sun/security/mscapi/SignatureOffsets.java
create mode 100644 jdk/test/sun/security/mscapi/SignedObjectChain.java
create mode 100644 jdk/test/sun/security/rsa/SignatureOffsets.java
create mode 100644 jdk/test/sun/security/rsa/SignedObjectChain.java
create mode 100644 jdk/test/sun/security/ssl/rsa/SignatureOffsets.java
create mode 100644 jdk/test/sun/security/ssl/rsa/SignedObjectChain.java
diff --git a/jdk/test/java/security/Signature/Offsets.java b/jdk/test/java/security/Signature/Offsets.java
new file mode 100644
index 00000000000..9e71690ea4f
--- /dev/null
+++ b/jdk/test/java/security/Signature/Offsets.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import jdk.testlibrary.RandomFactory;
+
+/*
+ * @test
+ * @bug 8050374
+ * @key randomness
+ * @summary This test validates signature verification
+ * Signature.verify(byte[], int, int). The test uses RandomFactory to
+ * get random set of clear text data to sign. After the signature
+ * generation, the test tries to verify signature with the above API
+ * and passing in different signature offset (0, 33, 66, 99).
+ * @library /lib/testlibrary
+ * @run main Offsets SUN NONEwithDSA
+ * @run main Offsets SUN SHA1withDSA
+ * @run main Offsets SUN SHA224withDSA
+ * @run main Offsets SUN SHA256withDSA
+ */
+public class Offsets {
+
+ private final int size;
+ private final byte[] cleartext;
+ private final PublicKey pubkey;
+ private final Signature signature;
+ private final byte[] signed;
+
+ private Offsets(Signature signature, PublicKey pubkey, PrivateKey privkey,
+ int size, byte[] cleartext) throws InvalidKeyException,
+ SignatureException {
+ this.pubkey = pubkey;
+ this.signature = signature;
+ this.size = size;
+ this.cleartext = cleartext;
+
+ signature.initSign(privkey);
+ signature.update(cleartext, 0, size);
+ signed = signature.sign();
+ }
+
+ int getDataSize() {
+ return size;
+ }
+
+ int getSignatureLength() {
+ return signed.length;
+ }
+
+ byte[] shiftSignData(int offset) {
+ byte[] testSignData = new byte[offset + signed.length];
+ System.arraycopy(signed, 0, testSignData, offset,
+ signed.length);
+ return testSignData;
+ }
+
+ boolean verifySignature(byte[] sigData, int sigOffset, int sigLength,
+ int updateOffset, int updateLength)
+ throws InvalidKeyException, SignatureException {
+ signature.initVerify(pubkey);
+ signature.update(cleartext, updateOffset, updateLength);
+ return signature.verify(sigData, sigOffset, sigLength);
+ }
+
+ static Offsets init(String provider, String algorithm)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ InvalidKeyException, SignatureException {
+ // fill the cleartext data with random bytes
+ byte[] cleartext = new byte[100];
+ RandomFactory.getRandom().nextBytes(cleartext);
+
+ // NONEwith requires input to be of 20 bytes
+ int size = algorithm.contains("NONEwith") ? 20 : 100;
+
+ // create signature instance
+ Signature signature = Signature.getInstance(algorithm, provider);
+
+ String keyAlgo;
+ if (algorithm.contains("RSA")) {
+ keyAlgo = "RSA";
+ } else if (algorithm.contains("ECDSA")) {
+ keyAlgo = "EC";
+ } else if (algorithm.contains("DSA")) {
+ keyAlgo = "DSA";
+ } else {
+ throw new RuntimeException("Test doesn't support this signature "
+ + "algorithm: " + algorithm);
+ }
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgo, provider);
+ KeyPair kp = kpg.generateKeyPair();
+ PublicKey pubkey = kp.getPublic();
+ PrivateKey privkey = kp.getPrivate();
+
+ return new Offsets(signature, pubkey, privkey, size, cleartext);
+ }
+
+ public static void main(String[] args) throws NoSuchAlgorithmException,
+ InvalidKeyException, SignatureException {
+ if (args.length < 2) {
+ throw new RuntimeException("Wrong parameters");
+ }
+
+ boolean result = true;
+ try {
+ Offsets test = init(args[0], args[1]);
+
+ // We are trying 3 different offsets, data size has nothing to do
+ // with signature length
+ for (int chunk = 3; chunk > 0; chunk--) {
+ int signOffset = test.getDataSize() / chunk;
+
+ System.out.println("Running test with offset " + signOffset);
+ byte[] signData = test.shiftSignData(signOffset);
+
+ boolean success = test.verifySignature(signData, signOffset,
+ test.getSignatureLength(), 0, test.getDataSize());
+
+ if (success) {
+ System.out.println("Successfully verified with offset "
+ + signOffset);
+ } else {
+ System.out.println("Verification failed with offset "
+ + signOffset);
+ result = false;
+ }
+ }
+
+ // save signature to offset 0
+ byte[] signData = test.shiftSignData(0);
+
+ // Negative tests
+
+ // Test signature offset 0.
+ // Wrong test data will be passed to update,
+ // so signature verification should fail.
+ for (int chunk = 3; chunk > 0; chunk--) {
+ int dataOffset = (test.getDataSize() - 1) / chunk;
+ boolean success;
+ try {
+ success = test.verifySignature(signData, 0,
+ test.getSignatureLength(), dataOffset,
+ (test.getDataSize() - dataOffset));
+ } catch (SignatureException e) {
+ // Since we are trying different data size, it can throw
+ // SignatureException
+ success = false;
+ }
+
+ if (!success) {
+ System.out.println("Signature verification failed "
+ + "as expected, with data offset " + dataOffset
+ + " and length "
+ + (test.getDataSize() - dataOffset));
+ } else {
+ System.out.println("Signature verification "
+ + "should not succeed, with data offset "
+ + dataOffset + " and length "
+ + (test.getDataSize() - dataOffset));
+ result = false;
+ }
+ }
+
+ // Tests with manipulating offset and length
+ result &= Offsets.checkFailure(test, signData, -1,
+ test.getSignatureLength());
+
+ result &= Offsets.checkFailure(test, signData, 0,
+ test.getSignatureLength() - 1);
+
+ result &= Offsets.checkFailure(test, signData,
+ test.getSignatureLength() + 1, test.getSignatureLength());
+
+ result &= Offsets.checkFailure(test, signData, 0,
+ test.getSignatureLength() + 1);
+
+ result &= Offsets.checkFailure(test, signData, 0, 0);
+
+ result &= Offsets.checkFailure(test, signData, 0, -1);
+
+ result &= Offsets.checkFailure(test, signData,
+ 2147483646, test.getSignatureLength());
+
+ result &= Offsets.checkFailure(test, null, 0,
+ test.getSignatureLength());
+ } catch (NoSuchProviderException nspe) {
+ System.out.println("No such provider: " + nspe);
+ }
+
+ if (!result) {
+ throw new RuntimeException("Some test cases failed");
+ }
+ }
+
+ static boolean checkFailure(Offsets test, byte[] signData, int offset,
+ int length) {
+ boolean success;
+ try {
+ success = test.verifySignature(signData, offset, length, 0,
+ test.getDataSize());
+ } catch (IllegalArgumentException | SignatureException e) {
+ System.out.println("Expected exception: " + e);
+ success = false;
+ } catch (InvalidKeyException e) {
+ System.out.println("Unexpected exception: " + e);
+ return false;
+ }
+
+ if (!success) {
+ System.out.println("Signature verification failed as expected, "
+ + "with signature offset " + offset + " and length "
+ + length);
+ return true;
+ } else {
+ System.out.println("Signature verification should not succeed, "
+ + "with signature offset " + offset + " and length "
+ + length);
+ return false;
+ }
+ }
+
+}
diff --git a/jdk/test/java/security/SignedObject/Chain.java b/jdk/test/java/security/SignedObject/Chain.java
new file mode 100644
index 00000000000..e6c423cbb02
--- /dev/null
+++ b/jdk/test/java/security/SignedObject/Chain.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.Signature;
+import java.security.SignedObject;
+import java.security.KeyPairGenerator;
+import java.security.KeyPair;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Arrays;
+
+/*
+ * @test
+ * @bug 8050374
+ * @summary Verify a chain of signed objects
+ */
+public class Chain {
+
+ static enum KeyAlg {
+ RSA("RSA"),
+ DSA("DSA"),
+ EC("EC");
+
+ final String name;
+
+ KeyAlg(String alg) {
+ this.name = alg;
+ }
+ }
+
+ static enum Provider {
+ Default("default"),
+ SunRsaSign("SunRsaSign"),
+ Sun("SUN"),
+ SunEC("SunEC"),
+ SunJSSE("SunJSSE"),
+ SunMSCAPI("SunMSCAPI");
+
+ final String name;
+
+ Provider(String name) {
+ this.name = name;
+ }
+ }
+
+ static enum SigAlg {
+ MD2withRSA("MD2withRSA"),
+ MD5withRSA("md5withRSA"),
+
+ SHA1withDSA("SHA1withDSA"),
+ SHA224withDSA("SHA224withDSA"),
+ SHA256withDSA("SHA256withDSA"),
+
+ SHA1withRSA("Sha1withrSA"),
+ SHA224withRSA("SHA224withRSA"),
+ SHA256withRSA("SHA256withRSA"),
+ SHA384withRSA("SHA384withRSA"),
+ SHA512withRSA("SHA512withRSA"),
+
+ SHA1withECDSA("SHA1withECDSA"),
+ SHA256withECDSA("SHA256withECDSA"),
+ SHA224withECDSA("SHA224withECDSA"),
+ SHA384withECDSA("SHA384withECDSA"),
+ SHA512withECDSA("SHA512withECDSA"),
+
+ MD5andSHA1withRSA("MD5andSHA1withRSA");
+
+ final String name;
+
+ SigAlg(String name) {
+ this.name = name;
+ }
+ }
+
+ static class Test {
+ final Provider provider;
+ final KeyAlg keyAlg;
+ final SigAlg sigAlg;
+
+ Test(SigAlg sigAlg, KeyAlg keyAlg, Provider privider) {
+ this.provider = privider;
+ this.keyAlg = keyAlg;
+ this.sigAlg = sigAlg;
+ }
+ }
+
+ private static final Test[] tests = {
+ new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Default),
+ new Test(SigAlg.MD2withRSA, KeyAlg.RSA, Provider.Default),
+ new Test(SigAlg.MD5withRSA, KeyAlg.RSA, Provider.Default),
+ new Test(SigAlg.SHA1withRSA, KeyAlg.RSA, Provider.Default),
+ new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Sun),
+ new Test(SigAlg.SHA224withDSA, KeyAlg.DSA, Provider.Sun),
+ new Test(SigAlg.SHA256withDSA, KeyAlg.DSA, Provider.Sun),
+ };
+
+ private static final String str = "to-be-signed";
+ private static final int N = 3;
+
+ public static void main(String argv[]) {
+ boolean result = Arrays.stream(tests).allMatch((test) -> runTest(test));
+ if(result) {
+ System.out.println("All tests passed");
+ } else {
+ throw new RuntimeException("Some tests failed");
+ }
+ }
+
+ static boolean runTest(Test test) {
+ System.out.format("Test: provider = %s, signature algorithm = %s, "
+ + "key algorithm = %s\n",
+ test.provider, test.sigAlg, test.keyAlg);
+ try {
+ // Generate all private/public key pairs
+ PrivateKey[] privKeys = new PrivateKey[N];
+ PublicKey[] pubKeys = new PublicKey[N];
+ PublicKey[] anotherPubKeys = new PublicKey[N];
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance(
+ test.keyAlg.name);
+ for (int j=0; j < N; j++) {
+ KeyPair kp = kpg.genKeyPair();
+ KeyPair anotherKp = kpg.genKeyPair();
+ privKeys[j] = kp.getPrivate();
+ pubKeys[j] = kp.getPublic();
+ anotherPubKeys[j] = anotherKp.getPublic();
+
+ if (Arrays.equals(pubKeys[j].getEncoded(),
+ anotherPubKeys[j].getEncoded())) {
+ System.out.println("Failed: it should not get "
+ + "the same pair of public key");
+ return false;
+ }
+ }
+
+ Signature signature;
+ if (test.provider != Provider.Default) {
+ signature = Signature.getInstance(test.sigAlg.name,
+ test.provider.name);
+ } else {
+ signature = Signature.getInstance(test.sigAlg.name);
+ }
+
+ // Create a chain of signed objects
+ SignedObject[] objects = new SignedObject[N];
+ objects[0] = new SignedObject(str, privKeys[0], signature);
+ for (int j = 1; j < N; j++) {
+ objects[j] = new SignedObject(objects[j - 1], privKeys[j],
+ signature);
+ }
+
+ // Verify the chain
+ int n = objects.length - 1;
+ SignedObject object = objects[n];
+ do {
+ if (!object.verify(pubKeys[n], signature)) {
+ System.out.println("Failed: verification failed, n = " + n);
+ return false;
+ }
+
+ if (object.verify(anotherPubKeys[n], signature)) {
+ System.out.println("Failed: verification should not "
+ + "succeed with wrong public key, n = " + n);
+ return false;
+ }
+
+ object = (SignedObject) object.getObject();
+ n--;
+ } while (n > 0);
+
+ System.out.println("signed data: " + object.getObject());
+ if (!str.equals(object.getObject())) {
+ System.out.println("Failed: signed data is not equal to "
+ + "original one");
+ return false;
+ }
+
+ System.out.println("Test passed");
+ return true;
+ } catch (NoSuchProviderException nspe) {
+ if (test.provider == Provider.SunMSCAPI
+ && !System.getProperty("os.name").startsWith("Windows")) {
+ System.out.println("SunMSCAPI is available only on Windows: "
+ + nspe);
+ return true;
+ }
+ System.out.println("Unexpected exception: " + nspe);
+ return false;
+ } catch (Exception e) {
+ System.out.println("Unexpected exception: " + e);
+ e.printStackTrace(System.out);
+ return false;
+ }
+ }
+}
+
diff --git a/jdk/test/java/security/SignedObject/Copy.java b/jdk/test/java/security/SignedObject/Copy.java
new file mode 100644
index 00000000000..22406ea2a84
--- /dev/null
+++ b/jdk/test/java/security/SignedObject/Copy.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.Serializable;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Signature;
+import java.security.SignedObject;
+
+/*
+ * @test
+ * @bug 8050374
+ * @summary Checks if a signed object is a copy of an original object
+ */
+public class Copy {
+
+ private static final String DSA = "DSA";
+ private static final int KEY_SIZE = 512;
+ private static final int MAGIC = 123;
+
+ public static void main(String args[]) throws Exception {
+ KeyPairGenerator kg = KeyPairGenerator.getInstance(DSA);
+ kg.initialize(KEY_SIZE);
+ KeyPair kp = kg.genKeyPair();
+
+ Signature signature = Signature.getInstance(DSA);
+ Test original = new Test();
+ SignedObject so = new SignedObject(original, kp.getPrivate(),
+ signature);
+ System.out.println("Signature algorithm: " + so.getAlgorithm());
+
+ signature = Signature.getInstance(DSA, "SUN");
+ if (!so.verify(kp.getPublic(), signature)) {
+ throw new RuntimeException("Verification failed");
+ }
+
+ kg = KeyPairGenerator.getInstance(DSA);
+ kg.initialize(KEY_SIZE);
+ kp = kg.genKeyPair();
+
+ if (so.verify(kp.getPublic(), signature)) {
+ throw new RuntimeException("Unexpected success");
+ }
+
+ Object copy = so.getObject();
+ if (!original.equals(copy)) {
+ throw new RuntimeException("Signed object is not equal "
+ + "to original one: " + copy);
+ }
+
+ /*
+ * The signed object is a copy of an original one.
+ * Once the copy is made, further manipulation
+ * of the original object shouldn't has any effect on the copy.
+ */
+ original.set(MAGIC - 1);
+ copy = so.getObject();
+ if (original.equals(copy)) {
+ throw new RuntimeException("Signed object is not a copy "
+ + "of original one: " + copy);
+ }
+
+ System.out.println("Test passed");
+ }
+
+ private static class Test implements Serializable {
+ private int number = MAGIC;
+
+ public int get() {
+ return number;
+ }
+
+ public void set(int magic) {
+ this.number = magic;
+ }
+
+ @Override
+ public int hashCode() {
+ return number;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ if (!(obj instanceof Test)) {
+ return false;
+ }
+
+ Test other = (Test) obj;
+ return number == other.number;
+ }
+
+ @Override
+ public String toString() {
+ return "" + number;
+ }
+ }
+}
+
+
diff --git a/jdk/test/sun/security/ec/SignatureOffsets.java b/jdk/test/sun/security/ec/SignatureOffsets.java
new file mode 100644
index 00000000000..948923e78ba
--- /dev/null
+++ b/jdk/test/sun/security/ec/SignatureOffsets.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+/*
+ * @test
+ * @bug 8050374
+ * @key randomness
+ * @summary This test validates signature verification
+ * Signature.verify(byte[], int, int). The test uses RandomFactory to
+ * get random set of clear text data to sign. After the signature
+ * generation, the test tries to verify signature with the above API
+ * and passing in different signature offset (0, 33, 66, 99).
+ * @library /lib/testlibrary
+ * @compile ../../../java/security/Signature/Offsets.java
+ * @run main SignatureOffsets SunEC NONEwithECDSA
+ * @run main SignatureOffsets SunEC SHA1withECDSA
+ * @run main SignatureOffsets SunEC SHA256withECDSA
+ * @run main SignatureOffsets SunEC SHA224withECDSA
+ * @run main SignatureOffsets SunEC SHA384withECDSA
+ * @run main SignatureOffsets SunEC SHA512withECDSA
+ */
+public class SignatureOffsets {
+
+ public static void main(String[] args) throws NoSuchAlgorithmException,
+ InvalidKeyException, SignatureException {
+ Offsets.main(args);
+ }
+}
\ No newline at end of file
diff --git a/jdk/test/sun/security/ec/SignedObjectChain.java b/jdk/test/sun/security/ec/SignedObjectChain.java
new file mode 100644
index 00000000000..6e93053a776
--- /dev/null
+++ b/jdk/test/sun/security/ec/SignedObjectChain.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8050374
+ * @compile ../../../java/security/SignedObject/Chain.java
+ * @summary Verify a chain of signed objects
+ */
+public class SignedObjectChain {
+
+ private static class Test extends Chain.Test {
+
+ public Test(Chain.SigAlg sigAlg) {
+ super(sigAlg, Chain.KeyAlg.EC, Chain.Provider.SunEC);
+ }
+ }
+
+ private static final Test[] tests = {
+ new Test(Chain.SigAlg.SHA1withECDSA),
+ new Test(Chain.SigAlg.SHA256withECDSA),
+ new Test(Chain.SigAlg.SHA224withECDSA),
+ new Test(Chain.SigAlg.SHA384withECDSA),
+ new Test(Chain.SigAlg.SHA512withECDSA),
+ };
+
+ public static void main(String argv[]) {
+ boolean resutl = java.util.Arrays.stream(tests).allMatch(
+ (test) -> Chain.runTest(test));
+
+ if(resutl) {
+ System.out.println("All tests passed");
+ } else {
+ throw new RuntimeException("Some tests failed");
+ }
+ }
+}
diff --git a/jdk/test/sun/security/mscapi/SignatureOffsets.java b/jdk/test/sun/security/mscapi/SignatureOffsets.java
new file mode 100644
index 00000000000..34f91fbf9be
--- /dev/null
+++ b/jdk/test/sun/security/mscapi/SignatureOffsets.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+/*
+ * @test
+ * @bug 8050374
+ * @key randomness
+ * @summary This test validates signature verification
+ * Signature.verify(byte[], int, int). The test uses RandomFactory to
+ * get random set of clear text data to sign. After the signature
+ * generation, the test tries to verify signature with the above API
+ * and passing in different signature offset (0, 33, 66, 99).
+ * @library /lib/testlibrary
+ * @compile ../../../java/security/Signature/Offsets.java
+ * @run main SignatureOffsets SunMSCAPI NONEwithRSA
+ * @run main SignatureOffsets SunMSCAPI MD2withRSA
+ * @run main SignatureOffsets SunMSCAPI MD5withRSA
+ * @run main SignatureOffsets SunMSCAPI SHA1withRSA
+ * @run main SignatureOffsets SunMSCAPI SHA256withRSA
+ * @run main SignatureOffsets SunMSCAPI SHA384withRSA
+ * @run main SignatureOffsets SunMSCAPI SHA512withRSA
+ */
+public class SignatureOffsets {
+
+ public static void main(String[] args) throws NoSuchAlgorithmException,
+ InvalidKeyException, SignatureException {
+ Offsets.main(args);
+ }
+}
\ No newline at end of file
diff --git a/jdk/test/sun/security/mscapi/SignedObjectChain.java b/jdk/test/sun/security/mscapi/SignedObjectChain.java
new file mode 100644
index 00000000000..9790daa919b
--- /dev/null
+++ b/jdk/test/sun/security/mscapi/SignedObjectChain.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8050374
+ * @compile ../../../java/security/SignedObject/Chain.java
+ * @summary Verify a chain of signed objects
+ */
+public class SignedObjectChain {
+
+ private static class Test extends Chain.Test {
+
+ public Test(Chain.SigAlg sigAlg) {
+ super(sigAlg, Chain.KeyAlg.RSA, Chain.Provider.SunMSCAPI);
+ }
+ }
+
+ private static final Test[] tests = {
+ new Test(Chain.SigAlg.MD2withRSA),
+ new Test(Chain.SigAlg.MD5withRSA),
+ new Test(Chain.SigAlg.SHA1withRSA),
+ new Test(Chain.SigAlg.SHA256withRSA),
+ new Test(Chain.SigAlg.SHA384withRSA),
+ new Test(Chain.SigAlg.SHA512withRSA),
+ };
+
+ public static void main(String argv[]) {
+ boolean resutl = java.util.Arrays.stream(tests).allMatch(
+ (test) -> Chain.runTest(test));
+
+ if(resutl) {
+ System.out.println("All tests passed");
+ } else {
+ throw new RuntimeException("Some tests failed");
+ }
+ }
+}
diff --git a/jdk/test/sun/security/rsa/SignatureOffsets.java b/jdk/test/sun/security/rsa/SignatureOffsets.java
new file mode 100644
index 00000000000..b813b26d4a5
--- /dev/null
+++ b/jdk/test/sun/security/rsa/SignatureOffsets.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+/*
+ * @test
+ * @bug 8050374
+ * @key randomness
+ * @summary This test validates signature verification
+ * Signature.verify(byte[], int, int). The test uses RandomFactory to
+ * get random set of clear text data to sign. After the signature
+ * generation, the test tries to verify signature with the above API
+ * and passing in different signature offset (0, 33, 66, 99).
+ * @library /lib/testlibrary
+ * @compile ../../../java/security/Signature/Offsets.java
+ * @run main SignatureOffsets SunRsaSign MD2withRSA
+ * @run main SignatureOffsets SunRsaSign MD5withRSA
+ * @run main SignatureOffsets SunRsaSign SHA1withRSA
+ * @run main SignatureOffsets SunRsaSign SHA224withRSA
+ * @run main SignatureOffsets SunRsaSign SHA256withRSA
+ * @run main SignatureOffsets SunRsaSign SHA384withRSA
+ * @run main SignatureOffsets SunRsaSign SHA512withRSA
+ */
+public class SignatureOffsets {
+
+ public static void main(String[] args) throws NoSuchAlgorithmException,
+ InvalidKeyException, SignatureException {
+ Offsets.main(args);
+ }
+}
\ No newline at end of file
diff --git a/jdk/test/sun/security/rsa/SignedObjectChain.java b/jdk/test/sun/security/rsa/SignedObjectChain.java
new file mode 100644
index 00000000000..7bda7cd4df6
--- /dev/null
+++ b/jdk/test/sun/security/rsa/SignedObjectChain.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8050374
+ * @compile ../../../java/security/SignedObject/Chain.java
+ * @summary Verify a chain of signed objects
+ */
+public class SignedObjectChain {
+
+ private static class Test extends Chain.Test {
+
+ public Test(Chain.SigAlg sigAlg) {
+ super(sigAlg, Chain.KeyAlg.RSA, Chain.Provider.SunRsaSign);
+ }
+ }
+
+ private static final Test[] tests = {
+ new Test(Chain.SigAlg.MD2withRSA),
+ new Test(Chain.SigAlg.MD5withRSA),
+ new Test(Chain.SigAlg.SHA1withRSA),
+ new Test(Chain.SigAlg.SHA224withRSA),
+ new Test(Chain.SigAlg.SHA256withRSA),
+ new Test(Chain.SigAlg.SHA384withRSA),
+ new Test(Chain.SigAlg.SHA512withRSA),
+ };
+
+ public static void main(String argv[]) {
+ boolean resutl = java.util.Arrays.stream(tests).allMatch(
+ (test) -> Chain.runTest(test));
+
+ if(resutl) {
+ System.out.println("All tests passed");
+ } else {
+ throw new RuntimeException("Some tests failed");
+ }
+ }
+}
diff --git a/jdk/test/sun/security/ssl/rsa/SignatureOffsets.java b/jdk/test/sun/security/ssl/rsa/SignatureOffsets.java
new file mode 100644
index 00000000000..618dde714d4
--- /dev/null
+++ b/jdk/test/sun/security/ssl/rsa/SignatureOffsets.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+/*
+ * @test
+ * @bug 8050374
+ * @key randomness
+ * @summary This test validates signature verification
+ * Signature.verify(byte[], int, int). The test uses RandomFactory to
+ * get random set of clear text data to sign. After the signature
+ * generation, the test tries to verify signature with the above API
+ * and passing in different signature offset (0, 33, 66, 99).
+ * @library /lib/testlibrary
+ * @compile ../../../../java/security/Signature/Offsets.java
+ * @run main SignatureOffsets SunJSSE MD2withRSA
+ * @run main SignatureOffsets SunJSSE MD5withRSA
+ * @run main SignatureOffsets SunJSSE SHA1withRSA
+ * @run main SignatureOffsets SunJSSE MD5andSHA1withRSA
+ */
+public class SignatureOffsets {
+
+ public static void main(String[] args) throws NoSuchAlgorithmException,
+ InvalidKeyException, SignatureException {
+ Offsets.main(args);
+ }
+}
\ No newline at end of file
diff --git a/jdk/test/sun/security/ssl/rsa/SignedObjectChain.java b/jdk/test/sun/security/ssl/rsa/SignedObjectChain.java
new file mode 100644
index 00000000000..ba4b00c56d8
--- /dev/null
+++ b/jdk/test/sun/security/ssl/rsa/SignedObjectChain.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8050374
+ * @compile ../../../../java/security/SignedObject/Chain.java
+ * @summary Verify a chain of signed objects
+ */
+public class SignedObjectChain {
+
+ private static class Test extends Chain.Test {
+
+ public Test(Chain.SigAlg sigAlg) {
+ super(sigAlg, Chain.KeyAlg.RSA, Chain.Provider.SunJSSE);
+ }
+ }
+
+ private static final Test[] tests = {
+ new Test(Chain.SigAlg.MD2withRSA),
+ new Test(Chain.SigAlg.MD5withRSA),
+ new Test(Chain.SigAlg.SHA1withRSA),
+ new Test(Chain.SigAlg.MD5andSHA1withRSA),
+ };
+
+ public static void main(String argv[]) {
+ boolean resutl = java.util.Arrays.stream(tests).allMatch(
+ (test) -> Chain.runTest(test));
+
+ if(resutl) {
+ System.out.println("All tests passed");
+ } else {
+ throw new RuntimeException("Some tests failed");
+ }
+ }
+}
From 27aac42dc557f13a83642e2dfd9281e4335ecb03 Mon Sep 17 00:00:00 2001
From: Katja Kantserova
Date: Mon, 25 May 2015 14:08:21 +0200
Subject: [PATCH 15/36] 8080833: JDK-8076524 has failed to remove binary files
Reviewed-by: sla
---
jdk/test/sun/tools/jhat/hprof.bin | Bin 282310 -> 0 bytes
jdk/test/sun/tools/jhat/jmap.bin | Bin 1732977 -> 0 bytes
jdk/test/sun/tools/jhat/minimal.bin | Bin 66153 -> 0 bytes
3 files changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 jdk/test/sun/tools/jhat/hprof.bin
delete mode 100644 jdk/test/sun/tools/jhat/jmap.bin
delete mode 100644 jdk/test/sun/tools/jhat/minimal.bin
diff --git a/jdk/test/sun/tools/jhat/hprof.bin b/jdk/test/sun/tools/jhat/hprof.bin
deleted file mode 100644
index a8f6f7d3f863c8794d8569221b1619c3e7e4e75c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 282310
zcmb4M2Y6h?)z!)p223%<^kP5;o8m?@9a&mgYpbDRW13j6*4En6uGn3<5PFg5)%4zb
z?j^~~zgEv?OU
ziH7*-N#iGupHznbD$2@YtDQKys(ZDv^5nrtSOHJ0tRiOrIr?(^bAEDRa(p(E8=vY<
z<_qcK_?lc-I^UWu^!F6YZNZUcvB85|4EF3d2@-~J_(!>6=r3k^0PX2Xr;3?ewoui!
zB%A8a=dzhY(_M|pK20?dROMwAhN@hs)&bS9LVtFAZ>EqM-7)Zis72V!eQmQBtn
z(DX+FxS|EFC_uK?N(R`2DvfVjQYfZ-t0rrK#{;*L#jPZ`4S`$P;Iim!9jy&DJ;_3$
zA(uq2)8JD9UfF_I7VvrikMOmv$@TUn^Jo~29QYZ?5f(W@kZS|EijSO{DYm5pmAnb4
zRV->1L2-nv>Q~aJT9YgkGnTR={I;E2v@g+s|z7J=t$kW>N4q`t|5lZ
zz?+~LX(>hu1zU6tUnh*i@pYMOvIiqS&@N8{yoLp@A>b_mUeka>J}8r&7tiN8dP8;|
zYzNPpmS;`j*#JCi`AW2>^S#gkJ)>%pw!uPR*Rt5P1iJ;WYik>na2|?e;O`(=+mfs;
zBzuBnlu^LALghGma;XJ{@zrzSk1$^M=}-5kyOej#S2e-oD*nN1!9U9Kj}rbd;9tkD
zAgzospN4Bnr446Q1LSC$6+p9&rCCR4HU-VPK22+XwwUQnx6oXLLa0Ok0)lld!MZ{)
z2?Xmcqn@p4ILmx8TckQ>7SK9f1NA39T;ElWy)W_VpLriWqghT8~YD-oTgiNRff-^k)O53VMqB!L^Cy+C;eMDK_=F%uLaS
z0hTW53?Bi-rj}w;p`be*?NbE$aHRXL0fy0*VYD#p4~ESQLwJ-0re`-Yj5q7(>q^4z
zRo>KHGB3O~sDkj#tnkf5I4!WbuRc2`26Q@Kn=B?9&>-1>tGON&n_G&_g@UeT3qw&z
zV_}ggE*am(|C1hK7Ca3kTUe4Ugk*h?RQX0wt1jI{pVpp;ZE97av1cXI5Da$$l)-
zV43*hqEaB}GS3Fj7|Sz8cy<8Kmc9zg+rf9*6;pk((2bQ}75~QJ6P9T0t^@0qmUT;E
z-3hE){eM}5UH1X-Ze@A565c7`9b1yu^UXn@)s)N5O=j|R(OTmx!93P7j}_+4!931q
zR!vbA@9irt2`w_V2FEzdF-|x*NVhf|W+j!#rnsyrX6E#Gy#oC#J1=b}L#@wN;M&@9
zZ7p0IgKHZ-l?A4A1s`||@NF!78-a6xZtJ>-w~}tl%)?|JU7!pu0mHVIVOwF~I%_+>
zGTyRK%e@Pz?JR0LL9GSUcqiABs6c~@0UB>X;|0WFFu@n4IEr_E;IsyR1i|)}V0$4L1r2r(4Y=sZ^`wJ?|2Kf`U|~B5j7$F=
zeYpv^z$7}W7WWQtJ6hb1g4-6joeVDQyh{v2#Wr|3*mkmPI|kmao^&tPL#i?Z
zAAw*OOR$R&aBA6g83aN79|py)mSR_-7z2vkT%VqfZGED-HrV0beTr5v@&EE%h4~yMHupGsE
z8Y~7;d~sif*qS7!B?TQ^0O+0;x~D+50(36}HT{Y6OpzVYbG`9we=j;_sQK0g(O#Bl
zFCn5A-`gjOc=1sDVmvtZwj6s4$0%@A)BI))TNvNiHfi#XlXV@Y16FNe)dJfFu&Jd*
zx26}S5s@jm$sL>kvZrDCT4SL#0%ZrR_4R1T
zWEZ5nWCoAS-dRx8T8dhspc9W93Nw$@_2iO)j{gNfaSMtIh+U`7mn*xZPzYk+U0~}h
zwob70ztendq6;GpD=MqCuJSQ}PqXl80_R$+-q$yo&E|?`Sv|hm{a;P8B1q~jNxhJa
z0ZC#xB*DS^ThJsdO+sim>ZThSjDqMkVOL}S}hn(M&qaZ1@sT4A38-`GtEVfCo
zTpu+XYwY`Q-0<6WtS_H-r$36ze=E-EYpUep&
zvbY(X5AZ$~ypMo6QMLLqJ?~hBFj6{^Eu^!Bj2Evg70UVve65zRRrom0+7w@RE*}_Y
z-vHERL2Uw}i)%L^xAADnXBMIs^U?_Sgm#mItAV54ac$R?K`}TF<=C*itVFsb;(9Aq|
zEU^1p?7o8Kj%l{hTL&jpkQ^-;nylu4XSU^;Ej;u#`xzeN9YdopT9NHRvY#c{Pe>T8
z-QOw0xj8b+4(zTfMu9!>ZddAO%;~HOLPkJk8=2@C~LPK+Ot6J3Kd?SZQTC%5SNmH^n
zEp}1*49);iw7)dH}&_<30Ps^OQ13ql@SyN?R+0q)04}lLtSCu4glv{
z;CumcQLw=EAk;XxH_HLDz+x5%hIQ>xb&WKAbx#H}PoU}d22qbC>JcIiz+MrKDX*!$
z^puwYxYvSv1x!O_{VIE>9?HA}e*!9NQCUH8UzrP|f-dG!;Bpq16C8VKAM0#_T3(c|
zA%|T=TPUnI@Co337Tzatn)wi^X)BIr0&O~Y9x#Vk%proIhspb@qJMj59#~9yA$eWd
zC&7@n40&M~1%`spFg1t0cQSCE^ci3U3o8hW?xCpKw+^RKc378+lJ5zQqU9(G2RmfH
z5pCRK$vJ#w0Q)VlUx3_SEGz*Gw$UE|U1*^T1xkZ0@~dlh$j#W_%Shx^F^SKwCE!R%}L~_q0qthdK~zpEdD6Lv%QY?@t!Zj;Z!oPDXs5#)(g!-q=z~+haExU*Mi}VQjx`KiJ#q=toDcbz1Asf$;*J&EuD~5i{IN|0fINs^xRv6yepv2TZ3na%|lH-MhZ8~5`+ybfO
z+Gwy0=mCo!5H!c~pze!}$$6R7P^ZqXfMU>63#HUMe+Kjf
z3q3)goZ3z-2@Q6qCjdUtf=?7M_X8)n@#jLvI4o47C^%8y4W5%M&q=~F3OpzKO4x%~
z-FW*0cCv+?EHG~VPVr$zrUDJz0?;WIbc%o|>(me^SXG9HPqna91vUn-(^yp-(u%Al
zB0HZN(41yzP7@kV&!-#dTnJ}+5H3z+OP;Ez+
z&af0`2nBomnaiXIT7whznU>^CA>lINEJI?3WH>_gA7IY1n6m`K);il@%f_JA;7^(J_YzW7JiPvDf?U>uDf&~N|FcoTnj!|
zz?6NS0i&Vyc}TdI4&DIxc@}=2z}ZUYYo~z4l#NWuMW?_4Ya>X`wiG@pf0ee3j{?sePI|CG}qI>U1)I^3XT)RMS6r_GVMvz&Bt+y7jpEiV7SOKTqF#f
z&M)>Q!;R$@g*ONE9~WET#R8=NyQBm#s5RHwmssc}0%cFW)Q2`Ei`~jXgZ02%YB84z
zh5>}j3`R|b(Z%w)z+PstmkE}0#pS*{8NuFWP)Qzm3Fyl$`f@?DS6!iO>;={lb&42x
zAHc7$@GAsPJ6-7u_vVS(bg<3?_X2vQgS%ouk3oxxij!u~!L}J?d&|ZT2K>
zxw*xNvn&VhYKyyCaJ*h~jUEJQmF9cAA!f?KW>8*ZDX$Sq&REx)YPhM|!^4FZ^SK`W
zNiPnB5P95qt>w8^cvz+Dd`rrm7}bD-M*w%7#a$;jcJb@Qj0ierOWeoV3Bc>16(+%8%7Wbgw
zxZr%q;LO0N#x1Sx-gGgOawAN)_79+V$WlBc6tvjGK81JWqfuM{J#0}A3yKQ=HjE0+
z=g$E5TZ{Xx;5bkH&N-LqIQef%mpJY}6WHHb?C%82!?j0znF(CrpNFUl?(HK)iUmJb
zGNtZ1Gcxjs<$6T8MuF@1hRcoRPkD)E%I?e(rr9pWU^c1XucST!gA;KgvC4|7!Kb*`pwhS-_z5Q!wj0vmu!~r
z!SP4S@kilcNcc%@-;Qh{IX4}+85Rzd{tHA;TB0X~h%2$DTm^zx_p5f+Ha`RKr!4#_
zfz#DL?ZII>1}&q9R|f+4v;{sbK+64-Yh5>amY91_0{l-F{wIMmV)cxXYr197YYsdQ
z$TJr5j6mqE|Lj8ow;^;rdjbBl1^-#Vtmj`0*!T}t)Lau)z=6*J{EG$tMSzt0tPjL+
z@MmNVejMOuE%;f0FZ!+ww?qMc&R03*u3?V%B1Z7qyd7@J@_n8wK=Pa=c}_^ifaLk*
zkQj&LXc%C5-qJiTG<0My7#cg-xs8Iuoe$g#7WabSb^-3M%MdRUU-S;WuG!U~{;Q?_
zt5A;w_1_G&UB+nyk3Iip5q}c|hwFk?8Tc!BUbZ|h3lFc4zp{LuV0Gy0Ua?HC2-6ra
zy&7QhJEZr{0UeUIWF=@`wKT5^4dW3Xq<^8+RfZR1UbEQO1j|*#>u&5%H@Dh6
zi)gWj0s6XyzAjMO^Y6Y`XHV~PPrA#$o99%x9Xx-xJbxD++VhR&^91e5HR~Ie=?!7x
z%JUzk=8h_JQHuwvqRLxLS{vibHU;i|!U|a1X%$wBUaVn9~0xV2Nf2
zm!XbeGZ6gC68uXD=-A#A0>oEfxU)|eo1N>bJe^=mR0DsR{%5Cht%bDiR
zuy-}n)omTnyk}|N6B7UNX&sl|LM7`l|tv_lJBG|@u$0KsRL
z;4>lMM(K0k0KHRQhdSNAx;~zOY1J2ocBem%jMg
zjJXJxG_R^SB>T#j7Wt({ekIll9SI6@a8n?^vdFIl$<6K82I(yic?Gd4SM-j6)m}?j
z26$WjYs>Pruy9`d#@AdfJ9{sM33PB2px;>NHv;95`qqb`M
z$h`fN`Pk#`xZ#&$l;F@kStjwa8xu3Eg95rI5klkHe-|nTL(x|9R~WhZ&0njBQS%mAwWK
zu!zMh4*$o)LEBh)6c?0;%K))*i!2u;nkP0)w6#kRC2sIgfQDJnFacq##LOoGyf(G3
zoVR#K0M4#=09s+86#_+fidFiWVxTwA#k~c*bRU_C9tFPA;wuG@AZu)eq4B{Q&oHLz*ad5c_d(0%11fY-F(
zH3iI`wiZR2j>fC2dAz#q-%4=`UkLPC7QL3Bu@Z}|ZA6#or~ZkdBWVN4+LmN(A=wQi
zqe`~i^4~Gm_1gmEqb&I-AxA(jwvO&t!7H&g4kro@yb6wWEXO*+K?AQ#4tJhsx>#*`
zPCpMK1Uz^;!0TG@x&r2STFqC&hc_*e8&Y*S@5Wv0l-A0K1>q#umG=VA+i~DUA*K
z{Fi~=#G*G5G;6-8Uvss0vaeB#@WJ%}-_*i46*y}?dPsOsKJHeLcp4D#zyme
z2HZTpSdmWUadlkPeDDxpH?!Ey1dAnKY;z;r_0DPixO=XFF#tEWz|93nm%9ap%E)(j
zDN2m~nPAw$GHf9Xbd}zF@!p;XQSzZy<~svlW${&l=g^409Iq8W5wI~9Hb!9h2vTgz
zz;Hyk7mji~KFebd7M8d(S=VxPpxV+>Z7Eb^K(&?MZM*|3bqOa*gZ*!8D@(JL&>-R+
z8*6B2OML4l&}{nwGS))I3WRkZ=Swy+gOQyEz{XkFIDygOZf#&@eEX-c1#h2kZ%MgY
zZwHdCEy>nGg6&*vn~-epgFsc@E9ecGIr-qGY_JHTZ7k6?LPY1ftxv?YQcE{JMUv~q
z%OOUkShPLVp1OEVeJB!{<&|KM$_cdsDpP^C6
z!G0jeTjY2_QtkxZ{msNzV$RwP=m{1*LC~BMCK|bHalS4SIA4(}4|W1P(Sj!mcvXNW
z&G9av2fYKQpGmg(Bq_c!icg+{J5Ir}uc7Q@TXwQ8yFIU%2FqeI9^2lQ-CoMB1l}ER
zwiPV;cNE>h7TrOLjzG~J3w-e{SojST-q9A`Q3_Mvo$%7dykJ?j-%hsdPEwY{JL67z
zGDM6ROKfLbcxNfR3JOo@GOt|*sd0K1n_^2(kz{kD68ce7aUu-aksrVQ+(}5lkNwEKHpGry3?3byeO!=#Sq4yaVvB
zi4Ztj)w}^7+3K3NTwN^?iiphy_-J<4B?g7w9*>!
zeI}=pV?l5>hS=y*E?lPx3&(D~W5LG}bNzYq=A?st)KXTCz1Pz1SyEu!1120y4$K*N
zz|LKSn^tu^IJ_vwKFshWgom@rbn=+#+`aXg=Az0WKL!%pjipmqSdg4mW&~}C!Io}|
z=#Mv}%CT2ix+?*Krv42?
zPM^_a;4&t1*{pYoPh-CXHV$kXiwl;bn~mx0RU)=RN%$9l*I9V8!12AkSc`_cn@Drf
zfaVipLlS-tLUbPX~A=%L|z6n^p(z$S%m@n`A?C
zdO$?HFogRaSr<}urq-@
zn8gLl&e%~J8yp1R0lgp4T?E9+hOPG<+yV!|OoR5_LJl8j!)K+u0`vht011b(bS?`E
zl0Lw^JMMsJMe{+q@hygdgHf~K8cq3umSvW(aAfaWN4%+u~FeCKv%Yy^|1Pj1M?iF$2VCFk6pldq}=V!F*P(>FFAGOLa-`PM0~`Ty#jb}
zBWCH9gotc*y_Am+eLbaWM%w#$na_f_P&sbAEWMgQVc8M?=o*?O#OfcZ`m`&7_GQps
zOD3V^o;p1=EtD%owIZlqu~ccHqSu*gsNk{m2a)(OM{T8*fqot6>j@AvJK;QE5&tHb
zx!LH~Vg$grIkNNymKQKZcl%%)Yb#+|Ty`kOC4;4R5FltSQZqi<7mXEemH)3&hFA@J
z?||orW2W{mU*BPY3DpOH$r2tWXS
z!bm9efra;Kc-Fw(jNv>_5ROPz`F$3i6*xy$E(j0%o*>IGusmd0a+PIUVk>PwMvTAa
zznD$rHnDGaY}Sg{6?x@oy+g*DW!eNb!358K=2ghuRI;}Z*=-!AMGuHev$4Ea*n})9
zZ2EeAWo0qSAu-F8#RmR_q}xR^o)f$!im|XpmIDz&mOZbL|5iwx>-oCiqYMmMm~#S2
zUlDA@vE%l~9>p)%?^PwD^e_}I5P+v2O5cDlNM9>JGA*RxBq5H3MgN1{aD;45HA~oX
z`nZ|8>J=10Ry<;~19gE)WQ1%JyF+Zlko$kEZHB?Bd@Ar%io)#Fi^uLiHIXRQs#?wp
zRt^^l))2A#g@zt&322r_GTf3Z@kz=nL|Go1yls^&hmtGc8Lm~Jxmi`M!owQqBE4K`b7z)U!gm77~vtq>BlR5nLabne6Gu9O{iauDy>Q
zJ5F^O%dgp~D_4U@;}Q0=g@LVl%)E3_16E^N2ym?y&$*m2QXn*h*m
z%h8R#?pWgSNPCXgE%BaeiB-@FtKwM=56)3N=@WrGekkct!vqaK5@2@GvZid9O
zmZ6Y8kJAO8?Y+Dm5y1ckMV!Sl5YYh<_0n6}E}yD)*$C~iF`iBE;LO|8g9CDD;5E*O
zkkM8M$Lvy!*(bn>z`2L#{B#bww(c#g+c|iS$0K8CN3GRoN-G(|qoEZJ!#!3`xaXQB
zTWEN0jtq9hb1gLo$njb>8#>%mZ_%q3U;B%YZizA^y@+K&Iva}OWYDwtib%Xws%qMx=tAWhCH&bULMpD@&Z;>-D?_4b+n@jkc@lf_H=t-wS)WbqR+FN_@
zLr?))cD~z6SYSWB;`dCThw?;{5sJsuvJAHqbb(1F3g9A%S3@qxZQj)&};|MQZ!r{40opRN>b7VOxO~4m1qgw5O!Q^U3MfBp?GXCVz^s^aN4~)
z-=EchotTE_XgpH8M?|lYNW7;j=N|}5Mj9FSTJ0oiH^DFFJb`zG%9_{}tWNPa;&_zi
ze-NeAo>HXIL);etA#@+c!G%rx6@#x~fx($?)dUDz?>6|%!S7I2zA-P%#CNPceK|+G@SZQU~X?6BQ
zM!4huUN_12s!4W3bL@_14?HdwOx+$C>+7M7X}i32H=&)=UI4PYJc5V1{kIHvQnYS+
zBO_vYt=kVux4od#-lCsosRoPGP{iQ2foE`L{{DX-!P@PVh(=8X+dX8&Q*!LpAY+*|
z`cc)W8nu~g}K&z6dlg3UN=F)ALJm;bA|Th??_LsMNu03Q9>{ae*j^)gXmd;
zi-O0NjgMRWp)869O8}2+I3Au=dptA-?JCckY`~3M_4e9|-cGbP(CuPf8*f5T#4$m~rQg6j*n{209epW2?nnfx;3Jgz(;rR0-
z5xXapj3;3C_d$u{YtL?LBJ+>M9DWTeoyTt;)#dUy67sUR>3A|^Qr!bRq0W`9kK#{Z
z^aTtZQD!>jk(i}n*W1dm=eRz*nwvzo@u&Jg(@Vyz!Vf)%!Y`UO4vf}^sEC&
zM3a``-Gl4GS++7S;ji@#vA`MSzP7-SwXIYYnT1;J%bMbus%^%~&}P?JF}L8P>?2)Z
zKU+ZSahSH(3QEju(C>%Gh!T5^0>jH;j~qDe+TY4}8Gku#y;p{nqgLVoTVTk#4p&O-
z4+RduW9lkOaLB#leq|}*JPt(mNqD&Tc?BBW2)^^R1_vP{+_$#ZW>`^aAQR_-&_c&w
zmae1<$-HO^iJD^}=GCz^|G$yj2@pr_t9b0lEq805(MWtP$T;*sJ=ik6hQBgUpV75k
zSyey=YA0%Wu(nka=&&*DNCxi;Tl$*jB5kLV6q~#a63A%TrfdP-pLWn1uBwF3fo3T@f&N6{f6rpwVSYYYRN5A)ZfSpIYq#!`5!(aYlk
zACAO-j|~Dc7VvNUwLNpVlgEnvNB17N8=(4*O%fR+0eRc*1tNWBJ~EFXCkvs^3@^iL
zRJxtkR824srtij+!82dmZ2{0>yWOZ+)>15tKP(U?Q8EsOcgE_;FnY`!NYOhS?41Hru75A-h{j{BSpK=tvW?%v
z_d(^~yW`*QmuSLh3u=d8E3c(yNlY?4(soDd0y$(nfahU6oHOqz!&_3iS=Ls~(t{@H
z#goO8(=0UN-FS}1BO$z}G|MQ(qGQZ`y3jhRkO_K0j0vTRSvCUw2ih#|tRU2|hoB&J
z`T&od6nv%?&Z`1)9Dw%^yirUsA8Ii!m(azg1WkQy*Yc
zdABaGaCu@jP-3{4>c_K?;>3g_!0>TC-PeO3PL;F`koL*gn!wVfgcn{!D2w8;UU;3Zq0(*J&@3A(7QN^@
zR2SMr71E2oK%q@lA-yCzRO|Db68b!-MU7T0T(MA#j-VnyJv^Q#)cM;HiA2?Lc0N%}1IFi3NT2;nqN(;;(F)-WOS0
zA@Q^2$_f%5VF^D|gwN|HIT9HKPM88jboL)CzK<_SG=yJi8<9hZ3Eqgu2lrt=_35Cm9~uZ3eLBCA2eoo;!5#9xVH-=;M?0~uk>KG%XLDZ!^h=ounhvz%E%%w3vgvSMK%
zMP_v#pj~r~Cw`{1NCj66h=>
z{yfAHqk5~k#2tpfbZhgaV+UJfsa4=-{N;-EL(G1!Y73l$jAdG22W5e?QS+sE&cWkG
z*V
zYa%g*vu8yhSsNm&T#kicK2;$VbD+?217PtW65G4i@z7c&D$jnX$wm+qwM#XFrB;<*UV#iADLHJq(m
zn=YjCnLd25G@{!jRyTB>^5JM)F6gVY8kgDvy7e>KygMs3E`j(<@dV6^AzZ#9x`=<3
zQ50kkSxI`xGHyFwMh2FJF4Dvo3CZfnSh*{WTVCnFbu760@)4z6ee~{wUh70JXkAVL
zB!hH@2u?+XzZdCPq?E6cGaurK51G1!n
z0%tW>BQs>fSeaI47p2TqP~vJ)Mpx;Y5-h_s%dU#$8eza+H=Rrb!^mK}?6$w>?%fS5
z^Vtb}eK4I@L6fxrT*Ln$MPwXZi<)D)FCWQr=p>&&lfcg7I%I?`5YT-$rTewe`8v^G
zEKe`9CYr;4%iT3fEwa|K)e6?bd_F_ElFRZb{I}fQjere6wsu<@pZN9$)DSl$uctbc
z%i^fp-C8&J1!UaB9?}JFR0ZUAqMNwryhgFMp`XDLYwV5ub^bq94)Fx0pqnU+
zgm|Pb`aaXr-BsgUkA}Gc&y9Fo%oVeA`MSPY3y}_TGdjp&c<5-?g}FX0!`r~R@9v>Q
z+ze_bMrynbkn7nR4{_aQG%8rmzzY916j-K3_EZ+R1s1s#&uz4fSY#A5+Yo)kRNH*8s)$Z2
zx#N(#k=EO@j&}BTndq3n1X!vSi-@{2ENZGMB%(|qE$Xi2iK3sJ7aZwzHO@x6@iyd!<|KCcTJce4rl=x3mA(#qVg3Rr(s
z)}aeL09g_LuFX4LX?q{EydTd4c-$*s^og6wy&Jp~98vN?rNgFBau^uhePJy2%14h)
z)CIlDLms4jH2%H~$Z$Yz)M`I$IUiL8p40`n8^cVk9dTJ8Kr=(t>p|4#Av_P`3EW%%
zoyQW;;~{OG2F3C_VZh%9#M#ico8ia2_*o?TjVQ_59a)=O&lL;`^Iw<|7cY@1T^5&)
zBQUQ$LK!53wi2|g)><|yEyX+VKE@-uP?IVo-XT(`Srw9Dk|dM1{qIZY<90&ZB6EvS
zt*x_Ob}iA=rj}c%TDleACdjOEdkp&qLuqUM!SYmrM{Xkq97>C-BOToD@jQy>587J$
zs6yi4OhIjk$E+ybFoDfot773n#$zH%`UoeWG2Z+3+~V>6w5yer*%f8B3|Z7$?7C=1
zAk^VA1bWfq6h$g!-$Qh5oi*%Q0SJnR`s{SONr|>+jjrgY$YF?>XIuy&FgaLma*DTMJ&?Rs+Wu{_zhG;yd
zIi$i|cyG=3OZ?BhMQZ$KWwEVMiayN7x4U5v;3_@wZ>|e*^1?F!hpX|NGr2jZx{HW
zUZgHBS|NwBDC+VJILBx$URs_O`zbA6g!Gq06VZafgz@w6I;Ey%V~z*4k{eq~7kH(F
zVq5Ck@2}*(44JQpY|Zj&2{HQJxTOaumRB{4Xuk#+CImL*l0#QBQ6`-dyY7H{eT_5(
z;E_HPxGi{~QbbSEujx7;qzdUtI#8%n71ERRYuYfcm(b@aUEuF1K%Wbz?KbuSg%4I@
zUWeuWj>qhlHOm{N#ON9&6$@wEH-t$SnxhKIY-K(#!v0I}_tGlhDh_
zw}*f^j3-+UF~pYJZXx|GH~r`K^c2ew`cF@2`DB)b&~G91J8hhQAtT%;p3?PBse1nd
zhWRI+f6+ji8sUAD|P-2RsJI?=}Nr~mb>v_S~j(&n80P~cWi;9RRK5OPeJ02
zwnF~M&C73>+m|wR5TV57wf{oGJtV^4`_R6T*D2pcMxR4PJ}JSnwXSWiV);a~NNra|ZKtG?*<6-a
zC$xs2G6(#3(H>qshX*Fltm5X*<5S_+ES~`#o&wyr^BBC!DHfTtJ_FN@x*GVm`L6>1
zN9HV3NQ?S>d7=(cEHbHm9u}2Xg>-=Cb1mwN5~5zv3KtZMc-=3;qKc}Jc2ZwR<7@yi
zyNsRgZN2og;!h&$pvbO)pG}Q)*e}tD7@p<3uqYamx^1j$^A!rf6PQVc1=xY{xoz)U
zeIzn=GaV$8GB@}&@@r;#eMBxd#7-6D+Q{6UL09%Jg2O%R8x{bX+ai0lqkMw4V!txb
zm$2Sfc)rH-jfi0F_wc_PS}Jt(Eyz*(*gGtW%AwcB-02&AGcEpYJC&w!;x5n3+?jn&G7HqWrz=k41Xq?2s}bv)NS<(
zGQ!U6OWop&Ra^atHu?$A&v<^(EWe_)WzwZle<~|0|539nQ7pd#?U)oxtZaEKhbk5u
zBaW4kO|!(n!qLI0TXeZx7br(Yqz7naf1|`;>W;oWknnrZ5qO1y*8%=6;O?Z7jW*4^4O^nTG+v|1d$thT-AgN<1rQTcURwV{0*ey1yrusfI!hw~LX&rJT
z!0}62S*%%GWHn^S=)WDkUuS*#w{n#paR>iZLX5o}01Inrz)7ScAoN$*Z
z<``d0Y;~B-I+@r=Ee0V6=VTye5EhAjqMPqn#j*yJbWEBBdMumeIG?3VoXnbJ(=1p~
zFPr7~5-e+lS+JZ~Hp@T>7F>4<>M{x};_$>S`ZO!XB}JrtwBZJo7&^RBc-CPv=qh7x
z9}yEcJ32wJsI#Nkx?0qUs*v5Q#MY%aEs6s~2CCHPNX>GRV$s8WJsDzHew0rS&yxNX
z7JIL8*;BMyqnfjD`yHI{l^OTVadl&6eTbhCzP%9{o+w3&mQQDC49^EptA*MQ9Oh`<
zayFn`&3II*I1Pynwu*Wo?SFdORZmr1Z{EE-0a_p@HhRehCGap^U?W=qPSAzFDs;=7
z?6*v8eYEQacs9hdk!IPrM8%KRET<@zjfY~{WO*#7Dwa)#V%Zcm3fuTGt;=aXOJHho
zAGM?tZNw$b)PfrPY=yg*v^|oWO0u~camJvdwcw>M6`{@~tvHRpJx
z-g}LWL8a*~TJem<{I_0N*|3wf+FPOkHobgpR1W)MSL*^>m8h5gsNm8wRlUZbUR&bX
ziuIFv(XqAZrnLdUarluMe{b-ouHhlHM7C#|E1F@PcI>Dl@xW8;~=Yp@?dQDaYkLwt&th-r#-p@o$c2%
zHVy{f8qXGZ+!a8ssb)3x_s)slsg7*}u`=P$!o2Y%$VO`e?VG>}=DZTfZ7q_^^?iZ-
zwhTYvB*;~eIJ?XK=Ak4~kNv#gLyWZMb_9TtZ2O@#xm9#;B;xDUOPAVOa{I6io^A1L
zr|mSp1jBE|PW*wjb1Xv)NcUySi9qeIUT*NzbKl8wcbvWSU?4s=!81Ym{+`k&R6>Hj
z-4Y{vxK>Ul{G!6rbFEI;62>OrnW$?tsRa5-sS#~*o^O+~+CKA*t=J@8;CxlU1_oo3
zw1~;5!83TC_G)0v?tXLt6La|i3;C-6&F)(Y?2QNNp&^4-b#mM9wH!`h2M`Kb_HCOH
zBScfiIWMr9V!Pz3G8qO5d>Z9KRYzb&+CefVd8b*&!_IVpT}RIb%C$
zQ9GhW;pPoA&?S}yowiIw>F-G|y>tjM_$gD*1#(;*r0u$
zHp#X(3`6U28;$T@
z%-u(#hw04VT@U<3yZibE7r6&Z9M4RH@>@wdNEX|bSQf=&gCVgs#Ns4Q;sd4pu_(6y
z!+x=RPFr_>u?xSy7ja&@5rP^W%2IG%M?m>mnlDvIAJUIkFw@$CyQ6d}ggRbOh;@{A
zr59&(fQ`SaTHXZ&outUQQ+MqveXGTGg|&9WvpXJl5X%*6+IA;nA00FbdAB`n8>NAP
zl}=cptc<_R>h()BVENo3iPSno3kZL{Kem?@F;|PwHrg8*k(SamzDm`2Pts4z#Z!Z4cTotjf${~?
z5T({qwO%`z4!i(5Yy(C&MRK9sqnkQpoKUxk+cxb145m3@I81Y+Xo3bW?_Cy`>Nz1X
zk3C+~Y0xZIX5UdP2hL3q%Uz~
z=WwwZuW9HCG=r4$UJj4!3*4dGI!NsEPsB=%g%%HQ#sb8iFamm_WDJIp9wFt0#Z7wnMC85%u|
z=<+YEY`d>)OfG{zti{}-#4tvNqqg;F$UdYSQ>rA;FnMvp
zxbYJ1Fo6ksCeZ}o5$g4|g17n##<-rFiN|yp5w|gr1?_nJqn42Wnq`eq074Ekj?vaa
zP(((EQ^u{jxpuitDZ>uJwaY9#`-(DLSQm@A!0+C1)b!(hK(&sJUWkd!CXyxb$SIJ%
z^cUN&g!ad3?Xg!8?MsjE+m-gSq4j>$9MArmg=={`|4EM-)};$zq3_(PjKT|a0W3=+
zHCe2i^bV!R0g!(no`dkXJ>~{rSg4!Se!eW!o^bAFpe@8-bnX*Yf!~}bEinNc@{@or
zY=U!g8`RZFk@@FfOT0)E>l)mtY9NlH6E!$kq^}9-i*Yoqeu`6@2$O#KVmuHe<2H7R
zE-(ifcJ6Xj%jg1FUP=My3opH_GvrhqV*0@^Bf
zE30(D8fiRp@yydK-C(g3rE>#2X_k8wi(Z<#FR-ixi~OcL*;5Sc`ZG)g_oMi07Ww=M
z0cj4p(ZdMQn#^aSMnG_&8!SM9@V?8e0mig#t&m^DaV`
z+poyv-a}53upDN;h0tgVZJT?QZ8EUzd^`*A;P+g;-on9s)L88eC7R}xSPeyvHb2%J
zk>3kzaIXw%3sSR<-
zVP_c3CVSJ^b9!aj)+ZE~^x;KJFM%y}Voy3dk00^zl2%31NfCWlLF&n2W$A2A!BB!^{
zNT%}z6zNE~>Q*B23};_f@yy=-VtTQFspwgFKO)axo|Z&b^K27#a;9L?()r0eT#l3?
z^qiFUdW9>;I-Z*;m?=wr9!oBtiq8o>b+$l>Cc?=i^gYkS$5XUXbnYO=K75ynUOa
zW$6q1vxVebXEJt)i)?IcZoyZcb-dW53ojMDq&L@9lk4||5q@d9C*2DLYLmsJ6lR-W
zR>0RUB!LAl=TDi!zDRavXGgjMU;JK>oR^-Q^3IC9igIyrWi}T{yDHVgR&$rrrjj!Bje=+ie}HWi+%Elf`}qWRW|p^@b=ymF_eR
zF+>5j%3Xb3DLp*dr|#}b&*{gq#kcuA{V6vX*ar9F>lu7CbeLRWKiEny3)mDrpLZ*BRS;$
zeJa`SlaTw-LJ@2b4j{{g>3ieH%Z2O`mrAvVWfzV(W62tJ-o`@Mv8Pv9&g
zm0Jj?8-XnM$DUjYI~otjrh5|ap?2Z-6(xKd2EVt+web8EX4V=FydQ{7Y(Z)osm9u|DA4TRPB^q;3N
z3qD`d+*F%rPc*x^iv?e3tFLbLu`Kx4_`Wp_9c_u3PBiWEw?)ZJF*pi{f3et&k0dx#
zvE)lM=`55^JD1D`d3jN$2faP-%F+<8a6F2Zr#8LEGdU2|!zkqSyya=Bd
z!FOPlK$5)P9ZL8+JC9JX-QPeTDLR91h?IX6`Z8Jk2uORTH=XM*lC;pB>v77lIsa);
z&2zQaX9fR7dC}xIDK(hPDf2DgaKX$KkooVqP9od1}Gdq4f9skwn|Sp9@r#NgouA3ll;neYh}^^ie91
z#7^{a0l$dYS5VV9r{zzoHPffnowe2NE{Wddv#E)u>ekt9@#@x^`p))xxV8G`hFU?5
zLXpo~<5--v#Y^XY(N^Dq-)Sw8OKzd}4*-;#O=Qnnk
zR+l2)2nD`1-nF@|tz&9KqOCp3Lc@ILh6;`MeY~-yeRgMC+>La0yC1w%l88N6_(v}p
zt4v9y2mMK`1Rox6l^ph`pRs1C>dNF@@8Oj43*zQdh(qevZk)wS0($1KGH>7D)I|3g
z7RzL%2snn7V;t#!4@>7=aR?q(A(up?5CjdY#KO*Lf}uKWg}!{Q&!rGI+=_OI)Mv#4
zzBiQYacSt8!&btY4kzE5eq~)zSZmk_gY!Om;wFn>t6<58{_4AYYO?CwOxkw{RCcw(
zlB}C~$+kLn0-ZCf8#V1Q$1h3IPyTuh_!kTS~{agYCu9eaYM>4I=39_B5
zaH$mL`(dMcGd(?-LPxfk=`n9Sn6n2d!KPRT3w-%Ey3Vk5G4JKECi2#$d!Ap09~npT
zdM3FUlil2&+#&!>4!p^*^;v~@Q+sP7-X`g6iw&?eX-F?L9?BHP&>6NN{Zkh_JMQHy
z%;0z31;Iwy$SiPh;ld+l(#9rfvLw+Ko6Ph4v*E-fUYmuB2p+Cr*yeVH$KOTuR`mwQzO@BraQt`x`<6*##j8x3x6(CEv!(A5LZSZ`aU?J#L^dlgHOblBwl{hR#4yrcJC5rV&2L
zmTT(ZbZt~%@?=|7C9~1DZ@^Nrl?zN$l1V$%2a>QN9JV8B)dZ&>Z=GotC8jJhc0$D>
z85Fm3Lua@=lc&^2l4-SF8am@`HPtOXIa7D752sSS-OyUqZS`8?-O*T~q&=WJm+fcDyy?m1k~4Q+!%=$y|D|#-=3Ks!ro3dRr`$5o?iTc8zA^
ztM+YaZi2(o87(Xy4`t9{?Nb}CtL|uM??g|iu2DKMvlXaBV@G4j%r?j>naSF>n_GCI
z0XtR)SI4rhH1(i0XEt?Uu`na{Q62%R>=IY`>;;HlMU
zFf4GKZ1(FUQqfgA8vOA?>N!ZRO|-^YQ)f!Dq>xdcsI85=-a`$$s%vVvNp6i-b3JJk
zAx+w*&uUGyy8*%$nQJrR`^IZJ{48?KYeT=mS`kY|XFh7$?WNbX#vKzyWW3~#HX8;s
zvMFLd_Oj-!z#2vYoGEDV1(MZ*jcjJIDIjXIv-K1ZigM!0b>a2wbZsUdq3uiAc!Vj-x*mefYghqJ+4vo!ylZN9>q1|yfasMkiE0*m
zGQF8V!}q7`@7IY!^o0xYt{O&)vjCTui@N7X5!!ZfrqIfL7lM6~%nB}Q$qFRXMubnSlAnv^LLjJ)9KBw$&%C_@V!kFB9zsIZR=B(Zcu
zSkSCt5RqYZ#Wu9UU~h79sXR983HHZ0IA{gKh1ZELaBRLF?7h7&1?WglQsHB$luW^4
z1xv9roQ$0g=VezZ8uSz-)-=~9nx+XM=aEy98gFuAl5Kq&lIjqHsQ2e-CZBFLgoEH7xWk7&UrI6Iv#=D27!P+Dkd0pXpV
zbSI)*E}i6U)ShM4HE3ru8t
zvG+wr?`07IY=-O$Gudv0+>7b1z%Nq!;Z371=dFvpN+l3M_HFwxw-9%P`WmvmQVfNGl8$2-bxB$P*8)Eo@yan-v=tM2K4DJu-MJgxo%ZnL?
zHw=Ugb%m!zTl$cwhF97=iL<(9xC+7h1ydP*^U2wWSI-HivB|EnX{dv9O|1U4TnV(a
zCYs^n-BdwGcpaA$ksLy<=S&!euo5>E&`+kCrB53g*flTLGdH3Vxka>PT|U>_raBaJ
zZ?fC^_Uf7$o$ak&Y|qqlOXS{+06|SdHD;(pV@pGvGccA$&ColJB}rSG7q~OUId$BE
z-=Xlr%l%zyo5A(Mt^HX^CAc5-KGL+wZp`F%uY)svYqa=!FF#l
z6fqoR_q8yt;@00}xW6_ILwZq7Bb~nT0k40V-p%U+e7i|_*xnB^Y8lR;p&zQpiXW@j
znpV>$f?@xDcuqgAOMCsBmiX<|#5B6HM73LaQ2F0AB-+~%k_zUqzdi!P;!UuCgW`z$
zeOJ1GU#nl@?`PQzk1p)3?!iXAt-pZaGY{ZIICKAy?O>oV4_DD{2C^IHw8>*xul_EP
zL+J4mX-{O0i*n^?<39$I*qBc;isTAW!c$DK;ap>NR^(|W!m#Gh$o1Vn;Y-O3&D(cT
zr4}^dGu2H^48*D4&d&7bxY|yV_%Cg&~uRO+7F`
zd!fM$I*=Cy)0i%H=gdKg0a5--9w?N5nUYZ{&dpN@COoJM(S@OLaei>0&K+25F#M)*FHN@VBeq{-Q6|G@gPC!ONT
zu@0+=Ts|;Y|C2|e=+lCrmHw4Rq|a0|ne`(qti+o-2kTqVDn3qlZ+TAG?`CbC)vc}7
zZdRbC|3(l#hlvOpITO-^Vb+H@
zQc3r*et|3wtdDSjoxxtz#D|TB>^&blt`b#e+kYa#-5T>squxX?`_qQ%rfD73)8d_t
zSpU@}5WpARY1q$F{)qL~IlSrbja=64^E?ivC4ocvi*PFj8_heE%c&G}TK@=9aLQGkg
zDXt6_P!;PH=DE!fj=?I{cgsTzjEW6f5<-Y!Td`q2nZ+#@Z|g9PbBXstkk|28Vxw#t
z=Lm>w?3d2x>TublI8`l;**F{P616!@g=t-cQa4GtumdZ*Y1ZtZMG=hoiqTvuYE!an
zZ#$9)S=EHSDtpwnJrL8D=2W6qW;D`vUAQ5okAUF!D#l|{zzs6z_gUu&
z^o8h`T2O-(97!H&B_
zeRJ~+=gVoD9TCe$Yws7F$0~Nh+hle221vfpoQ>l$gOF2?oq3^CZ%(Pllw^Mqy|v$u
z=24Gbu>NQF6gW%n${T%2tcF}YSaLTSso9*pnxb%_X1dd}
zS2d$OQZ7tE?v{AdG#u~ip;o@MrXmX%z;K>opKNbx>HZ~SHx*t0D$5TZm&+v@+(QNp6r+*9Q@~;
z4%eszq;QFB-MYM_&Y=0(OVX{)&FwsPZ;W))EawU^}W1eKzGu=xCHlLNOg123YazO
zWg^2KGx?&o&cSqUZfu(1h|8hB&1DL?2CIl0w9M#3hPh9W_pWG~QO+6mkhXXuj-L_@
zHHft(YN{K|m1$>f&QEz3X=C+BnqjCv~S=WO~GtgW8CY!_FxJPbt7!(KNVHrtfU?*^#
z$SNLQF!3PVmC$5Iw3+Kn({L2!f>G4%NH2Xht_+%M??wt~j`A{8*o-6NXkG{QnaOYr
z?$khkIKAN3y5d;djZBcryzqQBH7TrXzQXDUeN_ICdOpP5V1*h6NX)1E+hvILSo>Rj2dvL~F^j1XLF
zD1+k8Z$jLfhn`qS1@3sTwJyMX)__|9p)8Ke3u~GiaRZQ9rO=2(R9uAMZUQ#|yjwG!
z2n$a2tIAGvv8QJ!hw5J9sT+i_j+c7pvu*K~>egy?Zcc44Yry1)Bk@ocXTi&vHm$X~
zg|{O@`SjLT;HbU5wb?CG*e9;!TO!rYi?L5!g;R!^yn2Ys8`7iL`d7E%n7$eJBU~y?
zdkrt3bhdOf)wFj6!lWD~*J2E}wwKCfHLpVex>O#0^7YWQ$sDDZDnafWJnNN^%u3vd
zO2G`X8>jm9rOcb$U4v-e&8}+&^Vn9mc+!Fy+`8N@Qz%?ouNVv@j6`UZ0>ALOsjY8%7S-=
z3Yr2eNrZ^q3I*?8RzU=|s;Bx1O~&lD0=U*i$?qHb^zVC
z91wg9+?5_EtnU3Gl&5z{r>#-&flxt=`9`=4Px+`utnq^(2;564|A2F?iibi)r()Sv
ziz~&QP4Nz_THRpW5@jC_m0iYou0rwOhKk#JGEtS;Pk$FGJgXkpON^h9rbnQ$;*n4(
z>!CbV-J*$B`+cZnpxbrE;RS2;!TLBr9$hAcZ;iDkYMpbTkUxYFfi7EG$YaZdgoRM8
z$3uvg<`#R8#|*sApoioF=n2k_^%!5B5tqp9KXRHZolVE}B+;1vqG0AeMR3VnP9{$i
z8xhK!KM@zn;XruC!?egDF8UrWJ-}5pC;a6krnY|
zsJr4N1TVS+=a*!E8O!dxKIh>S@e0|igZF$mO};uec0tH5ZejH|7G;f%MV4^d)&
zA;;z4o4D*GB&@_+492N6PT>D$THyW@Tj@V@9gq{<+urr6V2pz8{EpkX=rAD_{x45i
zT^vp468CN(S9D|pyjSe)!v({%HYas|-|Q;=`q54wpe)w;0%w2v&|ZtiI;FF^ttR1u
zvy}Rg%WSXfoFXvx@{e`Sq@5&-jGqLvraE85%uj=v=KWc-S>Y=1vv6kT)Mj@JnNmO3
z1-758rG632@`)++%V4Ij5~Y3>%*2ttlF9;K2MbIM6rij6MhYa_nmeaV*>RUn7a?c%
zw~=h8IkUfuWbYsqWA^uvYQ
zgZv`-Gnx}qI$H(GtX~6J9V)A`OtKo=CQaVa4O^fpV}UGZMrM@;9nRm#|z{kSAa%~1}T6sOBtr7-y-SE{O3j~
z=lL;(RBoL2PnsxylXR*(hgSpz!s>3y3;mrqH*ae1oL)V%x|6TIsk<>W?C4S%m=G&B
ztBp_Xa91rceOGSYpEs{e8KY3<7GCt;>BT}-J-z1bAyWubVC5LRj~}{0M(mb$-zxgj
zG+VXcH9Bk~{VfwsGnSzxe-A_5#+eP8Kv|8gaigcEzO}gtrz*9Q!8X`tW^)7JzMrO`
zZLyX|>`n#fC}=zEO1$@0U1u1NMHjy1pf1~yb3*mhHr~K%7ePc%L{cJ{G-)c9$kW`s
z#A;7Qu(rB&TALu5wmrfzowaptbHTJ7n1(2glw%!t)p|#%I
zD}~wAMAu9!l$4W)7h>hin|Rn(4JLSHRT^@m8?Dl7V$XWgS=kQ)eT7
zQQ}4rA`z9-uJ7r
zT!<*kj@*D-Px=Y~U0LHCcSz2EHl^H~2vm&U7{@CEq8Ob@3+~W3FN45PN$C%@}wPR$z-p`45K$lP6{W+XFaAO=FEeW0i
za0)$uxjb_TX0ZVeWLBa%n8EIHke2~vaox*1b`BPz!ksMClnxy{&>J4ylf;!_+%uQ@
zu@RHOgI%`E9Pa)~%mgV+xO#)hHt4duDjYTmE88H=yZV9fHx-!Mhly9;t{kfad9TsWY}SS3AKQPIUr#5zN89Q{k?;C)(2pyr2SNumG!n^d7+{!L@y
z$O~7DB!!K8IPR4s6XDb&+(kwyOZFqx&XxZ@DwS~qka{28W54?&AnJV#-wanCgK8Wr
z-_|j67Aqi+!Iq9beX%Q-7D=LCD_*t_K*DpBtf
zl^LnxNnJP~?DKDWP}s>`Io$J5iR`_n=##h(6N}*m1arq$1hBzRHK%by6kvBb%@U!A
zx%%kLNEd#3W^SW*S+uJS7d~7Av$@W|<(;g#TO{&07SFV)_NyC`Mc;B3Eg4E@{m!<1
z(n)6FrF2B>oXW`btmmlo2J@{U5y9bcZbxjB?eoiwyQ_We(8&4caQ#piyv0Uz^ltIRwP;eLZhVDH}O+yale
z|4r?~@YPIA?Pqy=0;{#j+3kFle`EwN(z!*j(Kq8g)_yp(!;8|f?}^jwqvv$)#;0(i
zZ@=OybJ}D5di22^Uz`Nv5gq4g=(aua8KAbYuTF6L9?zMA*AV8qh0)>@IU}*--~%}P
zdXaP%HusiZ_3QHiDBJ+`HkMoeWS{oY=L^}Zwhm}quO3eRdbI6~FA%sUSk|^)J@GD%
z_lyfikf-`^!+19hk1XLtwztb?V?XWi@w&WchBevVx*x7?`)zUednQI7n}>Vuv+j(!
zZR@t3aKqO5wuWpRJHm7LsFQqO&)a2oIDRo#snd31cXeJKiOxH?9lJ)&$-#iZX^wxF
z<&1AP4jp(EzVk>79eCHUPi$GZyPEdAjI({@^Jcj%u$Sz?3kUsXjP@?UQ1=4wM|JPx
zUG<{wMMvjd?xOA`N7umhEVuV%IR?2JI`tLQVTjZtx?$`Ld&%@oH^|<{qd2C-v9FD>
ztXHYWkSywAYu)~6>?n!+OHY#yy+->Pb22w&wg@1
zrUU&k9rTWz+-csNF^vy6PaihX_uePB>L8!dZO`uwx>ewy^j2&s`2w}>JB;t)d>#pK
zNzLC14^bRW=@kfULox+IN;wEYYEnp`uo6OuLJ&e4g;WS(3LyyT6uyHHp^ye4gTgon
znH0hhvM8iO$VY*N=cmvCLIDaH5DHSrgiwe=We9~SWI-rGAs>XI6!JqTM&Wk|#VHhk
zP=Z212qh^Lf>4UWWe`eJC=8(tg=rAVQYZqU9EG9~%2Ox?;S>tRAylAH0zyR!B_ULz
zFbu+}6iPv;OyPA1RVb8(P?bU%2-PV30HHdCvJh%epnGdl=mMb@h4K(;Q#b{}X%s3z
zs6(M5glr0xAk>AB!iv?S=2QsvDb$6~fI<}r4JlNG(1=1c2#qOJhtPyV4G2vs)P&HC
z!aNAgDb#{+I)%3(w4hKM!Wk4!gK#E=IuOpHkPV?Fg?bQLQK%20HH8Kc+E8c+p)G~I
z5ZX~_1fe~J#t=GCXab=lg{BZXQD_FCGlk|5x==VBLRShcAatW}288Yu&VLg+)GHH5wpQrPSIQPT!Oe+q3OoI{}!Z{EoP#6GVB877yOrmfegvk^JLYP8f1%w<5gCI<$
zFc`u#3g<(ZPGJay85EX4m`Pzcgjp0uK$uNoB!oE-Qp!M>OU)<<^QhsTdjU10AzVmd
z421a~%z|(gh1n3UrZ5M>H55LFa4m(o5U!(e0fc1~=0jLc;UWkt
zC@g?*J%xo3ZlJIT!i^LbL%0b-3U|hvsks=!N(z@iSViGd2)9sJ3gK1?mqS=h;R*=1
zQMeMq?G&zpu!h3b5Y|$-2ErW_u7z+Xg!tD??
zQ&_2*OSZ8zJnX@I8dx6ds1~JcUgV_E2~P!V45OLwJ$G
zV-Q}V@Hm8*DLet;6$)D*?4__3!afSyAiPT9DG0AocpAd%6t+WngTgZq_EUHk!T}1;
zL3oqG4hRP+?1b}_y6!t^-jKTp3pHnyp;R_0HLHLrw
zAqdAPyaVAY3hzSrn!)1yg2K0)=TP{O(;o`I
zK?qX#2|_A`pCN=O`~o43!XFUA6#j&ePT?;I5eg?DWI#wk2`QNrAf;qc2tvq5Ar(S?
z3LyvuD5OCsNFfZN5QTIIg(*ZJ6rqp_p(uqc2*oJmhfthC0SF~16ogQcLLmsHC=`ZJ
znnDo>WhfMdP?kao2<0f0gixMBX$YrKC<~zig>n!oQYa6h5`|MBoJyergvt~uLa0Ka
z5`?N0PK8j7LRARWDO7_{gFVuM2(>BHf^Zsz+7RkcI1NHJg*p)GQpko-
zk3wAt^(oYY(11dH2n{JTfY69SLkNv2G=k8CLSqO`DKvr5j6zcg%_%g4a5@CezVHJ}
z5PpYn1_gGBGb!8(;VcR(A+&UbRxZ?<0?BPCFne1HG}w;9RS?>{LI(~o^qXtl*>&~S>kDW)M9fW}tIzkvkp)-WR6uLk-pF(#CLn!ovFqFc%5Qb402w^yd
zK@dhzz%HCJk^=VAlu;0Z?8c)h6oN2@LU9OVDX_1Oqrkp8oJ_6VKxOe}AzV!1AcRXO
z9D;Bug?At