blob: c54030544c1305eb5bd8a9df78f198f3d7e741ee [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.sessions;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.text.MessageFormat;
import java.util.Map;
import java.util.Properties;
import org.eclipse.persistence.Version;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.NonSynchronizedProperties;
import org.eclipse.persistence.internal.localization.ToStringLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.internal.security.SecurableObjectHolder;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.queries.ValueReadQuery;
import org.eclipse.persistence.sequencing.Sequence;
/**
* <p>
* <b>Purpose</b>:
* Hold the configuration information necessary to connect to a datasource.
* <p>
* <b>Description</b>:
* This is an abstract class that defines the common datasource independent connection configuration.
* It is extended to support specific datasources such as JDBC, JCA, XML, etc.
*/
public abstract class DatasourceLogin implements org.eclipse.persistence.sessions.Login, Serializable, Cloneable {
/** Version info */
private static final String versionStringTemplate = "{0} - {1}";
public static String versionString = null;
/** Connection properties (e.g. user, password, and driver-specific settings) */
protected Properties properties;
/** Implementation of platform-specific behaviors. */
protected Platform platform;
/** findbugs: removed the encrypted String that holds the expiry key */
/** The securable object holder and flag*/
private boolean isEncryptedPasswordSet;
private transient SecurableObjectHolder securableObjectHolder;
/** Provide a little flexibility for connecting to a database */
protected Connector connector;
/** True if we use an external connection pool such as WebLogic's JTS driver */
protected boolean usesExternalConnectionPooling;
/** True if we should use some external transaction service such as JTS. */
protected boolean usesExternalTransactionController;
/**
* By default concurrency is optimized and the cache is not locked during reads or writes,
* This allows for concurrent reading and writing and should never cause any problems. If the application
* uses no form of locking the last unit of work to merge changes will win, with no locking it is possible
* only under this scenario for two unit of works to merge changes different than the database although highly unlikely
* and if occurred is the entire purpose of locking. This property allows for the isolation level of changes to the
* cache to be configured for sever situation and it is not suggest that this be changed.
*/
protected int cacheTransactionIsolation = SYNCRONIZED_OBJECT_LEVEL_READ_WRITE_DATABASE;
/** Reads and unit of work merges can occur concurrently. */
public static final int CONCURRENT_READ_WRITE = 1;
/** Reads can occur concurrently but unit of work merges will be serialized. */
public static final int SYNCHRONIZED_WRITE = 2;
/** Reads and unit of work merges will be serialized. */
public static final int SYNCHRONIZED_READ_ON_WRITE = 3;
/** Writes to the cache (merge, object build/refresh will be synchronized
* as will cache access (cloning) based on when access is required.
*/
public static final int SYNCRONIZED_OBJECT_LEVEL_READ_WRITE = 4;
/** Writes to the cache (merge, object build/refresh will be synchronized
* as will cache access (cloning) based on database transaction.
*/
public static final int SYNCRONIZED_OBJECT_LEVEL_READ_WRITE_DATABASE = 5;
/**
* PUBLIC:
* Create a new login.
*/
protected DatasourceLogin() {
this(new DatasourcePlatform());
}
/**
* ADVANCED:
* Create a new login for the given platform.
*/
protected DatasourceLogin(Platform databasePlatform) {
this.platform = databasePlatform;
this.dontUseExternalConnectionPooling();
this.dontUseExternalTransactionController();
this.properties = new NonSynchronizedProperties(4);
this.properties.put("user", "");
this.isEncryptedPasswordSet = false;
this.securableObjectHolder = new SecurableObjectHolder();
}
/**
* INTERNAL:
* Return the encryption securable holder.
* Lazy initialize to handle serialization.
*/
protected SecurableObjectHolder getSecurableObjectHolder() {
if (securableObjectHolder == null) {
securableObjectHolder = new SecurableObjectHolder();
securableObjectHolder.getSecurableObject();
}
return securableObjectHolder;
}
/**
* INTERNAL:
* Clone the login.
* This also clones the platform as it is internal to the login.
*/
@Override
public DatasourceLogin clone() {
DatasourceLogin clone = null;
try {
clone = (DatasourceLogin)super.clone();
} catch (Exception exception) {
throw new AssertionError(exception);
}
if (getConnector() != null) {
clone.setConnector((Connector)getConnector().clone());
}
clone.setDatasourcePlatform((Platform)getDatasourcePlatform().clone());
clone.setProperties((Properties)properties.clone());
return clone;
}
/**
* INTERNAL:
* Connect to the datasource, and return the driver level connection object.
*/
@Override
public Object connectToDatasource(Accessor accessor, Session session) throws DatabaseException {
return getConnector().connect(prepareProperties(properties), session);
}
/**
* ADVANCED:
* By default concurrency is optimized and the cache is not locked more than required during reads or writes,
* This allows for virtual concurrent reading and writing and should never cause any problems. If the application
* uses no form of locking the last unit of work to merge changes will win, with no locking it is possible
* only under this scenario for two unit of works to merge changes different than the database although highly unlikely
* and if occurred is the entire purpose of locking and locking is the suggested solution if this is a problem.
* This property allows for the isolation level of changes to the
* cache to be configured for sever situations and it is not suggest that this be changed.
* <p>Setting are:<ul>
* <li>ConcurrentReadWrite - default
* <li>SynchronizedWrite - only allow a single writer (i.e. unit of work merge) to the cache at once
* <li>SynchronizedReadOnWrite - do not allow reading or other unit of work merge while a unit of work is in merge</ul>
*/
public int getCacheTransactionIsolation() {
return cacheTransactionIsolation;
}
/**
* ADVANCED:
* Return the connector that will instantiate the connection.
*/
public Connector getConnector() {
return connector;
}
/**
* INTERNAL:
* Return the database platform specific information.
* This allows EclipseLink to configure certain advanced features for the database desired.
* NOTE: this must only be used for relational specific usage and will not work for
* non-relational datasources.
*/
@Override
public DatabasePlatform getPlatform() {
try {
return (DatabasePlatform)getDatasourcePlatform();
} catch (ClassCastException wrongType) {
throw ValidationException.notSupportedForDatasource();
}
}
/**
* PUBLIC:
* Return the datasource platform specific information.
* This allows EclipseLink to configure certain advanced features for the datasource desired.
*/
@Override
public Platform getDatasourcePlatform() {
if (this.platform == null) {
this.platform = new DatasourcePlatform();
}
return platform;
}
/**
* INTERNAL:
* The properties are additional, driver-specific, connection information
* to be passed to the driver.<p>
* NOTE: Do not set the password directly by getting the properties and
* setting the "password" property directly. Use the method DatabaseLogin.setPassword(String).
*/
public Properties getProperties() {
return properties;
}
/**
* PUBLIC:
* The properties are additional, driver-specific, connection information
* to be passed to the driver.<p>
* NOTE: Do not set the password directly by getting the properties and
* setting the "password" property directly. Use the method DatabaseLogin.setPassword(String).
*/
@Override
public Object getProperty(String name) {
return getProperties().get(name);
}
/**
* PUBLIC:
* Return the qualifier for the all of the tables referenced by EclipseLink.
* This can be the creator of the table or database name the table exists on.
* This is required by some databases such as Oracle and DB2.
* This should only be used if all of the tables have the same qualifier.
* It can also be set on each descriptor when the table name is specified.
*/
@Override
public String getTableQualifier() {
return getDatasourcePlatform().getTableQualifier();
}
/**
* PUBLIC:
* The user name is the database login name.
* Some databases do not require a user name or the user is obtained from the OS,
* in this case the user name not be specified.
*/
@Override
public String getUserName() {
return properties.getProperty("user");
}
/**
* PUBLIC:
* This value defaults to false when not on a DatabaseLogin as the functionality has not been implemented
* for other datasource type. On an SQL Exception EclipseLink will ping the database to determine
* if the connection used can continue to be used for queries. This should have no impact on applications
* unless the user is using pessimistic locking queries with 'no wait' or are using a query timeout feature.
* If that is the case and the application is experiencing a performance impact from the health check then
* this feature can be turned off. Turning this feature off will prevent EclipseLink from being able to
* retry queries in the case of database failure.
*/
@Override
public boolean isConnectionHealthValidatedOnError(){
return false;
}
/**
* PUBLIC:
* Return the EclipseLink version.
* @return version of EclipseLink
*/
public static String getVersion() {
if (versionString == null) {
Object[] args = { Version.getProduct(), Version.getVersionString() };
versionString = MessageFormat.format(versionStringTemplate, args);
}
return versionString;
}
/**
* SECURE:
* The password in the login properties is encrypted. Return a clone
* of the properties with the password decrypted.
*/
private Properties prepareProperties(Properties properties) {
Properties result = properties;
Object passwordObject = result.get("password");
if (passwordObject != null) {
// Fix for bug # 2700529
// The securable object is initialized on first call of
// getSecurableObject. When setting an encrypted password
// we don't make this call since it is already encrypted, hence,
// we do not initialize the securable object on the holder.
//
// If neither setPassword or setEncryptedPassword is called
// (example, user sets properties via the setProperties method),
// when the user tries to connect they will get a null pointer
// exception. So if the holder does not hold
// a securable object or the setEncryptedPassword flag is not true,
// don't bother trying to decrypt.
if (getSecurableObjectHolder().hasSecurableObject() || isEncryptedPasswordSet) {
result = (Properties)properties.clone();
// Bug 4117441 - Secure programming practices, store password in char[]
// If isEncryptedPasswordSet is true, or we have a SecurableObject then we stored
// the password as a char[], and we need to convert it into a String for the
// prepared Properties object.
if (passwordObject instanceof char[]) {
result.put("password", getSecurableObjectHolder().getSecurableObject().decryptPassword(new String((char[])passwordObject)));
} else if (passwordObject instanceof String) {
result.put("password", getSecurableObjectHolder().getSecurableObject().decryptPassword((String)passwordObject));
} else {
//properties cannot store null
result.remove("password");
}
} else if ((passwordObject instanceof char[]) && (((char[])passwordObject).length == 0)) {
// Bug 236726 - deal with empty string for passwords
result.put("password", "");
}
}
return result;
}
/**
* PUBLIC:
* Some drivers don't like the "user" and "password" properties.
* They can be removed with this method, or by using setUserName(null) / setPassword(null)
*/
public void removeProperty(String propertyName) {
properties.remove(propertyName);
}
/**
* ADVANCED:
* By default concurrency is optimized and the cache is not locked more than required during reads or writes,
* This allows for virtual concurrent reading and writing and should never cause any problems. If the application
* uses no form of locking the last unit of work to merge changes will win, with no locking it is possible
* only under this scenario for two unit of works to merge changes different than the database although highly unlikely
* and if occurred is the entire purpose of locking and locking is the suggested solution if this is a problem.
* This property allows for the isolation level of changes to the
* cache to be configured for sever situations and it is not suggest that this be changed.
* <p>Setting are:<ul>
* <li>ConcurrentReadWrite - default
* <li>SynchronizedWrite - only allow a single writer (i.e. unit of work merge) to the cache at once
* <li>SynchronizedReadOnWrite - do not allow reading or other unit of work merge while a unit of work is in merge</ul>
*/
public void setCacheTransactionIsolation(int cacheTransactionIsolation) {
this.cacheTransactionIsolation = cacheTransactionIsolation;
}
/**
* PUBLIC:
* Set the connector that will instantiate the connection.
* As an example, to use a JNDI-supplied <code>DataSource</code>, use code
* something like the following:
* <blockquote><code>
* session.getLogin().setConnector(new JNDIConnector(context, dataSourceName));<br>
* session.login();
* </code></blockquote>
* where the <code>context</code> is an instance of a <code>javax.naming.Context</code> and
* the <code>dataSourceName</code> refers to the name of the <code>DataSource</code>
* within the context.
*/
public void setConnector(Connector connector) {
this.connector = connector;
}
/**
* PUBLIC:
* The default value to substitute for database NULLs can be configured
* on a per-class basis.
* Example: login.setDefaultNullValue(long.class, Long.valueOf(0))
*/
public void setDefaultNullValue(Class type, Object value) {
getDatasourcePlatform().getConversionManager().setDefaultNullValue(type, value);
}
/**
* Set the password.
*/
@Override
public void setPassword(String password) {
if (password != null) {
// PERF: Do not encrypt empty string.
if (password.isEmpty()) {
setProperty("password", "");
} else {
// first call to get will initialize the securable object
// Bug 4117441 - Secure programming practices, store password in char[]
String encryptedPassword = getSecurableObjectHolder().getSecurableObject().encryptPassword(password);
setProperty("password", encryptedPassword.toCharArray());
}
} else {
// is null so remove the property
removeProperty("password");
}
}
/**
* Return the password. It will be encrypted.
*/
@Override
public String getPassword() {
// Bug 4117441 - Secure programming practices, store password in char[]
Object password = properties.get("password");
if (password instanceof String) {
return (String)password;
}
char[] passwordObject = (char[]) password;
if (passwordObject != null) {
return new String(passwordObject);
} else {
// respect explicit de-referencing of password
return null;
}
}
/**
* Set the encrypted password.
*/
public void setEncryptedPassword(String password) {
// remember that we set an encrypted password
// flag will be needed in prepareProperties.
isEncryptedPasswordSet = true;
if (password != null) {
// Bug 4117441 - Secure programming practices, store password in char[]
setProperty("password", password.toCharArray());
} else {// is null so remove the property
removeProperty("password");
}
}
/**
* Sets the encryption class name
*/
public void setEncryptionClassName(String encryptionClassName) {
getSecurableObjectHolder().setEncryptionClassName(encryptionClassName);
}
/**
* INTERNAL:
* Set the database platform specific information.
* This allows EclipseLink to configure certain advanced features for the database desired.
*/
@Override
public void setPlatform(Platform platform) {
setDatasourcePlatform(platform);
}
/**
* PUBLIC:
* Set the database platform specific information.
* This allows EclipseLink to configure certain advanced features for the database desired.
*/
@Override
public void setDatasourcePlatform(Platform platform) {
this.platform = platform;
}
/**
* INTERNAL:
* Return the name of the database platform class.
*/
public String getPlatformClassName() {
return getDatasourcePlatform().getClass().getName();
}
/**
* INTERNAL:
* Set the name of the Platform to be used.
* Creates a new instance of the specified Class.
*/
public void setPlatformClassName(String platformClassName) throws ValidationException {
// Handle old Oracle platform conversion.
if (platformClassName.equals("org.eclipse.persistence.platform.database.oracle.OraclePlatform")) {
platformClassName = "org.eclipse.persistence.platform.database.OraclePlatform";
}
Class platformClass = null;
try {
//First try loading with the Login's class loader
platformClass = this.getClass().getClassLoader().loadClass(platformClassName);
} catch(Throwable cne) {
//next try using ConversionManager
try {
platformClass = ConversionManager.loadClass(platformClassName);
} catch(Throwable cne2) {
//set the original exception
cne2.addSuppressed(cne);
//if still not found, throw exception
throw ValidationException.platformClassNotFound(cne2, platformClassName);
}
}
Platform platform = null;
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
platform = (Platform)AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(platformClass));
} else {
platform = (Platform)PrivilegedAccessHelper.newInstanceFromClass(platformClass);
}
} catch (PrivilegedActionException exception) {
throw ValidationException.platformClassNotFound(exception.getException(), platformClassName);
} catch(Throwable cne) {
throw ValidationException.platformClassNotFound(cne, platformClassName);
}
usePlatform(platform);
}
/**
* INTERNAL:
* Set the name of the Platform to be created using the
* passed in class loader. If no class loader is passed
* in, of if an exception is thrown, call the
* setPlatformClassName method with no classloader.
* @see #setPlatformClassName(String platformClassName)
*/
public void setPlatformClassName(String platformClassName, ClassLoader loader) throws ValidationException {
boolean exceptionCaught = false;
Class platformClass = null;
try {
Platform platform = null;
if (loader != null) {
platformClass = loader.loadClass(platformClassName);
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
platform = (Platform)AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(platformClass));
} catch (PrivilegedActionException exception) {
throw ValidationException.platformClassNotFound(exception.getException(), platformClassName);
}
} else {
platform = (Platform)PrivilegedAccessHelper.newInstanceFromClass(platformClass);
}
}
usePlatform(platform);
} catch(Exception cne) {
exceptionCaught = true;
}
if (exceptionCaught || (loader == null))
{
//attempt to load with default classloader
this.setPlatformClassName(platformClassName);
}
}
/**
* ADVANCED:
* Set the database platform to be custom platform.
*/
public void usePlatform(Platform platform) {
if (getDatasourcePlatform() != null) {
getDatasourcePlatform().copyInto(platform);
}
setPlatform(platform);
}
/**
* PUBLIC:
* The properties are additional, driver-specific, connection information
* to be passed to the JDBC driver.
*/
@Override
public void setProperties(Properties properties) {
this.properties = properties;
}
/**
* PUBLIC:
* Some JDBC drivers require additional, driver-specific, properties.
* Add the specified property to those to be passed to the JDBC driver.
*/
@Override
public void setProperty(String propertyName, Object propertyValue) {
properties.put(propertyName, propertyValue);
}
/**
* PUBLIC:
* Set the default qualifier for all tables.
* This can be the creator of the table or database name the table exists on.
* This is required by some databases such as Oracle and DB2.
*/
public void setTableQualifier(String qualifier) {
getDatasourcePlatform().setTableQualifier(qualifier);
}
/**
* PUBLIC:
* Override the default query for returning a timestamp from the server.
*/
public void setTimestampQuery(ValueReadQuery timestampQuery) {
getDatasourcePlatform().setTimestampQuery(timestampQuery);
}
/**
* PUBLIC:
* The user name is the database login name.
* Some databases do not require a user name or the user is obtained from the OS,
* in this case this should not be specified.
*/
@Override
public void setUserName(String name) {
if (name != null) {
setProperty("user", name);
} else {
removeProperty("user");
}
}
/**
* PUBLIC:
* Return whether EclipseLink uses some external connection pooling service such as a JDBC 2.0 driver.
*/
public void setUsesExternalConnectionPooling(boolean usesExternalConnectionPooling) {
this.usesExternalConnectionPooling = usesExternalConnectionPooling;
}
/**
* PUBLIC:
* Return whether EclipseLink uses some external transaction service such as JTS.
*/
public void setUsesExternalTransactionController(boolean usesExternalTransactionController) {
this.usesExternalTransactionController = usesExternalTransactionController;
}
/**
* PUBLIC:
* Do not use external connection pooling. This is appropriate if using regular
* EclipseLink connection pooling and regular JDBC drivers.
*
* @see #useExternalConnectionPooling()
*/
public void dontUseExternalConnectionPooling() {
setUsesExternalConnectionPooling(false);
}
/**
* PUBLIC:
* Let EclipseLink control transactions instead of some external transaction
* service such as JTS.
*
* @see #useExternalTransactionController()
*/
public void dontUseExternalTransactionController() {
setUsesExternalTransactionController(false);
}
/**
* INTERNAL:
* Used for cache isolation.
*/
@Override
public boolean shouldAllowConcurrentReadWrite() {
return this.cacheTransactionIsolation == CONCURRENT_READ_WRITE;
}
/**
* INTERNAL:
* Used for cache isolation.
*/
@Override
public boolean shouldSynchronizedReadOnWrite() {
return this.cacheTransactionIsolation == SYNCHRONIZED_READ_ON_WRITE;
}
/**
* INTERNAL:
* Used for Cache Isolation. Causes EclipseLink to lock at the class level on
* cache updates.
*/
@Override
public boolean shouldSynchronizeWrites() {
return this.cacheTransactionIsolation == SYNCHRONIZED_WRITE;
}
/**
* INTERNAL:
* Used for Cache Isolation. Causes EclipseLink to lock at the object level on
* cache updates and cache access.
*/
@Override
public boolean shouldSynchronizeObjectLevelReadWrite(){
return this.cacheTransactionIsolation == SYNCRONIZED_OBJECT_LEVEL_READ_WRITE;
}
/**
* INTERNAL:
* Used for Cache Isolation. Causes EclipseLink to lock at the object level on
* cache updates and cache access, based on database transaction.
*/
@Override
public boolean shouldSynchronizeObjectLevelReadWriteDatabase(){
return this.cacheTransactionIsolation == SYNCRONIZED_OBJECT_LEVEL_READ_WRITE_DATABASE;
}
/**
* PUBLIC:
* Return whether EclipseLink uses some external connection pooling
* (e.g. WebLogic's JTS driver).
*
* @see #useExternalConnectionPooling()
* @see #dontUseExternalConnectionPooling()
*/
@Override
public boolean shouldUseExternalConnectionPooling() {
return usesExternalConnectionPooling;
}
/**
* PUBLIC:
* Return whether EclipseLink uses some external transaction service such as JTS.
*
* @see #useExternalTransactionController()
* @see #dontUseExternalTransactionController()
*/
@Override
public boolean shouldUseExternalTransactionController() {
return usesExternalTransactionController;
}
/**
* PUBLIC:
* Use external connection pooling.
*
* @see #dontUseExternalConnectionPooling()
* @see #shouldUseExternalConnectionPooling()
*/
public void useExternalConnectionPooling() {
setUsesExternalConnectionPooling(true);
}
/**
* PUBLIC:
* Use an external transaction controller such as a JTS service
*
* @see #dontUseExternalTransactionController()
* @see #shouldUseExternalTransactionController()
*/
public void useExternalTransactionController() {
setUsesExternalTransactionController(true);
}
/**
* PUBLIC:
* Print all of the connection information.
*/
@Override
public String toString() {
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
writer.write(Helper.getShortClassName(getClass()));
writer.println("(");
writer.println("\t" + ToStringLocalization.buildMessage("platform", null) + "=> " + getDatasourcePlatform());
if (!shouldUseExternalConnectionPooling()) {
writer.println("\t" + ToStringLocalization.buildMessage("user_name", null) + "=> \"" + getUserName() + "\"");
}
writer.print("\t");
getConnector().toString(writer);
writer.write(")");
return stringWriter.toString();
}
/**
* Get default sequence
*/
public Sequence getDefaultSequence() {
return getDatasourcePlatform().getDefaultSequence();
}
/**
* Set default sequence
*/
public void setDefaultSequence(Sequence sequence) {
getDatasourcePlatform().setDefaultSequence(sequence);
}
/**
* Add sequence corresponding to the name
* Don't use if the session is connected.
*/
public void addSequence(Sequence sequence) {
getDatasourcePlatform().addSequence(sequence);
}
/**
* Get sequence corresponding to the name
*/
public Sequence getSequence(String seqName) {
return getDatasourcePlatform().getSequence(seqName);
}
/**
* Returns a map of sequence names to Sequences (may be null).
*/
public Map<String, Sequence> getSequences() {
return getDatasourcePlatform().getSequences();
}
/**
* Remove sequence corresponding to name.
* Doesn't remove default sequence.
* Don't use if the session is connected.
*/
public Sequence removeSequence(String seqName) {
return getDatasourcePlatform().removeSequence(seqName);
}
/**
* Remove all sequences but the default one.
*/
public void removeAllSequences() {
getDatasourcePlatform().removeAllSequences();
}
/**
* INTERNAL:
* Used only for writing the login into XML or Java.
*/
public Sequence getDefaultSequenceToWrite() {
return getDatasourcePlatform().getDefaultSequenceToWrite();
}
/**
* INTERNAL:
* Used only for writing the login into XML or Java.
*/
public Map<String, Sequence> getSequencesToWrite() {
return getDatasourcePlatform().getSequencesToWrite();
}
/**
* INTERNAL:
* Used only for reading the login from XML.
*/
public void setSequences(Map<String, Sequence> sequences) {
getDatasourcePlatform().setSequences(sequences);
}
}