Groovy Sample – PbcsRestClient.groovy

package com.oracle.ceal

import javax.net.ssl.HostnameVerifier
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSession
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

import java.net.HttpURLConnection

import java.util.regex.Pattern
import java.util.regex.Matcher
import java.util.zip.ZipEntry
import java.util.zip.ZipFile

class PbcsRestClient {
	private HttpURLConnection connection
	private def planningUrl
	private def interopUrl
	private def proxyHost
	private def proxyPort
	private def user
	private def pwd
	private def domain
	private def ignoreSSLCertsErrors
	
	public PbcsRestClient(planningServerUrl, interopServerUrl,httpProxyHost, httpProxyPort, identityDomain,username, password, ignoreSSLCertificationPathErrors) {
		planningUrl=planningServerUrl
		interopUrl=interopServerUrl
		proxyHost=httpProxyHost
		proxyPort=httpProxyPort
		domain=identityDomain
		user=username
		pwd=password
		ignoreSSLCertsErrors=ignoreSSLCertificationPathErrors
		
	}
	
	def setProxyParams() {
		Properties systemProperties = System.getProperties()
		systemProperties.setProperty("http.proxyHost",proxyHost)
		systemProperties.setProperty("http.proxyPort",proxyPort)
		systemProperties.setProperty("https.proxyHost",proxyHost)
		systemProperties.setProperty("https.proxyPort",proxyPort)
	
	}
	
	def setSSLParams() {
		if (ignoreSSLCertsErrors !=null && ignoreSSLCertsErrors.toUpperCase()=="TRUE") {
			println "Ignoring SSL certification path errors"
			// Disable SSL cert validation
			
			def hostnameVerifier = [
				verify: { hostname, session -> true }
			]
			def trustManager = [
					checkServerTrusted: { chain, authType -> },
					checkClientTrusted: { chain, authType -> },
					getAcceptedIssuers: { null }
			]
				
			HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier as HostnameVerifier)
			HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory())
			
			SSLContext context = SSLContext.getInstance("SSL")
			context.init(null, [trustManager as X509TrustManager] as TrustManager[], null)
			
		}
	}
	
	def openConnection(restUrl,method,localFileNameWithPathForStorage) {
		println "Opening connection to $restUrl with method:$method"
		int statusCode
	
		setProxyParams()
		setSSLParams()
			
		URL newUrl
		newUrl=new URL(restUrl)
			
		connection = (HttpURLConnection) newUrl.openConnection()
		
		connection.setDoOutput(true)
		connection.setDoInput(true)
		connection.setUseCaches(false)
		if (method=="") 
			connection.setRequestMethod("GET")
		else
			connection.setRequestMethod(method)
			
		connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded")
		
		String userCredentials = domain +"."+user + ":" + pwd
		String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userCredentials.getBytes())
		connection.setRequestProperty("Authorization", basicAuth)
	
		String response=""
		try {
			statusCode = connection.responseCode
			println "Connection status code: $statusCode "
			if (statusCode==401) {
				println "Not authorized"
			}
			if (statusCode==200) {
				println "Authentication succeeded"
				println "Server response:"
				println "-----"
				response=displayServerResponse(connection,localFileNameWithPathForStorage)
				println "-----"
			}
			if (statusCode==400) {
				println "Bad request"
				println "Server response:"
				println "-----"
				response=displayServerResponse(connection,"")
				println "-----"
			}
		} catch (Exception e) {
			println "Error connecting to the URL"
			println e.getMessage()
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}
		
		return response
	}
	
	def displayServerResponse(connection,localFileNameWithPathForStorage) {
		InputStream is;
		if (connection.getResponseCode()==200) {
			is=connection.getInputStream();
		} else {
			is=connection.getErrorStream();
		} 
		println "Response Content-Type:"+connection.getContentType()
		if (connection.getContentType().contains("application/json")) {
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			StringBuilder sb = new StringBuilder();
			String line;
			while ((line = br.readLine()) != null) {
				sb.append(line+"\n");
			}
			br.close();
			println sb
			return sb.toString()
		} else {
		if (connection.getResponseCode()==200) {
		//storing content
			final int BUFFER_SIZE = 5 * 1024 * 1024;
			def fileExt = connection.getHeaderField("fileExtension");
			println "Downloading file with fileExtension header:"+fileExt
			if (fileExt!=null) {
				def saveFilePath = localFileNameWithPathForStorage;
				File f = new File(saveFilePath);
				is = connection.getInputStream();
				FileOutputStream outputStream = new FileOutputStream(f);
				int bytesRead = -1;
				byte[] buffer = new byte[BUFFER_SIZE];
				while ((bytesRead = is.read(buffer)) != -1) {
					outputStream.write(buffer, 0, bytesRead);
				}
				println "Downloaded file to $localFileNameWithPathForStorage"
				return localFileNameWithPathForStorage
			} else {
				println "Could not find fileExtension header"
			
			}
		}
		}
		
		return ""
	} 	
	
	def listFiles() {
		println "**Listing files**"
		def restUrl=interopUrl+"/applicationsnapshots"
		def response
		
		response=openConnection(restUrl,"GET","")
		println "****"
	}
	
	def deleteFile(serverFileName) {
		println "**deleting file**"
		def restUrl=interopUrl+"/applicationsnapshots/"+serverFileName
		def response
		
		response=openConnection(restUrl,"DELETE","")
		println "****"
	}	

	def getJobStatus(appName,jobId) {
		println "**get Job status**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs/" + jobId
		
		def response
		response=openConnection(restUrl,"GET","")
		println "****"
		return response	
	}
	
	def exportData(appName,jobName, exportServerFileName) {
		println "**Exporting data**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs?jobName=" + jobName + "&jobType=EXPORT_DATA"
		if (exportServerFileName!="") {
			def exportFileJSON="{exportFileName:$exportServerFileName}"
			restUrl=restUrl+"&parameters=" + exportFileJSON
		}
		
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
		return response
	}
	
	def getJobIdFromJSONResponse(response) {
		def jobId=""
		try {
			Pattern regex = Pattern.compile("\"jobId\":\\d+");
			Matcher matcher = regex.matcher(response);
			while (matcher.find()) {
				jobId = matcher.group(0).replace("\"jobId\":","");
			}
		
		} catch (Exception e) {
			println "No jobId found in server response"
		}
		return jobId
	}
	
	def downloadFile(serverFileName,localFolderForStorage) {
		println "**Downloading file**"
		def restUrl=interopUrl+"/applicationsnapshots/"+serverFileName+ "/contents"
		def response
		response=openConnection(restUrl,"GET",localFolderForStorage+"/"+serverFileName)
		println "****"
	}
	
	def exportMetaData(appName,jobName, exportServerFileName) {
		println "**Exporting metadata**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs?jobName=" + jobName + "&jobType=EXPORT_METADATA"
		if (exportServerFileName!="") {
			def exportFileJSON="{exportZipFileName:$exportServerFileName}"
			restUrl=restUrl+"&parameters=" + exportFileJSON
		}
		
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}
		
	def executeLCMExport(snapshotName) {
		println "**Exporting snapshot**"
		def typeExport="{type:export}"
		def restUrl=interopUrl+"/applicationsnapshots/"+snapshotName+ "/migration?q="+typeExport 
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}
	
	def executeLCMImport(snapshotName) {
		println "**Importing snapshot**"
		def typeImport="{type:import}"
		def restUrl=interopUrl+"/applicationsnapshots/"+snapshotName+ "/migration?q="+typeImport
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}
	
	def runBusinessRule(appName,jobName, JSONRuntimePrompt) {
		println "**Running business rule**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs?jobName=" + jobName + "&jobType=RULES"
		if (JSONRuntimePrompt!="") {
			// Example for JSONRuntimePrompt {Period:Q1,Entity:USA}
			restUrl=restUrl+"&parameters=" + JSONRuntimePrompt
		}

		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}

	def runRuleSet(appName,jobName) {
		println "**Running rule set**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs?jobName=" + jobName + "&jobType=RULESET"
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}

		
	def cubeRefresh(appName,jobName) {
		println "**Refreshing cube**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs?jobName=" + jobName + "&jobType=CUBE_REFRESH"
		
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}
	
	def runPlanTypeMap(appName,jobName, clearData) {
		println "**Running map (job of type plan_type_map)**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs?jobName=" + jobName + "&jobType=PLAN_TYPE_MAP"
		if (clearData!=null && clearData.toUpperCase()=="FALSE") {
			restUrl=restUrl+"&parameters={clearData:false}" 
		} else {
			println "Clear data is set to true (default)"
		}
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}
	
	def importData(appName,jobName, importFileName) {
		println "**Importing data**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs?jobName=" + jobName + "&jobType=IMPORT_DATA"
		if (importFileName!="") {
			def exportFileJSON="{importFileName:$importFileName}"
			restUrl=restUrl+"&parameters=" + exportFileJSON
		}
		
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}
	
	def importMetaData(appName,jobName, importZipFileName) {
		println "**Importing metadata**"
		def restUrl=planningUrl+"/applications/"+appName+"/jobs?jobName=" + jobName + "&jobType=IMPORT_METADATA"
		if (importZipFileName!="") {
			def exportFileJSON="{importZipFileName:$importZipFileName}"
			restUrl=restUrl+"&parameters=" + exportFileJSON
		}
		
		def response
		response=openConnection(restUrl,"POST","")
		println "****"
	}
	
	def uploadFile(localPath,fileName) {
		println "**Uploading file**"
		def restUrl=interopUrl+"/applicationsnapshots/"+fileName
		
		final int DEFAULT_CHUNK_SIZE = 50 * 1024 * 1024;
		int packetNo = 1;
		boolean status = true;
		byte[] lastChunk = null;
		File f = new File(localPath+"/"+fileName);
		InputStream fis = null;
		long totalFileSize = f.length();
		boolean isLast = false;
		Boolean isFirst = true;
		boolean firstRetry = true;
		int lastPacketNo = (int) (Math.ceil(totalFileSize/ (double) DEFAULT_CHUNK_SIZE));
		long totalbytesRead = 0;
		try {
			fis = new BufferedInputStream(new FileInputStream(localPath+"/"+fileName));
			while (totalbytesRead < totalFileSize && status) {
				int nextChunkSize = (int) Math.min(DEFAULT_CHUNK_SIZE, totalFileSize - totalbytesRead);
				if (lastChunk == null) {
					lastChunk = new byte[nextChunkSize];
					int bytesRead = fis.read(lastChunk);
					totalbytesRead += bytesRead;
					if (packetNo == lastPacketNo) {
						isLast = true;
					}
					status = sendRequestToRestForUpload(restUrl,isFirst, isLast,lastChunk);
					isFirst=false;
					if (status) {
						println "\r" + ((100 * totalbytesRead)/ totalFileSize) + "% completed";
					} else {
				break;
				}
					packetNo = packetNo + 1;
					lastChunk = null;
			}
			}
		} catch (Exception e) {
			println "Exception occurred while uploading file";
			println e.getMessage()
		} finally {
			if (null != fis) {
			}
		}
		println "****"
	}
	
	def sendRequestToRestForUpload(restUrl,isFirst, isLast,lastChunk) {
		
		def url=restUrl+"/contents?q={isLast:$isLast,chunkSize:"+lastChunk.length+",isFirst:$isLast}"
		println "Opening connection for upload to $url"
		int statusCode
	
		setProxyParams()
		setSSLParams()
			
		URL newUrl
		newUrl=new URL(url)
			
		connection = (HttpURLConnection) newUrl.openConnection()
		
		connection.setDoOutput(true)
		connection.setDoInput(true)
		connection.setUseCaches(false)
		connection.setRequestMethod("POST")
			
		connection.setRequestProperty("Content-Type","application/octet-stream")
		
		String userCredentials = domain +"."+user + ":" + pwd
		String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userCredentials.getBytes())
		connection.setRequestProperty("Authorization", basicAuth)
		DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
		wr.write(lastChunk);
		wr.flush();
	
		boolean status = false
		int execStatus
		try {
			execStatus = connection.getResponseCode();
			InputStream is = connection.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			StringBuilder sb = new StringBuilder();
			String line;
			while ((line = br.readLine()) != null) {
				sb.append(line+"\n");
			}
			br.close();
			String stat = sb.toString();
			if (null == stat || stat.isEmpty()) {
				return status;
			} else {
				if (200 == execStatus) {
					println stat
				}
			}
			
		} catch (Exception e) {
			println "Exception occurred while uploading file";
			println e.getMessage()
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}
	}
	
	// Helper functions
	
	 def unZip(fileName, destinationFolder) {
		// code from http://www.oracle.com/technetwork/articles/java/compress-1565076.html
		 println ("**Unzipping "+fileName+"**")
		 def fileList=[]
		int BUFFER = 2048;
		try {
			BufferedOutputStream dest = null;
			BufferedInputStream is = null;
			ZipEntry entry;
			ZipFile zipfile = new ZipFile(fileName);
			Enumeration e = zipfile.entries();
			while(e.hasMoreElements()) {
			   entry = (ZipEntry) e.nextElement();
			   //println("Extracting: " +entry);
			   is = new BufferedInputStream(zipfile.getInputStream(entry));
			   int count;
			   byte[] data;
			   data = new byte[BUFFER];
			   FileOutputStream fos = new FileOutputStream(destinationFolder+"/"+entry.getName());
			   fileList.push(entry.getName())
			   dest = new BufferedOutputStream(fos, BUFFER);
			   while ((count = is.read(data, 0, BUFFER)) != -1) {
				  dest.write(data, 0, count);
			   }
			   dest.flush();
			   dest.close();
			   is.close();
			}
		 } catch (FileNotFoundException fnfe) {
		 	println "Make sure there is not folder in the zip . Zip not processed"
		 	//fnfe.printStackTrace();
		 } catch(Exception e) {
		 	println "An error occurred while unzipping."
			 println e.getMessage()
			
		 }
		 return fileList
		 println "****"
	}
	 
	 def findNbOfColsInCSV(filePath, fileName, delimiter) {
		File csvFile=new File (filePath+"/"+fileName);
		Scanner scanner = new Scanner(csvFile);
        scanner.useDelimiter(delimiter);
    
 
		def nbCols
		nbCols=0
        if (scanner.hasNextLine()) {
            String[] vals = scanner.nextLine().split(delimiter);
			nbCols=vals.size()
        }
        scanner.close();
		
		return nbCols				 
		}

	 
	 def getHeadersInCSVAsList(filePath, fileName, delimiter) {
		 String[] headers =[]
		 
		 BufferedReader br = new BufferedReader(new FileReader(filePath+"/"+fileName));
		 String firstLine = br .readLine();
		 println "First line is : " + firstLine
		 println "Removing all non ascii chars from line"
		 firstLine = firstLine.replaceAll("[^ -~]", "");
		 firstLine = firstLine.replaceAll(" ", "");
		// firstLine = firstLine.replaceAll("\"", "");
		 headers = firstLine.split(delimiter);
		 
		 def headersList = headers as List
		 headersList = headersList.collect { it.trim() }
		 
		 return headersList
		 }
	
}

class WaitForCode {
	
static retry( sleepTime, nbOfRetries, Closure logicToRun){
  Throwable catched = null
  for(int i=0; i<nbOfRetries; i++){
	  try {
		  return logicToRun.call()
	  } catch(Throwable t){
		  catched = t
		  println ("Retrying...")
		  Thread.sleep(sleepTime)
	  }
  }
  println ("Retry count limit exceeded. Stopping check.")
  throw catched
}
}