package cz.trask.migration; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.Charset; import java.util.Base64; import java.util.HashMap; import java.util.Map; import javax.net.ssl.HttpsURLConnection; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.yaml.snakeyaml.Yaml; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import cz.trask.migration.config.ConfigManager; import cz.trask.migration.model.APIList; import cz.trask.migration.model.HttpResponse; import cz.trask.migration.model.RegisterResponse; import cz.trask.migration.model.TokenResponse; public abstract class AbstractProcess { private static Logger log = LogManager.getLogger(AbstractProcess.class); protected Gson gson; protected Yaml yaml; protected ConfigManager config = ConfigManager.getInstance(); protected AbstractProcess() { gson = new GsonBuilder().create(); yaml = new Yaml(); setTrustStoreCredentials(); javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() { public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { return true; } }); } protected String getTrustStorePath() { String path = config.getTruststorePath(); if (!new File(path).canRead()) { path = System.getProperty("user.dir") + File.separatorChar + config.getTruststorePath(); if (!new File(path).canRead()) { return null; } } return path; } protected void setTrustStoreCredentials() { log.info(getTrustStorePath()); System.setProperty("javax.net.ssl.trustStore", getTrustStorePath()); System.setProperty("javax.net.ssl.trustStorePassword", config.getTruststorePassword()); } /** * Retrieve access token based on clientId and clientSecret * * @param reg - client application object with clientId and clientSecret * @param scope - requested OAuth2 scope * @throws Exception */ protected TokenResponse getToken(String publisherurl, String wso2User, RegisterResponse reg, String scope) throws Exception { byte[] decoded = Base64.getDecoder().decode(wso2User); String decodedstring = new String(decoded); String[] decodedstringparts = decodedstring.split(":"); String username = decodedstringparts[0]; String password = decodedstringparts[1]; log.debug("Getting token with Username: '" + wso2User + "' URL: " + publisherurl); Map httpHeaders = new HashMap<>(); httpHeaders.put("Authorization", "Basic ".concat(Base64.getEncoder() .encodeToString(reg.getClientId().concat(":").concat(reg.getClientSecret()).getBytes()))); httpHeaders.put("Content-Type", "application/x-www-form-urlencoded"); String data = "grant_type=password&username=".concat(username).concat("&password=") .concat(URLEncoder.encode(password, "UTF-8")).concat("&scope=").concat(scope); HttpResponse response = makeDataRequest(publisherurl, httpHeaders, data); log.debug("Token response: HTTP Code " + response.getResponseCode() + " Json: " + response.getResponse()); TokenResponse resp = gson.fromJson(response.getResponse(), TokenResponse.class); return resp; } /** * Register client application to get clientId and clientSecret * * @throws Exception */ protected RegisterResponse register(String publisherurl, String wso2User) throws Exception { log.debug("Registering with Username: '" + wso2User + "' URL: " + publisherurl); byte[] decodedUserBytes = Base64.getDecoder().decode(wso2User); String decodeduserappkey = new String(decodedUserBytes); String[] decodeduserparts = decodeduserappkey.split(":"); String decodeduser = decodeduserparts[0]; Map httpHeaders = new HashMap<>(); httpHeaders.put("Authorization", "Basic ".concat(wso2User)); httpHeaders.put("Content-Type", "application/json"); String data = "{\"callbackUrl\": \"www.google.lk\",\"clientName\": \"rest_api_publisher" + decodeduser + "\",\"owner\": \"" + decodeduser + "\",\"grantType\": \"password refresh_token\",\"saasApp\": true}"; HttpResponse response = makeDataRequest(publisherurl, httpHeaders, data); log.debug( "Register API response: HTTP Code " + response.getResponseCode() + " Json: " + response.getResponse()); RegisterResponse resp = gson.fromJson(response.getResponse(), RegisterResponse.class); return resp; } /** * Common function used for http request * * @param method - http method * @param urlStr - url to dev poral * @param httpHeaders * @param params - currently is not used * @throws Exception */ protected HttpResponse makeRequest(String method, String urlStr, Map httpHeaders, Map params) throws Exception { return makeRequest(method, urlStr, httpHeaders, params, false); } /** * Common function used for http request * * @param method - http method * @param urlStr - url to dev poral * @param httpHeaders * @param data - request data * @param binary - binary or text mode * @throws Exception */ protected HttpResponse makeRequest(String method, String urlStr, Map httpHeaders, Map params, boolean binary) throws Exception { log.info("Calling URL: " + urlStr); String query = ""; for (String key : params.keySet()) { query = query.concat(URLEncoder.encode(key, "UTF-8")).concat("=") .concat(URLEncoder.encode(params.get(key), "UTF-8")).concat("&"); } if (query.length() > 1 && "GET".equals(method)) { urlStr = urlStr.concat("?").concat(query); } URL url = new URL(urlStr); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod(method); con.setDoInput(true); for (String key : httpHeaders.keySet()) { con.addRequestProperty(key, httpHeaders.get(key)); } if (query.length() > 1 && "POST".equals(method)) { con.setDoOutput(true); OutputStream out = con.getOutputStream(); out.write(query.getBytes("UTF-8")); } InputStream in = con.getInputStream(); String res = ""; byte[] buf = new byte[4096]; ByteArrayOutputStream baos = new ByteArrayOutputStream(); int read = in.read(buf); while (read != -1) { if (binary) baos.write(buf, 0, read); else res = res.concat(new String(buf, 0, read)); read = in.read(buf); } baos.flush(); HttpResponse resp = new HttpResponse(); resp.setHeaders(con.getHeaderFields()); if (binary) resp.setResponseBytes(baos.toByteArray()); else resp.setResponse(res); resp.setResponseCode(con.getResponseCode()); con.disconnect(); log.info("Response code: " + resp.getResponseCode()); // log.info("Response: " + resp.getResponse()); return resp; } /** * Common function used for http request * * @param urlStr - url to dev poral * @param httpHeaders * @param data - request data * @throws Exception */ protected HttpResponse makeDataRequest(String urlStr, Map httpHeaders, String data) throws Exception { byte[] json = data.getBytes(Charset.forName("UTF-8")); URL url = new URL(urlStr); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); for (String key : httpHeaders.keySet()) { con.addRequestProperty(key, httpHeaders.get(key)); } con.addRequestProperty("Content-Length", "" + json.length); OutputStream out = con.getOutputStream(); out.write(json); InputStream in = con.getInputStream(); String res = ""; byte[] buf = new byte[4096]; ByteArrayOutputStream baos = new ByteArrayOutputStream(); int read = in.read(buf); while (read != -1) { res = res.concat(new String(buf, 0, read)); read = in.read(buf); } baos.flush(); HttpResponse resp = new HttpResponse(); resp.setHeaders(con.getHeaderFields()); resp.setResponse(res); resp.setResponseCode(con.getResponseCode()); return resp; } /** * Retrieve the list of APIs by name. * * @param tokenResponse - WSO2 APIM access token * @throws Exception */ protected APIList getList(String publisherurl, TokenResponse tokenResponse) throws Exception { APIList listOfApis = null; try { String url = publisherurl.concat(String.format("/apis?limit=9999&offset=0")); log.debug("Getting APIs with token: '" + tokenResponse.getAccess_token() + "' URL: " + url); Map httpHeaders = new HashMap<>(); Map params = new HashMap<>(); httpHeaders.put("Authorization", "Bearer ".concat(tokenResponse.getAccess_token())); HttpResponse response = makeRequest("GET", url, httpHeaders, params); log.debug("Listing APIs: HTTP Code " + response.getResponseCode() + " Data: " + response.getResponse()); listOfApis = gson.fromJson(response.getResponse(), APIList.class); if (response.getResponseCode() != 200) log.error("Cannot list API. Something bad happened."); } catch (Exception e) { log.error("Cannot list API:" + e); throw new Exception("Cannot list API:" + e.getMessage()); } return listOfApis; } /** * Common function used for upload API * * @param urlStr - url to dev poral * @param httpHeaders * @param params - currently is not used * @param api - zip file to upload * @throws Exception */ protected static HttpResponse makeFileRequest(String method, String urlStr, Map httpHeaders, byte[] buff, String attachmentFileName) throws Exception { if (buff == null) { log.error("Cannot send NULL payload to rest service."); } String crlf = "\r\n"; String twoHyphens = "--"; String boundary = "----" + System.currentTimeMillis() + "----"; URL url = new URL(urlStr); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setUseCaches(false); con.setDoOutput(true); con.setRequestMethod(method); con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); con.setRequestProperty("User-Agent", "curl/7.55.1"); con.setRequestProperty("Accept", "*/*"); for (String key : httpHeaders.keySet()) { con.addRequestProperty(key, httpHeaders.get(key)); } DataOutputStream request = new DataOutputStream(con.getOutputStream()); request.writeBytes(crlf); request.writeBytes(twoHyphens + boundary + crlf); request.writeBytes( "Content-Disposition: form-data; name=\"file\"; filename=\"" + attachmentFileName + "\"" + crlf); request.writeBytes("Content-Type: application/octet-stream" + crlf); request.writeBytes("Content-Transfer-Encoding: binary" + crlf); request.writeBytes(crlf); request.write(buff); request.writeBytes(crlf); request.writeBytes(twoHyphens + boundary + twoHyphens + crlf); request.flush(); request.close(); String res = ""; byte[] buf = new byte[4096]; HttpResponse resp = new HttpResponse(); InputStream in; int responseCode = con.getResponseCode(); if (responseCode == 200 || responseCode == 201) { in = con.getInputStream(); } else { in = con.getErrorStream(); } while (in.available() > 0) { int read = in.read(buf); res = res.concat(new String(buf, 0, read)); } resp.setHeaders(con.getHeaderFields()); resp.setResponse(res); resp.setResponseCode(responseCode); return resp; } }