/*******************************************************************************
* Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.scplugin.model.adapter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.persistence.tools.workbench.platformsmodel.DatabasePlatform;
import org.eclipse.persistence.tools.workbench.platformsmodel.DatabasePlatformRepository;
import org.eclipse.persistence.tools.workbench.scplugin.SCPlugin;
import org.eclipse.persistence.tools.workbench.scplugin.SCProblemsConstants;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
import org.eclipse.persistence.tools.workbench.utility.iterators.CloneIterator;
import org.eclipse.persistence.tools.workbench.utility.iterators.TransformationIterator;
import org.eclipse.persistence.tools.workbench.utility.string.StringTools;
import org.eclipse.persistence.internal.sessions.factories.XMLSessionConfigProject;
import org.eclipse.persistence.internal.sessions.factories.model.event.SessionEventManagerConfig;
import org.eclipse.persistence.internal.sessions.factories.model.login.DatabaseLoginConfig;
import org.eclipse.persistence.internal.sessions.factories.model.login.EISLoginConfig;
import org.eclipse.persistence.internal.sessions.factories.model.login.LoginConfig;
import org.eclipse.persistence.internal.sessions.factories.model.project.ProjectConfig;
import org.eclipse.persistence.internal.sessions.factories.model.session.DatabaseSessionConfig;
/**
* Session Configuration model adapter class for the
* TopLink Foudation Library class DatabaseSessionConfig
*
* @see DatabaseSessionConfig
*
* @author Tran Le
*/
public class DatabaseSessionAdapter extends SessionAdapter implements LoginHandler {
// property change
private volatile ProjectAdapter primaryProject;
public final static String PRIMARY_PROJECT_PROPERTY = "primaryProject";
private Collection additionalProjects;
public final static String ADDITIONAL_PROJECTS_COLLECTION = "additionalProjects";
private volatile boolean useAdditionalProjects;
public final static String USE_ADDITIONAL_PROJECTS_COLLECTION = "useAdditionalProjects";
public final static String EXTERNAL_CONNECTION_POOLING_PROPERTY = "externalConnectionPooling";
private volatile LoginAdapter login;
public final static String LOGIN_CONFIG_PROPERTY = "login";
public static final String MAP_XML_TYPE = "project-xml";
public static final String MAP_CLASS_TYPE = "project-class";
public static final String DEFAULT_MAPPING_TYPE = MAP_CLASS_TYPE;
public static final String[] VALID_MAPPING_PROJECT_TYPE = {
MAP_XML_TYPE,
MAP_CLASS_TYPE
};
private volatile SessionBrokerAdapter broker; // parent broker
/**
* Creates a new DatabaseSessionAdapter for the specified model object.
*/
DatabaseSessionAdapter( SCAdapter parent, DatabaseSessionConfig scConfig) {
super( parent, scConfig);
}
/**
* Creates a new DatabaseSession.
*/
protected DatabaseSessionAdapter( SCAdapter parent, String name, ServerPlatform sp, DataSource ds) {
super( parent, name);
this.initializePlatforms( sp, ds);
}
/**
* Factory method for building this model.
*/
protected Object buildModel() {
DatabaseSessionConfig session = new DatabaseSessionConfig();
//TOREVIEW - collection not initialized in model class & SessionEventManagerConfig is not initialized
//FL_TOREVIEW
session.setAdditionalProjects( new Vector());
session.setSessionEventManagerConfig( new SessionEventManagerConfig());
return session;
}
/**
* Builds login adapter and intializes it config model.
*/
private LoginAdapter buildLogin( DataSource ds) {
LoginAdapter login = ds.buildLoginAdapter( this);
this.databaseSession().setLoginConfig(( LoginConfig)login.getModel());
login.setPlatformClass( ds.getPlatformClassName());
return login;
}
/**
* Builds a Default Login based on user's preferences.
* Used when no login and no datasource info available.
*/
LoginAdapter buildDefaultLogin() {
DataSource ds = null;
String dsType = this.preferences().get( SCPlugin.DATA_SOURCE_TYPE_PREFERENCE, "database");
if( dsType.equals( SCPlugin.DATA_SOURCE_TYPE_PREFERENCE_RELATIONAL_CHOICE))
ds = buildDefaultRdbmsDataSource();
else if( dsType.equals( SCPlugin.DATA_SOURCE_TYPE_PREFERENCE_EIS_CHOICE))
ds = buildDefaultEisDataSource();
else if( dsType.equals( SCPlugin.DATA_SOURCE_TYPE_PREFERENCE_XML_CHOICE))
ds = buildDefaultXmlDataSource();
else
throw new IllegalArgumentException( dsType);
return buildLogin( ds);
}
private DataSource buildDefaultRdbmsDataSource() {
String platformName = this.preferences().get( SCPlugin.DATABASE_PLATFORM_PREFERENCE, SCPlugin.DATABASE_PLATFORM_PREFERENCE_DEFAULT);
DatabasePlatform platform = DatabasePlatformRepository.getDefault().platformNamed( platformName);
return new DataSource( platform);
}
private DataSource buildDefaultEisDataSource() {
String platformName = this.preferences().get( SCPlugin.EIS_PLATFORM_PREFERENCE, SCPlugin.EIS_PLATFORM_PREFERENCE_DEFAULT);
return new DataSource( platformName);
}
private DataSource buildDefaultXmlDataSource() {
return DataSource.buildXmlDataSource();
}
/**
* Returns this Config Model Object.
*/
private final DatabaseSessionConfig databaseSession() {
return ( DatabaseSessionConfig)this.getModel();
}
/**
* Initializes this adapter.
*/
protected void initialize() {
super.initialize();
this.additionalProjects = new Vector();
}
/**
* Initializes this new model inst. var. and aggregates.
*/
protected void initialize( Object newConfig) {
super.initialize( newConfig);
this.databaseSession().setAdditionalProjects( new Vector());
// This will make the file valid but it will still have a problem
this.addPrimaryProjectXmlNamed( "");
}
/**
* Initializes this adapter from the specified config model.
*/
protected void initializeFromModel( Object scConfig) {
super.initializeFromModel( scConfig);
this.primaryProject = ( ProjectAdapter)this.adapt( databaseSession().getPrimaryProject());
this.additionalProjects.addAll( this.adaptAll( this.getAdditionalProjectsConfigs()));
this.useAdditionalProjects = !additionalProjects.isEmpty();
this.login = ( LoginAdapter)this.adapt( databaseSession().getLoginConfig());
}
protected void postInitializationFromModel() {
super.postInitializationFromModel();
if( this.configVersionIsPre10g()) {
if( login == null)
this.login = this.buildLogin( DataSource.buildDefault());
else if( StringTools.stringIsEmpty( this.login.getPlatformClass()))
this.setDefaultLoginPlatform();
}
else {
if( login == null)
this.login = this.buildLogin( DataSource.buildDefault());
}
return;
}
private void setDefaultLoginPlatform() {
DataSource ds = null;
if( this.login.platformIsRdbms())
ds = buildDefaultRdbmsDataSource();
else if( this.login.platformIsEis())
ds = buildDefaultEisDataSource();
else if (this.login.platformIsXml())
ds = buildDefaultXmlDataSource();
else
throw new IllegalStateException();
login.setPlatformClass( ds.getPlatformClassName());
}
/**
* Initializes Server platform and Login platform of this new model..
*/
private void initializePlatforms( ServerPlatform sp, DataSource ds) {
this.login = this.buildLogin( ds);
this.initializeServerPlatform( sp);
}
/**
* Pre Saving: Prepares this instance config model and
* its children config model for saving.
* If Login is clean, set this config model loginConfig to null to prevent being saved.
*/
protected void preSaving() {
super.preSaving();
if( this.getLogin().hasNoConfigToSave())
setEmptyLoginConfig();
else
this.getLogin().preSaving();
return;
}
/**
* Post Saving: Re-intilizes this instance config model and
* its children config model after saving.
*/
protected void postSaving() {
super.postSaving();
syncSessionConfigLogin();
this.getLogin().postSaving();
return;
}
/**
* Handles saving case when Login hasn't been configured,
* and prevent default data to be written to file.
*/
private void setEmptyLoginConfig() {
if( this.login.platformIsRdbms()) {
DatabaseLoginConfig emptyConfig = new DatabaseLoginConfig();
emptyConfig.setByteArrayBinding( XMLSessionConfigProject.BYTE_ARRAY_BINDING_DEFAULT);
emptyConfig.setOptimizeDataConversion( XMLSessionConfigProject.OPTIMIZE_DATA_CONVERSION_DEFAULT);
emptyConfig.setTrimStrings( XMLSessionConfigProject.TRIM_STRINGS_DEFAULT);
emptyConfig.setMaxBatchWritingSize( new Integer( XMLSessionConfigProject.MAX_BATCH_WRITING_SIZE_DEFAULT));
emptyConfig.setJdbcBatchWriting( XMLSessionConfigProject.JDBC20_BATCH_WRITING_DEFAULT);
databaseSession().setLoginConfig( emptyConfig);
}
else if( this.login.platformIsEis()) {
databaseSession().setLoginConfig( new EISLoginConfig());
}
}
/**
* Synchronizes this config model loginConfig to its adapter.
*/
private void syncSessionConfigLogin() {
if( databaseSession().getLoginConfig() != ( LoginConfig)this.getLogin().getModel())
databaseSession().setLoginConfig(( LoginConfig)this.getLogin().getModel());
}
/**
* Returns this login adapter.
*/
public LoginAdapter getLogin() {
return this.login;
}
/**
* Convenience method to get the login class platform.
*/
public String getPlatform() {
return this.getLogin().getPlatformClass();
}
/**
* Convenience method to get the datasource platform.
*/
public String getDataSourceName() {
return this.getLogin().getPlatformName();
}
public boolean platformIsRdbms() {
return this.login.platformIsRdbms();
}
public boolean platformIsEis() {
return this.login.platformIsEis();
}
public boolean platformIsXml() {
return this.login.platformIsXml();
}
public void toString( StringBuffer sb) {
super.toString( sb);
sb.append( ", ");
if( login == null)
sb.append( "NO LOGIN");
else
this.login.toString( sb);
}
@Override
public void setName( String name) {
String oldName = getName();
super.setName(name);
if( this.isManaged()) {
getBroker().sessionRenamed( oldName, name);
}
}
public SessionBrokerAdapter getBroker() {
return broker;
}
void setBroker( SessionBrokerAdapter broker) {
this.broker = broker;
this.setManaged( broker != null);
}
protected void setManaged( boolean managed) {
super.setManaged( managed);
if( managed) {
this.initializeDefaults();
}
this.updateExternalConnectionPooling();
}
void externalTransactionControllerClassChanged() {
if( this.hasJTA() && getServerPlatform().isCustom()) {
String jtaClass = (( CustomServerPlatformAdapter)getServerPlatform()).getExternalTransactionControllerClass();
boolean hasJtaClass = !StringTools.stringIsEmpty( jtaClass);
getLogin().setUsesExternalTransactionController( hasJtaClass);
}
getLogin().setUsesExternalTransactionController( this.hasJTA());
updateExternalConnectionPooling();
}
/**
* Returns an iterator on a collection of additionalProjects.
*/
public Iterator additionalProjects() {
return new CloneIterator(this.additionalProjects);
}
/**
* Returns an iterator on a collection of additionalProjects.
*/
public Iterator additionalProjectNames() {
return new TransformationIterator( additionalProjects()) {
protected Object transform( Object next) {
return (( ProjectAdapter) next).getName();
}
};
}
/**
* Returns the collection of additionalProjects from the config model.
*/
private Collection getAdditionalProjectsConfigs() {
if( this.databaseSession().getAdditionalProjects() == null)
this.databaseSession().setAdditionalProjects( new Vector());
return this.databaseSession().getAdditionalProjects();
}
/**
* Returns ProjectAdapter.
*/
private ProjectAdapter getPrimaryProject() {
return this.primaryProject;
}
public boolean isPrimaryProjectXml() {
return ( this.primaryProject instanceof ProjectXMLAdapter);
}
public boolean isPrimaryProjectClass() {
return ( this.primaryProject instanceof ProjectClassAdapter);
}
public boolean isServer() {
return false;
}
/**
* Returns this logLevel.
*/
public String getPrimaryProjectName() {
if( this.getPrimaryProject() == null)
return null;
return this.getPrimaryProject().getName();
}
public ProjectClassAdapter addPrimaryProjectClassNamed( String name) {
ProjectAdapter project = new ProjectClassAdapter( this, name);
setPrimaryProject( project);
return ( ProjectClassAdapter)this.primaryProject;
}
public ProjectXMLAdapter addPrimaryProjectXmlNamed( String name) {
ProjectAdapter project = new ProjectXMLAdapter( this, name);
setPrimaryProject( project);
return ( ProjectXMLAdapter)this.primaryProject;
}
public void removePrimaryProject() {
Object old = this.primaryProject;
this.primaryProject = null;
this.databaseSession().setPrimaryProject( null);
this.firePropertyChanged( PRIMARY_PROJECT_PROPERTY, old, null);
}
/**
* Sets this name and the config model.
*/
private void setPrimaryProject( ProjectAdapter project) {
Object old = this.primaryProject;
this.primaryProject = project;
this.databaseSession().setPrimaryProject(( ProjectConfig)project.getModel());
this.firePropertyChanged( PRIMARY_PROJECT_PROPERTY, old, project);
}
/**
* Factory method for adding a Project.
*/
public ProjectClassAdapter addProjectClassNamed( String name) {
ProjectClassAdapter project = new ProjectClassAdapter( this, name);
this.addAdditionalProjects( project);
this.fireItemAdded( ADDITIONAL_PROJECTS_COLLECTION, project);
return project;
}
/**
* Factory method for adding a Project.
*/
public ProjectXMLAdapter addProjectXmlNamed( String name) {
ProjectXMLAdapter project = new ProjectXMLAdapter( this, name);
this.addAdditionalProjects( project);
this.fireItemAdded( ADDITIONAL_PROJECTS_COLLECTION, project);
return project;
}
/**
* Remove a Project.
*/
public ProjectAdapter removeProject( ProjectAdapter project) {
this.removeAdditionalProject( project);
return project;
}
/**
* Returns the Project named with the given value.
*/
public ProjectAdapter projectNamed( String name) {
for( Iterator iter = additionalProjects(); iter.hasNext();) {
ProjectAdapter project = ( ProjectAdapter)iter.next();
if( name.equals( project.getName()))
return project;
}
return null;
}
/**
* Updates the Login ExternalConnectionPooling.
* Enable when External Transaction Controller is defined.
* When it is managed, depends on the Broker JTA and/or the Database Driver type.
*/
public void updateExternalConnectionPooling() {
this.setExternalConnectionPooling( this.hasJTA() || getLogin().databaseDriverIsDataSource());
}
/**
* Adds the given AdditionalProjects.
*/
private ProjectAdapter addAdditionalProjects( ProjectAdapter projectAdapter) {
// add config
this.getAdditionalProjectsConfigs().add( projectAdapter.getModel());
// add adapter
this.additionalProjects.add( projectAdapter);
return projectAdapter;
}
/**
* Removes the given AdditionalProjects.
*/
private void removeAdditionalProject( ProjectAdapter projectAdapter) {
// remove config
this.getAdditionalProjectsConfigs().remove( projectAdapter.getModel());
// notify listeners
this.removeItemFromCollection(projectAdapter, additionalProjects, ADDITIONAL_PROJECTS_COLLECTION);
}
private void removeAllAdditionalProjects() {
this.removeItemsFromCollection(CollectionTools.collection(additionalProjects()), additionalProjects, ADDITIONAL_PROJECTS_COLLECTION);
this.getAdditionalProjectsConfigs().clear();
}
public boolean usesAdditionalProjects() {
return useAdditionalProjects;
}
public void setUseAdditionalProjects( boolean useAdditionalProjects) {
boolean old = this.usesAdditionalProjects();
this.useAdditionalProjects = useAdditionalProjects;
this.firePropertyChanged( USE_ADDITIONAL_PROJECTS_COLLECTION, old, useAdditionalProjects);
if(! usesAdditionalProjects())
removeAllAdditionalProjects();
}
/**
* Returns usesExternalConnectionPooling.
*/
public boolean usesExternalConnectionPooling() {
return this.getLogin().usesExternalConnectionPooling();
}
/**
* Sets usesExternalConnectionPooling and the config model.
*/
public void setExternalConnectionPooling( boolean value) {
boolean old = this.getLogin().usesExternalConnectionPooling();
this.getLogin().setExternalConnectionPooling( value);
this.firePropertyChanged( EXTERNAL_CONNECTION_POOLING_PROPERTY, old, value);
}
/**
* Adds the children of this adapter to the given list.
* @param children The list of children
*/
protected void addChildrenTo(List children) {
super.addChildrenTo(children);
if( getLogin() != null)
children.add( getLogin());
}
/**
* Add any problems from this adapter to the given set.
*/
protected void addProblemsTo( List branchProblems) {
super.addProblemsTo(branchProblems);
verifyProblemMappingProject(branchProblems);
verifyProblemPlatformClass( branchProblems);
}
private void verifyProblemPlatformClass( List branchProblems) {
if( !this.login.platformIsRdbms()) return;
try {
DatabasePlatformRepository.getDefault().platformForRuntimePlatformClassNamed( this.login.getPlatformClass());
}
catch ( IllegalArgumentException e) {
branchProblems.add( buildProblem( SCProblemsConstants.DATABASE_LOGIN_PLATFORM_CLASS_NAME, displayString(), this.login.getPlatformClass()));
}
}
private void verifyProblemMappingProject( List branchProblems) {
if( StringTools.stringIsEmpty( getPrimaryProjectName())) {
branchProblems.add( buildProblem( SCProblemsConstants.SESSION_DATABASE_MAPPING_PROJECT, displayString()));
}
}
}