def get_overlay_actions(self, **kwargs): if 'file_path' in kwargs: id = kwargs.get('id', None) file_path = kwargs.get('file_path', None) if id == None: ext = mm_util.get_file_extension_no_period(file_path) api_name = mm_util.get_file_name_no_extension(file_path) mtype = mm_util.get_meta_type_by_suffix(ext) id = self.get_apex_entity_id_by_name( object_type=mtype['xmlName'], name=api_name) query_string = "Select Id, Line, Iteration, ExpirationDate, IsDumpingHeap from ApexExecutionOverlayAction Where ExecutableEntityId = '{0}'".format( id) payload = {'q': query_string} r = requests.get(self.get_tooling_url() + "/query/", params=payload, headers=self.get_rest_headers(), verify=False) return mm_util.parse_rest_response(r.text) else: query_string = "Select Id, ScopeId, ExecutableEntityId, Line, Iteration, ExpirationDate, IsDumpingHeap from ApexExecutionOverlayAction limit 5000" payload = {'q': query_string} r = requests.get(self.get_tooling_url() + "/query/", params=payload, headers=self.get_rest_headers(), verify=False) return mm_util.parse_rest_response(r.text)
def check_for_conflicts(self, files): local_store = self.get_local_store() retrieve_result = self.project.get_retrieve_result({"files": files}) properties = retrieve_result.fileProperties for f in files: ext = mm_util.get_file_extension_no_period(f) apex_type = mm_util.get_meta_type_by_suffix(ext) apex_entity_api_name = mm_util.get_file_name_no_extension(f) body_field = "Body" if apex_type["xmlName"] == "ApexPage" or apex_type["xmlName"] == "ApexComponent": body_field = "Markup" api_name_plus_extension = apex_entity_api_name + "." + ext server_property = None for p in properties: if p["fullName"] == apex_entity_api_name: server_property = p if api_name_plus_extension in local_store and server_property != None: local_store_entry = local_store[api_name_plus_extension] local_last_modified_date = local_store_entry["lastModifiedDate"] server_last_modified_date = server_property["lastModifiedDate"] last_modified_name = server_property["lastModifiedByName"] qr = self.project.sfdc_client.query( "Select LastModifiedById, LastModifiedDate, LastModifiedBy.Name, {0} From {1} Where Name = '{2}'".format( body_field, apex_type["xmlName"], apex_entity_api_name ) ) body = qr["records"][0][body_field] body = body.encode("utf-8") if ( str(local_last_modified_date) != str(server_last_modified_date) or local_store_entry["mmState"] == "dirty" ): if local_store_entry["mmState"] != "dirty": local_store_entry["mmState"] = "dirty" msg = mm_util.generate_request_for_action_response( "The local version of your file and the server copy are out of sync.\n\n{0} was last modified by {1} on {2}.".format( apex_entity_api_name, last_modified_name, server_last_modified_date ), "compile", ["Diff With Server", "Operation Canceled"], tmp_file_path=mm_util.put_tmp_file_on_disk( apex_entity_api_name, body, apex_type.get("suffix", "") ), ) self.mark_dirty(api_name_plus_extension) return True, msg return False, None
def get_apex_checkpoints(self, **kwargs): if 'file_path' in kwargs: id = kwargs.get('id', None) file_path = kwargs.get('file_path', None) if id == None: ext = mm_util.get_file_extension_no_period(file_path) api_name = mm_util.get_file_name_no_extension(file_path) mtype = mm_util.get_meta_type_by_suffix(ext) id = self.get_apex_entity_id_by_name(object_type=mtype['xmlName'], name=api_name) query_string = "Select Id, Line, Iteration, ExpirationDate, IsDumpingHeap from ApexExecutionOverlayAction Where ExecutableEntityId = '{0}'".format(id) payload = { 'q' : query_string } r = requests.get(self.get_tooling_url()+"/query/", params=payload, headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) return mm_util.parse_rest_response(r.text) else: query_string = "Select Id, ScopeId, ExecutableEntityId, Line, Iteration, ExpirationDate, IsDumpingHeap from ApexExecutionOverlayAction limit 5000" payload = { 'q' : query_string } r = requests.get(self.get_tooling_url()+"/query/", params=payload, headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) return mm_util.parse_rest_response(r.text)
def delete_apex_checkpoint(self, **kwargs): if 'overlay_id' in kwargs: r = requests.delete(self.get_tooling_url()+"/sobjects/ApexExecutionOverlayAction/{0}".format(kwargs['overlay_id']), headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) r.raise_for_status() return mm_util.generate_success_response('OK') else: id = kwargs.get('id', None) file_path = kwargs.get('file_path', None) line_number = kwargs.get('line_number', None) if id == None: ext = mm_util.get_file_extension_no_period(file_path) api_name = mm_util.get_file_name_no_extension(file_path) mtype = mm_util.get_meta_type_by_suffix(ext) id = self.get_apex_entity_id_by_name(object_type=mtype['xmlName'], name=api_name) query_string = "Select Id from ApexExecutionOverlayAction Where ExecutableEntityId = '{0}' AND Line = {1}".format(id, line_number) r = requests.get(self.get_tooling_url()+"/query/", params={'q':query_string}, headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) r.raise_for_status() query_result = mm_util.parse_rest_response(r.text) overlay_id = query_result['records'][0]['Id'] r = requests.delete(self.get_tooling_url()+"/sobjects/ApexExecutionOverlayAction/{0}".format(overlay_id), headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) r.raise_for_status() return mm_util.generate_success_response('OK')
def remove_overlay_action(self, **kwargs): if 'overlay_id' in kwargs: r = requests.delete( self.get_tooling_url() + "/sobjects/ApexExecutionOverlayAction/{0}".format( kwargs['overlay_id']), headers=self.get_rest_headers(), verify=False) r.raise_for_status() return mm_util.generate_success_response('OK') else: id = kwargs.get('id', None) file_path = kwargs.get('file_path', None) line_number = kwargs.get('line_number', None) if id == None: ext = mm_util.get_file_extension_no_period(file_path) api_name = mm_util.get_file_name_no_extension(file_path) mtype = mm_util.get_meta_type_by_suffix(ext) id = self.get_apex_entity_id_by_name( object_type=mtype['xmlName'], name=api_name) query_string = "Select Id from ApexExecutionOverlayAction Where ExecutableEntityId = '{0}' AND Line = {1}".format( id, line_number) r = requests.get(self.get_tooling_url() + "/query/", params={'q': query_string}, headers=self.get_rest_headers(), verify=False) r.raise_for_status() query_result = mm_util.parse_rest_response(r.text) overlay_id = query_result['records'][0]['Id'] r = requests.delete( self.get_tooling_url() + "/sobjects/ApexExecutionOverlayAction/{0}".format(overlay_id), headers=self.get_rest_headers(), verify=False) r.raise_for_status() return mm_util.generate_success_response('OK')
def compile_with_tooling_api(self, files, container_id): for file_path in files: payload = {} file_name = file_path.split('.')[0] file_name = mm_util.get_file_name_no_extension(file_path) metadata_def = mm_util.get_meta_type_by_suffix(file_path.split('.')[-1]) metadata_type = metadata_def['xmlName'] if metadata_type == 'ApexPage': tooling_type = 'ApexPageMember' elif metadata_type == 'ApexComponent': tooling_type = 'ApexComponentMember' elif metadata_type == 'ApexClass': tooling_type = 'ApexClassMember' elif metadata_type == 'ApexTrigger': tooling_type = 'ApexTriggerMember' #create/submit "member" payload['MetadataContainerId'] = container_id payload['ContentEntityId'] = self.get_apex_entity_id_by_name(object_type=metadata_type, name=file_name) payload['Body'] = open(file_path, 'r').read() #payload['LastSyncDate'] = TODO payload = json.dumps(payload) config.logger.debug(payload) r = requests.post(self.get_tooling_url()+"/sobjects/"+tooling_type, data=payload, headers=self.get_rest_headers('POST'), proxies=urllib.getproxies(), verify=False) response = mm_util.parse_rest_response(r.text) #if it's a dup (probably bc we failed to delete before, let's delete and retry) if type(response) is list and 'errorCode' in response[0]: if response[0]['errorCode'] == 'DUPLICATE_VALUE': dup_id = response[0]['message'].split(':')[-1] dup_id = dup_id.strip() query_string = "Select Id from "+tooling_type+" Where Id = '"+dup_id+"'" r = requests.get(self.get_tooling_url()+"/query/", params={'q':query_string}, headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) r.raise_for_status() query_result = mm_util.parse_rest_response(r.text) r = requests.delete(self.get_tooling_url()+"/sobjects/{0}/{1}".format(tooling_type, query_result['records'][0]['Id']), headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) r.raise_for_status() #retry member request r = requests.post(self.get_tooling_url()+"/sobjects/"+tooling_type, data=payload, headers=self.get_rest_headers('POST'), proxies=urllib.getproxies(), verify=False) response = mm_util.parse_rest_response(r.text) member_id = response['id'] elif response[0]['errorCode'] == 'INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY' or response[0]['errorCode'] == 'MALFORMED_ID': raise MetadataContainerException('Invalid metadata container') else: return mm_util.generate_error_response(response[0]['errorCode']) else: member_id = response['id'] #ok, now we're ready to submit an async request payload = {} payload['MetadataContainerId'] = container_id payload['IsCheckOnly'] = False payload['IsRunTests'] = False payload = json.dumps(payload) config.logger.debug(payload) r = requests.post(self.get_tooling_url()+"/sobjects/ContainerAsyncRequest", data=payload, headers=self.get_rest_headers('POST'), proxies=urllib.getproxies(), verify=False) response = mm_util.parse_rest_response(r.text) finished = False while finished == False: time.sleep(1) query_string = "Select Id, MetadataContainerId, MetadataContainerMemberId, State, IsCheckOnly, CompilerErrors, ErrorMsg FROM ContainerAsyncRequest WHERE Id='"+response["id"]+"'" r = requests.get(self.get_tooling_url()+"/query/", params={'q':query_string}, headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) r.raise_for_status() query_result = mm_util.parse_rest_response(r.text) if query_result["done"] == True and query_result["size"] == 1 and 'records' in query_result: if query_result['records'][0]["State"] != 'Queued': response = query_result['records'][0] finished = True #clean up the apex member if 'id' in response: #delete member r = requests.delete(self.get_tooling_url()+"/sobjects/{0}/{1}".format(tooling_type, member_id), headers=self.get_rest_headers(), proxies=urllib.getproxies(), verify=False) r.raise_for_status() return response