www.gusucode.com > ros 工具箱 matlab源码程序 > ros/+robotics/+ros/+internal/ROSException.m
classdef ROSException < MException %This class is for internal use only. It may be removed in the future. %ROSException Custom exception object for Java exceptions % To avoid exposing (and printing) the whole Java error stack % when exceptions are thrown, this class encapsulates the exception % causes and only make them available through custom interface % functions. % This ROS exception class can be used similarly to the normal % MException object, but call addCustomCause() instead of addCause() and % getCustomReport() instead of getReport(). % % % ROSException methods: % addCustomCause - Add a custom cause to this exception % getCustomReport - Print a report of all custom causes % saveCustomStackTrace - Save the stack trace before deletion % % % Example: % % % Create an exception % ex = MException('a:b:c', 'Error 1'); % % % Create the ROS exception object % newEx = robotics.ros.internal.ROSException('a:b:c', 'Error 2'); % newEx = newEx.addCustomCause(ex)); % % % Print out an exception report % newEx.getCustomReport % Copyright 2014 The MathWorks, Inc. properties (Access = ?matlab.unittest.TestCase) %CustomException - Custom exception object % This exception object stores all custom causes as normal causes CustomException; end methods function obj = ROSException(varargin) %ROSException Constructor % To properly handle backslashes, escape them in the message % The message input is fed directly into sprintf, % backslashes in the message can lead to undesired behavior. switch(nargin) case 1 % Called with (message) object input. validateattributes(varargin{1}, {'message'}, {'nonempty'}, ... 'ROSException', 'message'); case 2 % Called with (id, msg) input validateattributes(varargin{1}, {'char'}, {'nonempty'}, ... 'ROSException', 'identifier'); validateattributes(varargin{2}, {'char'}, {'nonempty'}, ... 'ROSException', 'msg'); % Escape backslashes to avoid warnings % on MException creation varargin{2} = strrep(varargin{2}, '\', '\\'); % If backslashes were doubly escaped, fix that varargin{2} = strrep(varargin{2}, '\\\\', '\\'); otherwise % Called with (id, msg, v1, ...) input validateattributes(varargin{1}, {'char'}, {'nonempty'}, ... 'ROSException', 'identifier'); validateattributes(varargin{2}, {'char'}, {'nonempty'}, ... 'ROSException', 'msg'); % Don't escape backslashes, because the additional % inputs indicate that message should be interpreted % as proper input to sprintf end obj = obj@MException(varargin{:}); obj.CustomException = obj; end function newObj = addCustomCause(obj, cause) %addCustomCause Add a custom cause to this exception % This function will not alter the cause list for this % exception object, but will store all causes in the object % stored in the CustomException property. % % Example: % % try % catch ex % newEx = robotics.ros.internal.ROSException( ... % message('robotics:ros:SomeError')); % throw(newEx.addCustomCause(ex)); % end if ~isa(cause, 'MException') return; end if ~isa(cause, 'robotics.ros.internal.ROSException') obj.CustomException = obj.CustomException.addCause(cause); else obj.CustomException = obj.CustomException.addCause(cause.CustomException); end newObj = obj; end function newObj = saveCustomStackTrace(obj) %saveCustomStackTrace Save the stack trace before deletion % To avoid the stack deletion when using the throwAsCaller % syntax, use this function to save the stack trace % internally. % % Example: % % try % catch ex % ex = saveCustomStackTrace(ex); % throwAsCaller(ex); % end % % ... % % ex = MException.last; % if isa(ex, 'robotics.ros.internal.ROSException') % % Print out full stack trace and list of causes % ex.getCustomReport; % else % ex.getReport; % end causes = obj.CustomException.cause; obj.CustomException = obj; if ~isempty(causes) for c = causes obj.CustomException = obj.CustomException.addCause(c{1}); end end newObj = obj; end function rep = getReport(obj, type, key, val) %getReport - Overloaded function from MException % Handle special case to avoid infinite recursion for % CustomException objects that are ROSExceptions themselves if exist('type', 'var') if strcmp(type, 'custom') rep = getReport@MException(obj); return; end end if strcmp(obj.logLevel, 'none') % Call the standard getReport function in normal mode switch nargin case 1 rep = getReport@MException(obj); case 2 rep = getReport@MException(obj, type); otherwise rep = getReport@MException(obj, type, key, val); end else % Retrieve the custom report in verbose mode rep = obj.getCustomReport; end end function rep = getCustomReport(obj) %getCustomReport - Print a report of all custom causes % This is simply getting a standard report from the CustomEx % exception. % % Example: % ex = MException.last; % if isa(ex, 'robotics.ros.internal.ROSException') % ex.getCustomReport; % else % ex.getReport; % end if isa(obj.CustomException, 'robotics.ros.internal.ROSException') rep = obj.CustomException.getReport('custom'); else rep = obj.CustomException.getReport; end end end methods (Static) function rosex = fromException(ex) %fromException Construct ROSException from other exception % The input EX can either be a generic MException or a % ROSException already. All other inputs are invalid. The % newly created ROSException is returned in ROSEX. if isa(ex, 'robotics.ros.internal.ROSException') rosex = saveCustomStackTrace(ex); return; elseif isa(ex, 'MException') rosex = robotics.ros.internal.ROSException(ex.identifier, ex.message); rosex.CustomException = ex; return; else error(message('robotics:ros:common:WrongInput')); end end end methods (Static, Access = private) function newLevel = logLevel(level) %logLevel Set the log level (verbosity) for ROS exceptions % The default log level is 'none' and all errors encountered % through the informal interface have no stack trace or % causes. Setting the log level to 'all' displays all error % information for debugging purposes, e.g. in testing. % % NEWLEVEL = robotics.ros.internal.ROSException.logLevel('LEVEL') sets % the ROSException log level to LEVEL, where LEVEL can be % either 'none' or 'all'. If successful, the new log level is % returned in NEWLEVEL. persistent currentLogLevel mlock if isempty(currentLogLevel) currentLogLevel = 'none'; end % Return current log level if no input if nargin == 0 newLevel = currentLogLevel; return; end % Valid log level strings % 'none' is the default log level that is appropriate for most % users; 'all' is the verbose log level for testing validLevels = {'all', 'none'}; if ischar(level) if any(strcmpi(level,validLevels)) currentLogLevel = level; newLevel = currentLogLevel; end end end end methods(Static) function enableVerboseLogging(enable) %enableVerboseLogging Enable verbose output for ROS exceptions % This is the public interface for enabling verbose exception % output for the informal interface. % % robotics.ros.internal.ROSException.enableVerboseLogging(ENABLE) % enables (ENABLE == true) or disables (ENABLE == false) the % verbose error output. validateattributes(enable, {'logical'}, {'nonempty'}, ... 'ROSException', 'enable'); if enable robotics.ros.internal.ROSException.logLevel('all'); else robotics.ros.internal.ROSException.logLevel('none'); end end end end