public void testJndiConnection() throws NamingException {
    // Cannot guarantee that this test will work if they have chosen to
    // resolve data sources other than by JNDI.
    if (MondrianProperties.instance().DataSourceResolverClass.isSet()) {
      return;
    }
    // get a regular connection
    Util.PropertyList properties = TestContext.instance().getConnectionProperties().clone();
    final StringBuilder buf = new StringBuilder();
    final DataSource dataSource = RolapConnection.createDataSource(null, properties, buf);
    // Don't know what the connect string is - it differs with database
    // and with the user's set up - but we know that it contains a JDBC
    // connect string. Best we can do is check that createDataSource is
    // setting it to something.
    final String desc = buf.toString();
    assertTrue(desc, desc.startsWith("Jdbc="));

    final List<String> lookupCalls = new ArrayList<String>();
    // mock the JNDI naming manager to provide that datasource
    THREAD_INITIAL_CONTEXT.set(
        // Use lazy initialization. Otherwise during initialization of this
        // initial context JNDI tries to create a default initial context
        // and bumps into itself coming the other way.
        new InitialContext(true) {
          public Object lookup(String str) {
            lookupCalls.add("Called");
            return dataSource;
          }
        });

    // Use the datasource property to connect to the database.
    // Remove user and password, because some data sources (those using
    // pools) don't allow you to override user.
    Util.PropertyList properties2 = TestContext.instance().getConnectionProperties().clone();
    properties2.remove(RolapConnectionProperties.Jdbc.name());
    properties2.remove(RolapConnectionProperties.JdbcUser.name());
    properties2.remove(RolapConnectionProperties.JdbcPassword.name());
    properties2.put(RolapConnectionProperties.DataSource.name(), "jnditest");
    DriverManager.getConnection(properties2, null);

    // if we've made it here with lookupCalls,
    // we've successfully used JNDI
    assertTrue(lookupCalls.size() > 0);
  }
  public void testConnectSansCatalogFails() {
    Util.PropertyList properties = TestContext.instance().getConnectionProperties().clone();
    properties.remove(RolapConnectionProperties.Catalog.name());
    properties.remove(RolapConnectionProperties.CatalogContent.name());

    if (RolapUtil.SQL_LOGGER.isDebugEnabled()) {
      RolapUtil.SQL_LOGGER.debug(
          this.getName() + "\n  [Connection Properties | " + properties + "]\n");
    } else {
      System.out.println(properties);
    }

    try {
      DriverManager.getConnection(properties, null);
      fail("expected exception");
    } catch (MondrianException e) {
      assertTrue(
          e.getMessage()
                  .indexOf(
                      "Connect string must contain property 'Catalog' or "
                          + "property 'CatalogContent'")
              >= 0);
    }
  }
  /**
   * Handle an {@link IllegalArgumentException} which occurs when have tried to create a connection
   * with an illegal charset.
   */
  private void handleIllegalArgumentException(
      Util.PropertyList properties, IllegalArgumentException e) {
    // Workaround Java bug #6504538 (see http://bugs.sun.com) with synopsis
    // "DriverManager.getConnection throws IllegalArgumentException".
    if (System.getProperties().getProperty("java.version").startsWith("1.6.")) {
      properties.remove("jdbc.charSet");

      final StringBuilder buf = new StringBuilder();
      DataSource dataSource = RolapConnection.createDataSource(null, properties, buf);
      final String desc = buf.toString();
      assertTrue(desc.startsWith("Jdbc="));

      try {
        Connection connection1 = dataSource.getConnection();
        connection1.close();
      } catch (SQLException e1) {
        // ignore
      }
    } else {
      fail("Expect IllegalArgumentException only in JDK 1.6, got " + e);
    }
  }
  protected void init(Util.PropertyList properties) {
    try {
      if (nativeConnection != null) { // Assume we're open
        close();
      }

      // Set a locale for this connection if specified in the platform's mondrian metadata
      // This is required if mondrian.i18n.LocalizingDynamicSchemaProcessor is being used
      if (properties.get(RolapConnectionProperties.Locale.name()) == null) {
        properties.put(
            RolapConnectionProperties.Locale.name(), LocaleHelper.getLocale().toString());
      }

      String dataSourceName = properties.get(RolapConnectionProperties.DataSource.name());

      mapPlatformRolesToMondrianRoles(properties);

      if (dataSourceName != null) {
        IDBDatasourceService datasourceService =
            PentahoSystem.getObjectFactory().get(IDBDatasourceService.class, null);
        DataSource dataSourceImpl = datasourceService.getDataSource(dataSourceName);
        if (dataSourceImpl != null) {
          properties.remove(RolapConnectionProperties.DataSource.name());
          nativeConnection = DriverManager.getConnection(properties, null, dataSourceImpl);
        } else {
          nativeConnection = DriverManager.getConnection(properties, null);
        }
      } else {
        nativeConnection = DriverManager.getConnection(properties, null);
      }

      if (nativeConnection != null) {
        if (role != null) {
          nativeConnection.setRole(role);
        }
      }

      if (nativeConnection == null) {
        logger.error(
            Messages.getInstance()
                .getErrorString(
                    "MDXConnection.ERROR_0002_INVALID_CONNECTION",
                    properties != null
                        ? properties.toString()
                        : "null")); //$NON-NLS-1$ //$NON-NLS-2$
      }
    } catch (Throwable t) {
      if (logger != null) {
        logger.error(
            Messages.getInstance()
                .getErrorString(
                    "MDXConnection.ERROR_0002_INVALID_CONNECTION",
                    properties != null ? properties.toString() : "null"),
            t); //$NON-NLS-1$ //$NON-NLS-2$
      } else {
        Logger.error(
            this.getClass().getName(),
            Messages.getInstance()
                .getErrorString(
                    "MDXConnection.ERROR_0002_INVALID_CONNECTION",
                    properties != null ? properties.toString() : "null"),
            t); //$NON-NLS-1$ //$NON-NLS-2$
      }
    }
  }
  public void testDataSourceOverrideUserPass() throws SQLException, NamingException {
    // use the datasource property to connect to the database
    Util.PropertyList properties = TestContext.instance().getConnectionProperties().clone();
    final Dialect dialect = TestContext.instance().getDialect();
    if (dialect.getDatabaseProduct() == Dialect.DatabaseProduct.ACCESS) {
      // Access doesn't accept user/password, so this test is pointless.
      return;
    }

    final String jdbcUser = properties.get(RolapConnectionProperties.JdbcUser.name());
    final String jdbcPassword = properties.get(RolapConnectionProperties.JdbcPassword.name());
    if (jdbcUser == null || jdbcPassword == null) {
      // Can only run this test if username and password are explicit.
      return;
    }

    // Define a data source with bogus user and password.
    properties.put(RolapConnectionProperties.JdbcUser.name(), "bogususer");
    properties.put(RolapConnectionProperties.JdbcPassword.name(), "boguspassword");
    properties.put(RolapConnectionProperties.PoolNeeded.name(), "false");
    final StringBuilder buf = new StringBuilder();
    final DataSource dataSource = RolapConnection.createDataSource(null, properties, buf);
    final String desc = buf.toString();
    assertTrue(desc, desc.startsWith("Jdbc="));
    assertTrue(desc, desc.indexOf("JdbcUser=bogususer; JdbcPassword=boguspassword") >= 0);
    final String jndiName = "jndiDataSource";
    THREAD_INITIAL_CONTEXT.set(
        new InitialContext() {
          public Object lookup(String str) {
            return str.equals(jndiName) ? dataSource : null;
          }
        });

    // Create a property list that we will use for the actual mondrian
    // connection. Replace the original JDBC info with the data source we
    // just created.
    final Util.PropertyList properties2 = new Util.PropertyList();
    for (Pair<String, String> entry : properties) {
      properties2.put(entry.getKey(), entry.getValue());
    }
    properties2.remove(RolapConnectionProperties.Jdbc.name());
    properties2.put(RolapConnectionProperties.DataSource.name(), jndiName);

    // With JdbcUser and JdbcPassword credentials in the mondrian connect
    // string, the data source's "user" and "password" properties are
    // overridden and the connection succeeds.
    properties2.put(RolapConnectionProperties.JdbcUser.name(), jdbcUser);
    properties2.put(RolapConnectionProperties.JdbcPassword.name(), jdbcPassword);
    mondrian.olap.Connection connection = null;
    try {
      connection = DriverManager.getConnection(properties2, null);
      Query query = connection.parseQuery("select from [Sales]");
      final Result result = connection.execute(query);
      assertNotNull(result);
    } finally {
      if (connection != null) {
        connection.close();
        connection = null;
      }
    }

    // If we don't specify JdbcUser and JdbcPassword in the mondrian
    // connection properties, mondrian uses the data source's
    // bogus credentials, and the connection fails.
    properties2.remove(RolapConnectionProperties.JdbcUser.name());
    properties2.remove(RolapConnectionProperties.JdbcPassword.name());
    for (String poolNeeded : Arrays.asList("false", "true")) {
      // Important to test with & without pooling. Connection pools
      // typically do not let you change user, so it's important that
      // mondrian handles these right.
      properties2.put(RolapConnectionProperties.PoolNeeded.name(), poolNeeded);
      try {
        connection = DriverManager.getConnection(properties2, null);
        fail("Expected exception");
      } catch (MondrianException e) {
        final String s = TestContext.getStackTrace(e);
        assertTrue(
            s,
            s.indexOf("Error while creating SQL connection: " + "DataSource=jndiDataSource") >= 0);
        switch (dialect.getDatabaseProduct()) {
          case DERBY:
            assertTrue(
                s,
                s.indexOf(
                        "Caused by: java.sql.SQLException: " + "Schema 'BOGUSUSER' does not exist")
                    >= 0);
            break;
          case ORACLE:
            assertTrue(
                s,
                s.indexOf(
                        "Caused by: java.sql.SQLException: ORA-01017: "
                            + "invalid username/password; logon denied")
                    >= 0);
            break;
          case MYSQL:
            assertTrue(
                s,
                s.indexOf(
                        "Caused by: java.sql.SQLException: Access denied " + "for user 'bogususer'")
                    >= 0);
            break;
          case POSTGRESQL:
            assertTrue(
                s,
                s.indexOf(
                        "Caused by: org.postgresql.util.PSQLException: "
                            + "FATAL: password authentication failed for "
                            + "user \"bogususer\"")
                    >= 0);
            break;
        }
      } finally {
        if (connection != null) {
          connection.close();
          connection = null;
        }
      }
    }
  }