/*************************************************************************************
* Copyright (c) 2014 Red Hat, 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:
* JBoss by Red Hat - Initial implementation.
************************************************************************************/
package org.jboss.tools.runtime.ui.internal.wizard.workflow;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
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.jboss.tools.foundation.core.xml.IMemento;
import org.jboss.tools.foundation.core.xml.XMLMemento;
import org.jboss.tools.foundation.ui.xpl.taskwizard.IWizardHandle;
import org.jboss.tools.foundation.ui.xpl.taskwizard.WizardFragment;
import org.jboss.tools.runtime.core.RuntimeCoreActivator;
import org.jboss.tools.runtime.core.model.DownloadRuntime;
import org.jboss.tools.runtime.ui.DownloadRuntimeMessages;
import org.jboss.tools.runtime.ui.RuntimeUIActivator;
import org.jboss.tools.runtime.ui.wizard.DownloadRuntimesTaskWizard;
/**
* This page will request credentials from the user to be used during the
* download of the file. It is customized for urls that are part of the download
* manager api, but will work for other urls that simply redirect
* to a file.
*
* It will first make a request without any xml headers. In the event
* of an error condition, it will try to use the xml header to know
* what the next step is, for example, signing the terms and conditions.
*/
public class DownloadManagerTermsAndConditionsFragment extends WizardFragment {
/**
* In the event of an error condition, the result of the api call
* will be stored in the task manager under this key.
*/
public static final String WORKFLOW_NEXT_STEP_KEY = "WORKFLOW_NEXT_STEP_KEY_TC"; //$NON-NLS-1$
private static final String DOWNLOAD_RUNTIME_SECTION = "downloadRuntimeSection"; //$NON-NLS-1$
private IDialogSettings downloadRuntimeSection;
private IWizardHandle handle;
private WizardFragment nextWorkflowFragment = null;
// data from the toc rest api
private String tocText;
private String tcUrl;
private HashMap<String, String> countryMap = null; // Not sure if k/v will ever change, so for now we'll use a map
private ArrayList<String> countryList = null;
private boolean initialized = false;
private Browser browser;
private Button retry;
public DownloadManagerTermsAndConditionsFragment() {
IDialogSettings dialogSettings = RuntimeUIActivator.getDefault().getDialogSettings();
downloadRuntimeSection = dialogSettings.getSection(DOWNLOAD_RUNTIME_SECTION);
if (downloadRuntimeSection == null) {
downloadRuntimeSection = dialogSettings.addNewSection(DOWNLOAD_RUNTIME_SECTION);
}
}
@Override
public boolean hasComposite() {
return true;
}
@Override
protected void createChildFragments(List<WizardFragment> list) {
if( nextWorkflowFragment != null ) {
list.add(nextWorkflowFragment);
}
}
@Override
public void enter() {
setComplete(false);
if( !initialized ) {
Display.getDefault().asyncExec(new Runnable(){
public void run() {
deferredEntry();
}
});
}
}
private void deferredEntry() {
try {
handle.run(true, false, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
initializeModel(monitor);
}
});
fillWidgets();
initialized = true;
handle.update();
} catch(Exception e) {
RuntimeUIActivator.pluginLog().logError(e);
}
}
protected void initializeModel(IProgressMonitor monitor) {
monitor.beginTask("Loading Terms and Conditions", 1000);
String workflowResponse = (String)getTaskModel().getObject(DownloadManagerCredentialsFragment.WORKFLOW_NEXT_STEP_KEY);
if( workflowResponse == null || workflowResponse.isEmpty()) {
Display.getDefault().asyncExec(new Runnable() { public void run() {
Exception e = new Exception("Unable to locate url for downloading runtime: Rest API response is empty.");
RuntimeCoreActivator.pluginLog().logError(e.getMessage(), e);
handle.setMessage(e.getMessage(), IWizardHandle.ERROR);
}});
return;
}
XMLMemento m = XMLMemento.createReadRoot(new ByteArrayInputStream(workflowResponse.getBytes()));
IMemento workflow = m.getChild("workflow");
IMemento tc = workflow.getChild("tc");
IMemento tcAccept = workflow.getChild("tc-accept");
this.tcUrl = ((XMLMemento)tc).getTextData();
// this.tcAcceptUrl = ((XMLMemento)tcAccept).getTextData();
monitor.worked(100);
// Long-running remote request
String tcResponseString = null;
try {
tcResponseString = getTCResponseString(new SubProgressMonitor(monitor, 800));
} catch(Exception e) {
final String msg = "An error occurred while loading the terms and conditions: " + e.getClass().getName() + " - " + e.getMessage();
RuntimeCoreActivator.pluginLog().logError(msg, e);
Display.getDefault().asyncExec(new Runnable() { public void run() {
handle.setMessage(msg, IWizardHandle.ERROR);
}});
return;
}
IMemento tocResponseMemento = XMLMemento.createReadRoot(new ByteArrayInputStream(tcResponseString.getBytes()));
// Get the options for country
IMemento customParamsMemento = tocResponseMemento.getChild("customParams");
IMemento[] params = customParamsMemento.getChildren("param");
IMemento countryParam = null;
IMemento downloadURLParam = null;
for( int i = 0; i < params.length; i++ ) {
String name = params[i].getString("name");
if( name.equals("country")) {
countryParam = params[i];
}
if( name.equals("downloadURL")) {
downloadURLParam = params[i];
}
}
IMemento countryOptions = countryParam.getChild("options");
IMemento[] countries = countryOptions.getChildren("option");
countryMap = new HashMap<String, String>();
countryList = new ArrayList<String>();
for( int i = 0; i < countries.length; i++ ) {
countryList.add(countries[i].getString("key"));
countryMap.put(countries[i].getString("key"), countries[i].getString("value"));
}
IMemento downloadURLOptions = downloadURLParam.getChild("options");
IMemento downloadURLOption = downloadURLOptions.getChild("option");
// downloadURL = downloadURLOption.getString("key");
// get the TC plaintext
IMemento tcPlainTextMemento = tocResponseMemento.getChild("htmlText");
String plaintext = ((XMLMemento)tcPlainTextMemento).getTextData();
tocText = plaintext;
monitor.worked(100);
monitor.done();
}
private void fillWidgets() {
if( browser != null && !browser.isDisposed() && tocText != null) {
browser.setText(tocText);
}
}
/*
* Long running task to get the terms and conditions
*/
private String getTCResponseString(IProgressMonitor monitor) throws Exception {
String result = "";
try {
// Now we need to fetch the terms and conditions
HttpURLConnection con =
(HttpURLConnection) new URL(tcUrl).openConnection();
con.setRequestMethod("GET");
// We need to get the content of this response to see what the next step is
InputStream stream = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = br.readLine()) != null) {
result+= line;
}
con.disconnect();
br.close();
} catch(Exception e) {
throw e;
}
return result;
}
@Override
public Composite createComposite(Composite parent, final IWizardHandle handle) {
this.handle = handle;
getPage().setTitle("JBoss.org Terms and Conditions");
getPage().setDescription("Please use the link below to sign the terms and conditions. Once complete, please press 'Retry' to continue.");
Composite contents = new Composite(parent, SWT.NONE);
GridData gd = new GridData(GridData.FILL_BOTH);
contents.setLayoutData(gd);
contents.setLayout(new FormLayout());
try {
browser = new Browser(contents, SWT.BORDER);
} catch (Exception e1) {
browser = new Browser(contents, SWT.BORDER | SWT.WEBKIT);
}
retry = new Button(contents, SWT.PUSH);
retry.setText("Retry");
retry.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
retryPressed();
}
});
FormData fd = new FormData();
fd.bottom = new FormAttachment(0, 400);
fd.left = new FormAttachment(0, 5);
fd.right = new FormAttachment(100, -5);
fd.top = new FormAttachment(0,5);
browser.setLayoutData(fd);
fd = new FormData();
fd.top = new FormAttachment(browser, 10);
fd.left = new FormAttachment(0,5);
retry.setLayoutData(fd);
setComplete(false);
fillWidgets();
return contents;
}
private DownloadRuntime getDownloadRuntimeFromTaskModel() {
return (DownloadRuntime)getTaskModel().getObject(DownloadRuntimesTaskWizard.DL_RUNTIME_PROP);
}
protected void retryPressed() {
final String userS = (String)getTaskModel().getObject(DownloadRuntimesTaskWizard.USERNAME_KEY);
final String passS = (String)getTaskModel().getObject(DownloadRuntimesTaskWizard.PASSWORD_KEY);
String errString = null;
try {
int response = DownloadManagerWorkflowUtility.getWorkflowStatus(getDownloadRuntimeFromTaskModel(), userS, passS);
if( response == DownloadManagerWorkflowUtility.CREDENTIALS_FAILED ) {
errString = DownloadRuntimeMessages.CredentialsIncorrect;
} else if( response == DownloadManagerWorkflowUtility.WORKFLOW_FAILED ) {
errString = "Your authorization process is still incomplete. Please press 'back' and try again.";
} else if( response == DownloadManagerWorkflowUtility.AUTHORIZED ) {
setComplete(true);
handle.update();
}
} catch(IOException e) {
RuntimeUIActivator.pluginLog().logError(e);
errString = NLS.bind(DownloadRuntimeMessages.CredentialError, e.getClass().getName(), e.getMessage());
} catch(CoreException ce) {
RuntimeUIActivator.pluginLog().logError(ce);
errString = NLS.bind(DownloadRuntimeMessages.CredentialError, ce.getClass().getName(), ce.getMessage());
}
if( errString != null ) {
setComplete(false);
handle.setMessage(errString, IMessageProvider.ERROR);
handle.update();
}
}
public void finishPage() {
// TODO
}
}