/*******************************************************************************
* Copyright (c) 2011, 2013 Wind River Systems, Inc. and others. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.ui.controls.net;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl;
import org.eclipse.tcf.te.ui.controls.activator.UIPlugin;
import org.eclipse.tcf.te.ui.controls.nls.Messages;
import org.eclipse.tcf.te.ui.controls.validator.NameOrIPValidator;
import org.eclipse.tcf.te.ui.controls.validator.NameOrIPVerifyListener;
import org.eclipse.tcf.te.ui.controls.validator.Validator;
/**
* Basic remote host name or IP-address control.
*/
public class RemoteHostAddressControl extends BaseEditBrowseTextControl {
/**
* Constructor.
*
* @param parentPage The parent dialog page this control is embedded in. Must not be <code>null</code>!
*/
public RemoteHostAddressControl(IDialogPage parentPage) {
super(parentPage);
setIsGroup(false);
setHasHistory(false);
setEditFieldLabel(Messages.RemoteHostAddressControl_label);
setButtonLabel(Messages.RemoteHostAddressControl_button_label);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl#onButtonControlSelected()
*/
@Override
protected void onButtonControlSelected() {
onCheckAddress();
getButtonControl().setEnabled(false);
// Reset the validation message.
if (getMessage() != null && getMessage().equals(getUserInformationTextCheckNameAddress())) {
setMessage(null, IMessageProvider.NONE);
}
if (getControlDecoration() != null) {
getControlDecoration().hide();
}
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl#modifyText(org.eclipse.swt.events.ModifyEvent)
*/
@Override
public void modifyText(ModifyEvent e) {
super.modifyText(e);
boolean enabled = isValid() &&
(!(getEditFieldValidator() instanceof NameOrIPValidator) || ((NameOrIPValidator)getEditFieldValidator()).isName());
setButtonControlEnabled(enabled);
if (enabled && getControlDecoration() != null) {
getControlDecoration().hide();
}
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl#setButtonControlEnabled(boolean)
*/
@Override
protected void setButtonControlEnabled(boolean enabled) {
boolean btnEnabled = enabled;
if (btnEnabled) {
// The "Check" button needs specific enablement
btnEnabled = isValid() &&
(!(getEditFieldValidator() instanceof NameOrIPValidator) || ((NameOrIPValidator)getEditFieldValidator()).isName());
}
super.setButtonControlEnabled(btnEnabled);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl#doCreateEditFieldValidator()
*/
@Override
protected Validator doCreateEditFieldValidator() {
return new NameOrIPValidator(
Validator.ATTR_MANDATORY |
NameOrIPValidator.ATTR_IP |
NameOrIPValidator.ATTR_NAME |
NameOrIPValidator.ATTR_CHECK_AVAILABLE);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl#configureEditFieldValidator(org.eclipse.tcf.te.ui.controls.validator.Validator)
*/
@Override
protected void configureEditFieldValidator(Validator validator) {
if (validator != null && validator instanceof NameOrIPValidator) {
validator.setMessageText(NameOrIPValidator.INFO_MISSING_NAME_OR_IP, Messages.RemoteHostAddressControl_information_missingTargetNameAddress);
validator.setMessageText(NameOrIPValidator.ERROR_INVALID_NAME_OR_IP, Messages.RemoteHostAddressControl_error_invalidTargetNameAddress);
validator.setMessageText(NameOrIPValidator.ERROR_INVALID_NAME, Messages.RemoteHostAddressControl_error_invalidTargetNameAddress);
validator.setMessageText(NameOrIPValidator.ERROR_INVALID_IP, Messages.RemoteHostAddressControl_error_invalidTargetIpAddress);
validator.setMessageText(NameOrIPValidator.INFO_CHECK_NAME, getUserInformationTextCheckNameAddress());
}
}
private VerifyListener verifyListener;
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl#doGetEditFieldControlVerifyListener()
*/
@Override
protected VerifyListener doGetEditFieldControlVerifyListener() {
if (verifyListener == null) {
verifyListener =
new NameOrIPVerifyListener(
NameOrIPVerifyListener.ATTR_IP |
NameOrIPVerifyListener.ATTR_NAME);
}
return verifyListener;
}
/**
* Returns the human readable text to present to the user in case of the edit field control
* content should be checked by user action (pressing the check button).
*
* @return The user information text or an empty string. Must be never <code>null</code>.
*/
protected String getUserInformationTextCheckNameAddress() {
return Messages.RemoteHostAddressControl_information_checkNameAddressUserInformation;
}
/**
* Returns the human readable text to present to the user as task name if checking if or if not
* the edit field content can be resolved to an IP-address.
*
* @return The task name for checking the host name. Must be never <code>null</code>.
*/
protected String getTaskNameCheckNameAddress() {
return Messages.RemoteHostAddressControl_information_checkNameAddressField;
}
/**
* Returns the human readable text to present to the user if the edit field content resolving to
* an IP-address succeeded.
*
* @return The information text. Must be never <code>null</code>.
*/
protected String getInformationTextCheckNameAddressSuccess() {
return Messages.RemoteHostAddressControl_information_checkNameAddressFieldOk;
}
/**
* Returns the human readable text to present to the user if the edit field content resolving to
* an IP-address failed.
*
* @return The error text. Must be never <code>null</code>.
*/
protected String getErrorTextCheckNameAddressFailed() {
return Messages.RemoteHostAddressControl_error_targetNameNotResolveable;
}
/**
* If the user entered a host name, we have to validate that we can really resolve the name
* to an IP address. Because this may really take a while, give the user the feedback what
* we are actually doing.
*/
private void onCheckAddress() {
ProgressMonitorDialog dialog = new ProgressMonitorDialog(getParentControl().getShell());
try {
dialog.run(false, false, new IRunnableWithProgress() {
private final String address = getEditFieldControlText();
private final Control control = getEditFieldControl();
private final IDialogPage parentPage = getParentPage();
/* (non-Javadoc)
* @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
monitor.setTaskName(getTaskNameCheckNameAddress());
InetAddress[] addresses = InetAddress.getAllByName(address);
if (Platform.inDebugMode() && addresses != null) {
StringBuilder message = new StringBuilder();
message.append("RemoteHostAddressControl: Name '"); //$NON-NLS-1$
message.append(address);
message.append("' resolves to: "); //$NON-NLS-1$
boolean firstAddress = true;
for (InetAddress address : addresses) {
if (!firstAddress) message.append(", "); //$NON-NLS-1$
message.append(address.getHostAddress());
firstAddress = false;
}
IStatus status = new Status(IStatus.WARNING, UIPlugin.getUniqueIdentifier(), message.toString());
UIPlugin.getDefault().getLog().log(status);
}
setCheckResultMessage(IMessageProvider.INFORMATION, getInformationTextCheckNameAddressSuccess());
} catch (Exception e) {
setCheckResultMessage(IMessageProvider.WARNING, getErrorTextCheckNameAddressFailed());
control.setFocus();
} finally {
// Trigger the wizard container update
IWizardContainer container = null;
try {
// Try to get the wizard container from the parent page
if (parentPage != null) {
Class<?>[] paramTypes = new Class[0];
Object[] args = new Object[0];
final Method method = parentPage.getClass().getMethod("getContainer", paramTypes); //$NON-NLS-1$
if (!method.isAccessible()) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
method.setAccessible(true);
return null;
}
});
}
Object result = method.invoke(parentPage, args);
if (result instanceof IWizardContainer) {
container = (IWizardContainer)result;
}
}
} catch (Exception e) {
// If the object does not have a "getContainer()" method,
// or the invocation fails or the access to the method
// is denied, we are done here and break the loop
container = null;
}
if (container != null) {
container.updateButtons();
container.updateMessage();
}
}
}
});
} catch (Exception e) {}
}
protected void setCheckResultMessage(int severity, String message) {
setMessage(message, severity);
if (getParentPage() instanceof DialogPage) {
((DialogPage)getParentPage()).setMessage(message, severity);
}
}
}