/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* IBM UrbanCode Deploy
* IBM UrbanCode Release
* IBM AnthillPro
* (c) Copyright IBM Corporation 2002, 2013. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*/
import org.codehaus.jettison.json.JSONObject;
import org.codehaus.jettison.json.JSONArray;
import com.urbancode.air.AirPluginTool;
import com.urbancode.air.XTrustProvider;
import java.net.URLEncoder
import org.apache.commons.httpclient.*
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.auth.AuthScope;
def MAX_RETRIES = 3;

XTrustProvider.install();

def apTool = new AirPluginTool(this.args[0], this.args[1]);
def props = apTool.getStepProperties();

def weburl = System.getenv("AH_WEB_URL");
def user = apTool.getAuthTokenUsername();
def password = apTool.getAuthToken();
def rootResourcePath = props['resourcePath'];
def webSphereUser = props['wasuser'];
def webSpherePassword = props['waspassword'];
def profilePath = props['profilePath'];
def wsadminPath = props['commandPath'];
def wasPort = props['port'];
def wasHost = props['host'];
def wasConnType = props['connType'];
def roleName = props['roleName'];
def compProcessRequestId = props['compProcessRequestId'];
def configurationTypes = props['configurationTypes'];

def WSDISC_HOME = System.getenv("PLUGIN_HOME");
def WE_ACTIVITY_ID = System.getenv("WE_ACTIVITY_ID");

def getDataFromWsadmin = {
    def wsadminExe = wsadminPath;

    while (wsadminExe.endsWith(File.separator)) {
        wsadminExe = wsadminExe.substring(0, wsadminExe.length()-1);
    }

    if (File.separator == "\\") {//windows platform
        wsadminExe = wsadminExe + File.separator + "wsadmin.bat";
    }
    else {
        wsadminExe = wsadminExe + File.separator + "wsadmin.sh";
    }


    def cmdArgs = [wsadminExe];

    if (wasHost?.trim() && !wasHost.startsWith("p:")) {
        cmdArgs << "-host";
        cmdArgs << wasHost.trim();
    }

    if (wasPort?.trim() && !wasPort.startsWith("p:")) {
        cmdArgs << "-port";
        cmdArgs << wasPort.trim();
    }

    if (wasConnType?.trim() && !wasConnType.startsWith("p:")) {
        cmdArgs << "-conntype";
        cmdArgs << wasConnType.trim();
    }

    if ( webSphereUser?.trim() && !webSphereUser.trim().startsWith("p:")) {
        println "Using credentials";
        cmdArgs << "-user" << webSphereUser << "-password" << webSpherePassword;
    }

    cmdArgs << "-lang";
    cmdArgs << "jython";

    cmdArgs << "-wsadmin_classpath" << "${WSDISC_HOME}" + java.io.File.separator + "lib" + java.io.File.separator + "jettison-1.1.jar" + java.io.File.pathSeparator + "${WSDISC_HOME}" + java.io.File.separator + "lib" + java.io.File.separator + "log4j.jar" + java.io.File.pathSeparator + "${WSDISC_HOME}" + java.io.File.separator + "lib" + java.io.File.separator + "commons-codec.jar" + java.io.File.pathSeparator + "${WSDISC_HOME}" + java.io.File.separator + "lib" + java.io.File.separator + "CommonsUtil.jar"

    cmdArgs << "-f" << "${WSDISC_HOME}" + java.io.File.separator + "jythonScripts" + java.io.File.separator + "livecomp.py";

    cmdArgs << this.args[0].replace("\\","\\\\");

    println "Running Configuration Discovery";
    println cmdArgs.join(" ");

    Process proc = cmdArgs.execute();
    proc.out.close();
    OutputStream oStream = new ByteArrayOutputStream();
    OutputStream eStream = new ByteArrayOutputStream();
    proc.waitForProcessOutput(oStream, eStream);
    String output = oStream.toString();
    println output;

    checkIfNullOrEmpty(compProcessRequestId, "Component Process Request Id");

    //pull the component process request so we can get the workflow ID from it
    componentProcessRequestRESTURL = "$weburl/rest/deploy/componentProcessRequest/$compProcessRequestId";
    componentProcessRequest = executeGetMethod(componentProcessRequestRESTURL, user, password);
    checkIfNullOrEmpty(componentProcessRequest, "Component Process Request JSON");
    componentProcessRequest = new JSONObject(componentProcessRequest);

    //pull workflow ID from the component process request
    workflowTraceId = componentProcessRequest.getJSONObject("rootTrace").getString("workflowTraceId");
    checkIfNullOrEmpty(workflowTraceId, "workflowTraceId");

    //package the ID's to be set as application process properties
    JSONArray requestPropertiesJSON = new JSONArray();
    requestPropertiesJSON.put(createPayloadJSON("workflowTraceId", workflowTraceId, false));
    requestPropertiesJSON.put(createPayloadJSON("activityTraceId", WE_ACTIVITY_ID, false));

    //send the payload to be set as application process properties so they can be accessed later
    processPropertiesRESTURL = "$weburl/rest/deploy/componentProcessRequest/$compProcessRequestId/saveProperties";
    executePutMethod(processPropertiesRESTURL, user, password, requestPropertiesJSON.toString());

    System.exit(proc.exitValue());
}

//check for nulls as well as provide an override for the error if it's safe to continue
private boolean checkIfNullOrEmpty(checkMe, checkedItemName, isError=true){
    if (checkMe == null || checkMe.isEmpty()){
        warningMsg = "$checkedItemName returned null or empty. Are the properties set correctly?";
        if (isError){
            throw new Exception(warningMsg);
        }
        else {
            //just a warning, tell the user but continue as normal
            println "WARNING: $warningMsg Further steps that depend on this one may not work correctly!";
            return true;
        }
    }
    return false;
}

private createPayloadJSON (name, value, isSecure){
    JSONObject result = new JSONObject();
    result.put("name", name);
    result.put("value", value);
    result.put("secure", isSecure);
    return result;
}
private executeGetMethod (requestRESTURL, ucdUsername, ucdPassword) {
    HttpMethod method = new GetMethod(requestRESTURL);

    Credentials defaultcreds = new UsernamePasswordCredentials(ucdUsername, ucdPassword);
    HttpClient client = new HttpClient();
    client.getState().setCredentials(AuthScope.ANY, defaultcreds);
    client.getParams().setAuthenticationPreemptive(true);

    def methodResult = client.executeMethod(method);
    def response = method.getResponseBodyAsString();

    if (methodResult != 200) {
        throw new Exception ("Received response ${methodResult}: ${response}");
    }

    return response;
}

private executePutMethod (requestRESTURL, ucdUsername, ucdPassword, payload) {
    PutMethod method = new PutMethod(requestRESTURL);
    StringRequestEntity payloadEntity = new StringRequestEntity(payload);
    method.setRequestEntity(payloadEntity);

    Credentials defaultcreds = new UsernamePasswordCredentials(ucdUsername, ucdPassword);
    HttpClient client = new HttpClient();
    client.getState().setCredentials(AuthScope.ANY, defaultcreds);
    client.getParams().setAuthenticationPreemptive(true);

    def methodResult = client.executeMethod(method);
    def response = method.getResponseBodyAsString();

    if (methodResult != 200) {
        throw new Exception ("Received response ${methodResult}: ${response}");
    }

    return response;
}

getDataFromWsadmin();
