All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.gjc.common.DataSourceObjectBuilder Maven / Gradle / Ivy

There is a newer version: 6.2024.6
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
//Portions Copyright [2017-2021] Payara Foundation and/or affiliates

package com.sun.gjc.common;

import java.lang.reflect.Method;
import java.util.*;

import com.sun.gjc.util.MethodExecutor;

import jakarta.resource.ResourceException;

import com.sun.logging.*;

import java.util.logging.Logger;
import java.util.logging.Level;

import com.sun.enterprise.util.i18n.StringManager;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.api.ClassLoaderHierarchy;

/**
 * Utility class, which would create necessary Datasource object according to the
 * specification.
 *
 * @author Binod P.G
 * @version 1.0, 02/07/23
 * @see com.sun.gjc.common.DataSourceSpec
 * @see com.sun.gjc.util.MethodExcecutor
 */
public class DataSourceObjectBuilder implements java.io.Serializable {

    private DataSourceSpec spec;

    private Hashtable driverProperties = null;

    private MethodExecutor executor = null;

    private static final Logger _logger = LogDomains.getLogger(MethodExecutor.class, LogDomains.RSR_LOGGER);

    private static boolean jdbc40;
    private static boolean jdbc41;
    private static boolean jdbc42;

    static {
        jdbc40 = detectJDBC40();
        jdbc41 = detectJDBC41();
        jdbc42 = detectJDBC42();
    }

    private static final StringManager sm = StringManager.getManager(DataSourceObjectBuilder.class);

    /**
     * Construct a DataSource Object from the spec.
     *
     * @param spec  DataSourceSpec  object.
     */
    public DataSourceObjectBuilder(DataSourceSpec spec) {
        this.spec = spec;
        executor = new MethodExecutor();
    }

    /**
     * Construct the DataSource Object from the spec.
     *
     * @return Object constructed using the DataSourceSpec.
     * @throws ResourceException if the class is not found or some issue in executing
     *                                        some method.
     */
    public Object constructDataSourceObject() throws ResourceException {
        driverProperties = parseDriverProperties(spec, true);
        Object dataSourceObject = getDataSourceObject();
        Method[] methods = dataSourceObject.getClass().getMethods();
        for (Method method : methods) {
            String methodName = method.getName();
            //Check for driver properties first since some jdbc properties
            //may be supported in form of driver properties
            if (driverProperties.containsKey(methodName.toUpperCase(Locale.getDefault()))) {
                Vector values = (Vector) driverProperties.get(methodName.toUpperCase(Locale.getDefault()));
                executor.runMethod(method, dataSourceObject, values);
            } else if (methodName.equalsIgnoreCase("setUser")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.USERNAME), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setPassword")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.PASSWORD), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setLoginTimeOut")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.LOGINTIMEOUT), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setLogWriter")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.LOGWRITER), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setDatabaseName")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.DATABASENAME), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setDataSourceName")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.DATASOURCENAME), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setDescription")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.DESCRIPTION), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setNetworkProtocol")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.NETWORKPROTOCOL), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setPortNumber")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.PORTNUMBER), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setRoleName")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.ROLENAME), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setServerName")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.SERVERNAME), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setMaxStatements")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.MAXSTATEMENTS), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setInitialPoolSize")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.INITIALPOOLSIZE), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setMinPoolSize")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.MINPOOLSIZE), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setMaxPoolSize")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.MAXPOOLSIZE), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setMaxIdleTime")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.MAXIDLETIME), method, dataSourceObject);
            } else if (methodName.equalsIgnoreCase("setPropertyCycle")) {
                executor.runJavaBeanMethod(spec.getDetail(DataSourceSpec.PROPERTYCYCLE), method, dataSourceObject);
            }
        }
        return dataSourceObject;
    }

    /**
     * Get the extra driver properties from the DataSourceSpec object and
     * parse them to a set of methodName and parameters. Prepare a hashtable
     * containing these details and return.
     *
     * @param spec  DataSourceSpec  object.
     * @return Hashtable containing method names and parameters,
     * @throws ResourceException If delimiter is not provided and property string
     *                           is not null.
     */
    public Hashtable parseDriverProperties(DataSourceSpec spec, boolean returnUpperCase) 
            throws ResourceException {
        String delim = spec.getDetail(DataSourceSpec.DELIMITER);
        String escape = spec.getDetail(DataSourceSpec.ESCAPECHARACTER);
        String prop = spec.getDetail(DataSourceSpec.DRIVERPROPERTIES);

        if (prop == null || prop.trim().equals("")) {
            return new Hashtable();
        } else if (delim == null || delim.equals("")) {
            String msg = sm.getString("dsob.delim_not_specified");
            throw new ResourceException(msg);
        }else if( escape == null  || escape.equals("")){
            String msg = sm.getString("dsob.escape_char_not_specified");
            throw new ResourceException(msg);
        }
        return parseDriverProperties(prop,escape, delim, returnUpperCase);
    }

    /**
     * parse the driver properties and re-generate name value pairs with unescaped values.
     * @param values driverProperties
     * @param escape escape character
     * @param delimiter delimiter
     * @return Hashtable
     */
    public Hashtable parseDriverProperties(String values, String escape, 
                String delimiter, boolean returnUpperCase){
        Hashtable result = new Hashtable();
        String parsedValue = "";
        String name = "";                
        String value = "";
        char escapeChar = escape.charAt(0);
        char delimiterChar = delimiter.charAt(0);
        while (values.length() > 0) {
            if (values.charAt(0) == delimiterChar) {
                if (values.length() > 1 && values.charAt(1) == delimiterChar) {
                    if (values.length() > 2 && values.charAt(2) == delimiterChar) {
                        //Check for first property that does not have a value
                        //There is no value specified for this property.
                        //Store the name or it will be lost
                        if (returnUpperCase) {
                            name = parsedValue.toUpperCase(Locale.getDefault());
                        } else {
                            name = parsedValue;
                        }
                        //no value specified for value
                        parsedValue = "";
                    }
                    value = parsedValue;
                    Vector v = new Vector();
                    v.add(value);
                    result.put(name, v);
                    parsedValue = "";
                    values = values.substring(2);
                } else {
                    if (returnUpperCase) {
                        name = parsedValue.toUpperCase(Locale.getDefault());
                    } else {
                        name = parsedValue;
                    }
                    parsedValue = "";
                    values = values.substring(1);
                }
            } else if (values.charAt(0) == escapeChar) {
                if (values.charAt(1) == escapeChar) {
                    parsedValue += values.charAt(1);
                } else if (values.charAt(1) == delimiterChar) {
                    parsedValue += values.charAt(1);
                }
                values = values.substring(2);
            } else if (values.charAt(0) != escapeChar) {
                parsedValue += values.charAt(0);
                values = values.substring(1);
            }
        }

        return result;
    }

    /**
     * Creates a Datasource object according to the spec.
     *
     * @return Initial DataSource Object instance.
     * @throws ResourceException If class name is wrong or classpath is not set
     *                                        properly.
     */
    private Object getDataSourceObject() throws ResourceException {
        String className = spec.getDetail(DataSourceSpec.CLASSNAME);
        try {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            Class dataSourceClass;
            try {
                dataSourceClass = Class.forName(className, true, cl);
            } catch (ClassNotFoundException cnfe) {
                // OSGi-ed apps can't see lib dir, so try using CommonClassLoader
                cl = Globals.get(ClassLoaderHierarchy.class).getCommonClassLoader();
                dataSourceClass = Class.forName(className, true, cl);
            }
            Object dataSourceObject = dataSourceClass.newInstance();
            return dataSourceObject;
        } catch (ClassNotFoundException cnfe) {
            _logger.log(Level.SEVERE, "jdbc.exc_cnfe_ds", cnfe);
            String msg = sm.getString("dsob.class_not_found", className);
            throw new ResourceException(msg);
        } catch (InstantiationException ce) {
            _logger.log(Level.SEVERE, "jdbc.exc_inst", className);
            String msg = sm.getString("dsob.error_instantiating", className);
            throw new ResourceException(msg);
        } catch (IllegalAccessException ce) {
            _logger.log(Level.SEVERE, "jdbc.exc_acc_inst", className);
            String msg = sm.getString("dsob.access_error", className);
            throw new ResourceException(msg);
        }
    }

    public static boolean isJDBC40() {
        return jdbc40;
    }

    public static boolean isJDBC41() {
        return jdbc41;
    }
    
    /**
     * Check whether the jdbc api version is 4.0 or not.
     *
     * @return boolean
     */
    private static boolean detectJDBC40() {
        boolean jdbc40 = false;
        try {
            Class.forName("java.sql.Wrapper");
            jdbc40 = true;
        } catch (ClassNotFoundException cnfe) {
            if(_logger.isLoggable(Level.FINEST)) {
                _logger.log(Level.FINEST,
                    "could not find Wrapper(available in jdbc-40), jdk supports only jdbc-30");
            }
        }
        return jdbc40;
    }

    /**
     * Detect if jdbc api version is 4.1 or not
     *
     * @return boolean
     */
    private static boolean detectJDBC41() {
        boolean jdbc41 = false;
        try {
            Class.forName("java.sql.PseudoColumnUsage");
            jdbc41 = true;
        } catch (ClassNotFoundException cnfe) {
            if(_logger.isLoggable(Level.FINEST)) {
                _logger.log(Level.FINEST,
                    "could not find PseudoColumnUsage(enum available in jdbc-41)," +
                    " jdk supports jdbc-40 or lesser");
            }
        }
        return jdbc41;
    }
    
   /**
     * Detect if jdbc api version is 4.2 or not
     *
     * @return boolean
     */
    private static boolean detectJDBC42() {
        boolean jdbc42 = false;
        try {
            Class.forName("java.sql.JDBCType");
            jdbc42 = true;
        } catch (ClassNotFoundException cnfe) {
            if (_logger.isLoggable(Level.FINEST)) {
                _logger.log(Level.FINEST,
                        "could not find JDBCType(enum available in jdbc-42),"
                        + " jdk supports jdbc-41 or lesser");
            }
        }
        return jdbc42;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy