/**
* Copyright (C) 2015 Orange
* Licensed 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 com.francetelecom.clara.cloud.paas.it.services.helper;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Assert;
import org.junit.internal.AssumptionViolatedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.francetelecom.clara.cloud.commons.TechnicalException;
import com.francetelecom.clara.cloud.logicalmodel.samplecatalog.SampleAppFactory;
import com.francetelecom.clara.cloud.services.dto.LinkDto;
/**
* PaasServicesEnvApplicationAccessHelper
* common code of : (PaasServicesEnv)<BaseIT|AdvancedIT>
* TO FIX BVA : (in progress)
* Last update : $LastChangedDate$
* Last author : $Author$
* @version : $Revision$
*/
public class PaasServicesEnvApplicationAccessHelper {
// logger
protected static Logger logger = LoggerFactory.getLogger(PaasServicesEnvApplicationAccessHelper.class.getName());
private SampleAppFactory logicalModelCatalog;
// Test url attempt count
private int webAppTestAttempts = 2;
// test url wait time in second
private int webAppTestWaitTime = 5;
public PaasServicesEnvApplicationAccessHelper(SampleAppFactory logicalModelCatalog, int webAppTestAttempts, int webAppTestWaitTime) {
this.logicalModelCatalog = logicalModelCatalog;
this.webAppTestAttempts = webAppTestAttempts;
this.webAppTestWaitTime = webAppTestWaitTime;
}
public void checkWebGuiServicesAccess(List<LinkDto> webGuiAccessLinks, boolean accessibleExpected, PaasServicesEnvITConfiguration itConfiguration) {
if (itConfiguration.isUseSshTunnel()) {
throw new TechnicalException("SSH Tunnel aren't supported anymore");
} else {
for (LinkDto guiAccessLink : webGuiAccessLinks) {
String httpProxyHost = null;
int httpProxyPort = 3128;
if (itConfiguration.isUseHttpIgeProxy()) {
httpProxyHost = itConfiguration.getHttpProxyHost();
httpProxyPort = itConfiguration.getHttpProxyPort();
}
checkWebGuiAccessLink(guiAccessLink, accessibleExpected, httpProxyHost, httpProxyPort);
}
}
}
private void checkWebGuiAccessLink(LinkDto link, boolean shouldAccessible, String httpProxyHost, int httpProxyPort) {
for (Map.Entry<String, String> entry : logicalModelCatalog.getAppUrlsAndKeywords(link.getUrl()).entrySet()) {
String testedUrl = link.getUrl().toExternalForm() + entry.getKey();
checkApplicationAccessFromUrlAndKeyword(testedUrl, entry.getValue(), shouldAccessible, httpProxyHost, httpProxyPort);
}
}
private void checkApplicationAccessFromUrlAndKeyword(String accessUrlString, String checkKeyword, boolean shouldAccessible, String httpProxyHost, int httpProxyPort) {
logger.debug("Testing url {} ", accessUrlString);
Assert.assertEquals("Access to application is not ok: " + accessUrlString,
shouldAccessible,
testUrl(
accessUrlString,
shouldAccessible ? webAppTestAttempts : 1,
webAppTestWaitTime,
checkKeyword, httpProxyHost, httpProxyPort));
}
//
//~ Utils static tools
//
/**
*
* @param httpProxyHost set to null for direct connection or to proxy host to use proxy
*/
public static boolean testUrl(String url, int maxAttempts, int waitingTimeSeconds, String checkKeyword, String httpProxyHost, int httpProxyPort) {
boolean urlTestSucceeded = false;
// Add an arbitrary parameter to disable all possible cache
final String urlNoCache;
if (url.contains("?")) {
urlNoCache = url + "&nocache=" + System.currentTimeMillis();
} else {
urlNoCache = url + "?nocache=" + System.currentTimeMillis();
}
URL targetApplicationUrl;
try {
targetApplicationUrl = new URL(urlNoCache);
} catch (MalformedURLException e) {
logger.error("url invalid {}", urlNoCache);
throw new AssumptionViolatedException(e, new NotValidURLMatcher(urlNoCache));
}
for (int tryCount = 0; tryCount < maxAttempts && !urlTestSucceeded; tryCount++) {
logger.info("Testing " + url + " - Attempt " + (tryCount + 1) + "/" + maxAttempts);
String cookie = checkStringAndReturnCookie(targetApplicationUrl, checkKeyword, httpProxyHost, httpProxyPort);
if (cookie != null) {
urlTestSucceeded = true;
} else {
logger.info("Sleeping " + waitingTimeSeconds + "s before next retry");
try {
Thread.sleep(waitingTimeSeconds * 1000);
} catch (InterruptedException e) {
break;
}
}
}
return urlTestSucceeded;
}
private static class NotValidURLMatcher extends BaseMatcher {
private String notValidUrl;
public NotValidURLMatcher(String notValidUrl) {
this.notValidUrl = notValidUrl;
}
@Override
public boolean matches(Object o) {
return false;
}
@Override
public void describeTo(Description description) {
description.appendText("unable to convert " + notValidUrl + " in a valid URL");
}
}
/**
* Check if a string appear in the html page
*
* @param url
* URL to test
* @param token
* String that must be in html page
* @return Cookie that identifies the was or null if the test failed. An
* empty string means that no cookie was found in the request, but
* the check succeeded.
*/
private static String checkStringAndReturnCookie(URL url, String token, String httpProxyHost, int httpProxyPort) {
InputStream is = null;
String cookie = null;
try {
HttpURLConnection connection;
if (httpProxyHost != null) {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(httpProxyHost, httpProxyPort));
connection = (HttpURLConnection) url.openConnection(proxy);
} else {
connection = (HttpURLConnection) url.openConnection();
}
connection.setRequestMethod("GET");
is = connection.getInputStream();
// check http status code
if (connection.getResponseCode() == 200) {
DataInputStream dis = new DataInputStream(new BufferedInputStream(is));
StringWriter writer = new StringWriter();
IOUtils.copy(dis, writer, "UTF-8");
if (writer.toString().contains(token)) {
cookie = connection.getHeaderField("Set-Cookie");
if (cookie == null)
cookie = "";
} else {
logger.info("URL " + url.getFile() + " returned code 200 but does not contain keyword '" + token + "'");
logger.debug("1000 first chars of response body: " + writer.toString().substring(0, 1000));
}
} else {
logger.error("URL " + url.getFile() + " returned code " + connection.getResponseCode() + " : " + connection.getResponseMessage());
if (System.getProperty("http.proxyHost") != null) {
logger.info("Using proxy=" + System.getProperty("http.proxyHost") + ":" + System.getProperty("http.proxyPort"));
}
}
} catch (IOException e) {
logger.error("URL test failed: " + url.getFile() + " => " + e.getMessage() + " (" + e.getClass().getName() + ")");
if (System.getProperty("http.proxyHost") != null) {
logger.info("Using proxy=" + System.getProperty("http.proxyHost") + ":" + System.getProperty("http.proxyPort"));
}
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException ioe) {
// just going to ignore this one
}
}
return cookie;
}
}