instance_identifier = uniqid();
		// Translate the error message
		$message = __($message, $variables);
		// Sets $this->message the proper way
		parent::__construct($message, $code);
	}
	/**
	 * Enable Kohana exception handling.
	 *
	 * @uses    Kohana_Exception::$template
	 * @return  void
	 */
	public static function enable()
	{
		if ( ! Kohana_Exception::$enabled)
		{
			set_exception_handler(array('Kohana_Exception', 'handle'));
			Kohana_Exception::$enabled = TRUE;
		}
	}
	/**
	 * Disable Kohana exception handling.
	 *
	 * @return  void
	 */
	public static function disable()
	{
		if (Kohana_Exception::$enabled)
		{
			restore_exception_handler();
			Kohana_Exception::$enabled = FALSE;
		}
	}
	/**
	 * Get a single line of text representing the exception:
	 *
	 * Error [ Code ]: Message ~ File [ Line ]
	 *
	 * @param   object  Exception
	 * @return  string
	 */
	public static function text($e)
	{
		return sprintf('%s [ %s ]: %s ~ %s [ %d ]',
			get_class($e), $e->getCode(), strip_tags($e->getMessage()), Kohana_Exception::debug_path($e->getFile()), $e->getLine());
	}
	/**
	 * exception handler, displays the error message, source of the
	 * exception, and the stack trace of the error.
	 *
	 * @uses    Kohana::message()
	 * @uses    Kohana_Exception::text()
	 * @param   object   exception object
	 * @return  void
	 */
	public static function handle(Exception $e)
	{
		try
		{
			// Get the exception information
			$type    = get_class($e);
			$code    = $e->getCode();
			$message = $e->getMessage();
			// Create a text version of the exception
			$error = Kohana_Exception::text($e);
			// Add this exception to the log
			Kohana_Log::add('error', $error);
			// Manually save logs after exceptions
			Kohana_Log::save();
			if (Kohana::config('kohana/core.display_errors') === FALSE)
			{
				// Do not show the details
				$file = $line = NULL;
				$trace = array();
				$template = '_disabled';
			}
			else
			{
				$file = $e->getFile();
				$line = $e->getLine();
				$trace = $e->getTrace();
				$template = '';
			}
			if ($e instanceof Kohana_Exception)
			{
				$template = $e->getTemplate().$template;
				if ( ! headers_sent())
				{
					$e->sendHeaders();
				}
				// Use the human-readable error name
				$code = Kohana::message('kohana/core.errors.'.$code);
			}
			else
			{
				$template = Kohana_Exception::$template.$template;
				if ( ! headers_sent())
				{
					header('HTTP/1.1 500 Internal Server Error');
				}
				if ($e instanceof ErrorException)
				{
					// Use the human-readable error name
					$code = Kohana::message('kohana/core.errors.'.$e->getSeverity());
					if (version_compare(PHP_VERSION, '5.3', '<'))
					{
						// Workaround for a bug in ErrorException::getTrace() that exists in
						// all PHP 5.2 versions. @see http://bugs.php.net/45895
						for ($i = count($trace) - 1; $i > 0; --$i)
						{
							if (isset($trace[$i - 1]['args']))
							{
								// Re-position the arguments
								$trace[$i]['args'] = $trace[$i - 1]['args'];
								unset($trace[$i - 1]['args']);
							}
						}
					}
				}
			}
			// Clean the output buffer if one exists
			ob_get_level() and ob_clean();
			if ($template = Kohana::find_file('views', $template))
			{
				include $template;
			}
		}
		catch (Exception $e)
		{
			// Clean the output buffer if one exists
			ob_get_level() and ob_clean();
			// Display the exception text
			echo Kohana_Exception::text($e), "\n";
		}
		if (Kohana::$server_api === 'cli')
		{
			// Exit with an error status
			exit(1);
		}
	}
	/**
	 * Returns the template for this exception.
	 *
	 * @uses    Kohana_Exception::$template
	 * @return  string
	 */
	public function getTemplate()
	{
		return Kohana_Exception::$template;
	}
	/**
	 * Sends an Internal Server Error header.
	 *
	 * @return  void
	 */
	public function sendHeaders()
	{
		// Send the 500 header
		header('HTTP/1.1 500 Internal Server Error');
	}
	/**
	 * Returns an HTML string of information about a single variable.
	 *
	 * Borrows heavily on concepts from the Debug class of {@link http://nettephp.com/ Nette}.
	 *
	 * @param   mixed    variable to dump
	 * @param   integer  maximum length of strings
	 * @param   integer  maximum levels of recursion
	 * @return  string
	 */
	public static function dump($value, $length = 128, $max_level = 5)
	{
		return Kohana_Exception::_dump($value, $length, $max_level);
	}
	/**
	 * Helper for Kohana_Exception::dump(), handles recursion in arrays and objects.
	 *
	 * @param   mixed    variable to dump
	 * @param   integer  maximum length of strings
	 * @param   integer  maximum levels of recursion
	 * @param   integer  current recursion level (internal)
	 * @return  string
	 */
	private static function _dump( & $var, $length = 128, $max_level = 5, $level = 0)
	{
		if ($var === NULL)
		{
			return 'NULL';
		}
		elseif (is_bool($var))
		{
			return 'bool '.($var ? 'TRUE' : 'FALSE');
		}
		elseif (is_float($var))
		{
			return 'float '.$var;
		}
		elseif (is_resource($var))
		{
			if (($type = get_resource_type($var)) === 'stream' AND $meta = stream_get_meta_data($var))
			{
				$meta = stream_get_meta_data($var);
				if (isset($meta['uri']))
				{
					$file = $meta['uri'];
					if (function_exists('stream_is_local'))
					{
						// Only exists on PHP >= 5.2.4
						if (stream_is_local($file))
						{
							$file = Kohana_Exception::debug_path($file);
						}
					}
					return 'resource('.$type.') '.htmlspecialchars($file, ENT_NOQUOTES, Kohana::CHARSET);
				}
			}
			else
			{
				return 'resource('.$type.')';
			}
		}
		elseif (is_string($var))
		{
			if (strlen($var) > $length)
			{
				// Encode the truncated string
				$str = htmlspecialchars(substr($var, 0, $length), ENT_NOQUOTES, Kohana::CHARSET).' …';
			}
			else
			{
				// Encode the string
				$str = htmlspecialchars($var, ENT_NOQUOTES, Kohana::CHARSET);
			}
			return 'string('.strlen($var).') "'.$str.'"';
		}
		elseif (is_array($var))
		{
			$output = array();
			// Indentation for this variable
			$space = str_repeat($s = '    ', $level);
			static $marker;
			if ($marker === NULL)
			{
				// Make a unique marker
				$marker = uniqid("\x00");
			}
			if (empty($var))
			{
				// Do nothing
			}
			elseif (isset($var[$marker]))
			{
				$output[] = "(\n$space$s*RECURSION*\n$space)";
			}
			elseif ($level <= $max_level)
			{
				$output[] = "(";
				$var[$marker] = TRUE;
				foreach ($var as $key => & $val)
				{
					if ($key === $marker) continue;
					if ( ! is_int($key))
					{
						$key = '"'.$key.'"';
					}
					$output[] = "$space$s$key => ".Kohana_Exception::_dump($val, $length, $max_level, $level + 1);
				}
				unset($var[$marker]);
				$output[] = "$space)";
			}
			else
			{
				// Depth too great
				$output[] = "(\n$space$s...\n$space)";
			}
			return 'array('.count($var).') '.implode("\n", $output);
		}
		elseif (is_object($var))
		{
			// Copy the object as an array
			$array = (array) $var;
			$output = array();
			// Indentation for this variable
			$space = str_repeat($s = '    ', $level);
			$hash = spl_object_hash($var);
			// Objects that are being dumped
			static $objects = array();
			if (empty($var))
			{
				// Do nothing
			}
			elseif (isset($objects[$hash]))
			{
				$output[] = "{\n$space$s*RECURSION*\n$space}";
			}
			elseif ($level <= $max_level)
			{
				$output[] = "{";
				$objects[$hash] = TRUE;
				foreach ($array as $key => & $val)
				{
					if ($key[0] === "\x00")
					{
						// Determine if the access is private or protected
						$access = ''.($key[1] === '*' ? 'protected' : 'private').'';
						// Remove the access level from the variable name
						$key = substr($key, strrpos($key, "\x00") + 1);
					}
					else
					{
						$access = 'public';
					}
					$output[] = "$space$s$access $key => ".Kohana_Exception::_dump($val, $length, $max_level, $level + 1);
				}
				unset($objects[$hash]);
				$output[] = "$space}";
			}
			else
			{
				// Depth too great
				$output[] = "{\n$space$s...\n$space}";
			}
			return 'object '.get_class($var).'('.count($array).') '.implode("\n", $output);
		}
		else
		{
			return ''.gettype($var).' '.htmlspecialchars(print_r($var, TRUE), ENT_NOQUOTES, Kohana::CHARSET);
		}
	}
	/**
	 * Removes APPPATH, SYSPATH, MODPATH, and DOCROOT from filenames, replacing
	 * them with the plain text equivalents.
	 *
	 * @param   string  path to sanitize
	 * @return  string
	 */
	public static function debug_path($file)
	{
		if (strpos($file, APPPATH) === 0)
		{
			$file = 'APPPATH/'.substr($file, strlen(APPPATH));
		}
		elseif (strpos($file, SYSPATH) === 0)
		{
			$file = 'SYSPATH/'.substr($file, strlen(SYSPATH));
		}
		elseif (strpos($file, MODPATH) === 0)
		{
			$file = 'MODPATH/'.substr($file, strlen(MODPATH));
		}
		elseif (strpos($file, DOCROOT) === 0)
		{
			$file = 'DOCROOT/'.substr($file, strlen(DOCROOT));
		}
		return $file;
	}
	/**
	 * Returns an array of lines from a file.
	 *
	 *     // Returns the current line of the current file
	 *     echo Kohana_Exception::debug_source(__FILE__, __LINE__);
	 *
	 * @param   string   file to open
	 * @param   integer  line number to find
	 * @param   integer  number of padding lines
	 * @return  array
	 */
	public static function debug_source($file, $line_number, $padding = 5)
	{
		// Make sure we can read the source file
		if ( ! is_readable($file))
			return array();
		// Open the file and set the line position
		$file = fopen($file, 'r');
		$line = 0;
		// Set the reading range
		$range = array('start' => $line_number - $padding, 'end' => $line_number + $padding);
		// Set the zero-padding amount for line numbers
		$format = '% '.strlen($range['end']).'d';
		$source = array();
		while (($row = fgets($file)) !== FALSE)
		{
			// Increment the line number
			if (++$line > $range['end'])
				break;
			if ($line >= $range['start'])
			{
				$source[sprintf($format, $line)] = $row;
			}
		}
		// Close the file
		fclose($file);
		return $source;
	}
	/**
	 * Returns an array of strings that represent each step in the backtrace.
	 *
	 * @param   array  trace to analyze
	 * @return  array
	 */
	public static function trace($trace = NULL)
	{
		if ($trace === NULL)
		{
			// Start a new trace
			$trace = debug_backtrace();
		}
		// Non-standard function calls
		$statements = array('include', 'include_once', 'require', 'require_once');
		$output = array();
		foreach ($trace as $step)
		{
			if ( ! isset($step['function']))
			{
				// Invalid trace step
				continue;
			}
			if (isset($step['file']) AND isset($step['line']))
			{
				// Include the source of this step
				$source = Kohana_Exception::debug_source($step['file'], $step['line']);
			}
			if (isset($step['file']))
			{
				$file = $step['file'];
				if (isset($step['line']))
				{
					$line = $step['line'];
				}
			}
			// function()
			$function = $step['function'];
			if (in_array($step['function'], $statements))
			{
				if (empty($step['args']))
				{
					// No arguments
					$args = array();
				}
				else
				{
					// Sanitize the file path
					$args = array($step['args'][0]);
				}
			}
			elseif (isset($step['args']))
			{
				if ($step['function'] === '{closure}')
				{
					// Introspection on closures in a stack trace is impossible
					$params = NULL;
				}
				else
				{
					if (isset($step['class']))
					{
						if (method_exists($step['class'], $step['function']))
						{
							$reflection = new ReflectionMethod($step['class'], $step['function']);
						}
						else
						{
							$reflection = new ReflectionMethod($step['class'], '__call');
						}
					}
					else
					{
						$reflection = new ReflectionFunction($step['function']);
					}
					// Get the function parameters
					$params = $reflection->getParameters();
				}
				$args = array();
				foreach ($step['args'] as $i => $arg)
				{
					if (isset($params[$i]))
					{
						// Assign the argument by the parameter name
						$args[$params[$i]->name] = $arg;
					}
					else
					{
						// Assign the argument by number
						$args[$i] = $arg;
					}
				}
			}
			if (isset($step['class']))
			{
				// Class->method() or Class::method()
				$function = $step['class'].$step['type'].$step['function'];
			}
			$output[] = array(
				'function' => $function,
				'args'     => isset($args)   ? $args : NULL,
				'file'     => isset($file)   ? $file : NULL,
				'line'     => isset($line)   ? $line : NULL,
				'source'   => isset($source) ? $source : NULL,
			);
			unset($function, $args, $file, $line, $source);
		}
		return $output;
	}
} // End Kohana Exception