blob: e5e3c1d8943a3433257cefa7058b179eef0ef54a [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 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(this);
}
}