private static String readRSAKey(Connection connection, String pkPath) throws SQLException {
    String res = null;
    byte[] fileBuf = new byte[2048];

    BufferedInputStream fileIn = null;

    try {
      File f = new File(pkPath);
      String canonicalPath = f.getCanonicalPath();
      fileIn = new BufferedInputStream(new FileInputStream(canonicalPath));

      int bytesRead = 0;

      StringBuffer sb = new StringBuffer();
      while ((bytesRead = fileIn.read(fileBuf)) != -1) {
        sb.append(StringUtils.toAsciiString(fileBuf, 0, bytesRead));
      }
      res = sb.toString();

    } catch (IOException ioEx) {

      if (connection.getParanoid()) {
        throw SQLError.createSQLException(
            Messages.getString("Sha256PasswordPlugin.0", new Object[] {""}),
            SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
            connection.getExceptionInterceptor());
      }
      throw SQLError.createSQLException(
          Messages.getString("Sha256PasswordPlugin.0", new Object[] {"'" + pkPath + "'"}),
          SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
          ioEx,
          connection.getExceptionInterceptor());

    } finally {
      if (fileIn != null) {
        try {
          fileIn.close();
        } catch (Exception ex) {
          SQLException sqlEx =
              SQLError.createSQLException(
                  Messages.getString("Sha256PasswordPlugin.1"),
                  SQLError.SQL_STATE_GENERAL_ERROR,
                  ex,
                  connection.getExceptionInterceptor());

          throw sqlEx;
        }
      }
    }

    return res;
  }
  /**
   * Returns an object that implements the given interface to allow access to non-standard methods,
   * or standard methods not exposed by the proxy. The result may be either the object found to
   * implement the interface or a proxy for that object. If the receiver implements the interface
   * then that is the object. If the receiver is a wrapper and the wrapped object implements the
   * interface then that is the object. Otherwise the object is the result of calling <code>unwrap
   * </code> recursively on the wrapped object. If the receiver is not a wrapper and does not
   * implement the interface, then an <code>SQLException</code> is thrown.
   *
   * @param iface A Class defining an interface that the result must implement.
   * @return an object that implements the interface. May be a proxy for the actual implementing
   *     object.
   * @throws java.sql.SQLException If no object found that implements the interface
   * @since 1.6
   */
  public synchronized <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
    try {
      if ("java.sql.Statement".equals(iface.getName())
          || "java.sql.PreparedStatement".equals(iface.getName())
          || "java.sql.Wrapper.class".equals(iface.getName())) {
        return iface.cast(this);
      }

      if (unwrappedInterfaces == null) {
        unwrappedInterfaces = new HashMap();
      }

      Object cachedUnwrapped = unwrappedInterfaces.get(iface);

      if (cachedUnwrapped == null) {
        if (cachedUnwrapped == null) {
          cachedUnwrapped =
              Proxy.newProxyInstance(
                  this.wrappedStmt.getClass().getClassLoader(),
                  new Class[] {iface},
                  new ConnectionErrorFiringInvocationHandler(this.wrappedStmt));
          unwrappedInterfaces.put(iface, cachedUnwrapped);
        }
        unwrappedInterfaces.put(iface, cachedUnwrapped);
      }

      return iface.cast(cachedUnwrapped);
    } catch (ClassCastException cce) {
      throw SQLError.createSQLException(
          "Unable to unwrap to " + iface.toString(),
          SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
          this.exceptionInterceptor);
    }
  }
  protected synchronized JDBC4ClientInfoProvider getClientInfoProviderImpl() throws SQLException {
    if (this.infoProvider == null) {
      try {
        try {
          this.infoProvider =
              (JDBC4ClientInfoProvider)
                  Util.getInstance(getClientInfoProvider(), new Class[0], new Object[0]);
        } catch (SQLException sqlEx) {
          if (sqlEx.getCause() instanceof ClassCastException) {
            // try with package name prepended
            this.infoProvider =
                (JDBC4ClientInfoProvider)
                    Util.getInstance(
                        "com.mysql.jdbc." + getClientInfoProvider(), new Class[0], new Object[0]);
          }
        }
      } catch (ClassCastException cce) {
        throw SQLError.createSQLException(
            Messages.getString(
                "JDBC4Connection.ClientInfoNotImplemented", new Object[] {getClientInfoProvider()}),
            SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
      }

      this.infoProvider.initialize(this, this.props);
    }

    return this.infoProvider;
  }
 /**
  * Returns an object that implements the given interface to allow access to non-standard methods,
  * or standard methods not exposed by the proxy. The result may be either the object found to
  * implement the interface or a proxy for that object. If the receiver implements the interface
  * then that is the object. If the receiver is a wrapper and the wrapped object implements the
  * interface then that is the object. Otherwise the object is the result of calling <code>unwrap
  * </code> recursively on the wrapped object. If the receiver is not a wrapper and does not
  * implement the interface, then an <code>SQLException</code> is thrown.
  *
  * @param iface A Class defining an interface that the result must implement.
  * @return an object that implements the interface. May be a proxy for the actual implementing
  *     object.
  * @throws java.sql.SQLException If no object found that implements the interface
  * @since 1.6
  */
 public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
   try {
     // This works for classes that aren't actually wrapping
     // anything
     return iface.cast(this);
   } catch (ClassCastException cce) {
     throw SQLError.createSQLException(
         "Unable to unwrap to " + iface.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
   }
 }
  public boolean nextAuthenticationStep(Buffer fromServer, List<Buffer> toServer)
      throws SQLException {
    toServer.clear();

    if (this.password == null || this.password.length() == 0 || fromServer == null) {
      // no password or changeUser()
      Buffer bresp = new Buffer(new byte[] {0});
      toServer.add(bresp);

    } else if (((MySQLConnection) connection).getIO().isSSLEstablished()) {
      // allow plain text over SSL
      Buffer bresp = new Buffer(StringUtils.getBytes(this.password));
      bresp.setPosition(bresp.getBufLength());
      int oldBufLength = bresp.getBufLength();
      bresp.writeByte((byte) 0);
      bresp.setBufLength(oldBufLength + 1);
      bresp.setPosition(0);
      toServer.add(bresp);

    } else if (this.connection.getServerRSAPublicKeyFile() != null) {
      // encrypt with given key, don't use "Public Key Retrieval"
      this.seed = fromServer.readString();
      Buffer bresp =
          new Buffer(
              encryptPassword(this.password, this.seed, this.connection, this.publicKeyString));
      toServer.add(bresp);

    } else {
      if (!this.connection.getAllowPublicKeyRetrieval()) {
        throw SQLError.createSQLException(
            Messages.getString("Sha256PasswordPlugin.2"),
            SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE,
            connection.getExceptionInterceptor());
      }

      // We must request the public key from the server to encrypt the password
      if (this.publicKeyRequested) {
        // read key response
        Buffer bresp =
            new Buffer(
                encryptPassword(
                    this.password, this.seed, this.connection, fromServer.readString()));
        toServer.add(bresp);
        this.publicKeyRequested = false;
      } else {
        // build and send Public Key Retrieval packet
        this.seed = fromServer.readString();
        Buffer bresp = new Buffer(new byte[] {1});
        toServer.add(bresp);
        this.publicKeyRequested = true;
      }
    }
    return true;
  }
 public void setPoolable(boolean poolable) throws SQLException {
   try {
     if (this.wrappedStmt != null) {
       this.wrappedStmt.setPoolable(poolable);
     } else {
       throw SQLError.createSQLException(
           "Statement already closed",
           SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
           this.exceptionInterceptor);
     }
   } catch (SQLException sqlEx) {
     checkAndFireConnectionError(sqlEx);
   }
 }
 public void setNClob(int parameterIndex, Reader reader) throws SQLException {
   try {
     if (this.wrappedStmt != null) {
       ((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex, reader);
     } else {
       throw SQLError.createSQLException(
           "No operations allowed after statement closed",
           SQLError.SQL_STATE_GENERAL_ERROR,
           this.exceptionInterceptor);
     }
   } catch (SQLException sqlEx) {
     checkAndFireConnectionError(sqlEx);
   }
 }
  public boolean isClosed() throws SQLException {
    try {
      if (this.wrappedStmt != null) {
        return this.wrappedStmt.isClosed();
      } else {
        throw SQLError.createSQLException(
            "Statement already closed",
            SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
            this.exceptionInterceptor);
      }
    } catch (SQLException sqlEx) {
      checkAndFireConnectionError(sqlEx);
    }

    return false; // never get here - compiler can't tell
  }
  private String getStringForNClob(int columnIndex) throws SQLException {
    String asString = null;

    String forcedEncoding = "UTF-8";

    try {
      byte[] asBytes = null;

      if (!this.isBinaryEncoded) {
        asBytes = getBytes(columnIndex);
      } else {
        asBytes = getNativeBytes(columnIndex, true);
      }

      if (asBytes != null) {
        asString = new String(asBytes, forcedEncoding);
      }
    } catch (UnsupportedEncodingException uee) {
      throw SQLError.createSQLException(
          "Unsupported character encoding " + forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
    }

    return asString;
  }
 public RowId getRowId(int columnIndex) throws SQLException {
   throw SQLError.notImplemented();
 }
 public int getHoldability() throws SQLException {
   throw SQLError.notImplemented();
 }