| /* |
| * Copyright (c) 1998, 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, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.eis; |
| |
| import java.io.*; |
| import java.util.*; |
| import javax.naming.*; |
| import jakarta.resource.*; |
| import jakarta.resource.cci.*; |
| import org.eclipse.persistence.sessions.*; |
| import org.eclipse.persistence.exceptions.*; |
| import org.eclipse.persistence.internal.helper.*; |
| |
| /** |
| * <p>An <code>EISConnectionSpec</code> specifies how the |
| * <code>jakarta.resource.cci.Connection</code> is accessed. There are three ways |
| * to connect to an EIS datasource through JCA: |
| * <ul> |
| * <li>Provide a JNDI name to the ConnectionFactory and use the default |
| * getConnection |
| * <li>Provide a JNDI name to the ConnectionFactory, and a driver specific |
| * ConnectionSpec to pass to the getConnection |
| * <li>Connect in a non-managed way directly to the driver specific |
| * ConnectionFactory |
| * </ul> |
| * |
| * @see EISLogin |
| * |
| * @author James |
| * @since OracleAS TopLink 10<i>g</i> (10.0.3) |
| */ |
| public class EISConnectionSpec implements Connector { |
| public static final String USER = "user"; |
| public static final String PASSWORD = "password"; |
| protected ConnectionSpec connectionSpec; |
| protected ConnectionFactory connectionFactory; |
| protected Context context; |
| protected Name name; |
| protected Writer log; |
| |
| /** |
| * PUBLIC: |
| * Construct a EISConnectionSpec with no settings. |
| * The ConnectionFactory name will still need to be set. |
| */ |
| public EISConnectionSpec() { |
| super(); |
| } |
| |
| /** |
| * PUBLIC: |
| * Construct a EISConnectionSpec with the specified settings. |
| */ |
| public EISConnectionSpec(Context context, String name) throws ValidationException { |
| this.context = context; |
| setName(name); |
| } |
| |
| /** |
| * PUBLIC: |
| * Construct a EISConnectionSpec with the specified settings. |
| */ |
| public EISConnectionSpec(String name) throws ValidationException { |
| this(); |
| setName(name); |
| } |
| |
| /** |
| * PUBLIC: |
| * Construct a EISConnectionSpec with the specified settings. |
| */ |
| public EISConnectionSpec(Context context, Name name) { |
| this.context = context; |
| this.name = name; |
| } |
| |
| /** |
| * PUBLIC: |
| * Construct a EISConnectionSpec with the specified settings. |
| */ |
| public EISConnectionSpec(Name name) { |
| this(); |
| this.name = name; |
| } |
| |
| /** |
| * PUBLIC: |
| * Returns the attunity adapter message log. |
| */ |
| public Writer getLog() { |
| return log; |
| } |
| |
| /** |
| * PUBLIC: |
| * Sets the attunity adapter message log. |
| */ |
| public void setLog(Writer log) { |
| this.log = log; |
| } |
| |
| /** |
| * INTERNAL: |
| * Clone the connector. |
| */ |
| @Override |
| public Object clone() { |
| try { |
| return super.clone(); |
| } catch (Exception exception) { |
| throw new InternalError("Clone failed"); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Required for interface, but never used, for JDBC. |
| */ |
| @Override |
| public java.sql.Connection connect(Properties properties, Session session) { |
| throw EISException.incorrectLoginInstanceProvided(EISLogin.class); |
| } |
| |
| /** |
| * Connect with the specified properties and return the Connection. |
| */ |
| public Connection connectToDataSource(EISAccessor accessor, Properties properties) throws DatabaseException, ValidationException { |
| ConnectionFactory connectionFactory = getConnectionFactory(); |
| if (connectionFactory == null) { |
| try { |
| connectionFactory = (ConnectionFactory)getContext().lookup(getName()); |
| setConnectionFactory(connectionFactory); |
| } catch (Exception exception) { |
| throw ValidationException.cannotAcquireDataSource(getName(), exception); |
| } |
| } |
| |
| try { |
| accessor.setRecordFactory(connectionFactory.getRecordFactory()); |
| if (getConnectionSpec() == null) { |
| return connectionFactory.getConnection(); |
| } else { |
| return connectionFactory.getConnection(getConnectionSpec()); |
| } |
| } catch (ResourceException exception) { |
| throw EISException.resourceException(exception, accessor, null); |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the JNDI Context that can supplied the named ConnectionFactory. |
| */ |
| public Context getContext() { |
| // Lazy initialize the context to avoid context error when a factory is not used. |
| if (context == null) { |
| try { |
| context = new InitialContext(); |
| } catch (Exception exception) { |
| // Ignore/leave blank for specification} |
| } |
| } |
| return context; |
| } |
| |
| /** |
| * INTERNAL: |
| * Retrieve the password property from the supplied Properties object |
| */ |
| public String getPasswordFromProperties(Properties properties) { |
| Object passwordObject = properties.get(PASSWORD); |
| // Bug 4117441 - Secure programming practices, store password in char[] |
| String password = null; |
| if (passwordObject instanceof char[]) { |
| password = new String((char[]) passwordObject); |
| } else if (passwordObject instanceof String) { |
| // password could potentially be a String if Properties object has been modified outside of TopLink |
| password = (String) passwordObject; |
| } |
| return password; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the jakarta.resource.cci.ConnectionFactory. |
| */ |
| public ConnectionFactory getConnectionFactory() { |
| return connectionFactory; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the jakarta.resource.cci.ConnectionSpec. |
| */ |
| public ConnectionSpec getConnectionSpec() { |
| return connectionSpec; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the name of the ConnectionFactory within the |
| * JNDI Context. |
| */ |
| public Name getName() { |
| return name; |
| } |
| |
| /** |
| * PUBLIC: |
| * Provide the details of my connection information. This is primarily for JMX runtime services. |
| * @return java.lang.String |
| */ |
| @Override |
| public String getConnectionDetails() { |
| return this.getName().toString(); |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the JNDI Context that can supply the named ConnectionFactory. |
| */ |
| public void setContext(Context context) { |
| this.context = context; |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the jakarta.resource.cci.ConnectionFactory. |
| */ |
| public void setConnectionFactory(ConnectionFactory connectionFactory) { |
| this.connectionFactory = connectionFactory; |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the jakarta.resource.cci.ConnectionFactory. |
| */ |
| public void setConnectionFactoryObject(Object connectionFactory) { |
| setConnectionFactory((ConnectionFactory)connectionFactory); |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the jakarta.resource.cci.ConnectionSpec. |
| * This is only required if the default getConnection() on the connection factory is not used. |
| * This must be set to the EIS adapter specific connection spec. |
| */ |
| public void setConnectionSpec(ConnectionSpec connectionSpec) { |
| this.connectionSpec = connectionSpec; |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the jakarta.resource.cci.ConnectionSpec. |
| * This is only required if the default getConnection() on the connection factory is not used. |
| * This must be set to the EIS adapter specific connection spec. |
| */ |
| public void setConnectionSpecObject(Object connectionFactory) { |
| setConnectionSpec((ConnectionSpec)connectionFactory); |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the name of the ConnectionFactory within the |
| * JNDI Context. |
| */ |
| public void setName(String name) throws ValidationException { |
| try { |
| this.name = new CompositeName(name); |
| } catch (InvalidNameException e) { |
| throw ValidationException.invalidDataSourceName(name, e); |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| * Set the name of the ConnectionFactory within the |
| * JNDI Context. |
| */ |
| public void setName(Name name) { |
| this.name = name; |
| } |
| |
| /** |
| * PUBLIC: |
| * Print data source info. |
| */ |
| @Override |
| public String toString() { |
| if (getName() != null) { |
| return Helper.getShortClassName(getClass()) + "(connection manager url => " + getName() + ")"; |
| } else { |
| return Helper.getShortClassName(getClass()) + "()"; |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Print something useful on the log. |
| */ |
| @Override |
| public void toString(java.io.PrintWriter writer) { |
| writer.println(toString()); |
| } |
| } |