blob: f7f658d9e6056a9f32bb610aaef974483ace746f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2010 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.jpa.core.internal.jpa1;
import org.eclipse.jpt.jpa.core.JpaDataSource;
import org.eclipse.jpt.jpa.core.JpaProject;
import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
import org.eclipse.jpt.jpa.core.internal.AbstractJpaNode;
import org.eclipse.jpt.jpa.db.ConnectionAdapter;
import org.eclipse.jpt.jpa.db.ConnectionListener;
import org.eclipse.jpt.jpa.db.ConnectionProfile;
import org.eclipse.jpt.jpa.db.ConnectionProfileFactory;
import org.eclipse.jpt.jpa.db.ConnectionProfileListener;
import org.eclipse.jpt.jpa.db.Database;
import org.eclipse.jpt.jpa.db.DatabaseIdentifierAdapter;
import org.eclipse.jpt.jpa.db.DatabaseObject;
/**
* GenericJpaDataSource
*/
public class GenericJpaDataSource
extends AbstractJpaNode
implements JpaDataSource
{
/**
* cache the connection profile name so we can detect when
* it changes and notify listeners
*/
protected String connectionProfileName;
protected transient ConnectionProfile connectionProfile;
/**
* listen for the connection to be added or removed or its name changed
*/
protected final ConnectionProfileListener connectionProfileListener;
/**
* listen for the connection to be opened or closed
*/
protected final ConnectionListener connectionListener;
private static final long serialVersionUID = 1L;
// ********** constructor/initialization **********
public GenericJpaDataSource(JpaProject jpaProject, String connectionProfileName) {
super(jpaProject);
//moving the building of the connection profile before the connectionProfileListener
//is added. Need to make sure the loading of db profiles is completed before
//listening, otherwise we get notifications before our model is finished being built.
//this means our updater is called before it is set which results in an IllegalStateException.
//Hopefully this change is temporary and DTP will fix bug 246270 where I suggest they
//not fire events when building profiles.
this.connectionProfileName = connectionProfileName;
this.connectionProfile = this.buildConnectionProfile(connectionProfileName);
this.connectionProfileListener = this.buildConnectionProfileListener();
this.getConnectionProfileFactory().addConnectionProfileListener(this.connectionProfileListener);
this.connectionListener = this.buildConnectionListener();
if (this.connectionProfile != null) {
this.connectionProfile.addConnectionListener(this.connectionListener);
}
}
protected ConnectionProfileFactory getConnectionProfileFactory() {
return this.getJpaPlatform().getConnectionProfileFactory();
}
protected ConnectionProfileListener buildConnectionProfileListener() {
return new LocalConnectionProfileListener();
}
protected ConnectionListener buildConnectionListener() {
return new LocalConnectionListener();
}
// ********** JpaDataSource implementation **********
public String getConnectionProfileName() {
return this.connectionProfileName;
}
public void setConnectionProfileName(String name) {
String old = this.connectionProfileName;
this.connectionProfileName = name;
if (this.firePropertyChanged(CONNECTION_PROFILE_NAME_PROPERTY, old, name)) {
// synch the connection profile when the name changes
this.setConnectionProfile(this.buildConnectionProfile(name));
JptJpaCorePlugin.setConnectionProfileName(this.getJpaProject().getProject(), name);
}
}
public ConnectionProfile getConnectionProfile() {
return this.connectionProfile;
}
@Override
public boolean connectionProfileIsActive() {
ConnectionProfile cp = this.connectionProfile;
return (cp != null) && cp.isActive();
}
@Override
public Database getDatabase() {
ConnectionProfile cp = this.connectionProfile;
return (cp == null) ? null : cp.getDatabase();
}
public <T extends DatabaseObject> T selectDatabaseObjectForIdentifier(Iterable<T> databaseObjects, String identifier) {
Database db = this.getDatabase();
return (db == null) ? null : db.selectDatabaseObjectForIdentifier(databaseObjects, identifier);
}
public void dispose() {
if (this.connectionProfile != null) {
this.connectionProfile.removeConnectionListener(this.connectionListener);
}
this.getConnectionProfileFactory().removeConnectionProfileListener(this.connectionProfileListener);
}
// ********** internal methods **********
protected ConnectionProfile buildConnectionProfile(String name) {
return this.getConnectionProfileFactory().buildConnectionProfile(name, this.buildDatabaseIdentifierAdapter());
}
protected DatabaseIdentifierAdapter buildDatabaseIdentifierAdapter() {
return this.isJpa2_0Compatible() ?
this.getJpaFactory2_0().buildDatabaseIdentifierAdapter(this) :
DatabaseIdentifierAdapter.Default.instance();
}
protected void setConnectionProfile(ConnectionProfile connectionProfile) {
ConnectionProfile old = this.connectionProfile;
if (old != null) {
old.removeConnectionListener(this.connectionListener);
}
this.connectionProfile = connectionProfile;
if (connectionProfile != null) {
connectionProfile.addConnectionListener(this.connectionListener);
}
this.firePropertyChanged(CONNECTION_PROFILE_PROPERTY, old, connectionProfile);
}
// ********** overrides **********
@Override
public void toString(StringBuilder sb) {
sb.append(this.connectionProfileName);
}
// ********** member classes **********
/**
* Listen for a connection profile with our name being removed.
* Also listen for our connection's name being changed.
*/
protected class LocalConnectionProfileListener
implements ConnectionProfileListener
{
protected LocalConnectionProfileListener() {
super();
}
public void connectionProfileAdded(String name) {
// check to see if a connection profile with our name was added
// (assume our connection profile is null)
if (GenericJpaDataSource.this.connectionProfile == null) {
if (name.equals(GenericJpaDataSource.this.getConnectionProfileName())) {
GenericJpaDataSource.this.setConnectionProfileName(name); // this will trigger creation of CP
}
}
}
public void connectionProfileRemoved(String name) {
if (GenericJpaDataSource.this.connectionProfile == null) {
return;
}
if (name.equals(GenericJpaDataSource.this.connectionProfile.getName())) {
GenericJpaDataSource.this.setConnectionProfile(null);
}
}
public void connectionProfileRenamed(String oldName, String newName) {
if (GenericJpaDataSource.this.connectionProfile == null) {
if (newName.equals(GenericJpaDataSource.this.connectionProfileName)) {
GenericJpaDataSource.this.setConnectionProfileName(newName);
}
return;
}
// the connection profile will already have the new name,
// we just need to synch the name held by the data source
if (newName.equals(GenericJpaDataSource.this.connectionProfile.getName())) {
GenericJpaDataSource.this.setConnectionProfileName(newName);
}
}
}
/**
* Whenever the connection is opened or closed trigger a project update.
*/
protected class LocalConnectionListener
extends ConnectionAdapter
{
@Override
public void opened(ConnectionProfile profile) {
GenericJpaDataSource.this.stateChanged();
}
@Override
public void closed(ConnectionProfile profile) {
GenericJpaDataSource.this.stateChanged();
}
}
}