| /* |
| * Copyright (c) 2022 Contributors to the Eclipse Foundation. |
| * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package com.sun.gjc.spi; |
| |
| import static com.sun.gjc.common.DataSourceSpec.CLASSNAME; |
| import static com.sun.gjc.common.DataSourceSpec.LOGINTIMEOUT; |
| import static com.sun.gjc.common.DataSourceSpec.PASSWORD; |
| import static com.sun.gjc.common.DataSourceSpec.URL; |
| import static com.sun.gjc.common.DataSourceSpec.USERNAME; |
| import static com.sun.gjc.util.SecurityUtils.getPasswordCredential; |
| import static java.util.logging.Level.FINE; |
| import static java.util.logging.Level.FINEST; |
| import static java.util.logging.Level.SEVERE; |
| |
| import java.sql.Connection; |
| import java.sql.DriverManager; |
| import java.sql.SQLException; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.logging.Logger; |
| |
| import javax.security.auth.Subject; |
| import javax.sql.DataSource; |
| |
| import com.sun.gjc.common.DataSourceObjectBuilder; |
| import com.sun.gjc.spi.base.AbstractDataSource; |
| import com.sun.gjc.spi.base.ConnectionHolder; |
| import com.sun.logging.LogDomains; |
| |
| import jakarta.resource.ResourceException; |
| import jakarta.resource.spi.ConfigProperty; |
| import jakarta.resource.spi.ConnectionDefinition; |
| import jakarta.resource.spi.ConnectionRequestInfo; |
| import jakarta.resource.spi.ManagedConnection; |
| import jakarta.resource.spi.ResourceAllocationException; |
| import jakarta.resource.spi.security.PasswordCredential; |
| |
| /** |
| * Driver Manager <code>ManagedConnectionFactory</code> implementation for |
| * Generic JDBC Connector. |
| * |
| * @author Evani Sai Surya Kiran |
| * @version 1.0, 02/07/31 |
| */ |
| @ConnectionDefinition( |
| connectionFactory = DataSource.class, |
| connectionFactoryImpl = AbstractDataSource.class, |
| connection = Connection.class, |
| connectionImpl = ConnectionHolder.class) |
| public class DMManagedConnectionFactory extends ManagedConnectionFactoryImpl { |
| |
| private static Logger _logger = LogDomains.getLogger(DMManagedConnectionFactory.class, LogDomains.RSR_LOGGER); |
| private boolean debug = _logger.isLoggable(FINE); |
| |
| Properties props; |
| |
| /** |
| * Creates a new physical connection to the underlying EIS resource manager. |
| * |
| * @param subject <code>Subject</code> instance passed by the application server |
| * @param cxRequestInfo <code>ConnectionRequestInfo</code> which may be created |
| * as a result of the invocation <code>getConnection(user, password)</code> on |
| * the <code>DataSource</code> object |
| * |
| * @return <code>ManagedConnection</code> object created |
| * |
| * @throws ResourceException if there is an error in instantiating the |
| * <code>DataSource</code> object used for the creation of the |
| * <code>ManagedConnection</code> object |
| * @throws SecurityException if there ino <code>PasswordCredential</code> object |
| * satisfying this request |
| */ |
| @Override |
| public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cxRequestInfo) throws ResourceException { |
| logFine("In createManagedConnection"); |
| |
| if (dataSourceObjectBuilder == null) { |
| dataSourceObjectBuilder = new DataSourceObjectBuilder(spec); |
| } |
| |
| PasswordCredential passwordCredential = getPasswordCredential(this, subject, cxRequestInfo); |
| |
| try { |
| Class.forName(spec.getDetail(CLASSNAME)); |
| } catch (ClassNotFoundException cnfe) { |
| _logger.log(SEVERE, "jdbc.exc_cnfe", cnfe); |
| throw new ResourceException("The driver could not be loaded: " + spec.getDetail(CLASSNAME)); |
| } |
| |
| Connection connection = null; |
| ManagedConnectionImpl managedConnectionImpl = null; |
| |
| Properties driverProps = new Properties(); |
| |
| // Will return a set of properties that would have setURL and <url> as objects |
| // Get a set of normal case properties |
| Map<String, List<String>> properties = dataSourceObjectBuilder.parseDriverProperties(spec, false); |
| for (Map.Entry<String, List<String>> entry : properties.entrySet()) { |
| String value = ""; |
| List<String> values = entry.getValue(); |
| |
| if (!values.isEmpty() && values.size() == 1) { |
| value = values.get(0); |
| } else if (values.size() > 1) { |
| logFine("More than one value for key : " + entry.getKey()); |
| } |
| |
| String parsedKey = getParsedKey(entry.getKey()); |
| driverProps.put(parsedKey, value); |
| if (parsedKey.equalsIgnoreCase("URL")) { |
| if (spec.getDetail(URL) == null) { |
| setConnectionURL(value); |
| } |
| } |
| } |
| |
| try { |
| if (cxRequestInfo != null) { |
| driverProps.setProperty("user", passwordCredential.getUserName()); |
| driverProps.setProperty("password", new String(passwordCredential.getPassword())); |
| } else { |
| String user = spec.getDetail(USERNAME); |
| String password = spec.getDetail(PASSWORD); |
| if (user != null) { |
| driverProps.setProperty("user", user); |
| } |
| if (password != null) { |
| driverProps.setProperty("password", password); |
| } |
| } |
| |
| connection = DriverManager.getConnection(spec.getDetail(URL), driverProps); |
| |
| } catch (SQLException sqle) { |
| _logger.log(SEVERE, "jdbc.exc_create_mc", sqle); |
| throw new ResourceAllocationException("The connection could not be allocated: " + sqle.getMessage()); |
| } |
| |
| try { |
| managedConnectionImpl = constructManagedConnection(null, connection, passwordCredential, this); |
| validateAndSetIsolation(managedConnectionImpl); |
| } finally { |
| if (managedConnectionImpl == null) { |
| try { |
| connection.close(); |
| } catch (SQLException e) { |
| _logger.log(FINEST, "Exception while closing connection : createManagedConnection" + connection, e); |
| } |
| } |
| } |
| |
| return managedConnectionImpl; |
| } |
| |
| /** |
| * Parses the key and removes the "set" string at the beginning of the property. |
| * |
| * @param key |
| * @return |
| */ |
| private String getParsedKey(String key) throws ResourceException { |
| String parsedKey = null; |
| int indexOfSet = -1; |
| try { |
| indexOfSet = key.indexOf("set"); |
| } catch (NullPointerException npe) { |
| if (debug) { |
| _logger.log(FINE, "jdbc.exc_caught_ign", npe.getMessage()); |
| } |
| |
| } |
| if (indexOfSet == 0) { |
| // Find the key String |
| try { |
| parsedKey = key.substring(indexOfSet + 3, key.length()).trim(); |
| } catch (IndexOutOfBoundsException iobe) { |
| if (debug) { |
| _logger.log(FINE, "jdbc.exc_caught_ign", iobe.getMessage()); |
| } |
| } |
| if (parsedKey != null && parsedKey.equals("")) { |
| throw new ResourceException("Invalid driver properties string - " + "Key cannot be an empty string"); |
| } |
| } |
| |
| return parsedKey; |
| } |
| |
| /** |
| * Sets the login timeout. |
| * |
| * @param loginTimeOut <code>String</code> |
| * @see <code>getLoginTimeOut</code> |
| */ |
| @Override |
| public void setLoginTimeOut(String loginTimeOut) { |
| try { |
| DriverManager.setLoginTimeout(Integer.parseInt(loginTimeOut)); |
| spec.setDetail(LOGINTIMEOUT, loginTimeOut); |
| } catch (Exception e) { |
| if (debug) { |
| _logger.log(FINE, "jdbc.exc_caught_ign", e.getMessage()); |
| } |
| } |
| } |
| |
| /** |
| * Sets the class name of the driver |
| * |
| * @param className <code>String</code> |
| */ |
| @ConfigProperty(type = String.class, defaultValue = "org.apache.derby.jdbc.ClientDriver") |
| @Override |
| public void setClassName(String className) { |
| spec.setDetail(CLASSNAME, className); |
| } |
| |
| public void setURL(String url) { |
| spec.setDetail(URL, url); |
| } |
| |
| public String getURL() { |
| return spec.getDetail(URL); |
| } |
| |
| /** |
| * Sets the connection url. |
| * |
| * @param url <code>String</code> |
| * @see <code>getConnectionURL</code> |
| */ |
| public void setConnectionURL(String url) { |
| spec.setDetail(URL, url); |
| } |
| |
| /** |
| * Gets the connection url. |
| * |
| * @return url |
| * @see <code>setConnectionURL</code> |
| */ |
| public String getConnectionURL() { |
| return spec.getDetail(URL); |
| } |
| |
| @Override |
| public Object getDataSource() throws ResourceException { |
| return null; |
| } |
| |
| /** |
| * Check if this <code>ManagedConnectionFactory</code> is equal to another |
| * <code>ManagedConnectionFactory</code>. |
| * |
| * @param other <code>ManagedConnectionFactory</code> object for checking |
| * equality with |
| * @return true if the property sets of both the |
| * <code>ManagedConnectionFactory</code> objects are the same false otherwise |
| */ |
| @Override |
| public boolean equals(Object other) { |
| logFine("In equals"); |
| |
| /** |
| * The check below means that two ManagedConnectionFactory objects are equal if |
| * and only if their properties are the same. |
| */ |
| if (other instanceof DMManagedConnectionFactory) { |
| DMManagedConnectionFactory otherMCF = (DMManagedConnectionFactory) other; |
| return this.spec.equals(otherMCF.spec); |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return 31 * 7 + (spec.hashCode()); |
| } |
| } |