com.alibaba.wasp.jdbcx.JdbcDataSource.java Source code

Java tutorial

Introduction

Here is the source code for com.alibaba.wasp.jdbcx.JdbcDataSource.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.wasp.jdbcx;

import com.alibaba.wasp.jdbc.Driver;
import com.alibaba.wasp.jdbc.JdbcConnection;
import com.alibaba.wasp.jdbc.JdbcException;
import com.alibaba.wasp.util.StringUtils;
import com.alibaba.wasp.util.Utils;
import org.apache.commons.lang.NotImplementedException;
import org.apache.hadoop.conf.Configuration;

import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.PooledConnection;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Logger;

/*## Java 1.7 ##
 import java.util.logging.Logger;
 //*/

/**
 * A data source for H2 database connections. It is a factory for XAConnection
 * and Connection objects. This class is usually registered in a JNDI naming
 * service. To create a data source object and register it with a JNDI service,
 * use the following code:
 * 
 * <pre>
 * import com.alibaba.wasp.jdbcx.JdbcDataSource;
 * import javax.naming.Context;
 * import javax.naming.InitialContext;
 * JdbcDataSource ds = new JdbcDataSource();
 * ds.setURL(&quot;jdbc:wasp:&tilde;/test&quot;);
 * ds.setUser(&quot;sa&quot;);
 * ds.setPassword(&quot;sa&quot;);
 * Context ctx = new InitialContext();
 * ctx.bind(&quot;jdbc/dsName&quot;, ds);
 * </pre>
 * 
 * To use a data source that is already registered, use the following code:
 * 
 * <pre>
 * import java.sql.Connection;
 * import javax.sql.DataSource;
 * import javax.naming.Context;
 * import javax.naming.InitialContext;
 * Context ctx = new InitialContext();
 * DataSource ds = (DataSource) ctx.lookup(&quot;jdbc/dsName&quot;);
 * Connection conn = ds.getConnection();
 * </pre>
 * 
 * In this example the user name and password are serialized as well; this may
 * be a security problem in some cases.
 */
public class JdbcDataSource
        implements XADataSource, DataSource, ConnectionPoolDataSource, Serializable, Referenceable {

    private static final long serialVersionUID = 1288136338451857771L;

    private transient JdbcDataSourceFactory factory;
    private transient PrintWriter logWriter;
    private int loginTimeout;
    private String userName = "";
    private char[] passwordChars = {};
    private String url = "";
    private String description;
    private Configuration conf;

    static {
        com.alibaba.wasp.jdbc.Driver.load();
    }

    /**
     * The public constructor.
     */
    public JdbcDataSource(Configuration conf) {
        this.conf = conf;
        initFactory();
    }

    /**
     * Called when de-serializing the object.
     * 
     * @param in
     *          the input stream
     */
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        initFactory();
        in.defaultReadObject();
    }

    private void initFactory() {
        factory = new JdbcDataSourceFactory(conf);
    }

    /**
     * Get the login timeout in seconds, 0 meaning no timeout.
     * 
     * @return the timeout in seconds
     */
    public int getLoginTimeout() {
        return loginTimeout;
    }

    /**
     * Set the login timeout in seconds, 0 meaning no timeout. The default value
     * is 0. This value is ignored by this database.
     * 
     * @param timeout
     *          the timeout in seconds
     */
    public void setLoginTimeout(int timeout) {
        this.loginTimeout = timeout;
    }

    /**
     * Get the current log writer for this object.
     * 
     * @return the log writer
     */
    public PrintWriter getLogWriter() {
        return logWriter;
    }

    /**
     * Set the current log writer for this object. This value is ignored by this
     * database.
     * 
     * @param out
     *          the log writer
     */
    public void setLogWriter(PrintWriter out) {
        logWriter = out;
    }

    /**
     * Open a new connection using the current URL, user name and password.
     * 
     * @return the connection
     */
    public Connection getConnection() throws SQLException {
        return getJdbcConnection(userName, StringUtils.cloneCharArray(passwordChars));
    }

    /**
     * Open a new connection using the current URL and the specified user name and
     * password.
     * 
     * @param user
     *          the user name
     * @param password
     *          the password
     * @return the connection
     */
    public Connection getConnection(String user, String password) throws SQLException {
        return getJdbcConnection(user, convertToCharArray(password));
    }

    private JdbcConnection getJdbcConnection(String user, char[] password) throws SQLException {
        Properties info = Utils.convertConfigurationToProperties(conf);
        info.setProperty("user", user);
        info.put("password", password);
        Connection conn = getConnectionInternal(getURL(url, true), info);
        if (conn == null) {
            throw new SQLException("No suitable driver found for " + url, "08001", 8001);
        } else if (!(conn instanceof JdbcConnection)) {
            throw new SQLException("Connecting with old version is not supported: " + url, "08001", 8001);
        }
        return (JdbcConnection) conn;
    }

    private static Connection getConnectionInternal(String url, Properties properties) throws SQLException {
        //com.alibaba.wasp.jdbc.Driver.load();
        Enumeration<java.sql.Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            java.sql.Driver driver = (java.sql.Driver) drivers.nextElement();
            if (!(driver instanceof Driver)) {
                DriverManager.deregisterDriver(driver);
            }
        }
        return DriverManager.getConnection(url, properties);
    }

    /**
     * Get the database URL for the given database name using the current
     * configuration options.
     *
     * @param name
     *          the database name
     * @param admin
     *          true if the current user is an admin
     * @return the database URL
     */
    protected static String getURL(String name, boolean admin) {
        String url;
        if (name.startsWith("jdbc:")) {
            return name;
        }
        url = name;
        return "jdbc:wasp:" + url;
    }

    /**
     * Get the current URL.
     * 
     * @return the URL
     */
    public String getURL() {
        return url;
    }

    /**
     * Set the current URL.
     * 
     * @param url
     *          the new URL
     */
    public void setURL(String url) {
        this.url = url;
    }

    /**
     * Set the current password.
     * 
     * @param password
     *          the new password.
     */
    public void setPassword(String password) {
        this.passwordChars = convertToCharArray(password);
    }

    /**
     * Set the current password in the form of a char array.
     * 
     * @param password
     *          the new password in the form of a char array.
     */
    public void setPasswordChars(char[] password) {
        this.passwordChars = password;
    }

    private static char[] convertToCharArray(String s) {
        return s == null ? null : s.toCharArray();
    }

    private static String convertToString(char[] a) {
        return a == null ? null : new String(a);
    }

    /**
     * Get the current password.
     * 
     * @return the password
     */
    public String getPassword() {
        return convertToString(passwordChars);
    }

    /**
     * Get the current user name.
     * 
     * @return the user name
     */
    public String getUser() {
        return userName;
    }

    /**
     * Set the current user name.
     * 
     * @param user
     *          the new user name
     */
    public void setUser(String user) {
        this.userName = user;
    }

    /**
     * Get the current description.
     * 
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    /**
     * Set the description.
     * 
     * @param description
     *          the new description
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * Get a new reference for this object, using the current settings.
     * 
     * @return the new reference
     */
    public Reference getReference() {
        String factoryClassName = JdbcDataSourceFactory.class.getName();
        Reference ref = new Reference(getClass().getName(), factoryClassName, null);
        ref.add(new StringRefAddr("url", url));
        ref.add(new StringRefAddr("user", userName));
        ref.add(new StringRefAddr("password", convertToString(passwordChars)));
        ref.add(new StringRefAddr("loginTimeout", String.valueOf(loginTimeout)));
        ref.add(new StringRefAddr("description", description));
        return ref;
    }

    /**
     * Open a new XA connection using the current URL, user name and password.
     * 
     * @return the connection
     */
    public XAConnection getXAConnection() throws SQLException {
        return new JdbcXAConnection(getJdbcConnection(userName, StringUtils.cloneCharArray(passwordChars)));
    }

    /**
     * Open a new XA connection using the current URL and the specified user name
     * and password.
     * 
     * @param user
     *          the user name
     * @param password
     *          the password
     * @return the connection
     */
    public XAConnection getXAConnection(String user, String password) throws SQLException {
        return new JdbcXAConnection(getJdbcConnection(user, convertToCharArray(password)));
    }

    /**
     * Open a new pooled connection using the current URL, user name and password.
     * 
     * @return the connection
     */
    public PooledConnection getPooledConnection() throws SQLException {
        return getXAConnection();
    }

    /**
     * Open a new pooled connection using the current URL and the specified user
     * name and password.
     * 
     * @param user
     *          the user name
     * @param password
     *          the password
     * @return the connection
     */
    public PooledConnection getPooledConnection(String user, String password) throws SQLException {
        return getXAConnection(user, password);
    }

    /**
     * [Not supported] Return an object of this class if possible.
     * 
     * @param iface
     *          the class
     */
    // ## Java 1.6 ##
    public <T> T unwrap(Class<T> iface) throws SQLException {
        throw JdbcException.getUnsupportedException("isWrapperFor unsupported");
    }

    // */

    /**
     * [Not supported] Checks if unwrap can return an object of this class.
     * 
     * @param iface
     *          the class
     */
    // ## Java 1.6 ##
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        throw JdbcException.getUnsupportedException("isWrapperFor unsupported");
    }

    // */

    /**
     * [Not supported]
     */
    public Logger getParentLogger() {
        throw new NotImplementedException();
    }

    /**
     * INTERNAL
     */
    public String toString() {
        return "JdbcDataSource : url=" + url + " user=" + userName;
    }

}