calcite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject [06/10] calcite git commit: [CALCITE-1667] In Avatica, forbid calls to JDK APIs that use the default locale, time zone or character set
Date Sat, 04 Mar 2017 21:03:25 GMT
[CALCITE-1667] In Avatica, forbid calls to JDK APIs that use the default locale, time zone or character set

Use the "forbidden-apis" maven plugin to detect calls to such APIs.
Eliminate calls to such APIs.


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/8df27ce9
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/8df27ce9
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/8df27ce9

Branch: refs/heads/master
Commit: 8df27ce9dfc24c3116e6343432d581d112d83557
Parents: 75152c5
Author: Julian Hyde <jhyde@apache.org>
Authored: Fri Mar 3 01:27:20 2017 -0800
Committer: Julian Hyde <jhyde@apache.org>
Committed: Fri Mar 3 11:08:49 2017 -0800

----------------------------------------------------------------------
 .../avatica/AvaticaPreparedStatement.java       |   3 +-
 .../calcite/avatica/AvaticaResultSet.java       |   3 +-
 .../org/apache/calcite/avatica/AvaticaSite.java |   3 +-
 .../apache/calcite/avatica/AvaticaUtils.java    |   1 +
 .../avatica/BuiltInConnectionProperty.java      |   3 +-
 .../calcite/avatica/ConnectionConfigImpl.java   |   3 +-
 .../org/apache/calcite/avatica/SqlState.java    |   7 +-
 .../remote/AvaticaRemoteConnectionProperty.java |   3 +-
 .../apache/calcite/avatica/remote/Driver.java   |   4 +-
 .../avatica/remote/RemoteProtobufService.java   |   4 +-
 .../calcite/avatica/util/AbstractCursor.java    |   2 +-
 .../org/apache/calcite/avatica/util/Base64.java |  24 ++--
 .../calcite/avatica/util/DateTimeUtils.java     |  32 +++--
 .../org/apache/calcite/avatica/util/Unsafe.java |  55 +++++++++
 .../AvaticaResultSetConversionsTest.java        |   5 +-
 .../calcite/avatica/MetaResultSetTest.java      |   7 +-
 .../avatica/remote/KerberosConnectionTest.java  |   4 +-
 .../calcite/avatica/remote/TypedValueTest.java  |  12 +-
 .../calcite/avatica/test/AvaticaUtilsTest.java  |   5 +-
 avatica/pom.xml                                 |  39 ++++++
 .../apache/calcite/avatica/jdbc/JdbcMeta.java   |   3 +-
 .../calcite/avatica/jdbc/JdbcResultSet.java     |   2 +-
 .../calcite/avatica/server/HttpServer.java      |   8 +-
 .../calcite/avatica/RemoteDriverTest.java       | 123 +++++++++++--------
 .../apache/calcite/avatica/SpnegoTestUtil.java  |  10 +-
 .../apache/calcite/avatica/SslDriverTest.java   |   5 +-
 .../calcite/avatica/remote/RemoteMetaTest.java  |  35 ++++--
 .../server/AbstractAvaticaHandlerTest.java      |   3 +-
 .../server/HttpServerSpnegoWithJaasTest.java    |   4 +-
 .../server/HttpServerSpnegoWithoutJaasTest.java |   4 +-
 .../main/config/forbidden-apis/signatures.txt   |  39 ++++++
 .../calcite/avatica/hsqldb/HsqldbServer.java    |   9 +-
 .../apache/calcite/avatica/tck/TestRunner.java  |  12 +-
 .../org/apache/calcite/avatica/tck/Unsafe.java  |  55 +++++++++
 34 files changed, 406 insertions(+), 125 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java
index 31cdfd2..e611c9a 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaPreparedStatement.java
@@ -39,6 +39,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Implementation of {@link java.sql.PreparedStatement}
@@ -115,7 +116,7 @@ public abstract class AvaticaPreparedStatement
    */
   protected synchronized Calendar getCalendar() {
     if (calendar == null) {
-      calendar = Calendar.getInstance(connection.getTimeZone());
+      calendar = Calendar.getInstance(connection.getTimeZone(), Locale.ROOT);
     }
     return calendar;
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
index a102eba..51bf8fa 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaResultSet.java
@@ -40,6 +40,7 @@ import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.Calendar;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.TimeZone;
 
@@ -87,7 +88,7 @@ public class AvaticaResultSet implements ResultSet, ArrayImpl.Factory {
     this.fetchSize = statement.getFetchSize();
     this.fetchDirection = statement.getFetchDirection();
     this.resultSetMetaData = resultSetMetaData;
-    this.localCalendar = Calendar.getInstance(timeZone);
+    this.localCalendar = Calendar.getInstance(timeZone, Locale.ROOT);
   }
 
   private int findColumn0(String columnLabel) throws SQLException {

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java
index b33b0b2..0e23866 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaSite.java
@@ -24,6 +24,7 @@ import java.io.Reader;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.sql.Array;
 import java.sql.Blob;
 import java.sql.Clob;
@@ -477,7 +478,7 @@ public class AvaticaSite {
       return (byte[]) x;
     }
     if (x instanceof String) {
-      return ((String) x).getBytes();
+      return ((String) x).getBytes(StandardCharsets.UTF_8);
     }
     throw unsupportedCast(x.getClass(), byte[].class);
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaUtils.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaUtils.java b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaUtils.java
index 53aff83..56a23c8 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaUtils.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/AvaticaUtils.java
@@ -37,6 +37,7 @@ import java.util.Set;
 
 /** Avatica utilities. */
 public class AvaticaUtils {
+
   private static final Map<Class, Class> BOX;
 
   private static final MethodHandle SET_LARGE_MAX_ROWS =

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/BuiltInConnectionProperty.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/BuiltInConnectionProperty.java b/avatica/core/src/main/java/org/apache/calcite/avatica/BuiltInConnectionProperty.java
index aa7d710..d68bae8 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/BuiltInConnectionProperty.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/BuiltInConnectionProperty.java
@@ -20,6 +20,7 @@ import org.apache.calcite.avatica.remote.AvaticaHttpClientFactoryImpl;
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -90,7 +91,7 @@ public enum BuiltInConnectionProperty implements ConnectionProperty {
   static {
     NAME_TO_PROPS = new HashMap<>();
     for (BuiltInConnectionProperty p : BuiltInConnectionProperty.values()) {
-      NAME_TO_PROPS.put(p.camelName.toUpperCase(), p);
+      NAME_TO_PROPS.put(p.camelName.toUpperCase(Locale.ROOT), p);
       NAME_TO_PROPS.put(p.name(), p);
     }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/ConnectionConfigImpl.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/ConnectionConfigImpl.java b/avatica/core/src/main/java/org/apache/calcite/avatica/ConnectionConfigImpl.java
index e9d7272..a003b82 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/ConnectionConfigImpl.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/ConnectionConfigImpl.java
@@ -22,6 +22,7 @@ import org.apache.calcite.avatica.remote.Service;
 import java.io.File;
 import java.math.BigDecimal;
 import java.util.LinkedHashMap;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 
@@ -121,7 +122,7 @@ public class ConnectionConfigImpl implements ConnectionConfig {
         new LinkedHashMap<ConnectionProperty, String>();
     for (String name : properties.stringPropertyNames()) {
       final ConnectionProperty connectionProperty =
-          nameToProps.get(name.toUpperCase());
+          nameToProps.get(name.toUpperCase(Locale.ROOT));
       if (connectionProperty == null) {
         // For now, don't throw. It messes up sub-projects.
         //throw new RuntimeException("Unknown property '" + name + "'");

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/SqlState.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/SqlState.java b/avatica/core/src/main/java/org/apache/calcite/avatica/SqlState.java
index 1459757..9f967aa 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/SqlState.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/SqlState.java
@@ -16,7 +16,10 @@
  */
 package org.apache.calcite.avatica;
 
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -1810,7 +1813,9 @@ public enum SqlState {
 
   /** Validates the data, and generates the HTML table. */
   private static void main(String[] args) {
-    PrintWriter pw = new PrintWriter(System.out);
+    PrintWriter pw = new PrintWriter(
+        new BufferedWriter(
+            new OutputStreamWriter(System.out, StandardCharsets.UTF_8)));
     pw.println(" * <table>");
     SqlState parent = null;
     for (SqlState s : values()) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaRemoteConnectionProperty.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaRemoteConnectionProperty.java b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaRemoteConnectionProperty.java
index e0d9bb1..e965989 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaRemoteConnectionProperty.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/AvaticaRemoteConnectionProperty.java
@@ -19,6 +19,7 @@ package org.apache.calcite.avatica.remote;
 import org.apache.calcite.avatica.ConnectionProperty;
 
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 
@@ -42,7 +43,7 @@ public enum AvaticaRemoteConnectionProperty implements ConnectionProperty {
     NAME_TO_PROPS = new HashMap<>();
     for (AvaticaRemoteConnectionProperty p
         : AvaticaRemoteConnectionProperty.values()) {
-      NAME_TO_PROPS.put(p.camelName.toUpperCase(), p);
+      NAME_TO_PROPS.put(p.camelName.toUpperCase(Locale.ROOT), p);
       NAME_TO_PROPS.put(p.name(), p);
     }
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Driver.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Driver.java b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Driver.java
index 86f0814..3f6d4df 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Driver.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/Driver.java
@@ -35,6 +35,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 import java.util.Properties;
 
 /**
@@ -184,7 +185,8 @@ public class Driver extends UnregisteredDriver {
     Serialization serializationType = Serialization.JSON;
     if (null != serializationStr) {
       try {
-        serializationType = Serialization.valueOf(serializationStr.toUpperCase());
+        serializationType =
+            Serialization.valueOf(serializationStr.toUpperCase(Locale.ROOT));
       } catch (Exception e) {
         // Log a warning instead of failing harshly? Intentionally no loggers available?
         throw new RuntimeException(e);

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/remote/RemoteProtobufService.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/RemoteProtobufService.java b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/RemoteProtobufService.java
index 2e92662..0f4cbfb 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/remote/RemoteProtobufService.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/remote/RemoteProtobufService.java
@@ -20,6 +20,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 
 /**
@@ -51,7 +52,8 @@ public class RemoteProtobufService extends ProtobufService {
     try {
       resp = translation.parseResponse(response);
     } catch (IOException e) {
-      LOG.debug("Failed to deserialize reponse to {}. '{}'", request, new String(response));
+      LOG.debug("Failed to deserialize reponse to {}. '{}'", request,
+          new String(response, StandardCharsets.UTF_8));
       // Not a protobuf that we could parse.
       throw new RuntimeException(e);
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java b/avatica/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
index 3bf69d6..77739ab 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
@@ -792,7 +792,7 @@ public abstract class AbstractCursor implements Cursor {
       if (obj instanceof ByteString) {
         return ((ByteString) obj).getBytes();
       } else if (obj instanceof String) {
-        return ((String) obj).getBytes();
+        return ((String) obj).getBytes(StandardCharsets.UTF_8);
       } else if (obj instanceof byte[]) {
         return (byte[]) obj;
       } else {

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/util/Base64.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/util/Base64.java b/avatica/core/src/main/java/org/apache/calcite/avatica/util/Base64.java
index c2393b1..c42b1f5 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/util/Base64.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/util/Base64.java
@@ -18,6 +18,9 @@ package org.apache.calcite.avatica.util;
 
 //CHECKSTYLE: OFF
 
+import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+
 /**
  * <p>Encodes and decodes to and from Base64 notation.</p>
  * <p>Homepage: <a href="http://iharder.net/base64">http://iharder.net/base64</a>.</p>
@@ -713,7 +716,7 @@ public class Base64
     }   // end try
     catch (java.io.UnsupportedEncodingException uue){
       // Fall back to some Java default
-      return new String( baos.toByteArray() );
+      return new String( baos.toByteArray(), StandardCharsets.UTF_8 );
     }   // end catch
 
   }   // end encode
@@ -853,7 +856,7 @@ public class Base64
       return new String( encoded, PREFERRED_ENCODING );
     }   // end try
     catch (java.io.UnsupportedEncodingException uue) {
-      return new String( encoded );
+      return new String( encoded, StandardCharsets.UTF_8 );
     }   // end catch
 
   }   // end encodeBytes
@@ -917,7 +920,9 @@ public class Base64
 
     if( off + len > source.length  ){
       throw new IllegalArgumentException(
-          String.format( "Cannot have offset of %d and length of %d with array of length %d", off,len,source.length));
+          String.format( Locale.ROOT,
+              "Cannot have offset of %d and length of %d with array of length %d",
+              off,len,source.length ) );
     }   // end if: off < 0
 
 
@@ -1057,11 +1062,11 @@ public class Base64
       throw new NullPointerException( "Destination array was null." );
     }   // end if
     if( srcOffset < 0 || srcOffset + 3 >= source.length ){
-      throw new IllegalArgumentException( String.format(
+      throw new IllegalArgumentException( String.format( Locale.ROOT,
           "Source array with length %d cannot have offset of %d and still process four bytes.", source.length, srcOffset ) );
     }   // end if
     if( destOffset < 0 || destOffset +2 >= destination.length ){
-      throw new IllegalArgumentException( String.format(
+      throw new IllegalArgumentException( String.format( Locale.ROOT,
           "Destination array with length %d cannot have offset of %d and still store three bytes.", destination.length, destOffset ) );
     }   // end if
 
@@ -1171,7 +1176,7 @@ public class Base64
       throw new NullPointerException( "Cannot decode null source array." );
     }   // end if
     if( off < 0 || off + len > source.length ){
-      throw new IllegalArgumentException( String.format(
+      throw new IllegalArgumentException( String.format( Locale.ROOT,
           "Source array with length %d cannot have offset of %d and process %d bytes.", source.length, off, len ) );
     }   // end if
 
@@ -1216,8 +1221,9 @@ public class Base64
       }   // end if: white space, equals sign or better
       else {
         // There's a bad input character in the Base64 stream.
-        throw new java.io.IOException( String.format(
-            "Bad Base64 input character decimal %d in array position %d", ((int)source[i])&0xFF, i ) );
+        throw new java.io.IOException( String.format( Locale.ROOT,
+            "Bad Base64 input character decimal %d in array position %d",
+            ((int)source[i])&0xFF, i ) );
       }   // end else:
     }   // each input character
 
@@ -1266,7 +1272,7 @@ public class Base64
       bytes = s.getBytes( PREFERRED_ENCODING );
     }   // end try
     catch( java.io.UnsupportedEncodingException uee ) {
-      bytes = s.getBytes();
+      bytes = s.getBytes( StandardCharsets.UTF_8 );
     }   // end catch
     //</change>
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java b/avatica/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java
index 85b6d6c..406dcfd 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java
@@ -20,6 +20,7 @@ import java.text.NumberFormat;
 import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
+import java.util.Locale;
 import java.util.TimeZone;
 
 /**
@@ -48,9 +49,15 @@ public class DateTimeUtils {
   public static final String TIMESTAMP_FORMAT_STRING =
       DATE_FORMAT_STRING + " " + TIME_FORMAT_STRING;
 
-  /** The GMT time zone. */
+  /** The GMT time zone.
+   *
+   * @deprecated Use {@link #UTC_ZONE} */
+  @Deprecated // to be removed before 2.0
   public static final TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT");
 
+  /** The UTC time zone. */
+  public static final TimeZone UTC_ZONE = TimeZone.getTimeZone("UTC");
+
   /** The Java default time zone. */
   public static final TimeZone DEFAULT_ZONE = TimeZone.getDefault();
 
@@ -85,15 +92,10 @@ public class DateTimeUtils {
   public static final Calendar ZERO_CALENDAR;
 
   static {
-    ZERO_CALENDAR = Calendar.getInstance(DateTimeUtils.GMT_ZONE);
+    ZERO_CALENDAR = Calendar.getInstance(DateTimeUtils.GMT_ZONE, Locale.ROOT);
     ZERO_CALENDAR.setTimeInMillis(0);
   }
 
-  /**
-   * Calendar set to local time.
-   */
-  private static final Calendar LOCAL_CALENDAR = Calendar.getInstance();
-
   //~ Methods ----------------------------------------------------------------
 
   /**
@@ -117,11 +119,11 @@ public class DateTimeUtils {
       TimeZone tz,
       ParsePosition pp) {
     assert pattern != null;
-    SimpleDateFormat df = new SimpleDateFormat(pattern);
+    SimpleDateFormat df = new SimpleDateFormat(pattern, Locale.ROOT);
     if (tz == null) {
       tz = DEFAULT_ZONE;
     }
-    Calendar ret = Calendar.getInstance(tz);
+    Calendar ret = Calendar.getInstance(tz, Locale.ROOT);
     df.setCalendar(ret);
     df.setLenient(false);
 
@@ -204,7 +206,7 @@ public class DateTimeUtils {
         if (!secFraction.matches("\\d+")) {
           return null;
         }
-        NumberFormat nf = NumberFormat.getIntegerInstance();
+        NumberFormat nf = NumberFormat.getIntegerInstance(Locale.ROOT);
         Number num = nf.parse(s, pp);
         if ((num == null) || (pp.getIndex() != s.length())) {
           // Invalid decimal portion
@@ -248,7 +250,7 @@ public class DateTimeUtils {
    * @throws IllegalArgumentException if the given pattern is invalid
    */
   public static void checkDateFormat(String pattern) {
-    new SimpleDateFormat(pattern);
+    new SimpleDateFormat(pattern, Locale.ROOT);
   }
 
   /**
@@ -258,7 +260,7 @@ public class DateTimeUtils {
    * @param format {@link SimpleDateFormat}  pattern
    */
   public static SimpleDateFormat newDateFormat(String format) {
-    SimpleDateFormat sdf = new SimpleDateFormat(format);
+    SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.ROOT);
     sdf.setLenient(false);
     return sdf;
   }
@@ -999,6 +1001,12 @@ public class DateTimeUtils {
     return x - floorDiv(x, y) * y;
   }
 
+  /** Creates an instance of {@link Calendar} in the root locale and UTC time
+   * zone. */
+  public static Calendar calendar() {
+    return Calendar.getInstance(UTC_ZONE, Locale.ROOT);
+  }
+
   //~ Inner Classes ----------------------------------------------------------
 
   /**

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/main/java/org/apache/calcite/avatica/util/Unsafe.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/util/Unsafe.java b/avatica/core/src/main/java/org/apache/calcite/avatica/util/Unsafe.java
new file mode 100644
index 0000000..1d0238c
--- /dev/null
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/util/Unsafe.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.util;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Contains methods that call JDK methods that the
+ * <a href="https://github.com/policeman-tools/forbidden-apis">forbidden
+ * APIs checker</a> does not approve of.
+ *
+ * <p>This class is excluded from the check, so methods called via this class
+ * will not fail the build.
+ */
+public class Unsafe {
+  private Unsafe() {}
+
+  /** Calls {@link System#exit}. */
+  public static void systemExit(int status) {
+    System.exit(status);
+  }
+
+  /** Calls {@link Object#notifyAll()}. */
+  public static void notifyAll(Object o) {
+    o.notifyAll();
+  }
+
+  /** Calls {@link Object#wait()}. */
+  public static void wait(Object o) throws InterruptedException {
+    o.wait();
+  }
+
+  /** Returns a {@link java.util.Calendar} with the local time zone and root
+   * locale. */
+  public static Calendar localCalendar() {
+    return Calendar.getInstance(Locale.ROOT);
+  }
+}
+
+// End Unsafe.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaResultSetConversionsTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaResultSetConversionsTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaResultSetConversionsTest.java
index 95d160b..bf3047f 100644
--- a/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaResultSetConversionsTest.java
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/AvaticaResultSetConversionsTest.java
@@ -18,6 +18,7 @@ package org.apache.calcite.avatica;
 
 import org.apache.calcite.avatica.ColumnMetaData.AvaticaType;
 import org.apache.calcite.avatica.remote.TypedValue;
+import org.apache.calcite.avatica.util.DateTimeUtils;
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -43,7 +44,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.TimeZone;
 
 import static org.hamcrest.CoreMatchers.isA;
 import static org.junit.Assert.assertEquals;
@@ -913,8 +913,7 @@ public class AvaticaResultSetConversionsTest {
     }
   }
 
-  private static final Calendar DEFAULT_CALENDAR = Calendar
-      .getInstance(TimeZone.getTimeZone("GMT"));
+  private static final Calendar DEFAULT_CALENDAR = DateTimeUtils.calendar();
 
   private static Connection connection = null;
   private static ResultSet resultSet = null;

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/test/java/org/apache/calcite/avatica/MetaResultSetTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/MetaResultSetTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/MetaResultSetTest.java
index 6ec1dc7..3d5eb80 100644
--- a/avatica/core/src/test/java/org/apache/calcite/avatica/MetaResultSetTest.java
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/MetaResultSetTest.java
@@ -30,6 +30,7 @@ import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Types;
 import java.util.List;
+import java.util.Locale;
 
 import static org.junit.Assert.assertEquals;
 
@@ -624,21 +625,21 @@ public class MetaResultSetTest {
   private static void assertColumn(ResultSetMetaData rsMeta, int column, String name, int type,
       int nullable) throws SQLException {
     assertEquals(
-        String.format(
+        String.format(Locale.ROOT,
             "Expected column %d to be named '%s', was '%s'.",
             column, name, rsMeta.getColumnName(column)),
         name,
         rsMeta.getColumnName(column));
 
     assertEquals(
-        String.format(
+        String.format(Locale.ROOT,
             "Expected column %d type to be '%d', was '%d'.",
             column, type, rsMeta.getColumnType(column)),
         type,
         rsMeta.getColumnType(column));
 
     assertEquals(
-        String.format(
+        String.format(Locale.ROOT,
             "Expected column %d nullability to be '%d', was '%d'.",
             column, nullable, rsMeta.isNullable(column)),
         nullable,

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/test/java/org/apache/calcite/avatica/remote/KerberosConnectionTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/KerberosConnectionTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/KerberosConnectionTest.java
index a57b95b..ad98569 100644
--- a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/KerberosConnectionTest.java
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/KerberosConnectionTest.java
@@ -22,6 +22,7 @@ import org.junit.Test;
 import org.mockito.Mockito;
 
 import java.io.File;
+import java.util.Locale;
 import java.util.Map.Entry;
 
 import javax.security.auth.Subject;
@@ -135,7 +136,8 @@ public class KerberosConnectionTest {
     end = start + 1000 * 60 * 60 * 24;
     // Ten minutes prior to expiration
     now = end - 1000 * 60 * 10;
-    assertTrue(String.format("start=%d, end=%d, now=%d", start, end, now),
+    assertTrue(
+        String.format(Locale.ROOT, "start=%d, end=%d, now=%d", start, end, now),
         renewal.shouldRenew(start, end, now));
   }
 }

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java
index 9343ed2..7606a87 100644
--- a/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/remote/TypedValueTest.java
@@ -20,12 +20,12 @@ import org.apache.calcite.avatica.ColumnMetaData.Rep;
 import org.apache.calcite.avatica.proto.Common;
 import org.apache.calcite.avatica.util.Base64;
 import org.apache.calcite.avatica.util.ByteString;
+import org.apache.calcite.avatica.util.DateTimeUtils;
 
 import org.junit.Test;
 
 import java.math.BigDecimal;
 import java.util.Calendar;
-import java.util.GregorianCalendar;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
@@ -123,7 +123,8 @@ public class TypedValueTest {
     assertEquals(new ByteString(bytes).toBase64String(), (String) deserializedObj);
 
     // But we should get a non-b64 byte array as the JDBC representation
-    deserializedObj = TypedValue.protoToJdbc(proto, GregorianCalendar.getInstance());
+    deserializedObj =
+        TypedValue.protoToJdbc(proto, DateTimeUtils.calendar());
     assertThat(deserializedObj, is(instanceOf(byte[].class)));
     assertArrayEquals(bytes, (byte[]) deserializedObj);
   }
@@ -151,7 +152,7 @@ public class TypedValueTest {
 
   @Test public void testLegacyDecimalParsing() {
     final BigDecimal decimal = new BigDecimal("123451234512345");
-    final Calendar calendar = GregorianCalendar.getInstance();
+    final Calendar calendar = DateTimeUtils.calendar();
 
     // CALCITE-1103 Decimals were (incorrectly) getting serialized as normal "numbers" which
     // caused them to use the numberValue field. TypedValue should still be able to handle
@@ -169,7 +170,7 @@ public class TypedValueTest {
     final byte[] b64Bytes = Base64.encodeBytes(bytes).getBytes(UTF_8);
     TypedValue tv = TypedValue.ofLocal(Rep.BYTE_STRING, new ByteString(bytes));
     // JSON encodes it as base64
-    assertEquals(new String(b64Bytes), tv.value);
+    assertEquals(new String(b64Bytes, UTF_8), tv.value);
 
     // Get the protobuf variant
     Common.TypedValue protoTv = tv.toProto();
@@ -182,7 +183,8 @@ public class TypedValueTest {
     assertArrayEquals(bytes, protoByteString.toByteArray());
 
     // We should have the b64 string as a backwards compatibility feature
-    assertEquals(new String(b64Bytes), protoTv.getStringValue());
+    assertEquals(new String(b64Bytes, UTF_8),
+        protoTv.getStringValue());
   }
 
   @Test public void testLegacyBase64StringEncodingForBytes() {

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java
index 366b507..b1a422c 100644
--- a/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java
+++ b/avatica/core/src/test/java/org/apache/calcite/avatica/test/AvaticaUtilsTest.java
@@ -28,6 +28,7 @@ import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
+import java.util.Locale;
 import java.util.Properties;
 import java.util.Set;
 
@@ -292,11 +293,11 @@ public class AvaticaUtilsTest {
     }
 
     public String name() {
-      return name.toUpperCase();
+      return name.toUpperCase(Locale.ROOT);
     }
 
     public String camelName() {
-      return name.toLowerCase();
+      return name.toLowerCase(Locale.ROOT);
     }
 
     public Object defaultValue() {

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/pom.xml
----------------------------------------------------------------------
diff --git a/avatica/pom.xml b/avatica/pom.xml
index d8952aa..5860bd9 100644
--- a/avatica/pom.xml
+++ b/avatica/pom.xml
@@ -58,6 +58,7 @@ limitations under the License.
     <build-helper-maven-plugin.version>1.9</build-helper-maven-plugin.version>
     <checksum-maven-plugin.version>1.2</checksum-maven-plugin.version>
     <dropwizard-metrics3.version>3.1.2</dropwizard-metrics3.version>
+    <forbiddenapis.version>2.3</forbiddenapis.version>
     <freemarker.version>2.3.19</freemarker.version>
     <git-commit-id-plugin.version>2.1.9</git-commit-id-plugin.version>
     <!-- We support guava versions as old as 14.0.1 (the version used by Hive)
@@ -300,6 +301,39 @@ limitations under the License.
     </extensions>
     <plugins>
       <plugin>
+        <groupId>de.thetaphi</groupId>
+        <artifactId>forbiddenapis</artifactId>
+        <configuration>
+          <!-- if the used Java version is too new, don't fail, just do nothing: -->
+          <failOnUnsupportedJava>false</failOnUnsupportedJava>
+          <bundledSignatures>
+            <!--
+              This will automatically choose the right
+              signatures based on 'maven.compiler.target':
+            -->
+            <bundledSignature>jdk-unsafe</bundledSignature>
+            <bundledSignature>jdk-deprecated</bundledSignature>
+            <!-- disallow undocumented classes like sun.misc.Unsafe: -->
+            <bundledSignature>jdk-non-portable</bundledSignature>
+          </bundledSignatures>
+          <signaturesFiles>
+            <signaturesFile>${top.dir}/src/main/config/forbidden-apis/signatures.txt</signaturesFile>
+          </signaturesFiles>
+          <excludes>
+            <exclude>**/org/apache/calcite/avatica/tck/Unsafe.class</exclude>
+            <exclude>**/org/apache/calcite/avatica/util/Unsafe.class</exclude>
+          </excludes>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>check</goal>
+              <goal>testCheck</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
         <groupId>org.apache.rat</groupId>
         <artifactId>apache-rat-plugin</artifactId>
         <configuration>
@@ -486,6 +520,11 @@ limitations under the License.
           </dependencies>
         </plugin>
         <plugin>
+          <groupId>de.thetaphi</groupId>
+          <artifactId>forbiddenapis</artifactId>
+          <version>${forbiddenapis.version}</version>
+        </plugin>
+        <plugin>
           <groupId>net.hydromatic</groupId>
           <artifactId>hydromatic-resource-maven-plugin</artifactId>
           <version>${hydromatic-resource.version}</version>

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java b/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
index e90d78a..4756e8d 100644
--- a/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
+++ b/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcMeta.java
@@ -35,6 +35,7 @@ import org.apache.calcite.avatica.proto.Common;
 import org.apache.calcite.avatica.proto.Requests;
 import org.apache.calcite.avatica.remote.ProtobufMeta;
 import org.apache.calcite.avatica.remote.TypedValue;
+import org.apache.calcite.avatica.util.Unsafe;
 
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
@@ -85,7 +86,7 @@ public class JdbcMeta implements ProtobufMeta {
 
   // End of constants, start of member variables
 
-  final Calendar calendar = Calendar.getInstance();
+  final Calendar calendar = Unsafe.localCalendar();
 
   /** Generates ids for statements. The ids are unique across all connections
    * created by this JdbcMeta. */

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java b/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java
index 5383289..17b33f8 100644
--- a/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java
+++ b/avatica/server/src/main/java/org/apache/calcite/avatica/jdbc/JdbcResultSet.java
@@ -77,7 +77,7 @@ class JdbcResultSet extends Meta.MetaResultSet {
   public static JdbcResultSet create(String connectionId, int statementId,
       ResultSet resultSet, int maxRowCount, Meta.Signature signature) {
     try {
-      final Calendar calendar = Calendar.getInstance(DateTimeUtils.GMT_ZONE);
+      final Calendar calendar = DateTimeUtils.calendar();
       final int fetchRowCount;
       if (maxRowCount == JdbcMeta.UNLIMITED_COUNT) {
         fetchRowCount = -1;

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/main/java/org/apache/calcite/avatica/server/HttpServer.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/main/java/org/apache/calcite/avatica/server/HttpServer.java b/avatica/server/src/main/java/org/apache/calcite/avatica/server/HttpServer.java
index 911d359..4c871f0 100644
--- a/avatica/server/src/main/java/org/apache/calcite/avatica/server/HttpServer.java
+++ b/avatica/server/src/main/java/org/apache/calcite/avatica/server/HttpServer.java
@@ -49,6 +49,7 @@ import java.security.Principal;
 import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -246,7 +247,8 @@ public class HttpServer {
 
     final int port = connector.getLocalPort();
 
-    return new RpcMetadataResponse(String.format("%s:%d", host, port));
+    return new RpcMetadataResponse(
+        String.format(Locale.ROOT, "%s:%d", host, port));
   }
 
   /**
@@ -804,7 +806,9 @@ public class HttpServer {
         options.put("doNotPrompt", "true");
         options.put("useKeyTab", "true");
         options.put("isInitiator", "false");
-        options.put("debug", System.getProperty("sun.security.krb5.debug", "false").toLowerCase());
+        options.put("debug",
+            System.getProperty("sun.security.krb5.debug", "false")
+                .toLowerCase(Locale.ROOT));
 
         return new AppConfigurationEntry[] {new AppConfigurationEntry(getKrb5LoginModuleName(),
             AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options)};

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java b/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
index 10bf85f..0823a12 100644
--- a/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
+++ b/avatica/server/src/test/java/org/apache/calcite/avatica/RemoteDriverTest.java
@@ -26,6 +26,7 @@ import org.apache.calcite.avatica.remote.ProtobufTranslation;
 import org.apache.calcite.avatica.remote.ProtobufTranslationImpl;
 import org.apache.calcite.avatica.remote.Service;
 import org.apache.calcite.avatica.remote.TypedValue;
+import org.apache.calcite.avatica.util.DateTimeUtils;
 
 import com.google.common.cache.Cache;
 
@@ -59,6 +60,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 import java.util.TimeZone;
@@ -363,10 +365,11 @@ public class RemoteDriverTest {
   @Test public void testInsertDrop() throws Exception {
     final String t = AvaticaUtils.unique("TEST_TABLE2");
     final String create =
-        String.format("create table if not exists %s ("
+        String.format(Locale.ROOT, "create table if not exists %s ("
             + "id int not null, "
             + "msg varchar(3) not null)", t);
-    final String insert = String.format("insert into %s values(1, 'foo')", t);
+    final String insert = String.format(Locale.ROOT,
+        "insert into %s values(1, 'foo')", t);
     Connection connection = ljs();
     Statement statement = connection.createStatement();
     statement.execute(create);
@@ -558,14 +561,17 @@ public class RemoteDriverTest {
   @Test public void testCreateInsertUpdateDrop() throws Exception {
     ConnectionSpec.getDatabaseLock().lock();
     final String t = AvaticaUtils.unique("TEST_TABLE");
-    final String drop = String.format("drop table %s if exists", t);
-    final String create = String.format("create table %s("
-        + "id int not null, "
-        + "msg varchar(3) not null)",
-        t);
-    final String insert = String.format("insert into %s values(1, 'foo')", t);
+    final String drop =
+        String.format(Locale.ROOT, "drop table %s if exists", t);
+    final String create =
+        String.format(Locale.ROOT, "create table %s("
+                + "id int not null, "
+                + "msg varchar(3) not null)",
+            t);
+    final String insert = String.format(Locale.ROOT,
+        "insert into %s values(1, 'foo')", t);
     final String update =
-        String.format("update %s set msg='bar' where id=1", t);
+        String.format(Locale.ROOT, "update %s set msg='bar' where id=1", t);
     try (Connection connection = getLocalConnection();
         Statement statement = connection.createStatement();
         PreparedStatement pstmt = connection.prepareStatement("values 1")) {
@@ -681,9 +687,11 @@ public class RemoteDriverTest {
   private void assertResultSetsEqual(Statement s1, Statement s2)
       throws SQLException {
     final TimeZone moscowTz = TimeZone.getTimeZone("Europe/Moscow");
-    final Calendar moscowCalendar = Calendar.getInstance(moscowTz);
+    final Calendar moscowCalendar =
+        Calendar.getInstance(moscowTz, Locale.ROOT);
     final TimeZone alaskaTz = TimeZone.getTimeZone("America/Anchorage");
-    final Calendar alaskaCalendar = Calendar.getInstance(alaskaTz);
+    final Calendar alaskaCalendar =
+        Calendar.getInstance(alaskaTz, Locale.ROOT);
     try (ResultSet rs1 = s1.getResultSet();
         ResultSet rs2 = s2.getResultSet()) {
       assertEquals(rs1.getMetaData().getColumnCount(),
@@ -1058,12 +1066,14 @@ public class RemoteDriverTest {
     try (Statement stmt = conn.createStatement()) {
       final String tableName = AvaticaUtils.unique("BATCH_EXECUTE");
       LOG.info("Creating table {}", tableName);
-      final String createCommand = String.format("create table if not exists %s ("
-          + "id int not null, "
-          + "msg varchar(10) not null)", tableName);
+      final String createCommand = String.format(Locale.ROOT,
+          "create table if not exists %s ("
+              + "id int not null, "
+              + "msg varchar(10) not null)", tableName);
       assertFalse("Failed to create table", stmt.execute(createCommand));
 
-      final String updatePrefix = String.format("INSERT INTO %s values(", tableName);
+      final String updatePrefix =
+          String.format(Locale.ROOT, "INSERT INTO %s values(", tableName);
       for (int i = 0; i < numRows;  i++) {
         stmt.addBatch(updatePrefix + i + ", '" + Integer.toString(i) + "')");
       }
@@ -1104,13 +1114,15 @@ public class RemoteDriverTest {
     final String tableName = AvaticaUtils.unique("PREPARED_BATCH_EXECUTE");
     LOG.info("Creating table {}", tableName);
     try (Statement stmt = conn.createStatement()) {
-      final String createCommand = String.format("create table if not exists %s ("
-          + "id int not null, "
-          + "msg varchar(10) not null)", tableName);
+      final String createCommand =
+          String.format(Locale.ROOT, "create table if not exists %s ("
+              + "id int not null, "
+              + "msg varchar(10) not null)", tableName);
       assertFalse("Failed to create table", stmt.execute(createCommand));
     }
 
-    final String insertSql = String.format("INSERT INTO %s values(?, ?)", tableName);
+    final String insertSql =
+        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
     try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
       // Add batches with the prepared statement
       for (int i = 0; i < numRows; i++) {
@@ -1157,13 +1169,15 @@ public class RemoteDriverTest {
     final String tableName = AvaticaUtils.unique("PREPARED_INSERT_EXECUTE");
     LOG.info("Creating table {}", tableName);
     try (Statement stmt = conn.createStatement()) {
-      final String createCommand = String.format("create table if not exists %s ("
-          + "id int not null, "
-          + "msg varchar(10) not null)", tableName);
+      final String createCommand =
+          String.format(Locale.ROOT, "create table if not exists %s ("
+              + "id int not null, "
+              + "msg varchar(10) not null)", tableName);
       assertFalse("Failed to create table", stmt.execute(createCommand));
     }
 
-    final String insertSql = String.format("INSERT INTO %s values(?, ?)", tableName);
+    final String insertSql =
+        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
     try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
       // Add batches with the prepared statement
       for (int i = 0; i < numRows; i++) {
@@ -1204,13 +1218,15 @@ public class RemoteDriverTest {
     final String tableName = AvaticaUtils.unique("PREPARED_INSERT_EXECUTE_NULLS");
     LOG.info("Creating table {}", tableName);
     try (Statement stmt = conn.createStatement()) {
-      final String createCommand = String.format("create table if not exists %s ("
-          + "id int not null, "
-          + "msg varchar(10))", tableName);
+      final String createCommand =
+          String.format(Locale.ROOT, "create table if not exists %s ("
+              + "id int not null, "
+              + "msg varchar(10))", tableName);
       assertFalse("Failed to create table", stmt.execute(createCommand));
     }
 
-    final String insertSql = String.format("INSERT INTO %s values(?, ?)", tableName);
+    final String insertSql =
+        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
     try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
       // Add batches with the prepared statement
       for (int i = 0; i < numRows; i++) {
@@ -1260,13 +1276,15 @@ public class RemoteDriverTest {
     final String tableName = AvaticaUtils.unique("BATCH_INSERT_EXECUTE_NULLS");
     LOG.info("Creating table {}", tableName);
     try (Statement stmt = conn.createStatement()) {
-      final String createCommand = String.format("create table if not exists %s ("
-          + "id int not null, "
-          + "msg varchar(10))", tableName);
+      final String createCommand =
+          String.format(Locale.ROOT, "create table if not exists %s ("
+              + "id int not null, "
+              + "msg varchar(10))", tableName);
       assertFalse("Failed to create table", stmt.execute(createCommand));
     }
 
-    final String insertSql = String.format("INSERT INTO %s values(?, ?)", tableName);
+    final String insertSql =
+        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
     try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
       // Add batches with the prepared statement
       for (int i = 0; i < numRows; i++) {
@@ -1367,22 +1385,25 @@ public class RemoteDriverTest {
   }
 
   private void executeBatchInsertWithDates(Connection conn) throws Exception {
-    final Calendar calendar = Calendar.getInstance();
+    final Calendar calendar = DateTimeUtils.calendar();
     long now = calendar.getTime().getTime();
     final int numRows = 10;
     final String tableName = AvaticaUtils.unique("BATCH_INSERT_EXECUTE_DATES");
     LOG.info("Creating table {}", tableName);
     try (Statement stmt = conn.createStatement()) {
-      final String dropCommand = String.format("drop table if exists %s", tableName);
+      final String dropCommand =
+          String.format(Locale.ROOT, "drop table if exists %s", tableName);
       assertFalse("Failed to drop table", stmt.execute(dropCommand));
-      final String createCommand = String.format("create table %s ("
-          + "id char(15) not null, "
-          + "created_date date not null, "
-          + "val_string varchar)", tableName);
+      final String createCommand =
+          String.format(Locale.ROOT, "create table %s ("
+              + "id char(15) not null, "
+              + "created_date date not null, "
+              + "val_string varchar)", tableName);
       assertFalse("Failed to create table", stmt.execute(createCommand));
     }
 
-    final String insertSql = String.format("INSERT INTO %s values(?, ?, ?)", tableName);
+    final String insertSql =
+        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?, ?)", tableName);
     try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
       // Add batches with the prepared statement
       for (int i = 0; i < numRows; i++) {
@@ -1472,7 +1493,7 @@ public class RemoteDriverTest {
       assertNotNull(metadata);
       String actualColumnName = metadata.getColumnName(1);
       // HSQLDB is going to upper-case the column name
-      assertEquals(columnName.toUpperCase(), actualColumnName);
+      assertEquals(columnName.toUpperCase(Locale.ROOT), actualColumnName);
     } finally {
       ConnectionSpec.getDatabaseLock().unlock();
     }
@@ -1521,13 +1542,15 @@ public class RemoteDriverTest {
     final String tableName = AvaticaUtils.unique("BATCH_CLEARS");
     LOG.info("Creating table {}", tableName);
     try (Statement stmt = conn.createStatement()) {
-      final String createCommand = String.format("create table if not exists %s ("
-          + "id int not null, "
-          + "msg varchar(10) not null)", tableName);
+      final String createCommand =
+          String.format(Locale.ROOT, "create table if not exists %s ("
+              + "id int not null, "
+              + "msg varchar(10) not null)", tableName);
       assertFalse("Failed to create table", stmt.execute(createCommand));
     }
 
-    final String insertSql = String.format("INSERT INTO %s values(?, ?)", tableName);
+    final String insertSql =
+        String.format(Locale.ROOT, "INSERT INTO %s values(?, ?)", tableName);
     try (PreparedStatement pstmt = conn.prepareStatement(insertSql)) {
       // Add batches with the prepared statement
       for (int i = 0; i < numRows; i++) {
@@ -1579,12 +1602,14 @@ public class RemoteDriverTest {
     try (Statement stmt = conn.createStatement()) {
       final String tableName = AvaticaUtils.unique("BATCH_EXECUTE");
       LOG.info("Creating table {}", tableName);
-      final String createCommand = String.format("create table if not exists %s ("
-          + "id int not null, "
-          + "msg varchar(10) not null)", tableName);
+      final String createCommand =
+          String.format(Locale.ROOT, "create table if not exists %s ("
+              + "id int not null, "
+              + "msg varchar(10) not null)", tableName);
       assertFalse("Failed to create table", stmt.execute(createCommand));
 
-      final String updatePrefix = String.format("INSERT INTO %s values(", tableName);
+      final String updatePrefix =
+          String.format(Locale.ROOT, "INSERT INTO %s values(", tableName);
       for (int i = 0; i < numRows;  i++) {
         stmt.addBatch(updatePrefix + i + ", '" + Integer.toString(i) + "')");
         if (numRows / 2 - 1 == i) {
@@ -1688,7 +1713,7 @@ public class RemoteDriverTest {
       String sql = "CREATE TABLE " + tableName + " (keycolumn VARCHAR(5), column1 date)";
       assertFalse(stmt.execute(sql));
       TimeZone tzUtc = TimeZone.getTimeZone("UTC");
-      Calendar cUtc = Calendar.getInstance(tzUtc);
+      Calendar cUtc = Calendar.getInstance(tzUtc, Locale.ROOT);
       cUtc.set(Calendar.YEAR, 1970);
       cUtc.set(Calendar.MONTH, Calendar.JANUARY);
       cUtc.set(Calendar.DAY_OF_MONTH, 1);
@@ -1726,7 +1751,7 @@ public class RemoteDriverTest {
       String sql = "CREATE TABLE " + tableName + " (keycolumn VARCHAR(5), column1 date)";
       assertFalse(stmt.execute(sql));
       TimeZone tzUtc = TimeZone.getTimeZone("GMT+8");
-      Calendar cUtc = Calendar.getInstance(tzUtc);
+      Calendar cUtc = Calendar.getInstance(tzUtc, Locale.ROOT);
       cUtc.set(Calendar.YEAR, 1970);
       cUtc.set(Calendar.MONTH, Calendar.JANUARY);
       cUtc.set(Calendar.DAY_OF_MONTH, 1);

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/test/java/org/apache/calcite/avatica/SpnegoTestUtil.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/test/java/org/apache/calcite/avatica/SpnegoTestUtil.java b/avatica/server/src/test/java/org/apache/calcite/avatica/SpnegoTestUtil.java
index 21248f6..ab4491d 100644
--- a/avatica/server/src/test/java/org/apache/calcite/avatica/SpnegoTestUtil.java
+++ b/avatica/server/src/test/java/org/apache/calcite/avatica/SpnegoTestUtil.java
@@ -32,9 +32,11 @@ import org.eclipse.jetty.server.handler.DefaultHandler;
 
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileWriter;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.net.ServerSocket;
+import java.nio.charset.StandardCharsets;
 import java.security.AccessController;
 import java.security.Principal;
 import java.security.PrivilegedAction;
@@ -99,7 +101,11 @@ public class SpnegoTestUtil {
    */
   public static void writeSpnegoConf(File configFile, File serverKeytab)
       throws Exception {
-    try (BufferedWriter writer = new BufferedWriter(new FileWriter(configFile))) {
+    try (BufferedWriter writer =
+             new BufferedWriter(
+                 new OutputStreamWriter(
+                     new FileOutputStream(configFile),
+                     StandardCharsets.UTF_8))) {
       // Server login
       writer.write("com.sun.security.jgss.accept {\n");
       writer.write(" com.sun.security.auth.module.Krb5LoginModule required\n");

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/test/java/org/apache/calcite/avatica/SslDriverTest.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/test/java/org/apache/calcite/avatica/SslDriverTest.java b/avatica/server/src/test/java/org/apache/calcite/avatica/SslDriverTest.java
index 9dcdfa2..e3b89f5 100644
--- a/avatica/server/src/test/java/org/apache/calcite/avatica/SslDriverTest.java
+++ b/avatica/server/src/test/java/org/apache/calcite/avatica/SslDriverTest.java
@@ -20,6 +20,7 @@ import org.apache.calcite.avatica.jdbc.JdbcMeta;
 import org.apache.calcite.avatica.remote.Driver;
 import org.apache.calcite.avatica.remote.LocalService;
 import org.apache.calcite.avatica.server.HttpServer;
+import org.apache.calcite.avatica.util.DateTimeUtils;
 
 import org.bouncycastle.asn1.x500.X500Name;
 import org.bouncycastle.asn1.x500.style.IETFUtils;
@@ -195,8 +196,8 @@ public class SslDriverTest {
         PublicKey signerPublicKey, PrivateKey signerPrivateKey) throws IOException,
         CertIOException, OperatorCreationException, CertificateException,
         NoSuchAlgorithmException {
-      Calendar startDate = Calendar.getInstance();
-      Calendar endDate = Calendar.getInstance();
+      Calendar startDate = DateTimeUtils.calendar();
+      Calendar endDate = DateTimeUtils.calendar();
       endDate.add(Calendar.YEAR, 100);
 
       BigInteger serialNumber = BigInteger.valueOf(startDate.getTimeInMillis());

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/test/java/org/apache/calcite/avatica/remote/RemoteMetaTest.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/test/java/org/apache/calcite/avatica/remote/RemoteMetaTest.java b/avatica/server/src/test/java/org/apache/calcite/avatica/remote/RemoteMetaTest.java
index 24bcdc6..ebd3c76 100644
--- a/avatica/server/src/test/java/org/apache/calcite/avatica/remote/RemoteMetaTest.java
+++ b/avatica/server/src/test/java/org/apache/calcite/avatica/remote/RemoteMetaTest.java
@@ -66,6 +66,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Random;
@@ -319,14 +320,15 @@ public class RemoteMetaTest {
       AvaticaConnection conn = (AvaticaConnection) DriverManager.getConnection(url);
       Statement statement = conn.createStatement();
       final String create =
-          String.format("create table if not exists %s ("
+          String.format(Locale.ROOT, "create table if not exists %s ("
               + "  id int not null, msg varchar(255) not null)", t);
       int status = statement.executeUpdate(create);
       assertEquals(status, 0);
 
       statement = conn.createStatement();
-      final String update = String.format("insert into %s values ('%d', '%s')",
-          t, RANDOM.nextInt(Integer.MAX_VALUE), UUID.randomUUID());
+      final String update =
+          String.format(Locale.ROOT, "insert into %s values ('%d', '%s')",
+              t, RANDOM.nextInt(Integer.MAX_VALUE), UUID.randomUUID());
       status = statement.executeUpdate(update);
       assertEquals(status, 1);
     } finally {
@@ -584,26 +586,35 @@ public class RemoteMetaTest {
       assertFalse(stmt.execute("DROP TABLE IF EXISTS " + productTable));
       assertFalse(
           stmt.execute(
-              String.format("CREATE TABLE %s(id integer, stock integer)", productTable)));
+              String.format(Locale.ROOT,
+                  "CREATE TABLE %s(id integer, stock integer)",
+                  productTable)));
       assertFalse(stmt.execute("DROP TABLE IF EXISTS " + salesTable));
       assertFalse(
           stmt.execute(
-              String.format("CREATE TABLE %s(id integer, units_sold integer)", salesTable)));
+              String.format(Locale.ROOT,
+                  "CREATE TABLE %s(id integer, units_sold integer)",
+                  salesTable)));
 
       final int productId = 1;
       // No products and no sales
       assertFalse(
           stmt.execute(
-              String.format("INSERT INTO %s VALUES(%d, 0)", productTable, productId)));
+              String.format(Locale.ROOT, "INSERT INTO %s VALUES(%d, 0)",
+                  productTable, productId)));
       assertFalse(
           stmt.execute(
-              String.format("INSERT INTO %s VALUES(%d, 0)", salesTable, productId)));
+              String.format(Locale.ROOT, "INSERT INTO %s VALUES(%d, 0)",
+                  salesTable, productId)));
 
       conn.setAutoCommit(false);
       PreparedStatement productStmt = conn.prepareStatement(
-          String.format("UPDATE %s SET stock = stock + ? WHERE id = ?", productTable));
+          String.format(Locale.ROOT,
+              "UPDATE %s SET stock = stock + ? WHERE id = ?", productTable));
       PreparedStatement salesStmt = conn.prepareStatement(
-          String.format("UPDATE %s SET units_sold = units_sold + ? WHERE id = ?", salesTable));
+          String.format(Locale.ROOT,
+              "UPDATE %s SET units_sold = units_sold + ? WHERE id = ?",
+              salesTable));
 
       // No stock
       assertEquals(0, getInventory(conn, productTable, productId));
@@ -651,7 +662,8 @@ public class RemoteMetaTest {
   private int getInventory(Connection conn, String productTable, int productId) throws Exception {
     try (Statement stmt = conn.createStatement()) {
       ResultSet results = stmt.executeQuery(
-          String.format("SELECT stock FROM %s WHERE id = %d", productTable, productId));
+          String.format(Locale.ROOT, "SELECT stock FROM %s WHERE id = %d",
+              productTable, productId));
       assertTrue(results.next());
       return results.getInt(1);
     }
@@ -660,7 +672,8 @@ public class RemoteMetaTest {
   private int getSales(Connection conn, String salesTable, int productId) throws Exception {
     try (Statement stmt = conn.createStatement()) {
       ResultSet results = stmt.executeQuery(
-          String.format("SELECT units_sold FROM %s WHERE id = %d", salesTable, productId));
+          String.format(Locale.ROOT, "SELECT units_sold FROM %s WHERE id = %d",
+              salesTable, productId));
       assertTrue(results.next());
       return results.getInt(1);
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/test/java/org/apache/calcite/avatica/server/AbstractAvaticaHandlerTest.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/test/java/org/apache/calcite/avatica/server/AbstractAvaticaHandlerTest.java b/avatica/server/src/test/java/org/apache/calcite/avatica/server/AbstractAvaticaHandlerTest.java
index c5f9441..66eb361 100644
--- a/avatica/server/src/test/java/org/apache/calcite/avatica/server/AbstractAvaticaHandlerTest.java
+++ b/avatica/server/src/test/java/org/apache/calcite/avatica/server/AbstractAvaticaHandlerTest.java
@@ -24,6 +24,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.net.HttpURLConnection;
+import java.nio.charset.StandardCharsets;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
@@ -72,7 +73,7 @@ public class AbstractAvaticaHandlerTest {
       }
 
       @Override public boolean matches(Object item) {
-        String msg = new String((byte[]) item);
+        String msg = new String((byte[]) item, StandardCharsets.UTF_8);
         return msg.contains("User is not authenticated");
       }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithJaasTest.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithJaasTest.java b/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithJaasTest.java
index e9c5299..8f6fede 100644
--- a/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithJaasTest.java
+++ b/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithJaasTest.java
@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
 import java.io.File;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.security.Principal;
 import java.security.PrivilegedExceptionAction;
 import java.util.Set;
@@ -220,7 +221,8 @@ public class HttpServerSpnegoWithJaasTest {
 
     // We should get a response which is "OK" with our client's name
     assertNotNull(response);
-    assertEquals("OK " + SpnegoTestUtil.CLIENT_PRINCIPAL, new String(response));
+    assertEquals("OK " + SpnegoTestUtil.CLIENT_PRINCIPAL,
+        new String(response, StandardCharsets.UTF_8));
   }
 }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithoutJaasTest.java
----------------------------------------------------------------------
diff --git a/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithoutJaasTest.java b/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithoutJaasTest.java
index 1f234d2..d30b760 100644
--- a/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithoutJaasTest.java
+++ b/avatica/server/src/test/java/org/apache/calcite/avatica/server/HttpServerSpnegoWithoutJaasTest.java
@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
 import java.io.File;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.security.Principal;
 import java.security.PrivilegedExceptionAction;
 import java.util.Set;
@@ -211,7 +212,8 @@ public class HttpServerSpnegoWithoutJaasTest {
 
     // We should get a response which is "OK" with our client's name
     assertNotNull(response);
-    assertEquals("OK " + SpnegoTestUtil.CLIENT_PRINCIPAL, new String(response));
+    assertEquals("OK " + SpnegoTestUtil.CLIENT_PRINCIPAL,
+        new String(response, StandardCharsets.UTF_8));
   }
 }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/src/main/config/forbidden-apis/signatures.txt
----------------------------------------------------------------------
diff --git a/avatica/src/main/config/forbidden-apis/signatures.txt b/avatica/src/main/config/forbidden-apis/signatures.txt
new file mode 100644
index 0000000..588837d
--- /dev/null
+++ b/avatica/src/main/config/forbidden-apis/signatures.txt
@@ -0,0 +1,39 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Signatures of APIs to avoid.
+# Cribbed from Elasticsearch
+
+java.lang.Character#codePointBefore(char[],int) @ Implicit start offset is error-prone when the char[] is a buffer and the first chars are random chars
+java.lang.Character#codePointAt(char[],int) @ Implicit end offset is error-prone when the char[] is a buffer and the last chars are random chars
+
+@defaultMessage Only use wait / notify when really needed try to use concurrency primitives, latches or callbacks instead.
+java.lang.Object#wait()
+java.lang.Object#wait(long)
+java.lang.Object#wait(long,int)
+java.lang.Object#notify()
+java.lang.Object#notifyAll()
+
+@defaultMessage Please do not try to stop the world
+java.lang.System#gc()
+
+@defaultMessage Please do not try to kill the world
+java.lang.System#exit(int)
+java.lang.Runtime#exit(int)
+
+@defaultMessage Don't interrupt threads; use FutureUtils#cancel(Future<T>) instead
+java.util.concurrent.Future#cancel(boolean)
+
+# End signatures.txt

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java
----------------------------------------------------------------------
diff --git a/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java b/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java
index 3e873a5..9e30dad 100644
--- a/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java
+++ b/avatica/standalone-server/src/main/java/org/apache/calcite/avatica/hsqldb/HsqldbServer.java
@@ -20,6 +20,7 @@ import org.apache.calcite.avatica.jdbc.JdbcMeta;
 import org.apache.calcite.avatica.remote.Driver.Serialization;
 import org.apache.calcite.avatica.remote.LocalService;
 import org.apache.calcite.avatica.server.HttpServer;
+import org.apache.calcite.avatica.util.Unsafe;
 
 import com.beust.jcommander.IStringConverter;
 import com.beust.jcommander.JCommander;
@@ -30,6 +31,8 @@ import net.hydromatic.scott.data.hsqldb.ScottHsqldb;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Locale;
+
 /**
  * An Avatica server for HSQLDB.
  */
@@ -49,7 +52,7 @@ public class HsqldbServer {
   public void start() {
     if (null != server) {
       LOG.error("The server was already started");
-      System.exit(ExitCodes.ALREADY_STARTED.ordinal());
+      Unsafe.systemExit(ExitCodes.ALREADY_STARTED.ordinal());
       return;
     }
 
@@ -71,7 +74,7 @@ public class HsqldbServer {
           serialization);
     } catch (Exception e) {
       LOG.error("Failed to start Avatica server", e);
-      System.exit(ExitCodes.START_FAILED.ordinal());
+      Unsafe.systemExit(ExitCodes.START_FAILED.ordinal());
     }
   }
 
@@ -117,7 +120,7 @@ public class HsqldbServer {
    */
   public static class SerializationConverter implements IStringConverter<Serialization> {
     @Override public Serialization convert(String value) {
-      return Serialization.valueOf(value.toUpperCase());
+      return Serialization.valueOf(value.toUpperCase(Locale.ROOT));
     }
   }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java
index 9ada4a4..6807354 100644
--- a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/TestRunner.java
@@ -77,7 +77,7 @@ public class TestRunner implements Runnable {
 
     if (null == driver) {
       LOG.error("Failed to find driver for {}", jdbcUrl);
-      System.exit(TestRunnerExitCodes.NO_SUCH_DRIVER.ordinal());
+      Unsafe.systemExit(TestRunnerExitCodes.NO_SUCH_DRIVER.ordinal());
       return;
     }
 
@@ -98,10 +98,10 @@ public class TestRunner implements Runnable {
 
     if (globalResults.numFailed > 0) {
       // Tests failed, don't exit normally
-      System.exit(TestRunnerExitCodes.FAILED_TESTS.ordinal());
+      Unsafe.systemExit(TestRunnerExitCodes.FAILED_TESTS.ordinal());
     } else {
       // Exited normally
-      System.exit(TestRunnerExitCodes.NORMAL.ordinal());
+      Unsafe.systemExit(TestRunnerExitCodes.NORMAL.ordinal());
     }
   }
 
@@ -132,7 +132,7 @@ public class TestRunner implements Runnable {
       return testClasses;
     } catch (Exception e) {
       LOG.error("Failed to instantiate test classes", e);
-      System.exit(TestRunnerExitCodes.TEST_CASE_INSTANTIATION.ordinal());
+      Unsafe.systemExit(TestRunnerExitCodes.TEST_CASE_INSTANTIATION.ordinal());
       // Unreachable..
       return null;
     }
@@ -146,10 +146,10 @@ public class TestRunner implements Runnable {
       driver = DriverManager.getDriver(driverUrl);
     } catch (SQLException e) {
       LOG.error("Could not instantiate JDBC Driver with URL: '{}'", jdbcUrl, e);
-      System.exit(TestRunnerExitCodes.BAD_JDBC_URL.ordinal());
+      Unsafe.systemExit(TestRunnerExitCodes.BAD_JDBC_URL.ordinal());
     } catch (ClassNotFoundException e) {
       LOG.error("Could not load Avatica Driver class", e);
-      System.exit(TestRunnerExitCodes.MISSING_DRIVER_CLASS.ordinal());
+      Unsafe.systemExit(TestRunnerExitCodes.MISSING_DRIVER_CLASS.ordinal());
     }
   }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/8df27ce9/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/Unsafe.java
----------------------------------------------------------------------
diff --git a/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/Unsafe.java b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/Unsafe.java
new file mode 100644
index 0000000..e88b6b7
--- /dev/null
+++ b/avatica/tck/src/main/java/org/apache/calcite/avatica/tck/Unsafe.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.avatica.tck;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Contains methods that call JDK methods that the
+ * <a href="https://github.com/policeman-tools/forbidden-apis">forbidden
+ * APIs checker</a> does not approve of.
+ *
+ * <p>This class is excluded from the check, so methods called via this class
+ * will not fail the build.
+ */
+class Unsafe {
+  private Unsafe() {}
+
+  /** Calls {@link System#exit}. */
+  static void systemExit(int status) {
+    System.exit(status);
+  }
+
+  /** Calls {@link Object#notifyAll()}. */
+  public static void notifyAll(Object o) {
+    o.notifyAll();
+  }
+
+  /** Calls {@link Object#wait()}. */
+  public static void wait(Object o) throws InterruptedException {
+    o.wait();
+  }
+
+  /** Returns a {@link Calendar} with the local time zone and root
+   * locale. */
+  public static Calendar localCalendar() {
+    return Calendar.getInstance(Locale.ROOT);
+  }
+}
+
+// End Unsafe.java


Mime
View raw message