/*******************************************************************************
* 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.ui.session.login;
// JDK
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContextHolder;
import org.eclipse.persistence.tools.workbench.platformsmodel.DatabasePlatform;
import org.eclipse.persistence.tools.workbench.platformsmodel.DatabasePlatformRepository;
import org.eclipse.persistence.tools.workbench.platformsplugin.ui.PlatformComponentFactory;
import org.eclipse.persistence.tools.workbench.scplugin.model.adapter.DatabaseLoginAdapter;
import org.eclipse.persistence.tools.workbench.scplugin.model.adapter.DatabaseSessionAdapter;
import org.eclipse.persistence.tools.workbench.scplugin.model.adapter.ServerPlatformAdapter;
import org.eclipse.persistence.tools.workbench.scplugin.model.adapter.SessionAdapter;
import org.eclipse.persistence.tools.workbench.scplugin.model.adapter.SessionBrokerAdapter;
import org.eclipse.persistence.tools.workbench.scplugin.ui.login.LoginExternalOptionsPane;
import org.eclipse.persistence.tools.workbench.scplugin.ui.login.RdbmsLoginPane;
import org.eclipse.persistence.tools.workbench.uitools.ComponentEnabler;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyAspectAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel;
import org.eclipse.persistence.tools.workbench.utility.node.AbstractNodeModel;
import org.eclipse.persistence.tools.workbench.utility.node.Node;
// Mapping Workbench
/**
* This page shows the information regarding the Database login which is
* specific for {@link DatabaseLoginAdapter}.
* <p>
* Here the layout:
* <pre>
* ___________________________________________
* | ____________________ |
* | Database Platform: | |V| |
* | -------------------- |
* | --------------------------------------- |
* | | | |
* | | {@link RdbmsLoginPane} | |
* | | | |
* | --------------------------------------- |
* | |
* | --------------------------------------- |
* | | | |
* | | {@link CustomizedExternalOptionsPane} | |<- {@link LoginExternalOptionsPane}
* | | | |
* | --------------------------------------- |
* | |
* -------------------------------------------</pre>
*
* @see LoginAdapter
* @see DatabaseLoginAdapter
*
* @version 10.1.3
* @author Pascal Filion
*/
public class RdbmsConnectionPropertiesPage extends AbstractLoginPropertiesPage
{
/**
* This model is used to transform 3 properties into a boolean property.
*/
private PseudoExternalConnectionPoolingModel pseudoModel;
/**
* Creates a new <code>RdbmsConnectionPropertiesPage</code>.
*
* @param nodeHolder The holder of {@link org.eclipse.persistence.tools.workbench.scplugin.ui.session.DatabaseSessionNode DatabaseSessionNode}
*/
public RdbmsConnectionPropertiesPage(PropertyValueModel nodeHolder, WorkbenchContextHolder contextHolder)
{
super(nodeHolder, contextHolder);
addHelpTopicId(this, "session.login.database.connection");
}
/**
* Creates the <code>PropertyValueModel</code> responsible to handle the
* Platform Class property.
*
* @return A new <code>PropertyValueModel</code>
*/
private PropertyValueModel buildDatabasePlatformHolder()
{
return new PropertyAspectAdapter(getSelectionHolder(), DatabaseLoginAdapter.PLATFORM_CLASS_PROPERTY)
{
protected Object getValueFromSubject()
{
DatabaseLoginAdapter login = (DatabaseLoginAdapter) subject;
String platformClass = login.getPlatformClass();
if (platformClass == null)
return null;
try
{
return DatabasePlatformRepository.getDefault().platformForRuntimePlatformClassNamed(platformClass);
}
catch (IllegalArgumentException e)
{
return null;
}
}
protected void setValueOnSubject(Object value)
{
DatabaseLoginAdapter login = (DatabaseLoginAdapter) subject;
DatabasePlatform platform = (DatabasePlatform) value;
if (platform != null)
{
login.setPlatformClass(platform.getRuntimePlatformClassName());
}
}
};
}
/**
* Initializes the layout of this pane.
*
* @return The container with all its widgets
*/
protected Component buildPage()
{
GridBagConstraints constraints = new GridBagConstraints();
// Create the container
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
// Platform widgets
JComponent platformWidgets = buildLabeledComponent
(
"CONNECTION_RDBMS_DATABASE_PLATFORM_FIELD",
PlatformComponentFactory.buildPlatformChooser(buildDatabasePlatformHolder())
);
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(0, 0, 0, 0);
panel.add(platformWidgets, constraints);
addHelpTopicId(platformWidgets, "session.login.database.connection.platform");
// Login pane
RdbmsLoginPane loginPane = new RdbmsLoginPane(getSelectionHolder(), getWorkbenchContextHolder());
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.insets = new Insets(5, 0, 0, 0);
panel.add(loginPane, constraints);
addPaneForAlignment(loginPane);
// External Connection Pooling check box
CustomizedExternalOptionsPane optionsPane = new CustomizedExternalOptionsPane();
constraints.gridx = 0;
constraints.gridy = 2;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
constraints.insets = new Insets(5, 0, 0, 0);
panel.add(optionsPane, constraints);
return panel;
}
/**
* Creates the <code>PropertyChangeListener</code> to keep the parent object
* of the {@link PseudoPreallocationSizeModel} in sync with the selection
* object.
*
* @return A new <code>PropertyChangeListener</code>
*/
private PropertyChangeListener buildSelectionHolderListener ()
{
return new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent e)
{
pseudoModel.setParentNode((AbstractNodeModel) e.getNewValue());
}
};
}
/**
* Initializes this <code>RdbmsConnectionPropertiesPage</code>.
*
* @param nodeHolder The holder of the subject, which is <code>DatabaseLoginAdapter</code>
*/
protected void initialize(PropertyValueModel nodeHolder)
{
super.initialize(nodeHolder);
getSelectionHolder().addPropertyChangeListener(PropertyValueModel.VALUE, buildSelectionHolderListener());
pseudoModel = new PseudoExternalConnectionPoolingModel();
pseudoModel.setParentNode((AbstractNodeModel) selection());
}
/**
* This customized <code>LoginExternalOptionsPane</code> disables and selects
* the External Transaction Pooling check box if the Database Driver is J2EE
* Data Source;
*/
private class CustomizedExternalOptionsPane extends LoginExternalOptionsPane
{
/**
* Creates a new <code>CustomizedExternalOptionsPane</code>.
*/
protected CustomizedExternalOptionsPane()
{
super(getSelectionHolder(),
RdbmsConnectionPropertiesPage.this.getApplicationContext());
}
/**
* Creates the <code>JCheckBox</code> for the property External Connection
* Pooling.
*
* @return A new <code>JCheckBox</code>
*/
protected JCheckBox buildExternalConnectionPoolingCheckBox()
{
JCheckBox checkBox = super.buildExternalConnectionPoolingCheckBox();
buildExternalConnectionPoolingEnabler(checkBox);
return checkBox;
}
/**
* Creates the <code>ComponentEnabler</code> that will keep the enable state
* of the components contained in the given collection in sync with the
* boolean value calculated by the enabled state holder.
*
* @param checkBox The External Connection Pooling check box
* @return A new <code>ComponentEnabler</code>
*/
private ComponentEnabler buildExternalConnectionPoolingEnabler(JCheckBox checkBox)
{
return new ComponentEnabler(buildExternalConnectionPoolingEnableStateHolder(),
Collections.singleton(checkBox));
}
/**
* Creates the <code>PropertyValueModel</code> responsible to listen to
* changes made in the model that will determine if the check box needs to
* be enabled or not.
*
* @return A new <code>PropertyValueModel</code>
*/
private PropertyValueModel buildExternalConnectionPoolingEnableStateHolder()
{
return new PropertyAspectAdapter(PseudoExternalConnectionPoolingModel.ENABLED_PROPERTY, pseudoModel)
{
protected Object getValueFromSubject()
{
PseudoExternalConnectionPoolingModel model = (PseudoExternalConnectionPoolingModel) subject;
return Boolean.valueOf(model.isEnabled());
}
};
}
}
/**
* A pseudo model merging two properties into a single property. Basically,
* the enable state of the External Connection Pooling is dedictated by the
* Database Driver type and the External Transaction Controller.
*/
private class PseudoExternalConnectionPoolingModel extends AbstractNodeModel
{
private boolean enabled;
private PropertyChangeListener listener;
private PropertyChangeListener managedListener;
private PropertyChangeListener serverPlatformListener;
private SessionBrokerAdapter sessionBroker;
public static final String ENABLED_PROPERTY = "enabled";
private PropertyChangeListener buildManagedPropertyChangeListener()
{
return new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent e)
{
DatabaseLoginAdapter login = (DatabaseLoginAdapter) getParent();
SessionAdapter session = (SessionAdapter) login.getParent();
// Disengage the listener for the Server Platform that was
// registered on the broker's Server Platform
if (sessionBroker != null)
{
ServerPlatformAdapter serverPlatform = sessionBroker.getServerPlatform();
serverPlatform.removePropertyChangeListener(ServerPlatformAdapter.ENABLE_JTA_PROPERTY, listener);
}
// Keep track of the broker
DatabaseSessionAdapter databaseSession = (DatabaseSessionAdapter) session;
sessionBroker = databaseSession.getBroker();
// Reinstall the listener on the Server Platform
ServerPlatformAdapter serverPlatform = session.getServerPlatform();
serverPlatform.addPropertyChangeListener(ServerPlatformAdapter.ENABLE_JTA_PROPERTY, listener);
updateEnableState();
}
};
}
private PropertyChangeListener buildPropertyChangeListener()
{
return new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent e)
{
updateEnableState();
}
};
}
private PropertyChangeListener buildServerPlatformPropertyChangeListener()
{
return new PropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent e)
{
ServerPlatformAdapter oldServerPlatform = (ServerPlatformAdapter) e.getOldValue();
oldServerPlatform.removePropertyChangeListener(ServerPlatformAdapter.ENABLE_JTA_PROPERTY, listener);
ServerPlatformAdapter newServerPlatform = (ServerPlatformAdapter) e.getNewValue();
newServerPlatform.addPropertyChangeListener(ServerPlatformAdapter.ENABLE_JTA_PROPERTY, listener);
updateEnableState();
}
};
}
protected void checkParent(Node parent)
{
// The parent is set/unset dynamically
}
private void disengageListeners()
{
// Database Driver: disable when it's J2EE Data Source
DatabaseLoginAdapter login = (DatabaseLoginAdapter) getParent();
login.removePropertyChangeListener(DatabaseLoginAdapter.USE_DRIVER_MANAGER_PROPERTY, listener);
// Server Platform
SessionAdapter session = (SessionAdapter) login.getParent();
session.removePropertyChangeListener(SessionAdapter.SERVER_PLATFORM_CONFIG_PROPERTY, serverPlatformListener);
// External Transaction Controller (JTA): disable if there is an entry
ServerPlatformAdapter serverPlatform;
if (sessionBroker != null)
serverPlatform = sessionBroker.getServerPlatform();
else
serverPlatform = session.getServerPlatform();
serverPlatform.removePropertyChangeListener(ServerPlatformAdapter.ENABLE_JTA_PROPERTY, listener);
// Managed session, needed to keep track of the session broker
if (!session.isBroker())
{
DatabaseSessionAdapter databaseSession = (DatabaseSessionAdapter) session;
databaseSession.removePropertyChangeListener(DatabaseSessionAdapter.MANAGED_BY_BROKER, managedListener);
sessionBroker = null;
}
}
public String displayString()
{
return null;
}
private void engageListeners()
{
// Database Driver: disable when it's J2EE Data Source
DatabaseLoginAdapter login = (DatabaseLoginAdapter) getParent();
login.addPropertyChangeListener(DatabaseLoginAdapter.USE_DRIVER_MANAGER_PROPERTY, listener);
// Server Platform
SessionAdapter session = (SessionAdapter) login.getParent();
session.addPropertyChangeListener(SessionAdapter.SERVER_PLATFORM_CONFIG_PROPERTY, serverPlatformListener);
// External Transaction Controller: disable if there is an entry
ServerPlatformAdapter serverPlatform = session.getServerPlatform();
serverPlatform.addPropertyChangeListener(ServerPlatformAdapter.ENABLE_JTA_PROPERTY, listener);
// Managed session, need to keep track of the session broker
if (!session.isBroker())
{
DatabaseSessionAdapter databaseSession = (DatabaseSessionAdapter) session;
databaseSession.addPropertyChangeListener(DatabaseSessionAdapter.MANAGED_BY_BROKER, managedListener);
sessionBroker = databaseSession.getBroker();
}
}
/**
* Initializes this pseudo model.
*/
protected void initialize()
{
super.initialize();
listener = buildPropertyChangeListener();
managedListener = buildManagedPropertyChangeListener();
serverPlatformListener = buildServerPlatformPropertyChangeListener();
}
public boolean isEnabled()
{
return enabled;
}
public void setEnabled(boolean enabled)
{
boolean oldEnabled = isEnabled();
this.enabled = enabled;
firePropertyChanged(ENABLED_PROPERTY, oldEnabled, enabled);
}
public void setParentNode(Node parentNode)
{
if (getParent() != null)
{
disengageListeners();
}
super.setParent(parentNode);
if (parentNode != null)
{
engageListeners();
updateEnableState();
}
}
/**
* Updates the enable state based on certain criteras.
*/
private void updateEnableState()
{
DatabaseLoginAdapter login = (DatabaseLoginAdapter) getParent();
DatabaseSessionAdapter session = (DatabaseSessionAdapter) login.getParent();
boolean enabled = login.databaseDriverIsDriverManager() && !session.hasJTA();
if (session.isManaged() && session.getBroker().hasJTA())
{
enabled = false;
}
setEnabled(enabled);
}
}
}