// Copyright 2008 Google Inc.
//
// Licensed 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 com.google.gwtorm.jdbc;

import java.io.File;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

import javax.sql.DataSource;

/** A simple non-pooling DataSource representation. */
public class SimpleDataSource implements DataSource {
  private final Properties connectionInfo;
  private final String url;
  private final Driver driver;
  private PrintWriter logWriter;

  /**
   * Create a non-pooling data source.
   * <p>
   * The JDBC properties information must define at least <code>url</code> and
   * <code>driver</code>, but may also include driver specific properties such
   * as <code>username</code> and <code>password</code>.
   *
   * @param dbInfo JDBC connection information. The property table is copied.
   * @throws SQLException the driver class is not available through the current
   *         class loader.
   */
  public SimpleDataSource(final Properties dbInfo) throws SQLException {
    connectionInfo = new Properties();
    connectionInfo.putAll(dbInfo);

    url = (String) connectionInfo.remove("url");
    if (url == null) {
      throw new SQLException("Required property 'url' not defined");
    }

    final String driverName = (String) connectionInfo.remove("driver");
    final String classpath = (String) connectionInfo.remove("classpath");
    if (driverName != null) {
      ClassLoader cl = threadCL();
      if (classpath != null && classpath.length() > 0) {
        final List<URL> urls = new ArrayList<>();
        for (final String path : classpath.split(File.pathSeparator)) {
          try {
            urls.add(new URL(path));
          } catch (MalformedURLException e1) {
            final File f = new File(path);
            if (f.exists()) {
              try {
                urls.add(f.getAbsoluteFile().toURI().toURL());
              } catch (MalformedURLException e2) {
                throw badClasspath(classpath, e2);
              }
            } else {
              throw badClasspath(classpath, e1);
            }
          }
        }
        cl = new URLClassLoader(urls.toArray(new URL[urls.size()]), cl);
      }
      driver = loadDriver(driverName, cl);
    } else {
      driver = null;
    }

    logWriter = new PrintWriter(System.out);
  }

  private static SQLException badClasspath(final String classpath,
      final MalformedURLException e1) {
    final SQLException sqle;
    sqle = new SQLException("Invalid driver classpath " + classpath);
    sqle.initCause(e1);
    return sqle;
  }

  @Override
  public Connection getConnection() throws SQLException {
    if (driver != null) {
      return driver.connect(url, connectionInfo);
    }
    return DriverManager.getConnection(url, connectionInfo);
  }

  @Override
  public Connection getConnection(String user, String password)
      throws SQLException {
    if (driver != null) {
      final Properties info = new Properties(connectionInfo);
      if (user != null) {
        info.put("user", user);
      }
      if (password != null) {
        info.put("password", password);
      }
      return driver.connect(url, info);
    }
    return DriverManager.getConnection(url, user, password);
  }

  @Override
  public PrintWriter getLogWriter() {
    return logWriter;
  }

  @Override
  public void setLogWriter(final PrintWriter out) {
    logWriter = out;
  }

  @Override
  public int getLoginTimeout() {
    return 0;
  }

  @Override
  public void setLoginTimeout(int seconds) {
  }

  @Override
  public boolean isWrapperFor(Class<?> iface) {
    return false;
  }

  @Override
  public <T> T unwrap(Class<T> iface) throws SQLException {
    throw new SQLException(getClass().getName() + " wraps nothing");
  }

  @Override
  public Logger getParentLogger() throws SQLFeatureNotSupportedException {
    throw new SQLFeatureNotSupportedException();
  }

  private static synchronized Driver loadDriver(final String driver,
      final ClassLoader loader) throws SQLException {
    // I've seen some drivers (*cough* Informix *cough*) which won't load
    // on multiple threads at the same time. Forcing our code to synchronize
    // around loading the driver ensures we won't ever ask for the same driver
    // to initialize from different threads. Of course that could still happen
    // in other parts of the same JVM, but its quite unlikely.
    //
    try {
      return (Driver) Class.forName(driver, true, loader).newInstance();
    } catch (Throwable err) {
      final SQLException e;
      e = new SQLException("Driver class " + driver + " not available");
      e.initCause(err);
      throw e;
    }
  }

  private static ClassLoader threadCL() {
    try {
      return Thread.currentThread().getContextClassLoader();
    } catch (SecurityException e) {
      return SimpleDataSource.class.getClassLoader();
    }
  }
}
