Package com.alibaba.druid.proxy

Source Code of com.alibaba.druid.proxy.DruidDriver

/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* 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.alibaba.druid.proxy;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.logging.Log;
import com.alibaba.druid.logging.LogFactory;
import com.alibaba.druid.proxy.config.AbstractDruidFilterConfig;
import com.alibaba.druid.proxy.config.DruidFilterConfigLoader;
import com.alibaba.druid.proxy.jdbc.DataSourceProxy;
import com.alibaba.druid.proxy.jdbc.DataSourceProxyConfig;
import com.alibaba.druid.proxy.jdbc.DataSourceProxyImpl;
import com.alibaba.druid.stat.JdbcStatManager;
import com.alibaba.druid.util.DruidLoaderUtils;
import com.alibaba.druid.util.JMXUtils;
import com.alibaba.druid.util.JdbcUtils;

/**
* @author wenshao<szujobs@hotmail.com>
*/
public class DruidDriver implements Driver, DruidDriverMBean {
    private final static Log LOG = LogFactory.getLog(DruidDriver.class);
   
    private final static DruidDriver                                instance                 = new DruidDriver();

    private final static ConcurrentMap<String, DataSourceProxyImpl> proxyDataSources         = new ConcurrentHashMap<String, DataSourceProxyImpl>();
    private final static AtomicInteger                              dataSourceIdSeed         = new AtomicInteger(0);

    public final static String                                      DEFAULT_PREFIX           = "jdbc:wrap-jdbc:";
    public final static String                                      CONFIG_PREFIX            = "druid.config";
    public final static String                                      DRIVER_PREFIX            = "driver=";
    public final static String                                      PASSWORD_CALLBACK_PREFIX = "passwordCallback=";
    public final static String                                      NAME_PREFIX              = "name=";
    public final static String                                      JMX_PREFIX               = "jmx=";
    public final static String                                      FILTERS_PREFIX           = "filters=";

    private final AtomicLong                                        connectCounter           = new AtomicLong(0);

    private String                                                  acceptPrefix             = DEFAULT_PREFIX;

    private int                                                     majorVersion             = 4;

    private int                                                     minorVersion             = 0;

    static {
        registerDriver(instance);
    }

    public static boolean registerDriver(Driver driver) {
        try {
            DriverManager.registerDriver(driver);

            return true;
        } catch (Exception e) {
            LOG.error("registerDriver error", e);
        }

        return false;
    }

    public DruidDriver(){

    }

    public static DruidDriver getInstance() {
        return instance;
    }

    public static int createDataSourceId() {
        return dataSourceIdSeed.incrementAndGet();
    }

    @Override
    public boolean acceptsURL(String url) throws SQLException {
        if (url == null) {
            return false;
        }

        if (url.startsWith(acceptPrefix)) {
            return true;
        }

        return false;
    }

    @Override
    public Connection connect(String url, Properties info) throws SQLException {
        if (!acceptsURL(url)) {
            return null;
        }

        connectCounter.incrementAndGet();

        DataSourceProxyImpl dataSource = getDataSource(url, info);

        return dataSource.connect(info);
    }

    /**
     * 参数定义: com.alibaba.druid.log.LogFilter=filter com.alibaba.druid.log.LogFilter.p1=prop-value
     * com.alibaba.druid.log.LogFilter.p2=prop-value
     *
     * @param url
     * @return
     * @throws SQLException
     */
    private DataSourceProxyImpl getDataSource(String url, Properties info) throws SQLException {
        DataSourceProxyImpl dataSource = proxyDataSources.get(url);

        if (dataSource == null) {
            String restUrl = url.substring(DEFAULT_PREFIX.length());

            DataSourceProxyConfig config;

            config = new DataSourceProxyConfig();

            List<AbstractDruidFilterConfig> druidFilterConfigList = new ArrayList<AbstractDruidFilterConfig>();
            String configFile = info.getProperty(CONFIG_PREFIX);
            if (configFile != null) {
                DruidFilterConfigLoader.loadConfig(configFile.trim(), druidFilterConfigList);
            }

            if (restUrl.startsWith(DRIVER_PREFIX)) {
                int pos = restUrl.indexOf(':', DRIVER_PREFIX.length());
                String driverText = restUrl.substring(DRIVER_PREFIX.length(), pos);
                if (driverText.length() > 0) {
                    config.setRawDriverClassName(driverText.trim());
                }
                restUrl = restUrl.substring(pos + 1);
            }

            if (restUrl.startsWith(FILTERS_PREFIX)) {
                int pos = restUrl.indexOf(':', FILTERS_PREFIX.length());
                String filtersText = restUrl.substring(FILTERS_PREFIX.length(), pos);
                for (String filterItem : filtersText.split(",")) {
                    DruidLoaderUtils.loadFilter(config.getFilters(), filterItem);
                }
                restUrl = restUrl.substring(pos + 1);
            }
            // 如果url中并无定义filter 采用配置
            if (config.getFilters().size() <= 0) {
                DruidLoaderUtils.loadFilter(config.getFilters(), druidFilterConfigList);
            }

            if (restUrl.startsWith(NAME_PREFIX)) {
                int pos = restUrl.indexOf(':', NAME_PREFIX.length());
                String name = restUrl.substring(NAME_PREFIX.length(), pos);
                config.setName(name);
                restUrl = restUrl.substring(pos + 1);
            }

            if (restUrl.startsWith(JMX_PREFIX)) {
                int pos = restUrl.indexOf(':', JMX_PREFIX.length());
                String jmxOption = restUrl.substring(JMX_PREFIX.length(), pos);
                config.setJmxOption(jmxOption);
                restUrl = restUrl.substring(pos + 1);
            }

            String rawUrl = restUrl;
            config.setRawUrl(rawUrl);

            if (config.getRawDriverClassName() == null) {
                String rawDriverClassname = JdbcUtils.getDriverClassName(rawUrl);
                config.setRawDriverClassName(rawDriverClassname);
            }

            config.setUrl(url);

            Driver rawDriver = createDriver(config.getRawDriverClassName());

            DataSourceProxyImpl newDataSource = new DataSourceProxyImpl(rawDriver, config);
            {
                int dataSourceId = createDataSourceId();
                newDataSource.setId(dataSourceId);

                for (Filter filter : config.getFilters()) {
                    filter.init(newDataSource);
                }
            }

            DataSourceProxy oldDataSource = proxyDataSources.putIfAbsent(url, newDataSource); // 多线程处理需要
            if (oldDataSource == null) {
                // 放进去的线程负责注册MBean
                if (config.isJmxOption()) {
                    JMXUtils.register("com.alibaba.druid:type=JdbcStat", JdbcStatManager.getInstance());
                }
            }

            dataSource = proxyDataSources.get(url);
        }
        return dataSource;
    }

    public Driver createDriver(String className) throws SQLException {
        Class<?> rawDriverClass = DruidLoaderUtils.loadClass(className);

        if (rawDriverClass == null) {
            throw new SQLException("jdbc-driver's class not found. '" + className + "'");
        }

        Driver rawDriver;
        try {
            rawDriver = (Driver) rawDriverClass.newInstance();
        } catch (InstantiationException e) {
            throw new SQLException("create driver instance error, driver className '" + className + "'");
        } catch (IllegalAccessException e) {
            throw new SQLException("create driver instance error, driver className '" + className + "'");
        }

        return rawDriver;
    }

    @Override
    public int getMajorVersion() {
        return this.majorVersion;
    }

    @Override
    public int getMinorVersion() {
        return this.minorVersion;
    }

    @Override
    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
        DataSourceProxyImpl dataSource = getDataSource(url, info);
        return dataSource.getRawDriver().getPropertyInfo(dataSource.getConfig().getRawUrl(), info);
    }

    @Override
    public boolean jdbcCompliant() {
        return true;
    }

    @Override
    public long getConnectCount() {
        return connectCounter.get();
    }

    public String getAcceptPrefix() {
        return acceptPrefix;
    }

    @Override
    public String[] getDataSourceUrls() {
        return proxyDataSources.keySet().toArray(new String[proxyDataSources.size()]);
    }

    public static ConcurrentMap<String, DataSourceProxyImpl> getProxyDataSources() {
        return proxyDataSources;
    }
}
TOP

Related Classes of com.alibaba.druid.proxy.DruidDriver

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.