/*************************************************************************************
* 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.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.zip.GZIPInputStream;
import org.eclipse.core.internal.preferences.Base64;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.jboss.tools.foundation.core.xml.IMemento;
import org.jboss.tools.foundation.core.xml.XMLMemento;
import org.jboss.tools.foundation.ui.xpl.taskwizard.WizardFragment;
import org.jboss.tools.runtime.core.model.DownloadRuntime;
import org.jboss.tools.runtime.ui.RuntimeUIActivator;
/**
* A utility class for running the remote download-manager header commands
* to verify if the downloadRuntime is set to be downloaded.
*/
public class DownloadManagerWorkflowUtility {
public static final int AUTHORIZED = 1;
public static final int CREDENTIALS_FAILED = 2;
public static final int WORKFLOW_FAILED = 3;
public static int getWorkflowStatus(DownloadRuntime dr, String userS, String passS)
throws CoreException, MalformedURLException, IOException {
int response = headerOnlyStatusCode(dr, userS, passS);
if( response == 401 ) {
// 401 means bad credentials, change nothing
return CREDENTIALS_FAILED;
} else if( response == 403 || response == 200) {
// 403 means workflow incomplete / forbidden, need a child page
return WORKFLOW_FAILED;
} else if( response == 302 ) {
// 302 means all's clear / redirect, no child page needed
return AUTHORIZED;
}
throw new CoreException(new Status(IStatus.ERROR, RuntimeUIActivator.PLUGIN_ID, "Unknown response code: " + response));
}
private static int headerOnlyStatusCode(DownloadRuntime dr, String userS, String passS)
throws CoreException, MalformedURLException, IOException {
HttpURLConnection con = getWorkflowConnection(dr, userS, passS, "HEAD", true);
int response = con.getResponseCode();
con.disconnect();
return response;
}
// Example curl command:
// curl --verbose -L -u user:pass -H "Content-Type: application/xml" -H "Accept: application/xml" -O https://www.jboss.org/download-manager/jdf/file/jboss-eap-6.3.0.GA.zip
// This is a connection to see where we stand in the workflow
private static HttpURLConnection getWorkflowConnection(DownloadRuntime dr,
String user, String pass, String requestMethod, boolean useXMLHeader)
throws IOException, MalformedURLException {
String url = dr.getUrl();
HttpURLConnection con =
(HttpURLConnection) new URL(url).openConnection();
con.setInstanceFollowRedirects(false);
String userCredentials = user+ ":" + pass;
String basicAuth = "Basic " + new String(new Base64().encode(userCredentials.getBytes()));
con.setRequestProperty ("Authorization", basicAuth);
if( useXMLHeader ) {
con.setRequestProperty("Content-Type", "application/xml");
con.setRequestProperty("Accept", "application/xml");
}
con.setRequestMethod(requestMethod);
return con;
}
private static String findNextStep(String responseContent) {
if( responseContent != null && !responseContent.isEmpty()) {
XMLMemento m = XMLMemento.createReadRoot(new ByteArrayInputStream(responseContent.getBytes()));
if( m != null ) {
IMemento workflow = m.getChild("workflow");
IMemento step = workflow.getChild("step");
String nextStep = ((XMLMemento)step).getTextData();
return nextStep;
}
}
return null;
}
/**
* Try to acquire the xml response indicating what the next step in the t&c is for this url.
* Due to a bug on the server, the current implementation will check both normal responses,
* and a gzip'd response. If the normal response is properly formatted xml, it will be used.
* If it is not, we will attempt to read the input stream through a gzip input stream,
* to see if that one returns properly formatted xml.
*
* @param dr
* @param userS
* @param passS
* @return A workflow response if it can be found, or null
* @throws IOException
*/
public static String getWorkflowResponseContent(DownloadRuntime dr, String userS, String passS) throws IOException {
HttpURLConnection con = getWorkflowConnection(dr, userS, passS, "GET", true);
// We need to get the content of this response to see what the next step is
InputStream stream = con.getInputStream();
// As byte array
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = stream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[] bytes = buffer.toByteArray();
con.disconnect();
// Try to read it normally
String result = "";
BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes)));
String line;
while ((line = br.readLine()) != null) {
result += line;
}
br.close();
// Parse the response to see the next step in the process
String nextStep = findNextStep(result);
int x;
// If the result was not properly formatted xml, try via gzip
if( nextStep == null ) {
// Try to read it gzip-style, due to bugs on the server: JBIDE-17253
result = "";
br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(bytes))));
while ((line = br.readLine()) != null) {
result += line;
}
br.close();
}
return result;
}
public static WizardFragment getNextWorkflowFragment(String response) {
String nextStep = findNextStep(response);
if( "termsAndConditions".equals(nextStep)) { //$NON-NLS-1$
// return the tc page
return new DownloadManagerTermsAndConditionsFragment();
}
return null;
}
}