Package org.adbcj.jdbc

Source Code of org.adbcj.jdbc.JdbcConnectionManager

/*
*   Copyright (c) 2007 Mike Heath.  All rights reserved.
*
*   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 org.adbcj.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.adbcj.Connection;
import org.adbcj.ConnectionManager;
import org.adbcj.DbException;
import org.adbcj.DbFuture;
import org.adbcj.DbListener;
import org.adbcj.support.DbFutureConcurrentProxy;
import org.adbcj.support.DefaultDbFuture;

public class JdbcConnectionManager implements ConnectionManager {

  private static final Object USER = "user";
  private static final Object PASSWORD = "password";
 
  private final String jdbcUrl;
  private final Properties properties;
  private final ExecutorService executorService;

  private final Object lock = this;
  private final Set<JdbcConnection> connections = new HashSet<JdbcConnection>(); // Access must be synchronized on lock
 
  private volatile DefaultDbFuture<Void> closeFuture;

  private volatile boolean pipeliningEnabled = false;

  public JdbcConnectionManager(String jdbcUrl, String username,
      String password, Properties properties) {
    this(jdbcUrl, username, password, Executors.newCachedThreadPool(), properties);
  }

  public JdbcConnectionManager(String jdbcUrl, String username,
      String password, ExecutorService executorService, Properties properties) {
    this.jdbcUrl = jdbcUrl;
    this.properties = new Properties(properties);
    this.executorService = executorService;

    this.properties.put(USER, username);
    this.properties.put(PASSWORD, password);
  }

  public DbFuture<Connection> connect() throws DbException {
    if (isClosed()) {
      throw new DbException("This connection manager is closed");
    }
    final DbFutureConcurrentProxy<Connection> future = new DbFutureConcurrentProxy<Connection>();
    Future<Connection> executorFuture = executorService.submit(new Callable<Connection>() {
      public Connection call() throws Exception {
        try {
          java.sql.Connection jdbcConnection = DriverManager.getConnection(jdbcUrl, properties);
          JdbcConnection connection = new JdbcConnection(JdbcConnectionManager.this, jdbcConnection);
          synchronized (lock) {
            if (isClosed()) {
              connection.close(true);
              future.setException(new DbException("Connection manager closed"));
            } else {
              connections.add(connection);
              future.setValue(connection);
            }
          }
          return connection;
        } catch (SQLException e) {
          future.setException(new DbException(e));
          e.printStackTrace();
          throw e;
        } finally {
          future.setDone();
        }
      }
    });
    future.setFuture(executorFuture);
    return future;
  }

  public DbFuture<Void> close(boolean immediate) throws DbException {
    synchronized (lock) {
      if (closeFuture == null) {
        closeFuture = new DefaultDbFuture<Void>();
        closeFuture.addListener(new DbListener<Void>() {
          @Override
          public void onCompletion(DbFuture<Void> future) throws Exception {
            executorService.shutdown();
          }
        });
      } else {
        return closeFuture;
      }
    }
    final AtomicInteger countDown = new AtomicInteger();
    final AtomicBoolean allClosed = new AtomicBoolean(false);
   
    DbListener<Void> listener = new DbListener<Void>() {
      @Override
      public void onCompletion(DbFuture<Void> future) {
        try {
          int count = countDown.decrementAndGet();
          future.get();
          if (allClosed.get() && count == 0) {
            closeFuture.setResult(null);
          }
        } catch (Exception e) {
          // If the connection close errored out, error out our closeFuture too
          closeFuture.setException(e);
        }
      }
    };
    synchronized (lock) {
      for (JdbcConnection connection : connections) {
        countDown.incrementAndGet();
        connection.close(immediate).addListener(listener);
      }
    }
    allClosed.set(true);
    if (countDown.get() == 0) {
      closeFuture.setResult(null);
    }
    return closeFuture;
  }

  public boolean isClosed() {
    return closeFuture != null;
  }

  /*
   *
   * Non API Method
   *
   */
 
  public ExecutorService getExecutorService() {
    return executorService;
  }

  boolean removeConnection(JdbcConnection connection) {
    synchronized (lock) {
      return connections.remove(connection);
    }
  }

  public boolean isPipeliningEnabled() {
    return pipeliningEnabled;
  }

  public void setPipeliningEnabled(boolean pipeliningEnabled) {
    this.pipeliningEnabled = pipeliningEnabled;
  }

  @Override
  public String toString() {
    return String.format("%s: %s (user: %s)", getClass().getName(), jdbcUrl, properties.get(USER));
  }
 
}
TOP

Related Classes of org.adbcj.jdbc.JdbcConnectionManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.