github.com/haagen/force@v0.19.6-0.20140911230915-22addd930b34/partner.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/xml"
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  )
     9  
    10  type ForcePartner struct {
    11  	Force *Force
    12  }
    13  
    14  type TestCoverage struct {
    15  	Log                       string   `xml:"Header>DebuggingInfo>debugLog"`
    16  	NumberRun                 int      `xml:"Body>runTestsResponse>result>numTestsRun"`
    17  	NumberLocations           []int    `xml:"Body>runTestsResponse>result>codeCoverage>numLocations"`
    18  	NumberLocationsNotCovered []int    `xml:"Body>runTestsResponse>result>codeCoverage>numLocationsNotCovered"`
    19  	Name                      []string `xml:"Body>runTestsResponse>result>codeCoverage>name"`
    20  	SMethodNames              []string `xml:"Body>runTestsResponse>result>successes>methodName"`
    21  	SClassNames               []string `xml:"Body>runTestsResponse>result>successes>name"`
    22  	FMethodNames              []string `xml:"Body>runTestsResponse>result>failures>methodName"`
    23  	FClassNames               []string `xml:"Body>runTestsResponse>result>failures>name"`
    24  	FMessage                  []string `xml:"Body>runTestsResponse>result>failures>message"`
    25  	FStackTrace               []string `xml:"Body>runTestsResponse>result>failures>stackTrace"`
    26  }
    27  
    28  func NewForcePartner(force *Force) (partner *ForcePartner) {
    29  	partner = &ForcePartner{Force: force}
    30  	return
    31  }
    32  
    33  func (partner *ForcePartner) CheckStatus(id string) (err error) {
    34  	body, err := partner.soapExecute("checkStatus", fmt.Sprintf("<id>%s</id>", id))
    35  	if err != nil {
    36  		return
    37  	}
    38  	var status struct {
    39  		Done    bool   `xml:"Body>checkStatusResponse>result>done"`
    40  		State   string `xml:"Body>checkStatusResponse>result>state"`
    41  		Message string `xml:"Body>checkStatusResponse>result>message"`
    42  	}
    43  	if err = xml.Unmarshal(body, &status); err != nil {
    44  		return
    45  	}
    46  	switch {
    47  	case !status.Done:
    48  		return partner.CheckStatus(id)
    49  	case status.State == "Error":
    50  		return errors.New(status.Message)
    51  	}
    52  	return
    53  }
    54  
    55  func (partner *ForcePartner) ExecuteAnonymous(apex string) (output string, err error) {
    56  	soap := "<apexcode><![CDATA[%s]]></apexcode>"
    57  	body, err := partner.soapExecute("executeAnonymous", fmt.Sprintf(soap, apex))
    58  	if err != nil {
    59  		return
    60  	}
    61  	var result struct {
    62  		Compiled         bool   `xml:"Body>executeAnonymousResponse>result>compiled"`
    63  		CompileProblem   string `xml:"Body>executeAnonymousResponse>result>compileProblem"`
    64  		ExceptionMessage string `xml:"Body>executeAnonymousResponse>result>exceptionMessage"`
    65  		ExceptionTrace   string `xml:"Body>executeAnonymousResponse>result>exceptionStackTrace"`
    66  		Log              string `xml:"Header>DebuggingInfo>debugLog"`
    67  		Success          bool   `xml:"Body>executeAnonymousResponse>result>success"`
    68  	}
    69  	if err = xml.Unmarshal(body, &result); err != nil {
    70  		return
    71  	}
    72  	if !result.Compiled {
    73  		message := strings.Replace(result.CompileProblem, "%", "%%", -1)
    74  		err = errors.New(message)
    75  		return
    76  	}
    77  	output = result.Log
    78  	return
    79  }
    80  
    81  func (partner *ForcePartner) soapExecuteCore(action, query string) (response []byte, err error) {
    82  	login, err := partner.Force.Get(partner.Force.Credentials.Id)
    83  	if err != nil {
    84  		return
    85  	}
    86  	version := strings.Replace(apiVersion, "v", "", 1)
    87  	url := strings.Replace(login["urls"].(map[string]interface{})["partner"].(string), "{version}", version, 1)
    88  	//url = strings.Replace(url, "/u/", "/s/", 1) // seems dirty
    89  	soap := NewSoap(url, "urn:partner.soap.sforce.com", partner.Force.Credentials.AccessToken)
    90  	soap.Header = "<apex:DebuggingHeader><apex:debugLevel>DEBUGONLY</apex:debugLevel></apex:DebuggingHeader>"
    91  	response, err = soap.Execute(action, query)
    92  	return
    93  }
    94  
    95  func (partner *ForcePartner) RunTests(tests []string, namespace string) (output TestCoverage, err error) {
    96  	soap := "<RunTestsRequest>\n"
    97  	if strings.EqualFold(tests[0], "all") {
    98  		soap += "<allTests>True</allTests>\n"
    99  	} else {
   100  		for _, element := range tests {
   101  			soap += "<classes>" + element + "</classes>\n"
   102  		}
   103  	}
   104  	if namespace != "" {
   105  		soap += "<namespace>" + namespace + "</namespace>\n"
   106  	}
   107  	soap += "</RunTestsRequest>"
   108  	body, err := partner.soapExecute("runTests", soap)
   109  	if err != nil {
   110  		return
   111  	}
   112  	var result TestCoverage
   113  	if err = xml.Unmarshal(body, &result); err != nil {
   114  		return
   115  	}
   116  	output = result
   117  	return
   118  }
   119  
   120  func (partner *ForcePartner) soapExecute(action, query string) (response []byte, err error) {
   121  	login, err := partner.Force.Get(partner.Force.Credentials.Id)
   122  	if err != nil {
   123  		return
   124  	}
   125  	version := strings.Replace(apiVersion, "v", "", 1)
   126  	url := strings.Replace(login["urls"].(map[string]interface{})["partner"].(string), "{version}", version, 1)
   127  	url = strings.Replace(url, "/u/", "/s/", 1) // seems dirty
   128  	soap := NewSoap(url, "http://soap.sforce.com/2006/08/apex", partner.Force.Credentials.AccessToken)
   129  	soap.Header = "<apex:DebuggingHeader><apex:debugLevel>DEBUGONLY</apex:debugLevel></apex:DebuggingHeader>"
   130  	response, err = soap.Execute(action, query)
   131  	return
   132  }