/*******************************************************************************
* Copyright (c) 2014 Zend Technologies.
* All rights reserved. This program and the accompanying materials
* are the copyright of Zend Technologies and is protected under
* copyright laws of the United States.
* You must not copy, adapt or redistribute this document for
* any use.
*******************************************************************************/
package org.zend.php.zendserver.deployment.ui.servers;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.php.internal.server.core.Server;
import org.eclipse.php.internal.ui.wizards.IControlHandler;
import org.eclipse.php.internal.ui.wizards.IControlHandler.Kind;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
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.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.zend.php.server.ui.fragments.AbstractCompositeFragment;
import org.zend.php.zendserver.deployment.core.debugger.DeploymentAttributes;
import org.zend.php.zendserver.deployment.core.targets.EclipseApiKeyDetector;
import org.zend.php.zendserver.deployment.core.targets.TargetsManagerService;
import org.zend.php.zendserver.deployment.debug.core.DebugUtils;
import org.zend.php.zendserver.deployment.ui.Activator;
import org.zend.sdklib.SdkException;
import org.zend.sdklib.internal.target.ApiKeyDetector;
import org.zend.sdklib.internal.target.ZendTarget;
import org.zend.sdklib.manager.TargetException;
import org.zend.sdklib.manager.TargetsManager;
import org.zend.sdklib.target.IZendTarget;
import org.zend.sdklib.target.InvalidCredentialsException;
import org.zend.sdklib.target.LicenseExpiredException;
/**
* @author Wojciech Galanciak, 2014
*
*/
@SuppressWarnings("restriction")
public class WebApiCompositeFragment extends AbstractCompositeFragment {
private static String ID = "org.zend.php.zendserver.deployment.ui.servers.WebApiCompositeFragment"; //$NON-NLS-1$
private class KeyDetectionRunnable implements IRunnableWithProgress {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask(Messages.WebApiCompositeFragment_DetectingCredentials, IProgressMonitor.UNKNOWN);
try {
detectApiKey(null);
} catch (SdkException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
}
private class ServerPropertyChangeListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals(Server.HOSTNAME)) {
detectOnEnter = true;
}
}
}
private static final String DEFAULT_HOST = "http://"; //$NON-NLS-1$
private Button enableButton;
private Text hostText;
private Text keyText;
private Text secretText;
private Button detectButton;
private boolean enable;
private String host;
private String key;
private String secret;
private IZendTarget target;
private boolean detectOnEnter;
private boolean keysDetected;
private boolean isModified = false;
private ServerPropertyChangeListener phpServerListener;
/**
* PlatformCompositeFragment constructor
*
* @param parent
* @param handler
* @param isForEditing
*/
public WebApiCompositeFragment(Composite parent, IControlHandler handler, boolean isForEditing) {
super(parent, handler, isForEditing, Messages.WebApiCompositeFragment_Name,
Messages.WebApiCompositeFragment_Title, Messages.WebApiCompositeFragment_Description);
setImageDescriptor(Activator.getImageDescriptor(Activator.IMAGE_WIZ_DEPLOYMENT));
handler.setImageDescriptor(getImageDescriptor());
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
unregisterListeners();
removeDisposeListener(this);
}
});
}
@Override
public boolean performOk() {
// remove temporary attributes
getServer().removeAttribute(DeploymentAttributes.ENABLED.getName());
getServer().removeAttribute(DeploymentAttributes.TARGET_HOST.getName());
if (!enable) {
if (target != null) {
TargetsManager manager = TargetsManagerService.INSTANCE.getTargetManager();
if (manager.getTargetById(target.getId()) != null) {
manager.remove(target);
}
}
return true;
}
if (!isForEditing()) {
return isComplete();
}
if (target != null && !isModified()) {
return true;
}
isModified = false;
boolean webApiTest = webApiTest();
if (!webApiTest)
return false;
return isComplete();
}
@Override
public String getId() {
return ID;
}
@Override
public void validate() {
if (enableButton.getSelection()) {
if (host != null && host.trim().isEmpty()) {
setMessage(Messages.WebApiCompositeFragment_EmptyHostMessage, IMessageProvider.ERROR);
return;
}
if (key != null && key.trim().isEmpty()) {
setMessage(Messages.WebApiCompositeFragment_EmptyKeyMessage, IMessageProvider.ERROR);
return;
}
if (secret != null && secret.trim().isEmpty()) {
setMessage(Messages.WebApiCompositeFragment_EmptySecretMessage, IMessageProvider.ERROR);
return;
}
}
setMessage(getDescription(), IMessageProvider.NONE);
}
public void performTesting(IProgressMonitor monitor) {
if (!enable) {
return;
}
saveValues();
monitor.beginTask(Messages.WebApiCompositeFragment_TestingConnection, IProgressMonitor.UNKNOWN);
TargetsManager manager = TargetsManagerService.INSTANCE.getTargetManager();
IStatus status = null;
TargetConnectionTester tester = new TargetConnectionTester();
ZendTarget oldTarget = getOldTarget(target);
if (oldTarget != null) {
status = tester.testConnection(oldTarget, monitor);
}
if (status == null) {
if (target.isTemporary()) {
status = tester.testConnection(target, monitor);
} else {
status = tester.testConnection(target, monitor);
}
}
switch (status.getSeverity()) {
case IStatus.OK:
List<IZendTarget> finalTargets = tester.getFinalTargets();
for (IZendTarget target : finalTargets) {
if (target != null) {
if (manager.getTargetById(target.getId()) != null) {
manager.updateTarget(target, true);
} else {
try {
manager.add(target, true);
} catch (TargetException e) {
// cannot occur, suppress connection
} catch (LicenseExpiredException e) {
// cannot occur, suppress connection
}
}
}
}
break;
case IStatus.WARNING:
setMessage(status.getMessage(), IMessageProvider.WARNING);
break;
case IStatus.ERROR:
setMessage(status.getMessage(), IMessageProvider.ERROR);
break;
default:
break;
}
}
@Override
public void setData(Object server) throws IllegalArgumentException {
unregisterListeners();
super.setData(server);
if (getServer() != null && hostText != null && !hostText.isDisposed()) {
String suggestedHost = DEFAULT_HOST + getServer().getHost() + ":10081"; //$NON-NLS-1$
hostText.setText(suggestedHost);
registerListeners();
}
initialDetect();
}
public void setDetectOnEnter(boolean value) {
this.detectOnEnter = value;
}
private void initialDetect() {
if (controlHandler.getKind() == Kind.WIZARD && detectOnEnter) {
detectOnEnter = false;
handleDetect();
if (keysDetected) {
enableButton.setSelection(keysDetected);
enable = enableButton.getSelection();
updateState(keysDetected);
webApiTest();
IZendTarget zendTarget = getOldTarget(target) != null ? getOldTarget(target) : target;
getServer().setDebuggerId(DebugUtils.getDebuggerId(zendTarget));
}
}
}
@Override
protected void createContents(Composite parent) {
ModifyListener modifyListener = new ModifyListener() {
public void modifyText(ModifyEvent e) {
updateData();
isModified = true;
validate();
}
};
enableButton = new Button(parent, SWT.CHECK);
enableButton.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 3, 1));
enableButton.setText(Messages.WebApiCompositeFragment_EnableLabel);
enableButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
updateState(enableButton.getSelection());
if (!enableButton.getSelection() && target != null) {
TargetsManager manager = TargetsManagerService.INSTANCE.getTargetManager();
if (manager.getTargetById(target.getId()) != null) {
manager.remove(target);
}
}
updateData();
validate();
webApiTest();
}
});
CLabel noteIcon = new CLabel(parent, SWT.NONE);
noteIcon.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
noteIcon.setImage(Dialog.getImage(Dialog.DLG_IMG_MESSAGE_INFO));
noteIcon.setText(Messages.WebApiCompositeFragment_Enabling_web_api_info_message);
Label label = new Label(parent, SWT.NONE);
label.setText(Messages.WebApiCompositeFragment_Host);
hostText = new Text(parent, SWT.BORDER);
hostText.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
hostText.addModifyListener(modifyListener);
hostText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent event) {
if (hostText != null && detectButton != null) {
String host = hostText.getText().trim();
if (!host.isEmpty() && !DEFAULT_HOST.equals(host)) {
try {
new URL(host);
if (enable) {
detectButton.setEnabled(true);
}
return;
} catch (MalformedURLException e) {
// set detect to false
}
}
detectButton.setEnabled(false);
}
}
});
label = new Label(parent, SWT.NONE);
label.setText(Messages.WebApiCompositeFragment_KeyName);
keyText = new Text(parent, SWT.BORDER);
keyText.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
keyText.addModifyListener(modifyListener);
label = new Label(parent, SWT.NONE);
label.setText(Messages.WebApiCompositeFragment_KeySecret);
secretText = new Text(parent, SWT.BORDER);
secretText.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));
secretText.addModifyListener(modifyListener);
detectButton = new Button(parent, SWT.PUSH);
detectButton.setText(Messages.WebApiCompositeFragment_DetectLabel);
detectButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
detectButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
handleDetect();
}
});
Link link = new Link(parent, SWT.WRAP);
link.setText(Messages.WebApiCompositeFragment_WebApiDetails);
GridData layoutData = new GridData(SWT.FILL, SWT.TOP, true, false);
layoutData.widthHint = 400;
layoutData.horizontalSpan = 3;
link.setLayoutData(layoutData);
link.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
try {
PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL(new URL(event.text));
} catch (PartInitException e) {
Activator.log(e);
} catch (MalformedURLException e) {
Activator.log(e);
}
}
});
}
@Override
protected void init() {
TargetsManager manager = TargetsManagerService.INSTANCE.getTargetManager();
Server server = getServer();
if (server != null) {
String serverName = server.getName();
IZendTarget[] targets = manager.getTargets();
for (IZendTarget target : targets) {
if (serverName.equals(target.getServerName())) {
this.target = target;
hostText.setText(target.getHost().toString());
keyText.setText(target.getKey());
secretText.setText(target.getSecretKey());
enableButton.setSelection(true);
detectButton.setEnabled(true);
server.setAttribute(DeploymentAttributes.ENABLED.getName(), String.valueOf(true));
server.setAttribute(DeploymentAttributes.TARGET_HOST.getName(), hostText.getText());
updateState(true);
break;
}
}
}
if (target == null) {
String id = manager.createUniqueId(null);
target = new ZendTarget(id, null, null, null, true);
enableButton.setSelection(false);
if (server != null) {
server.setAttribute(DeploymentAttributes.ENABLED.getName(), String.valueOf(false));
}
updateState(false);
}
updateData();
validate();
}
private void saveValues() {
ZendTarget t = (ZendTarget) target;
Server server = getServer();
if (server != null) {
t.setServerName(server.getName());
try {
t.setHost(new URL(host));
t.setDefaultServerURL(new URL(server.getBaseURL()));
} catch (MalformedURLException e) {
Activator.log(e);
}
t.setKey(key);
t.setSecretKey(secret);
}
}
private void updateData() {
Server server = getServer();
if (enableButton != null) {
enable = enableButton.getSelection();
if (server != null) {
server.setAttribute(DeploymentAttributes.ENABLED.getName(), String.valueOf(enable));
}
}
if (hostText != null) {
host = hostText.getText();
if (enable) {
if (server != null) {
server.setAttribute(DeploymentAttributes.TARGET_HOST.getName(), host);
}
} else {
if (server != null) {
server.removeAttribute(DeploymentAttributes.TARGET_HOST.getName());
}
}
}
if (keyText != null) {
key = keyText.getText();
}
if (secretText != null) {
secret = secretText.getText();
}
}
private ZendTarget getOldTarget(IZendTarget target) {
TargetsManager manager = TargetsManagerService.INSTANCE.getTargetManager();
IZendTarget[] targets = manager.getTargets();
for (IZendTarget t : targets) {
if (t.getHost().equals(target.getHost())) {
ZendTarget oldTarget = (ZendTarget) copyTemp((ZendTarget) t);
Server server = getServer();
oldTarget.setServerName(server.getName());
oldTarget.setDefaultServerURL(target.getDefaultServerURL());
oldTarget.setHost(target.getHost());
oldTarget.setKey(target.getKey());
oldTarget.setSecretKey(target.getSecretKey());
return oldTarget;
}
}
return null;
}
private IZendTarget copyTemp(ZendTarget t) {
ZendTarget target = new ZendTarget(t.getId(), t.getHost(), t.getDefaultServerURL(), t.getKey(),
t.getSecretKey(), true);
String[] keys = t.getPropertiesKeys();
for (String key : keys) {
target.addProperty(key, t.getProperty(key));
}
return target;
}
private void handleDetect() {
KeyDetectionRunnable detector = new KeyDetectionRunnable();
try {
controlHandler.run(true, true, detector);
} catch (InvocationTargetException e) {
String message = MessageFormat.format(Messages.WebApiCompositeFragment_DetectingWebApi_Error,
e.getCause().getLocalizedMessage());
setMessage(message, IMessageProvider.ERROR);
Activator.logError(message, e);
return;
} catch (InterruptedException e) {
String message = Messages.WebApiCompositeFragment_DetectingWebApiInterrupted_Info;
setMessage(message, IMessageProvider.INFORMATION);
Activator.logInfo(message);
return;
}
webApiTest();
validate();
}
private void detectApiKey(String message) throws SdkException {
try {
final ApiKeyDetector detector = new EclipseApiKeyDetector(host + "/ZendServer"); //$NON-NLS-1$
if (detector.createApiKey(message)) {
keysDetected = true;
Display.getDefault().asyncExec(new Runnable() {
public void run() {
String key = detector.getKey();
String secret = detector.getSecretKey();
if (key != null && secret != null) {
keyText.setText(key);
secretText.setText(secret);
}
}
});
}
} catch (InvalidCredentialsException e) {
detectApiKey(Messages.WebApiCompositeFragment_InvalidCredentialsError);
}
}
private void updateState(boolean enabled) {
hostText.setEnabled(enabled);
keyText.setEnabled(enabled);
secretText.setEnabled(enabled);
detectButton.setEnabled(enabled);
}
private boolean isModified() {
return isModified;
}
private boolean webApiTest() {
try {
controlHandler.run(true, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
performTesting(monitor);
}
});
} catch (InvocationTargetException e) {
Activator.log(e);
return false;
} catch (InterruptedException e) {
Activator.log(e);
return false;
}
return true;
}
private void registerListeners() {
if(phpServerListener == null)
phpServerListener = new ServerPropertyChangeListener();
getServer().addPropertyChangeListener(phpServerListener);
}
private void unregisterListeners() {
Server server = getServer();
if(server == null)
return;
server.removePropertyChangeListener(phpServerListener);
}
}