blob: 70f3aca63b40c15e57d49cff3717a000c683710b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.studio.connection.ui.widgets;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import org.apache.commons.lang3.StringUtils;
import org.apache.directory.api.ldap.model.url.LdapUrl;
import org.apache.directory.api.ldap.model.url.LdapUrl.Extension;
import org.apache.directory.api.util.Strings;
import org.apache.directory.studio.common.ui.CommonUIUtils;
import org.apache.directory.studio.common.ui.HistoryUtils;
import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils;
import org.apache.directory.studio.connection.core.Connection;
import org.apache.directory.studio.connection.core.ConnectionCoreConstants;
import org.apache.directory.studio.connection.core.ConnectionCorePlugin;
import org.apache.directory.studio.connection.core.ConnectionParameter;
import org.apache.directory.studio.connection.core.ConnectionParameter.EncryptionMethod;
import org.apache.directory.studio.connection.core.jobs.CheckNetworkParameterRunnable;
import org.apache.directory.studio.connection.ui.AbstractConnectionParameterPage;
import org.apache.directory.studio.connection.ui.ConnectionUIConstants;
import org.apache.directory.studio.connection.ui.ConnectionUIPlugin;
import org.apache.directory.studio.connection.ui.RunnableContextRunner;
import org.apache.directory.studio.connection.ui.dialogs.CertificateInfoDialog;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.PreferencesUtil;
/**
* The NetworkParameterPage is used the edit the network parameters of a
* connection. This is a tab in the connection property widget :
*
* <pre>
* .---------------------------------------------------------------------------.
* | Connection |
* +---------------------------------------------------------------------------+
* | .---[Network Parameter]|Authentication||Browser Options||Edit Options|--. |
* | | | |
* | | Connection name : [-------------------------------------] | |
* | | | |
* | | Network Parameter | |
* | | .-------------------------------------------------------------------. | |
* | | | | | |
* | | | Hostname : [----------------------------------------|v] | | |
* | | | Port : [----------------------------------------|v] | | |
* | | | Timeout : [ ] | | |
* | | | Encryption method : [-No encryption--------------------------|v] | | |
* | | | Server certificates for LDAP connections can | | |
* | | | managed in the '<certificate validation>' | | |
* | | | preference page. | | |
* | | | | | |
* | | | (Check Network Parameter) | | |
* | | +-------------------------------------------------------------------+ | |
* | | | |
* | | [] Read-Only (prevents any add, delete, modify or rename operation) | |
* | | | |
* | +-----------------------------------------------------------------------+ |
* +---------------------------------------------------------------------------+
* </pre>
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class NetworkParameterPage extends AbstractConnectionParameterPage
{
private static final String X_CONNECTION_NAME = "X-CONNECTION-NAME"; //$NON-NLS-1$
private static final String X_ENCRYPTION = "X-ENCRYPTION"; //$NON-NLS-1$
private static final String X_ENCRYPTION_LDAPS = "ldaps"; //$NON-NLS-1$
private static final String X_ENCRYPTION_START_TLS = "StartTLS"; //$NON-NLS-1$
/** The connection name text widget */
private Text nameText;
/** The host name combo with the history of recently used host names */
private Combo hostCombo;
/** The host combo with the history of recently used ports */
private Combo portCombo;
/** The combo to select the encryption method */
private Combo encryptionMethodCombo;
/** The button to fetch and show the server's certificate */
private Button viewServerCertificateButton;
/** The button to check the connection parameters */
private Button checkConnectionButton;
/** The checkbox to make the connection read-only */
private Button readOnlyConnectionCheckbox;
/** A timeout for the connection. Default to 30s */
private Text timeoutSecondsText;
/**
* A listener for the Link data widget. It will open the CertificateValidationPreference dialog.
*/
private SelectionAdapter linkDataWidgetListener = new SelectionAdapter()
{
@Override
public void widgetSelected( SelectionEvent event )
{
String certificateValidationPreferencePageId = ConnectionUIPlugin.getDefault()
.getPluginProperties().getString( "PrefPage_CertificateValidationPreferencePage_id" ); //$NON-NLS-1$
PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn( Display.getDefault()
.getActiveShell(), certificateValidationPreferencePageId, new String[]
{ certificateValidationPreferencePageId }, null );
dialog.open();
}
};
/**
* Gets the connection name.
*
* @return the connectio name
*/
private String getName()
{
return nameText.getText();
}
/**
* Gets the host name.
*
* @return the host name
*/
private String getHostName()
{
return hostCombo.getText();
}
/**
* Gets the port.
*
* @return the port
*/
private int getPort()
{
return Integer.parseInt( portCombo.getText() );
}
/**
* Gets the timeout in seconds.
*
* @return The timeout in seconds
*/
private int getTimeoutSeconds()
{
String timeoutSecondsString = timeoutSecondsText.getText();
if ( Strings.isEmpty( timeoutSecondsString ) )
{
return 30;
}
else
{
return Integer.parseInt( timeoutSecondsString );
}
}
/**
* Gets the encyrption method.
*
* @return the encyrption method
*/
private ConnectionParameter.EncryptionMethod getEncyrptionMethod()
{
switch ( encryptionMethodCombo.getSelectionIndex() )
{
case 1:
return ConnectionParameter.EncryptionMethod.LDAPS;
case 2:
return ConnectionParameter.EncryptionMethod.START_TLS;
default:
return ConnectionParameter.EncryptionMethod.NONE;
}
}
/**
* Gets a temporary connection with all connection parameter
* entered in this page.
*
* @return a test connection
*/
private Connection getTestConnection()
{
ConnectionParameter connectionParameter = new ConnectionParameter( null, getHostName(), getPort(),
getEncyrptionMethod(), ConnectionParameter.AuthenticationMethod.NONE, null, null, null, true, null,
30000L );
return new Connection( connectionParameter );
}
/**
* Gets read only flag.
*
* @return the read only flag
*/
private boolean isReadOnly()
{
return readOnlyConnectionCheckbox.getSelection();
}
/**
* {@inheritDoc}
*/
@Override
protected void createComposite( Composite parent )
{
Composite composite = BaseWidgetUtils.createColumnContainer( parent, 1, 1 );
Composite nameComposite = BaseWidgetUtils.createColumnContainer( composite, 2, 1 );
BaseWidgetUtils.createLabel( nameComposite, Messages.getString( "NetworkParameterPage.ConnectionName" ), 1 ); //$NON-NLS-1$
nameText = BaseWidgetUtils.createText( nameComposite, StringUtils.EMPTY, 1 ); //$NON-NLS-1$
BaseWidgetUtils.createSpacer( composite, 1 );
Group group = BaseWidgetUtils.createGroup( composite, Messages
.getString( "NetworkParameterPage.NetworkParameter" ), 1 ); //$NON-NLS-1$
IDialogSettings dialogSettings = ConnectionUIPlugin.getDefault().getDialogSettings();
// The network hostname
Composite groupComposite = BaseWidgetUtils.createColumnContainer( group, 3, 1 );
BaseWidgetUtils.createLabel( groupComposite, Messages.getString( "NetworkParameterPage.HostName" ), 1 ); //$NON-NLS-1$
String[] hostHistory = HistoryUtils.load( dialogSettings,
ConnectionUIConstants.DIALOGSETTING_KEY_HOST_HISTORY );
hostCombo = BaseWidgetUtils.createCombo( groupComposite, hostHistory, -1, 2 );
// The network port
BaseWidgetUtils.createLabel( groupComposite, Messages.getString( "NetworkParameterPage.Port" ), 1 ); //$NON-NLS-1$
String[] portHistory = HistoryUtils.load( dialogSettings,
ConnectionUIConstants.DIALOGSETTING_KEY_PORT_HISTORY );
portCombo = BaseWidgetUtils.createCombo( groupComposite, portHistory, -1, 2 );
portCombo.setTextLimit( 5 );
portCombo.setText( "389" ); //$NON-NLS-1$
// The timeout
BaseWidgetUtils.createLabel( groupComposite, Messages.getString( "NetworkParameterPage.Timeout" ), 2 ); //$NON-NLS-1$
timeoutSecondsText = BaseWidgetUtils.createText( groupComposite, "30", 1 ); //$NON-NLS-1$
timeoutSecondsText.setTextLimit( 7 );
String[] encMethods = new String[]
{
Messages.getString( "NetworkParameterPage.NoEncryption" ), //$NON-NLS-1$
Messages.getString( "NetworkParameterPage.UseSSLEncryption" ), //$NON-NLS-1$
Messages.getString( "NetworkParameterPage.UseStartTLS" ) //$NON-NLS-1$
};
BaseWidgetUtils.createLabel( groupComposite, Messages.getString( "NetworkParameterPage.EncryptionMethod" ), 1 ); //$NON-NLS-1$
encryptionMethodCombo = BaseWidgetUtils.createReadonlyCombo( groupComposite, encMethods, 0, 2 );
boolean validateCertificates = ConnectionCorePlugin.getDefault().getPluginPreferences().getBoolean(
ConnectionCoreConstants.PREFERENCE_VALIDATE_CERTIFICATES );
if ( validateCertificates )
{
BaseWidgetUtils.createSpacer( groupComposite, 1 );
Link link = BaseWidgetUtils.createLink( groupComposite,
Messages.getString( "NetworkParameterPage.CertificateValidationLink" ), 2 ); //$NON-NLS-1$
GridData linkGridData = new GridData( GridData.FILL_HORIZONTAL );
linkGridData.horizontalSpan = 2;
linkGridData.widthHint = 100;
link.setLayoutData( linkGridData );
link.addSelectionListener( linkDataWidgetListener );
}
else
{
BaseWidgetUtils.createSpacer( groupComposite, 1 );
BaseWidgetUtils.createLabel( groupComposite, Messages
.getString( "NetworkParameterPage.WarningCertificateValidation" ), 2 ); //$NON-NLS-1$
}
BaseWidgetUtils.createSpacer( groupComposite, 1 );
GridData gridData = new GridData();
gridData.horizontalAlignment = SWT.RIGHT;
gridData.verticalAlignment = SWT.BOTTOM;
viewServerCertificateButton = new Button( groupComposite, SWT.PUSH );
viewServerCertificateButton.setLayoutData( gridData );
viewServerCertificateButton.setText( Messages.getString( "NetworkParameterPage.ViewCertificate" ) ); //$NON-NLS-1$
checkConnectionButton = new Button( groupComposite, SWT.PUSH );
checkConnectionButton.setLayoutData( gridData );
checkConnectionButton.setText( Messages.getString( "NetworkParameterPage.CheckNetworkParameter" ) ); //$NON-NLS-1$
readOnlyConnectionCheckbox = BaseWidgetUtils.createCheckbox( composite,
Messages.getString( "NetworkParameterPage.ReadOnly" ), 1 ); //$NON-NLS-1$
BaseWidgetUtils.createSpacer( composite, 1 );
nameText.setFocus();
}
/**
* {@inheritDoc}
*/
@Override
protected void validate()
{
// set enabled/disabled state of check connection button
checkConnectionButton.setEnabled( !hostCombo.getText().equals( StringUtils.EMPTY ) &&
!portCombo.getText().equals( StringUtils.EMPTY ) );
// set enabled/disabled state of show server certificate button
viewServerCertificateButton.setEnabled( checkConnectionButton.isEnabled()
&& getEncyrptionMethod() != EncryptionMethod.NONE );
// validate input fields
message = null;
infoMessage = null;
errorMessage = null;
if ( Strings.isEmpty( portCombo.getText() ) ) //$NON-NLS-1$
{
message = Messages.getString( "NetworkParameterPage.PleaseEnterPort" ); //$NON-NLS-1$
}
if ( Strings.isEmpty( hostCombo.getText() ) ) //$NON-NLS-1$
{
message = Messages.getString( "NetworkParameterPage.PleaseEnterHostname" ); //$NON-NLS-1$
}
if ( Strings.isEmpty( nameText.getText() ) ) //$NON-NLS-1$
{
message = Messages.getString( "NetworkParameterPage.PleaseEnterConnectionName" ); //$NON-NLS-1$
}
if ( Strings.isEmpty( timeoutSecondsText.getText() ) ) //$NON-NLS-1$
{
timeoutSecondsText.setText( "30" );
}
if ( ConnectionCorePlugin.getDefault().getConnectionManager().getConnectionByName( nameText.getText() ) != null
&& ( ( connectionParameter == null ) || !nameText.getText().equals( connectionParameter.getName() ) ) )
{
errorMessage = NLS.bind(
Messages.getString( "NetworkParameterPage.ConnectionExists" ), new String[] //$NON-NLS-1$
{ nameText.getText() } );
}
}
/**
* {@inheritDoc}
*/
@Override
protected void loadParameters( ConnectionParameter parameter )
{
connectionParameter = parameter;
nameText.setText( CommonUIUtils.getTextValue( parameter.getName() ) );
hostCombo.setText( CommonUIUtils.getTextValue( parameter.getHost() ) );
portCombo.setText( Integer.toString( parameter.getPort() ) );
int encryptionMethodIndex = 0;
if ( parameter.getEncryptionMethod() == EncryptionMethod.LDAPS )
{
encryptionMethodIndex = 1;
}
else if ( parameter.getEncryptionMethod() == EncryptionMethod.START_TLS )
{
encryptionMethodIndex = 2;
}
encryptionMethodCombo.select( encryptionMethodIndex );
readOnlyConnectionCheckbox.setSelection( parameter.isReadOnly() );
timeoutSecondsText.setText( Long.toString( parameter.getTimeoutMillis() / 1000L ) );
}
/**
* {@inheritDoc}
*/
@Override
protected void initListeners()
{
nameText.addModifyListener( event -> connectionPageModified() );
hostCombo.addModifyListener( event -> connectionPageModified() );
portCombo.addVerifyListener( event -> {
if ( !event.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
{
event.doit = false;
}
} );
portCombo.addModifyListener( event -> connectionPageModified() );
encryptionMethodCombo.addSelectionListener( new SelectionAdapter()
{
/**
* {@inheritDoc}
*/
@Override
public void widgetSelected( SelectionEvent event )
{
connectionPageModified();
}
} );
checkConnectionButton.addSelectionListener( new SelectionAdapter()
{
/**
* {@inheritDoc}
*/
@Override
public void widgetSelected( SelectionEvent event )
{
Connection connection = getTestConnection();
CheckNetworkParameterRunnable runnable = new CheckNetworkParameterRunnable( connection );
IStatus status = RunnableContextRunner.execute( runnable, runnableContext, true );
if ( status.isOK() )
{
String title = Messages.getString( "NetworkParameterPage.CheckNetworkParameter" ); //$NON-NLS-1$
String message = Messages.getString( "NetworkParameterPage.ConnectionEstablished" ); //$NON-NLS-1$
SSLSession sslSession = runnable.getSslSession();
if ( sslSession != null )
{
message += "\n\nProtocol: " + sslSession.getProtocol();
message += "\nCipher Suite: " + sslSession.getCipherSuite();
}
MessageDialog.openInformation( Display.getDefault().getActiveShell(), title, message );
}
}
} );
viewServerCertificateButton.addSelectionListener( new SelectionAdapter()
{
@Override
public void widgetSelected( SelectionEvent event )
{
Connection connection = getTestConnection();
CheckNetworkParameterRunnable runnable = new CheckNetworkParameterRunnable( connection );
IStatus status = RunnableContextRunner.execute( runnable, runnableContext, true );
if ( status.isOK() )
{
try
{
SSLSession sslSession = runnable.getSslSession();
Certificate[] certificates = sslSession.getPeerCertificates();
X509Certificate[] serverCertificates = new X509Certificate[certificates.length];
for ( int i = 0; i < certificates.length; i++ )
{
serverCertificates[i] = ( X509Certificate ) certificates[i];
}
new CertificateInfoDialog( Display.getDefault().getActiveShell(), serverCertificates ).open();
}
catch ( SSLPeerUnverifiedException e )
{
throw new RuntimeException( e );
}
}
}
} );
readOnlyConnectionCheckbox.addSelectionListener( new SelectionAdapter()
{
/**
* {@inheritDoc}
*/
@Override
public void widgetSelected( SelectionEvent event )
{
connectionPageModified();
}
} );
// The timeout events
timeoutSecondsText.addModifyListener( event -> connectionPageModified() );
timeoutSecondsText.addVerifyListener( event -> {
if ( !event.text.matches( "[0-9]*" ) ) //$NON-NLS-1$
{
event.doit = false;
}
} );
}
/**
* {@inheritDoc}
*/
@Override
public void saveParameters( ConnectionParameter parameter )
{
parameter.setName( getName() );
parameter.setHost( getHostName() );
parameter.setPort( getPort() );
parameter.setEncryptionMethod( getEncyrptionMethod() );
parameter.setReadOnly( isReadOnly() );
parameter.setTimeoutMillis( getTimeoutSeconds() * 1000L );
}
/**
* {@inheritDoc}
*/
@Override
public void saveDialogSettings()
{
IDialogSettings dialogSettings = ConnectionUIPlugin.getDefault().getDialogSettings();
HistoryUtils.save( dialogSettings, ConnectionUIConstants.DIALOGSETTING_KEY_HOST_HISTORY, hostCombo.getText() );
HistoryUtils.save( dialogSettings, ConnectionUIConstants.DIALOGSETTING_KEY_PORT_HISTORY, portCombo.getText() );
}
/**
* {@inheritDoc}
*/
@Override
public void setFocus()
{
nameText.setFocus();
}
/**
* {@inheritDoc}
*/
@Override
public boolean areParametersModifed()
{
return isReconnectionRequired() || !StringUtils.equals( connectionParameter.getName(), getName() );
}
/**
* {@inheritDoc}
*/
@Override
public boolean isReconnectionRequired()
{
return ( connectionParameter == null )
|| ( !StringUtils.equals( connectionParameter.getHost(), getHostName() ) )
|| ( connectionParameter.getPort() != getPort() )
|| ( connectionParameter.getEncryptionMethod() != getEncyrptionMethod() )
|| ( connectionParameter.isReadOnly() != isReadOnly() )
|| ( connectionParameter.getTimeoutMillis() != getTimeoutSeconds() * 1000L );
}
/**
* {@inheritDoc}
*/
@Override
public void mergeParametersToLdapURL( ConnectionParameter parameter, LdapUrl ldapUrl )
{
ldapUrl.getExtensions().add( new Extension( false, X_CONNECTION_NAME, parameter.getName() ) );
ldapUrl.setHost( parameter.getHost() );
ldapUrl.setPort( parameter.getPort() );
switch ( parameter.getEncryptionMethod() )
{
case NONE:
// default
break;
case LDAPS:
ldapUrl.getExtensions().add( new Extension( false, X_ENCRYPTION, X_ENCRYPTION_LDAPS ) );
break;
case START_TLS:
ldapUrl.getExtensions().add( new Extension( false, X_ENCRYPTION, X_ENCRYPTION_START_TLS ) );
break;
}
}
/**
* {@inheritDoc}
*/
@Override
public void mergeLdapUrlToParameters( LdapUrl ldapUrl, ConnectionParameter parameter )
{
// connection name, current date if absent
String name = ldapUrl.getExtensionValue( X_CONNECTION_NAME );
if ( StringUtils.isEmpty( name ) )
{
name = new SimpleDateFormat( "yyyy-MM-dd HH-mm-ss" ).format( new Date() ); //$NON-NLS-1$
}
parameter.setName( name );
// host
parameter.setHost( ldapUrl.getHost() );
// port
parameter.setPort( ldapUrl.getPort() );
// encryption method, none if unknown or absent
String encryption = ldapUrl.getExtensionValue( X_ENCRYPTION );
if ( StringUtils.isNotEmpty( encryption ) && X_ENCRYPTION_LDAPS.equalsIgnoreCase( encryption ) )
{
parameter.setEncryptionMethod( ConnectionParameter.EncryptionMethod.LDAPS );
}
else if ( StringUtils.isNotEmpty( encryption ) && X_ENCRYPTION_START_TLS.equalsIgnoreCase( encryption ) )
{
parameter.setEncryptionMethod( ConnectionParameter.EncryptionMethod.START_TLS );
}
else
{
parameter.setEncryptionMethod( ConnectionParameter.EncryptionMethod.NONE );
}
}
}