/*******************************************************************************
* 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.login;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.text.Document;
import org.eclipse.persistence.sessions.JNDIConnector;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContextHolder;
import org.eclipse.persistence.tools.workbench.framework.resources.ResourceRepository;
import org.eclipse.persistence.tools.workbench.framework.uitools.Pane;
import org.eclipse.persistence.tools.workbench.framework.uitools.RegexpDocument;
import org.eclipse.persistence.tools.workbench.scplugin.model.adapter.DatabaseLoginAdapter;
import org.eclipse.persistence.tools.workbench.scplugin.ui.tools.BooleanCellRendererAdapter;
import org.eclipse.persistence.tools.workbench.scplugin.ui.tools.ClassChooserTools;
import org.eclipse.persistence.tools.workbench.uitools.ComponentEnabler;
import org.eclipse.persistence.tools.workbench.uitools.Displayable;
import org.eclipse.persistence.tools.workbench.uitools.SwitcherPanel;
import org.eclipse.persistence.tools.workbench.uitools.app.CollectionAspectAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.CollectionValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.ListValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyAspectAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.ReadOnlyCollectionValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.ReadOnlyListValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.SortedListValueModelAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.ComboBoxModelAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.DocumentAdapter;
import org.eclipse.persistence.tools.workbench.uitools.cell.AbstractCellRendererAdapter;
import org.eclipse.persistence.tools.workbench.uitools.cell.AdaptableListCellRenderer;
import org.eclipse.persistence.tools.workbench.uitools.cell.CellRendererAdapter;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
import org.eclipse.persistence.tools.workbench.utility.Transformer;
/**
* This page shows the information regarding the Database login which is
* specific for {@link org.eclipse.persistence.tools.workbench.scplugin.model.adapter.DatabaseLoginAdapter DatabaseLoginAdapter}.
* <p>
* Here the layout:
* <pre>
* ---------------------------------------------
* | ---------------------- | --------------------
* | Database Driver: | |v| |<-| Driver Manager |
* | ---------------------- | | J2EE Data Source |
* | -PanelSwitcher--------------------------- | --------------------
* | | | |
* | | Driver Manager widgets | |
* | | or | |
* | | J2EE Data Source widgets | |
* | | | |
* | ----------------------------------------- |
* | -------------------- |
* | Username (Optional): | I | |
* | -------------------- |
* | -------------------- |
* | Password (Optional): | I | |
* | -------------------- |
* ---------------------------------------------</pre>
*
* Known containers of this pane:<br>
* - {@link RdbmsConnectionPropertiesPage}
* - {@link RdbmsPoolLoginPropertiesPage}
*
* @see DatabaseLoginAdapter
*
* @version 10.1.3
* @author Pascal Filion
*/
abstract class AbstractRdbmsLoginPane extends AbstractLoginPane
{
/**
* The sub-pane containing the Database Source widgets.
*/
private JComponent databaseSourcePane;
/**
* The sub-pane containing the Driver Manager widgets.
*/
private JComponent driverManagerPane;
/**
* Creates a new <code>AbstractRdbmsLoginPane</code>.
*
* @param subjectHolder The holder of {@link DatabaseLoginAdapter}
* @param context The plug-in context to be used, such as <code>ResourceRepository</code>
*/
public AbstractRdbmsLoginPane(PropertyValueModel subjectHolder, WorkbenchContextHolder contextHolder)
{
super(subjectHolder, contextHolder);
}
/**
* Creates the <code>CollectionValueModel</code> containing the actual items
* to be shown in the Clustering combo box.
*
* @return The <code>CollectionValueModel</code> containing the items
*/
private CollectionValueModel buildDatabaseDriverCollectionHolder()
{
Vector booleanValues = new Vector();
booleanValues.add(Boolean.TRUE);
booleanValues.add(Boolean.FALSE);
return new ReadOnlyCollectionValueModel(booleanValues);
}
/**
* Creates the <code>ComboBoxModel</code> that keeps the selected item in the
* combo box in sync with the value in the model and vice versa.
*
* @return The model showing two choices: "Driver Manager (True)" and "J2EE
* Data Source (False)"
*/
private ComboBoxModel buildDatabaseDriverComboBoxAdapter()
{
return new ComboBoxModelAdapter(buildDatabaseDriverCollectionHolder(),
buildDatabaseDriverSelectionHolder());
}
/**
* Creates the <code>PropertyValueModel</code> responsible to handle the
* Database Driver property.
*
* @return A new <code>PropertyValueModel</code>
*/
private PropertyValueModel buildDatabaseDriverHolder()
{
return new PropertyAspectAdapter(getSubjectHolder(), DatabaseLoginAdapter.USE_DRIVER_MANAGER_PROPERTY)
{
protected Object getValueFromSubject()
{
DatabaseLoginAdapter login = (DatabaseLoginAdapter) subject;
return Boolean.valueOf(login.databaseDriverIsDriverManager());
}
};
}
/**
* Creates the decorator responsible to format the <code>Boolean</code>
* values in the Clustering combo box.
*
* @return {@link SessionClusteringPropertiesPage.BooleanLabelDecorator}
*/
private CellRendererAdapter buildDatabaseDriverLabelDecorator()
{
ResourceRepository resourceRepository = resourceRepository();
return new BooleanCellRendererAdapter(resourceRepository.getString("CONNECTION_RDBMS_DRIVER_MANAGER_CHOICE"),
resourceRepository.getString("CONNECTION_RDBMS_DATA_SOURCE_CHOICE"));
}
/**
* Creates the <code>PropertyValueModel</code> responsible to listen to
* changes made to the type of Database Driver to be used, which is either
* Driver Manager or J2EE Data Source.
*
* @return {@link PropertyAspectAdapter}
*/
protected abstract PropertyValueModel buildDatabaseDriverSelectionHolder();
/**
* Creates the <code>SwitcherPanel</code> ...
*
* @return A new <code>SwitcherPanel</code>
*/
private SwitcherPanel buildDatabaseDriverSwitcherPanel()
{
getDriverManagerPane();
getDataSourcePane();
return new SwitcherPanel(buildDatabaseDriverHolder(),
buildDatabaseDriverTransformer());
}
/**
* Creates the <code>Transformer</code> responsible to convert the Clustering
* type into the corresponding <code>Component</code>.
*
* @return A new <code>Transformer</code>
*/
private Transformer buildDatabaseDriverTransformer()
{
return new Transformer()
{
public Object transform(Object value)
{
DatabaseLoginAdapter login = (DatabaseLoginAdapter) subject();
if ((value == null) || (login == null))
return null;
if (Boolean.TRUE.equals(value))
return getDriverManagerPane();
return getDataSourcePane();
}
};
}
/**
* Creates the <code>DocumentAdapter</code> that keeps the value from the
* text field in sync with the Data Source Name value in the model and vice
* versa.
*
* @return A new <code>DocumentAdapter</code>
*/
private Document buildDataSourceNameDocumentAdapter()
{
return new DocumentAdapter(buildDataSourceNameHolder());
}
/**
* Creates the <code>PropertyValueModel</code> responsible to handle the
* Data Source Name property.
*
* @return A new <code>PropertyValueModel</code>
*/
private PropertyValueModel buildDataSourceNameHolder()
{
return new PropertyAspectAdapter(getSubjectHolder(), DatabaseLoginAdapter.DATA_SOURCE_PROPERTY)
{
protected Object getValueFromSubject()
{
DatabaseLoginAdapter adapter = (DatabaseLoginAdapter) subject;
return adapter.getDataSourceName();
}
protected void setValueOnSubject(Object value)
{
DatabaseLoginAdapter adapter = (DatabaseLoginAdapter) subject;
adapter.setDataSourceName((String) value);
}
};
}
private JComponent buildDataSourcePane()
{
GridBagConstraints constraints = new GridBagConstraints();
// Create the container
Pane panel = new Pane(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
JComponent lookupTypeWidgets = buildLabeledComboBox
(
"CONNECTION_RDBMS_LOOKUP_TYPE_FIELD",
buildLookupTypeComboModel(),
buildLookupTypeCellRenderer()
);
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(lookupTypeWidgets, constraints);
JComponent nameWidgets = buildLabeledTextField
(
"CONNECTION_RDBMS_DATA_SOURCE_FIELD",
buildDataSourceNameDocumentAdapter()
);
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.CENTER;
constraints.insets = new Insets(5, 0, 0, 0);
panel.add(nameWidgets, constraints);
return panel;
}
/**
* Creates a Browse button that will take care to show the class chooser.
*
* @return A new <code>JButton</code>
*/
private JButton buildDriverClassBrowseButton()
{
return ClassChooserTools.buildBrowseButton
(
getWorkbenchContextHolder(),
"CONNECTION_RDBMS_DRIVER_CLASS_BROWSE_BUTTON",
buildClassRepositoryHolder(),
buildDriverClassHolder()
);
}
/**
* Creates the <code>ListValueModel</code> containing all the items to be
* shown in the Driver Class combo box.
*
* @return A new <code>ListValueModel</code>
*/
private ListValueModel buildDriverClassCollectionHolder()
{
Collection driverClasses = CollectionTools.collection(DatabaseLoginAdapter.driverClasses());
ReadOnlyCollectionValueModel collectionHolder = new ReadOnlyCollectionValueModel(driverClasses);
return new SortedListValueModelAdapter(collectionHolder);
}
/**
* Creates the <code>ComboBoxModel</code> that keeps the value from the combo
* box in sync with the Driver Class value in the model and vice versa.
*
* @return A new <code>ComboBoxModel</code>
*/
private ComboBoxModel buildDriverClassComboAdapter()
{
return new ComboBoxModelAdapter(buildDriverClassCollectionHolder(),
buildDriverClassHolder());
}
/**
* Creates the <code>PropertyValueModel</code> responsible to handle the
* Driver Class property.
*
* @return A new <code>PropertyValueModel</code>
*/
private PropertyValueModel buildDriverClassHolder()
{
return new PropertyAspectAdapter(getSubjectHolder(), DatabaseLoginAdapter.DRIVER_CLASS_PROPERTY)
{
protected Object getValueFromSubject()
{
DatabaseLoginAdapter adapter = (DatabaseLoginAdapter) subject;
return adapter.getDriverClassName();
}
protected void setValueOnSubject(Object value)
{
DatabaseLoginAdapter adapter = (DatabaseLoginAdapter) subject;
adapter.setDriverClassName((String) value);
}
};
}
/**
* Creates the sub-pane that contains the widgets that edit the Driver
* Manager specific information.
*
* @return The initialized sub-pane
*/
private JComponent buildDriverManagerPane()
{
GridBagConstraints constraints = new GridBagConstraints();
// Create the container
Pane panel = new Pane(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
// Driver Class widgets
JComboBox driverClassComboBox = new JComboBox(buildDriverClassComboAdapter());
driverClassComboBox.setEditable(true);
driverClassComboBox.setPrototypeDisplayValue("m");
JTextField textField = (JTextField) driverClassComboBox.getEditor().getEditorComponent();
textField.setDocument(RegexpDocument.buildDocument(RegexpDocument.RE_FULLY_QUALIFIED_CLASS_NAME));
// Driver Class browse button
Component driverClassWidgets = buildLabeledComponent
(
"CONNECTION_RDBMS_DRIVER_CLASS_COMBO_BOX",
driverClassComboBox,
buildDriverClassBrowseButton()
);
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(driverClassWidgets, constraints);
// Driver URL combo box
Component driverURLWidgets = buildLabeledEditableComboBox
(
"CONNECTION_RDBMS_DRIVER_URL_COMBO_BOX",
buildDriverURLComboAdapter()
);
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.CENTER;
constraints.insets = new Insets(5, 0, 0, 0);
panel.add(driverURLWidgets, constraints);
return panel;
}
/**
* Creates the <code>ListValueModel</code> containing all the items to
* be shown in the Driver URL combo box.
*
* @return A new <code>ListValueModel</code>
*/
private ListValueModel buildDriverURLCollectionHolder()
{
return new SortedListValueModelAdapter
(
new CollectionAspectAdapter(buildDriverClassHolder())
{
protected Iterator getValueFromSubject()
{
return DatabaseLoginAdapter.driverURLs((String) subject);
}
}
);
}
/**
* Creates the <code>DocumentAdapter</code> that keeps the value from the
* combo box in sync with the Driver URL value in the model and vice versa.
*
* @return A new <code>ComboBoxModel</code>
*/
private ComboBoxModel buildDriverURLComboAdapter()
{
return new ComboBoxModelAdapter(buildDriverURLCollectionHolder(),
buildDriverURLHolder());
}
/**
* Creates the <code>PropertyValueModel</code> responsible to handle the
* Driver URL property.
*
* @return A new <code>PropertyValueModel</code>
*/
private PropertyValueModel buildDriverURLHolder()
{
return new PropertyAspectAdapter(getSubjectHolder(), DatabaseLoginAdapter.CONNECTION_URL_PROPERTY)
{
protected Object getValueFromSubject()
{
DatabaseLoginAdapter login = (DatabaseLoginAdapter) subject;
return login.getConnectionURL();
}
protected void setValueOnSubject(Object value)
{
DatabaseLoginAdapter login = (DatabaseLoginAdapter) subject;
login.setConnectionURL((String) value);
}
};
}
private ListCellRenderer buildLookupTypeCellRenderer()
{
return new AdaptableListCellRenderer(new AbstractCellRendererAdapter()
{
public String buildText(Object value)
{
LookupType lookupType = (LookupType) value;
return lookupType.displayString();
}
});
}
private ListValueModel buildLookupTypeCollectionHolder(List lookupChoices)
{
return new ReadOnlyListValueModel(lookupChoices);
}
private ComboBoxModel buildLookupTypeComboModel()
{
LookupType string = new LookupType
(
resourceRepository().getString("CONNECTION_RDBMS_LOOKUP_TYPE_STRING_CHOICE"),
new Integer(JNDIConnector.STRING_LOOKUP)
);
LookupType compound = new LookupType
(
resourceRepository().getString("CONNECTION_RDBMS_LOOKUP_TYPE_COMPOUND_NAME_CHOICE"),
new Integer(JNDIConnector.COMPOUND_NAME_LOOKUP)
);
LookupType composite = new LookupType
(
resourceRepository().getString("CONNECTION_RDBMS_LOOKUP_TYPE_COMPOSITE_NAME_CHOICE"),
new Integer(JNDIConnector.COMPOSITE_NAME_LOOKUP)
);
List lookupTypes = new Vector(3);
lookupTypes.add(string);
lookupTypes.add(compound);
lookupTypes.add(composite);
CollectionTools.sort(lookupTypes, buildLookupTypeComparator());
return new ComboBoxModelAdapter(buildLookupTypeCollectionHolder(lookupTypes),
buildLookupTypeHolder(lookupTypes));
}
private Comparator buildLookupTypeComparator()
{
return new Comparator()
{
public int compare(Object object1, Object object2)
{
LookupType lookupType1 = (LookupType) object1;
LookupType lookupType2 = (LookupType) object2;
return Displayable.DEFAULT_COLLATOR.compare(lookupType1.displayString(), lookupType2.displayString());
}
};
}
private PropertyValueModel buildLookupTypeHolder(final List lookupChoices)
{
return new PropertyAspectAdapter(getSubjectHolder(), DatabaseLoginAdapter.LOOKUP_TYPE_PROPERTY)
{
private LookupType findLookupType(List lookupChoices, Integer lookupValue)
{
for (int index = lookupChoices.size(); --index >= 0; )
{
LookupType choice = (LookupType) lookupChoices.get(index);
if (choice.lookupValue().intValue() == lookupValue.intValue())
return choice;
}
return null; // Never go here
}
protected Object getValueFromSubject()
{
DatabaseLoginAdapter adapter = (DatabaseLoginAdapter) subject;
return findLookupType(lookupChoices, adapter.getLookupType());
}
protected void setValueOnSubject(Object value)
{
LookupType lookupType = (LookupType) value;
DatabaseLoginAdapter adapter = (DatabaseLoginAdapter) subject;
adapter.setLookupType(lookupType.lookupValue());
}
};
}
/**
* Returns the sub-pane containing the Data Source specific widgets.
*
* @return The initialized container
*/
private Component getDataSourcePane()
{
if (this.databaseSourcePane == null)
{
this.databaseSourcePane = buildDataSourcePane();
}
return this.databaseSourcePane;
}
/**
* Returns the sub-pane containing the Driver Manager specific widgets.
*
* @return The initialize container
* @see #buildDriverManagerPane
*/
private JComponent getDriverManagerPane()
{
if (this.driverManagerPane == null)
this.driverManagerPane = buildDriverManagerPane();
return this.driverManagerPane;
}
/**
* Initializes the layout of this pane.
*/
protected void initializeLayout()
{
GridBagConstraints constraints = new GridBagConstraints();
// Database Driver widgets
Component databaseDriverWidgets = buildLabeledComboBox
(
"CONNECTION_RDBMS_DATABASE_DRIVER_COMBO_BOX",
buildDatabaseDriverComboBoxAdapter(),
new AdaptableListCellRenderer(buildDatabaseDriverLabelDecorator())
);
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);
add(databaseDriverWidgets, constraints);
// PanelSwitcher for Driver Manager and Data Source panes
SwitcherPanel panelSwitcher = buildDatabaseDriverSwitcherPanel();
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.CENTER;
constraints.insets = new Insets(0, 0, 0, 0);
add(panelSwitcher, constraints);
// Create the Save username check box
JCheckBox saveUsernameCheckBox = buildSaveUsernameCheckBox();
constraints.gridx = 0;
constraints.gridy = 2;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.insets = new Insets(2, 0, 0, 0);
add(saveUsernameCheckBox, constraints);
// Username widgets
Component usernameWidgets = buildUserNameWidgets();
constraints.gridx = 0;
constraints.gridy = 3;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(5, 10, 0, 0);
add(usernameWidgets, constraints);
new ComponentEnabler(buildSaveUsernameHolder(), usernameWidgets);
// Create the Save Password check box
JCheckBox savePasswordCheckBox = buildSavePasswordCheckBox();
constraints.gridx = 0;
constraints.gridy = 4;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.insets = new Insets(2, 0, 0, 0);
add(savePasswordCheckBox, constraints);
// Password widgets
Component passwordWidgets = buildPasswordWidgets();
constraints.gridx = 0;
constraints.gridy = 5;
constraints.gridwidth = 3;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(5, 10, 0, 0);
add(passwordWidgets, constraints);
new ComponentEnabler(buildSavePasswordHolder(), passwordWidgets);
}
/**
* Updates the enable state of the children of this pane.
*
* @param enabled <code>true<code> if this component and its children should
* be enabled, <code>false<code> otherwise
*/
protected void updateEnableStateOfChildren(boolean enabled)
{
super.updateEnableStateOfChildren(enabled);
if (this.databaseSourcePane != null)
this.databaseSourcePane.setEnabled(enabled);
if (this.driverManagerPane != null)
this.driverManagerPane.setEnabled(enabled);
}
private class LookupType
{
private String displayString;
private Integer lookupValue;
LookupType(String displayString, Integer lookupValue)
{
super();
this.displayString = displayString;
this.lookupValue = lookupValue;
}
public String displayString()
{
return displayString;
}
public Integer lookupValue()
{
return lookupValue;
}
}
}