This is an automated email from the ASF dual-hosted git repository.

ctubbsii pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo.git


The following commit(s) were added to refs/heads/main by this push:
     new 40fb5d0  Make build work on Java 17 (#2500)
40fb5d0 is described below

commit 40fb5d01ffeefd6fb2e9a867a03bcf5737b56578
Author: Christopher Tubbs <ctubb...@apache.org>
AuthorDate: Tue Feb 15 19:28:16 2022 -0500

    Make build work on Java 17 (#2500)
    
    Ensure it is possible to successfully build using Java 17
    These changes were tested with `mvn clean verify -Psunny`
    
    * Add JDK 17 build to GitHub Actions
    * Change format of `PasswordToken` serialization so it doesn't use GZip
      from Hadoop's `WritableUtils.writeCompressedByteArray()`, which seems
      to have changed format slightly between Java 11 and 17, resulting in
      slightly different GZip header information. However, still support
      reading the old version (added tests for these)
    * Pass absurd jdk adds-opens options to ensure test code has access
      parts of the JDK needed for mocking / junit testing
---
 .github/workflows/maven.yaml                       | 11 +++---
 .../security/tokens/AuthenticationToken.java       | 12 +-----
 .../core/client/security/tokens/PasswordToken.java | 43 ++++++++++++++++++++--
 .../client/security/tokens/PasswordTokenTest.java  | 39 ++++++++++++++++++++
 .../accumulo/core/conf/ClientPropertyTest.java     |  6 +--
 .../accumulo/core/security/CredentialsTest.java    |  3 +-
 pom.xml                                            | 13 ++++++-
 .../org/apache/accumulo/compactor/Compactor.java   |  2 +-
 .../apache/accumulo/compactor/CompactorTest.java   | 34 ++++-------------
 9 files changed, 111 insertions(+), 52 deletions(-)

diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml
index 5a9666d..701665c 100644
--- a/.github/workflows/maven.yaml
+++ b/.github/workflows/maven.yaml
@@ -60,17 +60,18 @@ jobs:
     strategy:
       matrix:
         profile:
-          - {name: 'unit-tests',    args: 'verify -PskipQA -DskipTests=false'}
-          - {name: 'qa-checks',     args: 'verify javadoc:jar -Psec-bugs 
-DskipTests -Dspotbugs.timeout=3600000'}
-          - {name: 'hadoop-compat', args: 'package -DskipTests 
-Dhadoop.version=3.0.3'}
+          - {name: 'unit-tests',    javaver: 11, args: 'verify -PskipQA 
-DskipTests=false'}
+          - {name: 'qa-checks',     javaver: 11, args: 'verify javadoc:jar 
-Psec-bugs -DskipTests -Dspotbugs.timeout=3600000'}
+          - {name: 'hadoop-compat', javaver: 11, args: 'package -DskipTests 
-Dhadoop.version=3.0.3'}
+          - {name: 'jdk17',         javaver: 17, args: 'verify -DskipITs'}
       fail-fast: false
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v2
-    - name: Set up JDK 11
+    - name: Set up JDK ${{ matrix.profile.javaver }}
       uses: actions/setup-java@v1
       with:
-        java-version: 11
+        java-version: ${{ matrix.profile.javaver }}
     - name: Cache local maven repository
       uses: actions/cache@v2
       with:
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/security/tokens/AuthenticationToken.java
 
b/core/src/main/java/org/apache/accumulo/core/client/security/tokens/AuthenticationToken.java
index a09a651..c57ef7a 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/security/tokens/AuthenticationToken.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/security/tokens/AuthenticationToken.java
@@ -118,20 +118,12 @@ public interface AuthenticationToken extends Writable, 
Destroyable, Cloneable {
      * @see #deserialize(Class, byte[])
      */
     public static byte[] serialize(AuthenticationToken token) {
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      DataOutputStream out = new DataOutputStream(baos);
-      try {
+      try (var baos = new ByteArrayOutputStream(); var out = new 
DataOutputStream(baos)) {
         token.write(out);
+        return baos.toByteArray();
       } catch (IOException e) {
         throw new RuntimeException("Bug found in serialization code", e);
       }
-      byte[] bytes = baos.toByteArray();
-      try {
-        out.close();
-      } catch (IOException e) {
-        throw new IllegalStateException("Shouldn't happen with 
ByteArrayOutputStream", e);
-      }
-      return bytes;
     }
   }
 
diff --git 
a/core/src/main/java/org/apache/accumulo/core/client/security/tokens/PasswordToken.java
 
b/core/src/main/java/org/apache/accumulo/core/client/security/tokens/PasswordToken.java
index d7aa53f..9348ed6 100644
--- 
a/core/src/main/java/org/apache/accumulo/core/client/security/tokens/PasswordToken.java
+++ 
b/core/src/main/java/org/apache/accumulo/core/client/security/tokens/PasswordToken.java
@@ -23,11 +23,14 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.util.Arrays;
 import java.util.LinkedHashSet;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.security.auth.DestroyFailedException;
 
@@ -83,12 +86,46 @@ public class PasswordToken implements AuthenticationToken {
 
   @Override
   public void readFields(DataInput arg0) throws IOException {
-    password = WritableUtils.readCompressedByteArray(arg0);
+    int version = arg0.readInt();
+    // -1 is null, consistent with legacy format; legacy format length must be 
>= -1
+    // so, use -2 as a magic number to indicate the new format
+    if (version == -1) {
+      password = null;
+    } else if (version == -2) {
+      byte[] passwordTmp = new byte[arg0.readInt()];
+      arg0.readFully(passwordTmp);
+      password = passwordTmp;
+    } else {
+      // legacy format; should avoid reading/writing compressed byte arrays 
using WritableUtils,
+      // because GZip is expensive and it doesn't actually compress passwords 
very well
+      AtomicBoolean calledFirstReadInt = new AtomicBoolean(false);
+      DataInput wrapped = (DataInput) 
Proxy.newProxyInstance(DataInput.class.getClassLoader(),
+          arg0.getClass().getInterfaces(), (obj, method, args) -> {
+            // wrap the original DataInput in order to return the integer that 
was read
+            // and then not used, because it didn't match -2
+            if (!calledFirstReadInt.get() && 
method.getName().equals("readInt")) {
+              calledFirstReadInt.set(true);
+              return version;
+            }
+            try {
+              return method.invoke(arg0, args);
+            } catch (InvocationTargetException e) {
+              throw e.getCause();
+            }
+          });
+      password = WritableUtils.readCompressedByteArray(wrapped);
+    }
   }
 
   @Override
   public void write(DataOutput arg0) throws IOException {
-    WritableUtils.writeCompressedByteArray(arg0, password);
+    if (password == null) {
+      arg0.writeInt(-1);
+      return;
+    }
+    arg0.writeInt(-2); // magic number
+    arg0.writeInt(password.length);
+    arg0.write(password);
   }
 
   @Override
@@ -134,7 +171,7 @@ public class PasswordToken implements AuthenticationToken {
   protected void setPassword(CharBuffer charBuffer) {
     // encode() kicks back a C-string, which is not compatible with the old 
passwording system
     ByteBuffer bb = UTF_8.encode(charBuffer);
-    // create array using byter buffer length
+    // create array using byte buffer length
     this.password = new byte[bb.remaining()];
     bb.get(this.password);
     if (!bb.isReadOnly()) {
diff --git 
a/core/src/test/java/org/apache/accumulo/core/client/security/tokens/PasswordTokenTest.java
 
b/core/src/test/java/org/apache/accumulo/core/client/security/tokens/PasswordTokenTest.java
index 7ea740e..4422914 100644
--- 
a/core/src/test/java/org/apache/accumulo/core/client/security/tokens/PasswordTokenTest.java
+++ 
b/core/src/test/java/org/apache/accumulo/core/client/security/tokens/PasswordTokenTest.java
@@ -19,8 +19,17 @@
 package org.apache.accumulo.core.client.security.tokens;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+import java.util.List;
+
 import javax.security.auth.DestroyFailedException;
 
 import org.junit.Test;
@@ -41,4 +50,34 @@ public class PasswordTokenTest {
     s = new String(pt.getPassword(), UTF_8);
     assertEquals("五六", s);
   }
+
+  @Test
+  public void testReadingLegacyFormat() throws IOException {
+    String newFormat = "/////gAAAAh0ZXN0cGFzcw=="; // the new format without 
using GZip
+    String oldFormat1 = "AAAAHB+LCAAAAAAAAAArSS0uKUgsLgYAGRFm+ggAAAA="; // jdk 
11 GZip produced this
+    String oldFormat2 = "AAAAHB+LCAAAAAAAAP8rSS0uKUgsLgYAGRFm+ggAAAA="; // jdk 
17 GZip produced this
+    for (String format : List.of(oldFormat1, oldFormat2, newFormat)) {
+      byte[] array = Base64.getDecoder().decode(format);
+      try (var bais = new ByteArrayInputStream(array); var dis = new 
DataInputStream(bais)) {
+        var deserializedToken = new PasswordToken();
+        deserializedToken.readFields(dis);
+        assertArrayEquals("testpass".getBytes(UTF_8), 
deserializedToken.getPassword());
+      }
+    }
+  }
+
+  @Test
+  public void testReadingAndWriting() throws IOException {
+    var originalToken = new PasswordToken("testpass");
+    byte[] saved;
+    try (var baos = new ByteArrayOutputStream(); var dos = new 
DataOutputStream(baos)) {
+      originalToken.write(dos);
+      saved = baos.toByteArray();
+    }
+    try (var bais = new ByteArrayInputStream(saved); var dis = new 
DataInputStream(bais)) {
+      var deserializedToken = new PasswordToken();
+      deserializedToken.readFields(dis);
+      assertArrayEquals(originalToken.getPassword(), 
deserializedToken.getPassword());
+    }
+  }
 }
diff --git 
a/core/src/test/java/org/apache/accumulo/core/conf/ClientPropertyTest.java 
b/core/src/test/java/org/apache/accumulo/core/conf/ClientPropertyTest.java
index 6f861f5..f15b20c 100644
--- a/core/src/test/java/org/apache/accumulo/core/conf/ClientPropertyTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/conf/ClientPropertyTest.java
@@ -41,15 +41,13 @@ public class ClientPropertyTest {
     assertEquals("testpass1", new String(((PasswordToken) 
token).getPassword()));
 
     ClientProperty.setAuthenticationToken(props, new 
PasswordToken("testpass2"));
-    assertEquals("AAAAHR+LCAAAAAAAAAArSS0uKUgsLjYCANxwRH4JAAAA",
-        ClientProperty.AUTH_TOKEN.getValue(props));
+    assertEquals("/////gAAAAl0ZXN0cGFzczI=", 
ClientProperty.AUTH_TOKEN.getValue(props));
     token = ClientProperty.getAuthenticationToken(props);
     assertTrue(token instanceof PasswordToken);
     assertEquals("testpass2", new String(((PasswordToken) 
token).getPassword()));
 
     ClientProperty.setAuthenticationToken(props, new 
PasswordToken("testpass3"));
-    assertEquals("AAAAHR+LCAAAAAAAAAArSS0uKUgsLjYGAEpAQwkJAAAA",
-        ClientProperty.AUTH_TOKEN.getValue(props));
+    assertEquals("/////gAAAAl0ZXN0cGFzczM=", 
ClientProperty.AUTH_TOKEN.getValue(props));
     token = ClientProperty.getAuthenticationToken(props);
     assertTrue(token instanceof PasswordToken);
     assertEquals("testpass3", new String(((PasswordToken) 
token).getPassword()));
diff --git 
a/core/src/test/java/org/apache/accumulo/core/security/CredentialsTest.java 
b/core/src/test/java/org/apache/accumulo/core/security/CredentialsTest.java
index 59878e3..0837599 100644
--- a/core/src/test/java/org/apache/accumulo/core/security/CredentialsTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/security/CredentialsTest.java
@@ -24,7 +24,6 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
 
 import javax.security.auth.DestroyFailedException;
 
@@ -61,7 +60,7 @@ public class CredentialsTest {
     // verify that we can't serialize if it's destroyed
     creds.getToken().destroy();
     Exception e = assertThrows(RuntimeException.class, () -> 
creds.toThrift(instanceID));
-    assertTrue(e.getCause() instanceof AccumuloSecurityException);
+    assertEquals(AccumuloSecurityException.class, e.getCause().getClass());
     
assertEquals(AccumuloSecurityException.class.cast(e.getCause()).getSecurityErrorCode(),
         SecurityErrorCode.TOKEN_EXPIRED);
   }
diff --git a/pom.xml b/pom.xml
index e1e3ae2..254ab2c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,6 +125,7 @@
     <errorprone.version>2.11.0</errorprone.version>
     <!-- avoid error shutting down built-in ForkJoinPool.commonPool() during 
exec:java tasks -->
     <exec.cleanupDaemonThreads>false</exec.cleanupDaemonThreads>
+    <extraTestArgs />
     <failsafe.excludedGroups />
     <failsafe.forkCount>1</failsafe.forkCount>
     <failsafe.groups />
@@ -852,7 +853,7 @@
             <systemPropertyVariables>
               <java.io.tmpdir>${project.build.directory}</java.io.tmpdir>
             </systemPropertyVariables>
-            <argLine>${unitTestMemSize}</argLine>
+            <argLine>${unitTestMemSize} ${extraTestArgs}</argLine>
           </configuration>
         </plugin>
         <plugin>
@@ -866,6 +867,7 @@
             <systemPropertyVariables>
               <java.io.tmpdir>${project.build.directory}</java.io.tmpdir>
             </systemPropertyVariables>
+            <argLine>${extraTestArgs}</argLine>
             <trimStackTrace>false</trimStackTrace>
           </configuration>
         </plugin>
@@ -1683,5 +1685,14 @@
         </plugins>
       </build>
     </profile>
+    <profile>
+      <id>jdk17</id>
+      <activation>
+        <jdk>[17,)</jdk>
+      </activation>
+      <properties>
+        <extraTestArgs>--add-opens java.base/java.lang=ALL-UNNAMED --add-opens 
java.base/java.util=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED 
--add-opens java.base/java.net=ALL-UNNAMED --add-opens 
java.management/java.lang.management=ALL-UNNAMED --add-opens 
java.management/sun.management=ALL-UNNAMED --add-opens 
java.base/java.security=ALL-UNNAMED --add-opens 
java.base/java.lang.reflect=ALL-UNNAMED --add-opens 
java.base/java.util.concurrent=ALL-UNNAMED --add-opens java.base/jav [...]
+      </properties>
+    </profile>
   </profiles>
 </project>
diff --git 
a/server/compactor/src/main/java/org/apache/accumulo/compactor/Compactor.java 
b/server/compactor/src/main/java/org/apache/accumulo/compactor/Compactor.java
index 1a3bc49..8701e33 100644
--- 
a/server/compactor/src/main/java/org/apache/accumulo/compactor/Compactor.java
+++ 
b/server/compactor/src/main/java/org/apache/accumulo/compactor/Compactor.java
@@ -621,7 +621,7 @@ public class Compactor extends AbstractServer implements 
MetricsProducer, Compac
    *          number of bytes in input file
    * @return number of seconds to wait between progress checks
    */
-  protected long calculateProgressCheckTime(long numBytes) {
+  static long calculateProgressCheckTime(long numBytes) {
     return Math.max(1, (numBytes / TEN_MEGABYTES));
   }
 
diff --git 
a/server/compactor/src/test/java/org/apache/accumulo/compactor/CompactorTest.java
 
b/server/compactor/src/test/java/org/apache/accumulo/compactor/CompactorTest.java
index 6e1bbdc..9a27352 100644
--- 
a/server/compactor/src/test/java/org/apache/accumulo/compactor/CompactorTest.java
+++ 
b/server/compactor/src/test/java/org/apache/accumulo/compactor/CompactorTest.java
@@ -59,7 +59,6 @@ import 
org.powermock.core.classloader.annotations.PowerMockIgnore;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import 
org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
 import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.reflect.Whitebox;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -298,24 +297,17 @@ public class CompactorTest {
 
   @Test
   public void testCheckTime() throws Exception {
-    // Instantiates class without calling constructor
-    Compactor c = Whitebox.newInstance(Compactor.class);
-    assertEquals(1, c.calculateProgressCheckTime(1024));
-    assertEquals(1, c.calculateProgressCheckTime(1048576));
-    assertEquals(1, c.calculateProgressCheckTime(10485760));
-    assertEquals(10, c.calculateProgressCheckTime(104857600));
-    assertEquals(102, c.calculateProgressCheckTime(1024 * 1024 * 1024));
+    assertEquals(1, Compactor.calculateProgressCheckTime(1024));
+    assertEquals(1, Compactor.calculateProgressCheckTime(1048576));
+    assertEquals(1, Compactor.calculateProgressCheckTime(10485760));
+    assertEquals(10, Compactor.calculateProgressCheckTime(104857600));
+    assertEquals(102, Compactor.calculateProgressCheckTime(1024 * 1024 * 
1024));
   }
 
   @Test
   public void testCompactionSucceeds() throws Exception {
     UUID uuid = UUID.randomUUID();
-    Supplier<UUID> supplier = new Supplier<>() {
-      @Override
-      public UUID get() {
-        return uuid;
-      }
-    };
+    Supplier<UUID> supplier = () -> uuid;
 
     ExternalCompactionId eci = ExternalCompactionId.generate(supplier.get());
 
@@ -362,12 +354,7 @@ public class CompactorTest {
   @Test
   public void testCompactionFails() throws Exception {
     UUID uuid = UUID.randomUUID();
-    Supplier<UUID> supplier = new Supplier<>() {
-      @Override
-      public UUID get() {
-        return uuid;
-      }
-    };
+    Supplier<UUID> supplier = () -> uuid;
 
     ExternalCompactionId eci = ExternalCompactionId.generate(supplier.get());
 
@@ -416,12 +403,7 @@ public class CompactorTest {
   @Test
   public void testCompactionInterrupted() throws Exception {
     UUID uuid = UUID.randomUUID();
-    Supplier<UUID> supplier = new Supplier<>() {
-      @Override
-      public UUID get() {
-        return uuid;
-      }
-    };
+    Supplier<UUID> supplier = () -> uuid;
 
     ExternalCompactionId eci = ExternalCompactionId.generate(supplier.get());
 

Reply via email to